AlexNet深度学习网络-结构简介
参考博文:https://www.cnblogs.com/wangguchangqing/p/10333370.html
第一个典型的CNN是LeNet5网络结构,但是第一个引起大家注意的网络却是AlexNet,也就是文章《ImageNet Classification with Deep Convolutional Neural Networks》介绍的网络结构。这篇文章的网络是在2012年的ImageNet竞赛中取得冠军的一个模型整理后发表的文章。作者是多伦多大学的Alex Krizhevsky等人。Alex Krizhevsky其实是Hinton的学生,这个团队领导者是Hinton,那么Hinton是谁呢?这就要好好说说了,网上流行说 Hinton, LeCun和Bengio是神经网络领域三巨头,LeCun就是LeNet5作者(Yann LeCun),昨天的文章就提到了这个人。而今天的主角虽然不是Hinton,但却和他有关系,这篇的论文第一作者是Alex,所以网络结构称为AlexNet。这篇论文很有意思,因为我读完这篇论文之后,没有遇到比较难以理解的地方,遇到的都是之前学过的概念,比如Relu,dropout。之前学的时候只知道Relu是怎么一回事,今天才知道它真正的来源。这篇文章在2012年发表,文章中的模型参加的竞赛是ImageNet LSVRC-2010,该ImageNet数据集有1.2 million幅高分辨率图像,总共有1000个类别。测试集分为top-1和top-5,并且分别拿到了37.5%和17%的error rates。这样的结果在当时已经超过了之前的工艺水平。
AlexNet网络结构在整体上类似于LeNet,都是先卷积然后在全连接。但在细节上有很大不同。AlexNet更为复杂。AlexNet有60 million个参数和65000个 神经元,五层卷积,三层全连接网络,最终的输出层是1000通道的softmax。AlexNet利用了两块GPU进行计算,大大提高了运算效率,并且在ILSVRC-2012竞赛中获得了top-5测试的15.3%error rate, 获得第二名的方法error rate 是 26.2%,可以说差距是非常的大了,足以说明这个网络在当时给学术界和工业界带来的冲击之大。
一些背景
在计算机视觉领域object detection & recognition 通常用机器学习的方法来解决。为了提高识别的效果,我们可以通过收集更多的可训练的数据来让模型的泛化性能提高。目前,在以一万为单位的数量级层面的数据(称为简单的识别任务)已经获得了非常好的性能,例如:MNIST 手写数字识别任务,最好的性能已经达到了<0.3%的误差。但是现实中的物体存在相当多的变化属性,所以学习识别它们需要更多的数据。事实上,小的图像训练数据有很多的缺点,无论以我们的直觉想还是理论证明都是有依据的,理论上论文《Why is real-world visual object recognition hard?》给出了研究方法。随着互联网技术的发展,以及智能手机的普及图像数据获取可以说越来越容易。所以就有组织去收集这些现实中事物的图像并进行标记和分割。例如:LabelMe(Labelme: a database and web-based tool for image annotation. ),包含了成百上千的全分割图像。 ImageNet(ImageNet: A Large-Scale Hierarchical Image Database. I),包含15 billion 标记的高分辨率图像,包含超过了22000种现实中的事物。
文章中说该模型有5层卷积,去掉任意一层都会使结果不好,所以这个网络的深度似乎是很重要的,这样的话难免引起我们的思考,记得不知道哪位大神在一篇论文中证明了,神经网络可以模拟任意多项式,只要神经元数量足够多,并且和深度关系不大。但这里的实验却表示深度会对网络的性能有影响。文章中还提到了,他们用5-6天训练了这个模型,并且限制了网络的大小,因为现有的硬件智能允许那么大的内存,用更好的设备还可以获得更好的效果。
AlexNet特点
AlexNet是在LeNet的基础上加深了网络的结构,学习更丰富更高维的图像特征。AlexNet的特点:
- 更深的网络结构
- 使用层叠的卷积层,即卷积层+卷积层+池化层来提取图像的特征
- 使用Dropout抑制过拟合
- 使用数据增强Data Augmentation抑制过拟合
- 使用Relu替换之前的sigmoid的作为激活函数
- 多GPU训练
ReLu作为激活函数
在最初的感知机模型中,输入和输出的关系如下:
只是单纯的线性关系,这样的网络结构有很大的局限性:即使用很多这样结构的网络层叠加,其输出和输入仍然是线性关系,无法处理有非线性关系的输入输出。因此,对每个神经元的输出做个非线性的转换也就是,将上面就加权求和∑iwixi+b∑iwixi+b的结果输入到一个非线性函数,也就是激活函数中。 这样,由于激活函数的引入,多个网络层的叠加就不再是单纯的线性变换,而是具有更强的表现能力。
Sigmoid
在最初,sigmoidsigmoid和tanhtanh函数最常用的激活函数。在网络层数较少时,sigmoidsigmoid函数的特性能够很好的满足激活函数的作用:它把一个实数压缩至0到1之间,当输入的数字非常大的时候,结果会接近1;当输入非常大的负数时,则会得到接近0的结果。这种特性,能够很好的模拟神经元在受刺激后,是否被激活向后传递信息(输出为0,几乎不被激活;输出为1,完全被激活)。
sigmoidsigmoid一个很大的问题就是梯度饱和。 观察sigmoidsigmoid函数的曲线,当输入的数字较大(或较小)时,其函数值趋于不变,其导数变的非常的小。这样,在层数很多的的网络结构中,进行反向传播时,由于很多个很小的sigmoidsigmoid导数累成,导致其结果趋于0,权值更新较慢。
ReLu
针对sigmoidsigmoid梯度饱和导致训练收敛慢的问题,在AlexNet中引入了ReLU。ReLU是一个分段线性函数,小于等于0则输出为0;大于0的则恒等输出。相比于sigmoidsigmoid,ReLU有以下有点:
-
- 计算开销下。sigmoidsigmoid的正向传播有指数运算,倒数运算,而ReLu是线性输出;反向传播中,sigmoidsigmoid有指数运算,而ReLU有输出的部分,导数始终为1.
- 梯度饱和问题
- 稀疏性。Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生。
这里有个问题,前面提到,激活函数要用非线性的,是为了使网络结构有更强的表达的能力。那这里使用ReLU本质上却是个线性的分段函数,是怎么进行非线性变换的。把神经网络看着一个巨大的变换矩阵MM,其输入为所有训练样本组成的矩阵AA,输出为矩阵BB: B=M⋅AB=M⋅A这里的MM是一个线性变换的话,则所有的训练样本AA进行了线性变换输出为BB。那么对于ReLU来说,由于其是分段的,0的部分可以看着神经元没有激活,不同的神经元激活或者不激活,其神经玩过组成的变换矩阵是不一样的。
设有两个训练样本 a1,a2,其训练时神经网络组成的变换矩阵为M1,M2M1,M2。 由于M1M1变换对应的神经网络中激活神经元和M2M2是不一样的,这样M1,M2M1,M2实际上是两个不同的线性变换。也就是说,每个训练样本使用的线性变换矩阵MiMi是不一样的,在整个训练样本空间来说,其经历的是非线性变换。
简单来说,不同训练样本中的同样的特征,在经过神经网络学习时,流经的神经元是不一样的(激活函数值为0的神经元不会被激活)。这样,最终的输出实际上是输入样本的非线性变换。
单个训练样本是线性变换,但是每个训练样本的线性变换是不一样的,这样整个训练样本集来说,就是非线性的变换。
数据增强
神经网络由于训练的参数多,表能能力强,所以需要比较多的数据量,不然很容易过拟合。当训练数据有限时,可以通过一些变换从已有的训练数据集中生成一些新的数据,以快速地扩充训练数据。对于图像数据集来说,可以对图像进行一些形变操作:
- 翻转
- 随机裁剪
- 平移,颜色光照的变换
- ...
AlexNet中对数据做了以下操作:
- 随机裁剪,对256×256256×256的图片进行随机裁剪到227×227227×227,然后进行水平翻转。
- 测试的时候,对左上、右上、左下、右下、中间分别做了5次裁剪,然后翻转,共10个裁剪,之后对结果求平均。
- 对RGB空间做PCA(主成分分析),然后对主成分做一个(0, 0.1)的高斯扰动,也就是对颜色、光照作变换,结果使错误率又下降了1%。
层叠池化
在LeNet中池化是不重叠的,即池化的窗口的大小和步长是相等的,如下
在AlexNet中使用的池化(Pooling)却是可重叠的,也就是说,在池化的时候,每次移动的步长小于池化的窗口长度。AlexNet池化的大小为3×3的正方形,每次池化移动步长为2,这样就会出现重叠。重叠池化可以避免过拟合,这个策略贡献了0.3%的Top-5错误率。与非重叠方案s=2,z=2s=2,z=2相比,输出的维度是相等的,并且能在一定程度上抑制过拟合。
局部相应归一化
Dropout
这个是比较常用的抑制过拟合的方法了。引入Dropout主要是为了防止过拟合。在神经网络中Dropout通过修改神经网络本身结构来实现,对于某一层的神经元,通过定义的概率将神经元置为0,这个神经元就不参与前向和后向传播,就如同在网络中被删除了一样,同时保持输入层与输出层神经元的个数不变,然后按照神经网络的学习方法进行参数更新。在下一次迭代中,又重新随机删除一些神经元(置为0),直至训练结束。
Dropout应该算是AlexNet中一个很大的创新,现在神经网络中的必备结构之一。Dropout也可以看成是一种模型组合,每次生成的网络结构都不一样,通过组合多个模型的方式能够有效地减少过拟合,Dropout只需要两倍的训练时间即可实现模型组合(类似取平均)的效果,非常高效。如下图:
Alex网络结构
上图中的输入是224×224224×224,不过经过计算(224−11)/4=54.75(224−11)/4=54.75并不是论文中的55×5555×55,而使用227×227227×227作为输入,则(227−11)/4=55(227−11)/4=55
网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层。最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000类标签的分布网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层。最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000类标签的分布。
卷积层1,输入为 224×224×3224 \times 224 \times 3224×224×3的图像,卷积核的数量为96,论文中两片GPU分别计算48个核; 卷积核的大小为 11×11×311 \times 11 \times 311×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
具体分析:
AlexNet参数数量
卷积层的参数 = 卷积核的数量 * 卷积核 + 偏置
- C1: 96个11×11×311×11×3的卷积核,96×11×11×3+96=3484896×11×11×3+96=34848
- C2: 2组,每组128个5×5×485×5×48的卷积核,(128×5×5×48+128)×2=307456(128×5×5×48+128)×2=307456
- C3: 384个3×3×2563×3×256的卷积核,3×3×256×384+384=8851203×3×256×384+384=885120
- C4: 2组,每组192个3×3×1923×3×192的卷积核,(3×3×192×192+192)×2=663936(3×3×192×192+192)×2=663936
- C5: 2组,每组128个3×3×1923×3×192的卷积核,(3×3×192×128+128)×2=442624(3×3×192×128+128)×2=442624
- FC6: 4096个6×6×2566×6×256的卷积核,6×6×256×4096+4096=377528326×6×256×4096+4096=37752832
- FC7: 4096∗4096+4096=167813124096∗4096+4096=16781312
- output: 4096∗1000=40960004096∗1000=4096000
卷积层 C2,C4,C5中的卷积核只和位于同一GPU的上一层的FeatureMap相连。从上面可以看出,参数大多数集中在全连接层,在卷积层由于权值共享,权值参数较少。
Keras实现
由于AlexNet是使用两块显卡进行训练的,其网络结构的实际是分组进行的。并且,在C2,C4,C5上其卷积核只和上一层的同一个GPU上的卷积核相连。 对于单显卡来说,并不适用,本文基于Keras的实现,忽略其关于双显卡的的结构,并且将局部归一化操作换成了BN。其网络结构如下:
AlexNet的论文下载地址:点击打开链接