前言

  作为深度学习的开山之作AlexNet,确实给后来的研究者们很大的启发,使用神经网络来做具体的任务,如分类任务、回归(预测)任务等,尽管AlexNet在今天看来已经有很多神经网络超越了它,但是它依然是重要的。AlexNet的作者Alex Krizhevsky首次在两块GTX 580 GPU上做神经网络,并且在2012年ImageNet竞赛中取得了冠军,这是一件非常有意义的事情,为后来深度学习的兴起奠定了重要基础,包括现在的显卡公司NVIDIA的市值超越苹果,都有深度学习的一份功劳。

  下面讲解一下AlexNet的网络结构和论文复现。实验为使用AlexNet网络做猫狗分类任务;实验经过了模型搭建,训练,测试以及结果分析。

1.网络结构

  AlexNet的网络一共有8层,前5层是卷积层,剩下3层是全连接层,具体如下所示:

  第一层:卷积层1,输入为 224 × 224 × 3 的图像,卷积核的数量为96,论文中两片GPU分别计算48个核; 卷积核的大小为 11 × 11 × 3;stride = 4, stride表示的是步长, pad = 0, 表示不扩充边缘;卷积后的图形大小为:wide = (224 + 2 * padding - kernel_size) / stride + 1 = 54,height = (224 + 2 * padding - kernel_size) / stride + 1 = 54,dimention = 96,然后进行 (Local Response Normalized), 后面跟着池化pool_size = (3, 3), stride = 2, pad = 0 最终获得第一层卷积的feature map;

  第二层:卷积层2, 输入为上一层卷积的feature map, 卷积的个数为256个,论文中的两个GPU分别有128个卷积核。卷积核的大小为:5 × 5 × 48;pad = 2, stride = 1; 然后做 LRN,最后 max_pooling, pool_size = (3, 3), stride = 2;

  第三层:卷积3, 输入为第二层的输出,卷积核个数为384,kernel_size = (3 × 3 × 128),padding = 1,第三层没有做LRN和Pool;

  第四层:卷积4, 输入为第三层的输出,卷积核个数为384,kernel_size = (3 × 3 × 192),padding = 1,和第三层一样,没有LRN和Pool;

  第五层:卷积5, 输入为第四层的输出,卷积核个数为256,kernel_size = (3 × 3 × 192),padding = 1。然后直接进行max_pooling, pool_size = (3, 3), stride = 2;

  第6,7,8层是全连接层,每一层的神经元的个数为4096,最终输出softmax为1000,因为上面介绍过,ImageNet这个比赛的分类个数为1000。全连接层中使用了Relu和Dropout。

2.数据集

  数据集为猫狗的图片,其中猫的图片12500张,狗的图片12500张;训练数据集猫12300张,狗12300张,验证集猫100张,狗100张,测试集猫100张,狗100张;数据集链接:https://pan.baidu.com/s/11UHodPIHRDwHiRoae_fqtQ 提取码:d0fa;下图为训练集示意图:

3.数据集分类

  将数据集中的猫和狗分别放在train_0和train_1中:

import os
import re
import shutil origin_path = '/workspace/src/how-to-read-paper/dataset/train'
target_path_0 = '/workspace/src/how-to-read-paper/dataset/train_0/0'
target_path_1 = '/workspace/src/how-to-read-paper/dataset/train_0/1' os.makedirs(target_path_0, exist_ok=True)
os.makedirs(target_path_1, exist_ok=True) file_list = os.listdir(origin_path) for i in range(len(file_list)):
old_path = os.path.join(origin_path, file_list[i])
result = re.findall(r'\w+', file_list[i])[0]
if result == 'cat':
shutil.move(old_path, target_path_0)
else:
shutil.move(old_path, target_path_1)

4.模型搭建

  进行模型搭建和数据导入:

