赞
踩
ImageNet
数据集:一个开源的图片数据集,包含超过 1400万张图片和图片对应的标签,包含2万多个类别。
自从2010
年以来,ImageNet
每年举办一次比赛,即:ImageNet
大规模视觉识别挑战赛ILSVRC
,比赛使用 1000 个类别图片。
2017年7月,ImageNet
宣布ILSVRC
于2017
年正式结束,因为图像分类、物体检测、物体识别任务中计算机的正确率都远超人类,计算机视觉在感知方面的问题基本得到解决,后续将专注于目前尚未解决的问题。
ImageNet
中使用两种错误率作为评估指标:
top-5
错误率:对一个图片,如果正确标记在模型输出的前 5 个最佳预测(即:概率最高的前5个)中,则认为是正确的,否则认为是错误的。
最终错误预测的样本数占总样本数的比例就是 top-5
错误率。
top-1
错误率:对一个图片,如果正确标记等于模型输出的最佳预测(即:概率最高的那个),则认为是正确的,否则认为是错误的。
最终错误预测的样本数占总样本数的比例就是 top-1
错误率。
在LeNet提出后,卷积神经⽹络在计算机视觉和机器学习领域中很有名⽓。但卷积神经⽹络并没有主导这些领域。这是因为虽然LeNet在⼩数据集上取得了很好的效果,但是在更⼤、更真实的数据集上训练卷积神经⽹络的性能和可⾏性还有待研究。事实上,在上世纪90年代初到2012年之间的⼤部分时间⾥,神经⽹络往往被其他机器学习⽅法超越,如⽀持向量机(support vector machines)。
Alex Krizhevsky
【Hinton的博士,AlexNet一作】、Ilya Sutskever
【OpenAI联合创始人和首席科学家】和Geoff Hinton
【2018 年,与 Yoshua Bengio、Yann LeCun 共同获得了图灵奖】提出了⼀种新的卷积神经⽹络变体AlexNet,在2012年ImageNet挑战赛中,AlexeNet
以远超第二名的成绩夺冠,使得深度学习重回历史舞台,具有重大历史意义。
AlexNet论文下载地址:https://proceedings.neurips.cc/paper/2012/file/c399862d3b9d6b76c8436e924a68c45b-Paper.pdf
【论文摘要翻译如下】
"""
我们训练了一个大型的深度卷积神经网络,将ImageNet LSVRC-2010竞赛中的120万张高分辨率图像分类成
1000种不同的类别。在测试数据上,我们取得了Top1 37.5%和Top-5 17.0%的错误率,这个结果已经远超
以前的最高水平。该神经网络具有6千万个参数和650,000个神经元,它由5个卷积层和3个全连接层构成,其
中部分卷积层后边跟有最大池化层,全连接层后边则是一个1000路的softmax分类器。为了使训练速度更
快,我们使用了非饱和神经元和一种卷积操作的非常高效的GPU实现。为了减少全连接层中的过拟合,我们使
用了一个最近开发的被称作“暂退法”的正则化方法,该方法已被证明十分有效。在IOLSVRC-2012竞赛中,我
们正式提出这个模型的一种变体,并以15.3%的top-5测试误差率赢得榜首,相比而言,第二好的参赛队伍则
只取得26.2%的成绩。
"""
AlexNet和LeNet的架构⾮常相似,这⾥我们提供了⼀个稍微精简版本的AlexNet,去除了当年需要两个⼩型GPU同时运算的设计特点。
左边为LeNet,右边为AlexNet
AlexNet和LeNet的设计理念⾮常相似,但也存在显著差异。
⾸先,AlexNet⽐相对较小的LeNet5要深得多。
AlexNet由⼋层组成:五个卷积层、两个全连接隐藏层和⼀个全连接输出层。
其次,AlexNet使⽤ReLU⽽不是sigmoid作为其激活函数。
可以看到,由于早期GPU显存有限,原版的AlexNet采⽤了双数据流设计,使得每个GPU只负责存储和计算模型的⼀半参数。幸运的是,现在GPU显存相对充裕,所以我们现在很少需要跨GPU分解模型
AlexNet
有5个广义卷积层和3个广义全连接层。
ReLU
、LRN
层等。ReLU
、Dropout
层等。网络结构如下表所示:
输入层会将3@224x224
的三维图片预处理变成3@227x227
的三维图片。
第二层广义卷积层、第四层广义卷积层、第五层广义卷积层都是分组卷积,仅采用本GPU
内的通道数据进行计算。
第一层广义卷积层、第三层广义卷积层、第六层连接层、第七层连接层、第八层连接层执行的是全部通道数据的计算。
第二层广义卷积层的卷积、第三层广义卷积层的卷积、第四层广义卷积层的卷积、第五层广义卷积层的卷积均采用same
填充。
当卷积的步长为1,核大小为
3x3
时,如果不填充0,则feature map
的宽/高都会缩减 2 。因此这里填充0,使得输出feature map
的宽/高保持不变。
其它层的卷积,以及所有的池化都是valid
填充(即:不填充 0 )。
第六层广义连接层的卷积之后,会将feature map
展平为长度为 4096 的一维向量。
编号 | 网络层 | 子层 | 核/池大小 | 核数量 | 步长 | 填充 | 激活函数 | 输入尺寸 | 输出尺寸 |
---|---|---|---|---|---|---|---|---|---|
第0层 | 输入层 | - | - | - | - | - | - | - | 3@224x224 |
第1层 | 广义卷积层 | 卷积 | 11x11 | 96 | 4 | - | ReLU | 3@227x227 | 96@55x55 |
第1层 | 广义卷积层 | 池化 | 3x3 | - | 2 | - | - | 96@55x55 | 96@27x27 |
第1层 | 广义卷积层 | LRN | - | - | - | - | - | 96@27x27 | 96@27x27 |
第2层 | 广义卷积层 | 卷积 | 5x5 | 256 | 1 | 2 | ReLU | 96@27x27 | 256@27x27 |
第2层 | 广义卷积层 | 池化 | 3x3 | - | 2 | - | - | 256@27x27 | 256@13x13 |
第2层 | 广义卷积层 | LRN | - | - | - | - | - | 256@13x13 | 256@13x13 |
第3层 | 广义卷积层 | 卷积 | 3x3 | 384 | 1 | 1 | ReLU | 256@13x13 | 384@13x13 |
第4层 | 广义卷积层 | 卷积 | 3x3 | 384 | 1 | 1 | ReLU | 384@13x13 | 384@13x13 |
第5层 | 广义卷积层 | 卷积 | 3x3 | 256 | 1 | 1 | ReLU | 384@13x13 | 256@13x13 |
第5层 | 广义卷积层 | 池化 | 3x3 | - | 2 | - | - | 256@13x13 | 256@6x6 |
第6层 | 广义连接层 | 卷积 | 6x6 | 4096 | 1 | - | ReLU | 256@6x6 | 4096@1x1 |
第6层 | 广义连接层 | dropout | - | - | - | - | - | 4096@1x1 | 4096@1x1 |
第7层 | 广义连接层 | 全连接 | - | - | - | - | ReLU | 4096 | 4096 |
第7层 | 广义连接层 | dropout | - | - | - | - | - | 4096 | 4096 |
第8层 | 广义连接层 | 全连接 | - | - | - | - | - | 4096 | 1000 |
我们用pytorch进行实现
import torch.nn as nn import torch class AlexNet(nn.Module): def __init__(self): super().__init__() self.model = nn.Sequential( # 使⽤⼀个11*11的更⼤窗⼝来捕捉对象。 # 同时,步幅为4,以减少输出的⾼度和宽度。 # 另外,输出通道的数⽬远⼤于LeNet nn.Conv2d(1, 96, kernel_size=11, stride=4), nn.ReLU(), nn.MaxPool2d(kernel_size=3, stride=2), # 减⼩卷积窗⼝,使⽤填充为2来使得输⼊与输出的⾼和宽⼀致,且增⼤输出通道数 nn.Conv2d(96, 256, kernel_size=5, padding=2), nn.ReLU(), nn.MaxPool2d(kernel_size=3, stride=2), # 使⽤三个连续的卷积层和较⼩的卷积窗⼝。 # 除了最后的卷积层,输出通道的数量进⼀步增加。 # 在前两个卷积层之后,汇聚层不⽤于减少输⼊的⾼度和宽度 nn.Conv2d(256, 384, kernel_size=3, padding=1), nn.ReLU(), nn.Conv2d(384, 384, kernel_size=3, padding=1), nn.ReLU(), nn.Conv2d(384, 256, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(kernel_size=3, stride=2), nn.Flatten(), # 这⾥,全连接层的输出数量是LeNet中的好⼏倍。使⽤dropout层来减轻过拟合 nn.Linear(9216, 4096), nn.ReLU(), nn.Dropout(p=0.5), nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(p=0.5), # 最后是输出层。由于这⾥使⽤Fashion-MNIST,所以⽤类别数为10,⽽⾮论⽂中的1000 nn.Linear(4096, 10) ) def forward(self, X): X = self.model(X) return X if __name__ == '__main__': net = AlexNet() # 测试神经网络是否可运行 # inputs = torch.rand(size=(1, 1, 227, 227), dtype=torch.float32) # outputs = net(inputs) # print(outputs.shape) X = torch.rand(size=(1, 1, 227, 227), dtype=torch.float32) for layer in net.model: X = layer(X) print(layer.__class__.__name__, 'output shape:', X.shape)
""" 第1层:广义卷积层 Conv2d output shape: torch.Size([1, 96, 55, 55]) ReLU output shape: torch.Size([1, 96, 55, 55]) MaxPool2d output shape: torch.Size([1, 96, 27, 27]) 第2层:广义卷积层 Conv2d output shape: torch.Size([1, 256, 27, 27]) ReLU output shape: torch.Size([1, 256, 27, 27]) MaxPool2d output shape: torch.Size([1, 256, 13, 13]) 第3层:广义卷积层 Conv2d output shape: torch.Size([1, 384, 13, 13]) ReLU output shape: torch.Size([1, 384, 13, 13]) 第4层:广义卷积层 Conv2d output shape: torch.Size([1, 384, 13, 13]) ReLU output shape: torch.Size([1, 384, 13, 13]) 第5层:广义卷积层 Conv2d output shape: torch.Size([1, 256, 13, 13]) ReLU output shape: torch.Size([1, 256, 13, 13]) MaxPool2d output shape: torch.Size([1, 256, 6, 6]) 第6层:广义连接层 Flatten output shape: torch.Size([1, 9216]) Linear output shape: torch.Size([1, 4096]) ReLU output shape: torch.Size([1, 4096]) Dropout output shape: torch.Size([1, 4096]) 第7层:广义连接层 Linear output shape: torch.Size([1, 4096]) ReLU output shape: torch.Size([1, 4096]) Dropout output shape: torch.Size([1, 4096]) 第8层:广义连接层 Linear output shape: torch.Size([1, 10]) """
网络参数数量
:总计约 6237万。
AlexNet
成功的主要原因在于:
ReLU
激活函数。dropout
、数据集增强 、重叠池化等防止过拟合的方法。GPU
训练,以及的LRN
使用。mini batch
随机梯度下降来训练。局部响应规范层LRN
:目地是为了进行一个横向抑制,使得不同的卷积核所获得的响应产生竞争。
LRN
层现在很少使用,因为效果不是很明显,而且增加了内存消耗和计算时间。AlexNet
中使用的数据集增强手段:
随机裁剪、随机水平翻转:原始图片的尺寸为256xx256
,裁剪大小为224x224
。
每一个epoch
中,对同一张图片进行随机性的裁剪,然后随机性的水平翻转。理论上相当于扩充了数据集 倍。
在预测阶段不是随机裁剪,而是固定裁剪图片四个角、一个中心位置,再加上水平翻转,一共获得 10 张图片。
用这10张图片的预测结果的均值作为原始图片的预测结果。
PCA
降噪:对RGB
空间做PCA
变换来完成去噪功能。同时在特征值上放大一个随机性的因子倍数(单位1
加上一个 的高斯绕动),从而保证图像的多样性。
epoch
重新生成一个随机因子。1%
。AlexNet
的预测方法存在两个问题:
固定裁剪四个角、一个中心
的方式,把图片的很多区域都给忽略掉了。很有可能一些重要的信息就被裁剪掉。改进的思路是:
具体做法为:将全连接层用等效的卷积层替代,然后直接使用原始大小的测试图片进行预测。将输出的各位置处的概率值按每一类取平均(或者取最大),则得到原始测试图像的输出类别概率。
一般的池化是不重叠的,池化区域的大小与步长相同。Alexnet
中,池化是可重叠的,即:步长小于池化区域的大小。
重叠池化可以缓解过拟合,该策略贡献了0.4%
的错误率。
为什么重叠池化会减少过拟合,很难用数学甚至直观上的观点来解答。一个稍微合理的解释是:重叠池化会带来更多的特征,这些特征很可能会有利于提高模型的泛化能力。
import torch.nn as nn import torch class AlexNet(nn.Module): def __init__(self): super().__init__() self.model = nn.Sequential( # 这⾥,我们使⽤⼀个11*11的更⼤窗⼝来捕捉对象。 # 同时,步幅为4,以减少输出的⾼度和宽度。 # 另外,输出通道的数⽬远⼤于LeNet nn.Conv2d(1, 96, kernel_size=11, stride=4,padding=1), # 1、填充设置为1 nn.ReLU(), nn.MaxPool2d(kernel_size=3, stride=2), # 减⼩卷积窗⼝,使⽤填充为2来使得输⼊与输出的⾼和宽⼀致,且增⼤输出通道数 nn.Conv2d(96, 256, kernel_size=5, padding=2), nn.ReLU(), nn.MaxPool2d(kernel_size=3, stride=2), # 使⽤三个连续的卷积层和较⼩的卷积窗⼝。 # 除了最后的卷积层,输出通道的数量进⼀步增加。 # 在前两个卷积层之后,汇聚层不⽤于减少输⼊的⾼度和宽度 nn.Conv2d(256, 384, kernel_size=3, padding=1), nn.ReLU(), nn.Conv2d(384, 384, kernel_size=3, padding=1), nn.ReLU(), nn.Conv2d(384, 256, kernel_size=3, padding=1), nn.ReLU(), nn.MaxPool2d(kernel_size=3, stride=2), nn.Flatten(), # 这⾥,全连接层的输出数量是LeNet中的好⼏倍。使⽤dropout层来减轻过拟合 nn.Linear(6400, 4096), nn.ReLU(), # 2、输出相对2.1.3降为6400 nn.Dropout(p=0.5), nn.Linear(4096, 4096), nn.ReLU(), nn.Dropout(p=0.5), # 最后是输出层。由于这⾥使⽤Fashion-MNIST,所以⽤类别数为10,⽽⾮论⽂中的1000 nn.Linear(4096, 10) ) def forward(self, X): X = self.model(X) return X if __name__ == '__main__': net = AlexNet() # 测试神经网络是否可运行 inputs = torch.rand(size=(1, 1, 224, 224), dtype=torch.float32) outputs = net(inputs) print(outputs.shape) # X = torch.rand(size=(1, 1, 224, 224), dtype=torch.float32) # for layer in net.model: # X = layer(X) # print(layer.__class__.__name__, 'output shape:', X.shape)
其他所有的函数,与经典神经网络(1)LeNet及其在Fashion-MNIST数据集上的应用完全一致。
'''
Fashion-MNIST图像的分辨率(28×28像素)低于ImageNet图像。为了解决这个问题,增加到224×224
'''
batch_size = 128
train_iter, test_iter = load_data_fashion_mnist(batch_size, resize=224)
from _02_AlexNet import AlexNet
# 初始化模型
net = AlexNet()
# 与LeNet相比,使⽤更⼩的学习速率训练,这是因为⽹络更深更⼴、图像分辨率更⾼,训练卷积神经⽹络就更昂贵
# 注意需要用GPU进行训练
lr, num_epochs = 0.01, 10
train_ch(net, train_iter, test_iter, num_epochs, lr, try_gpu())
loss 0.327, train acc 0.881, test acc 0.885
4149.6 examples/sec on cuda:0
注:AlexNet用GPU才能跑,如果自己电脑没有合适的GPU,可以参考下面文章进行租借
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。