import torch
import os
from torch import nn
from torch.nn import functional as F
from torch.autograd import Variable
import matplotlib.pyplot as plt
from torchvision.datasets import ImageFolder
import torch.optim as optim
import torch.utils.data
from PIL import Image
import torchvision.transforms as transforms # 超参数设置
DEVICE = torch.device('cuda'if torch.cuda.is_available() else 'cpu')
EPOCH = 100
BATCH_SIZE = 256 # 卷积层和全连接层、前向传播
class AlexNet(nn.Module):
def __init__(self, num_classes=2):
super(AlexNet, self).__init__()
# 卷积层
self.features = nn.Sequential(
nn.Conv2d(3, 48, kernel_size=11),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(48, 128, kernel_size=5, padding=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
nn.Conv2d(128, 192, kernel_size=3, stride=1, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(192, 192, kernel_size=3, stride=1, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(192, 128, kernel_size=3, stride=1, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2),
)
# 全连接层q
self.classifier = nn.Sequential(
nn.Linear(6*6*128, 2048),
nn.ReLU(inplace=True),
nn.Dropout(0.5),
nn.Linear(2048, 2048),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(2048, num_classes),
)
# 前向传播
def forward(self, x):
x = self.features(x)
x = torch.flatten(x, start_dim=1)
x = self.classifier(x) return x # 训练集、测试集、验证集的导入
# 归一化处理
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 训练集
path_1 = '/workspace/src/how-to-read-paper/dataset/train_0'
trans_1 = transforms.Compose([
transforms.Resize((65, 65)),
transforms.ToTensor(),
normalize,
]) # 数据集
train_set = ImageFolder(root=path_1, transform=trans_1)
# 数据加载器
train_loader = torch.utils.data.DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True, num_workers=0) # 测试集
path_2 = '/workspace/src/how-to-read-paper/dataset/test'
trans_2 = transforms.Compose([
transforms.Resize((65, 65)),
transforms.ToTensor(),
normalize,
])
test_data = ImageFolder(root=path_2, transform=trans_2)
test_loader = torch.utils.data.DataLoader(test_data, batch_size=BATCH_SIZE, shuffle=True, num_workers=0) # 验证集
path_3 = '/workspace/src/how-to-read-paper/dataset/valid'
trans_3 = transforms.Compose([
transforms.Resize((65, 65)),
transforms.ToTensor(),
normalize,
])
valid_data = ImageFolder(root=path_3, transform=trans_3)
valid_loader = torch.utils.data.DataLoader(valid_data, batch_size=BATCH_SIZE, shuffle=True, num_workers=0)

5.训练

  进行模型训练:

# 定义模型
model = AlexNet().to(DEVICE)
# 优化器的选择
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9, weight_decay=0.0005) def train_model(model, device, train_loader, optimizer, epoch):
train_loss = 0
model.train()
for batch_index, (data, label) in enumerate(train_loader):
data, label = data.to(device), label.to(device)
optimizer.zero_grad()
output = model(data)
loss = F.cross_entropy(output, label)
loss.backward()
optimizer.step()
if batch_index % 300 == 0:
train_loss = loss.item()
print('Train Epoch:{}\ttrain loss:{:.6f}'.format(epoch, loss.item())) return train_loss def test_model(model, device, test_loader):
model.eval()
correct = 0.0
test_loss = 0.0 # 不需要梯度的记录
with torch.no_grad():
for data, label in test_loader:
data, label = data.to(device), label.to(device)
output = model(data)
test_loss += F.cross_entropy(output, label).item()
pred = output.argmax(dim=1)
correct += pred.eq(label.view_as(pred)).sum().item()
test_loss /= len(test_loader.dataset)
print('Test_average_loss:{:.4f}, Accuracy:{:3f}\n'.format(test_loss, 100*correct/len(test_loader.dataset)))
acc = 100*correct / len(test_loader.dataset) return test_loss, acc # 开始训练¶
list = []
Train_Loss_list = []
Valid_Loss_list = []
Valid_Accuracy_list = [] for epoch in range(1, EPOCH+1):
# 训练集训练
train_loss = train_model(model, DEVICE, train_loader, optimizer, epoch)
Train_Loss_list.append(train_loss)
torch.save(model, r'/workspace/src/how-to-read-paper/model/model%s.pth' % epoch) # 验证集进行验证
test_loss, acc = test_model(model, DEVICE, valid_loader)
Valid_Loss_list.append(test_loss)
Valid_Accuracy_list.append(acc)
list.append(test_loss)

6.测试

  进行模型测试:

# 验证集的test_loss

min_num = min(list)
min_index = list.index(min_num) print('model%s' % (min_index+1))
print('验证集最高准确率:')
print('{}'.format(Valid_Accuracy_list[min_index])) # 取最好的进入测试集进行测试
model = torch.load('/workspace/src/how-to-read-paper/model/model%s.pth' % (min_index+1))
model.eval() accuracy = test_model(model, DEVICE, test_loader)
print('测试集准确率')
print('{}%'.format(accuracy))

7.实验结果分析

  下图为epoch为50和100的loss和acc的折线图,其中使用最优的模型epoch=50时测试集的loss=0.00132, acc=89.0%;其中使用最优的模型epoch=100时测试集的loss=0.00203, acc=91.5%;从实验结果可以看出epoch=20时模型train已经很好了,那么想要train一个更好的模型有方法吗?答案肯定是有的,比如说做一下数据增强、使用正则化项、噪声注入等,这些大家都可以尝试一下。

  注:本实验代码地址

 

AlexNet论文解读的更多相关文章

  1. AlexNet详细解读

    AlexNet详细解读 目前在自学计算机视觉与深度学习方向的论文,今天给大家带来的是很经典的一篇文章 :<ImageNet Classification with Deep Convolutio ...

  2. 自监督学习(Self-Supervised Learning)多篇论文解读(下)

    自监督学习(Self-Supervised Learning)多篇论文解读(下) 之前的研究思路主要是设计各种各样的pretext任务,比如patch相对位置预测.旋转预测.灰度图片上色.视频帧排序等 ...

  3. itemKNN发展史----推荐系统的三篇重要的论文解读

    itemKNN发展史----推荐系统的三篇重要的论文解读 本文用到的符号标识 1.Item-based CF 基本过程: 计算相似度矩阵 Cosine相似度 皮尔逊相似系数 参数聚合进行推荐 根据用户 ...

  4. CVPR2019 | Mask Scoring R-CNN 论文解读

    Mask Scoring R-CNN CVPR2019 | Mask Scoring R-CNN 论文解读 作者 | 文永亮 研究方向 | 目标检测.GAN 推荐理由: 本文解读的是一篇发表于CVPR ...

  5. AAAI2019 | 基于区域分解集成的目标检测 论文解读

    Object Detection based on Region Decomposition and Assembly AAAI2019 | 基于区域分解集成的目标检测 论文解读 作者 | 文永亮 学 ...

  6. < AlexNet - 论文研读个人笔记 >

    Alexnet - 论文研读个人笔记 一.论文架构 摘要: 简要说明了获得成绩.网络架构.技巧特点 1.introduction 领域方向概述 前人模型成绩 本文具体贡献 2.The Dataset ...

  7. Gaussian field consensus论文解读及MATLAB实现

    Gaussian field consensus论文解读及MATLAB实现 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 一.Introduction ...

  8. zz扔掉anchor!真正的CenterNet——Objects as Points论文解读

    首发于深度学习那些事 已关注写文章   扔掉anchor!真正的CenterNet——Objects as Points论文解读 OLDPAN 不明觉厉的人工智障程序员 ​关注他 JustDoIT 等 ...

  9. NIPS2018最佳论文解读:Neural Ordinary Differential Equations

    NIPS2018最佳论文解读:Neural Ordinary Differential Equations 雷锋网2019-01-10 23:32     雷锋网 AI 科技评论按,不久前,NeurI ...

  10. [论文解读] 阿里DIEN整体代码结构

    [论文解读] 阿里DIEN整体代码结构 目录 [论文解读] 阿里DIEN整体代码结构 0x00 摘要 0x01 文件简介 0x02 总体架构 0x03 总体代码 0x04 模型基类 4.1 基本逻辑 ...

随机推荐

  1. 阿里巴巴在 Envoy Gateway 的演进历程浅析

    ​简介:最近阅读 <Envoy Gateway 来了>这篇文章,深感 Envoy 强大的可扩展性和基于 Envoy Gateway 带来的易用性,在 K8s 架构下,Envoy 重新定义了 ...

  2. 阿里开源自研工业级稀疏模型高性能训练框架 PAI-HybridBackend

    ​简介:近年来,随着稀疏模型对算力日益增长的需求, CPU集群必须不断扩大集群规模来满足训练的时效需求,这同时也带来了不断上升的资源成本以及实验的调试成本.为了解决这一问题,阿里云机器学习PAI平台开 ...

  3. 10倍性能提升!DLA SQL推出基于Alluxio的数据湖分析加速功能

    简介: 在存储计算分离的场景下,通过网络从远端存储读取数据是一个代价较大的操作,往往会带来性能的损耗.以OSS为例,OSS数据读取延时通常较本地磁盘大很多,同时OSS对单个用户使用的带宽上限做了限制, ...

  4. 基于容器服务 ACK 发行版打造 CNStack 社区版

    ​简介:本文将介绍如何使用 ACK Distro 作为基础镜像打造 CNStack 社区版以及CNStack 社区版中的容器服务 ACK 敏捷版产品如何帮助用户更好的使用容器平台能力. 作者:临石 C ...

  5. Flink Sort-Shuffle 实现简介

    简介:Sort-Shuffle 使 Flink 在应对大规模批数据处理任务时更加游刃有余 本文介绍 Sort-Shuffle 如何帮助 Flink 在应对大规模批数据处理任务时更加游刃有余.主要内容包 ...

  6. S/4 HANA 中的 Email Template

    电子邮件是非常常见的业务需求. SAP 了解这一点,并在 S/4 HANA(cloud和on premise)中引入了非常有趣的功能--Email Template.它将CDS视图和HTML模板结合了 ...

  7. ES_CCS/R(一):建立集群之间的安全互信

    为了能够实现 CCR(跨集群复制 Cross-cluster replication) 及 CCS(跨集群搜索 Cross-cluster search ),我们必须让集群之间能够互信,这样才可以建立 ...

  8. 关于ITIL的习惯性误解

    关于ITIL的习惯性误解 1. ITIL是标准?不是!ITIL本质是一套适合西方社会信息化阶段的 模板原版教材 最佳实践(Best Practice),不是标准. 大量的培训师和咨询顾问将其包装成&q ...

  9. sqli-labs-master 导入导出 + 第七关

    1.load_file()导出文件 load_file(file_name):读取文件并返回该文件内容作为一个字符串. 使用条件: A:必须有权限读取并且文件完全可读 B:预读取文件必修在服务器上 C ...

  10. golang向上取整、向下取整和四舍五入

    一.概述 官方的math 包中提供了取整的方法,向上取整math.Ceil() ,向下取整math.Floor() 二.用法 package main import ( "fmt" ...