VGGNet论文给出了一个非常振奋人心的结论:卷积神经网络的深度增加和小卷积核的使用对网络的最终分类识别效果有很大的作用。
VGGNet由牛津大学的视觉几何组(Visual Geometry Group)和 Google DeepMind公司的研究员一起研发的的深度卷积神经网络,在 ILSVRC 2014 上取得了第二名的成绩,将 Top-5错误率降到7.3%。目前使用比较多的网络结构主要有ResNet(152-1000层),GooleNet(22层),VGGNet(19层),大多数模型都是基于这几个模型上改进,采用新的优化算法,多模型融合等。到目前为止,VGG Net 依然经常被用来提取图像特征。
输入是大小为224x224的RGB图像,预处理(preprocession)时计算出三个通道的平均值,在每个像素上减去平均值(处理后迭代更少,更快收敛,加速网络训练)。
图像经过一系列卷积层处理,在卷积层中使用了非常小的3x3卷积核,在有些卷积层里则使用了1x1的卷积核(在全连接层之间用的是1x1的卷积操作)。
卷积层步长(stride)设置为1个像素,3x3卷积层的填充(padding)设置为1个像素。池化层采用max pooling,共有5层,在一部分卷积层后,max-pooling的窗口是2x2,步长设置为2。
卷积层之后是三个全连接层(fully-connected layers,FC)。前两个全连接层均有4096个通道,第三个全连接层有1000个通道,用来分类。所有网络的全连接层配置相同。
全连接层后是Softmax,用来分类。
所有隐藏层(每个conv层中间)都使用ReLU作为激活函数。VGGNet不使用局部响应标准化(LRN),这种标准化并不能在ILSVRC数据集上提升性能,却导致更多的内存消耗和计算时间(LRN:Local Response Normalization,局部响应归一化,用于增强网络的泛化能力)。
表1:ConvNet配置(以列显示)。随着更多的层被添加,配置的深度从左(A)增加到右(E)(添加的层以粗体显示)。卷积层参数表示为“conv⟨感受野大小⟩-通道数⟩”。为了简洁起见,不显示ReLU激活功能。
表2:参数数量(百万级别)
1、选择采用3x3的卷积核是因为3x3是最小的能够捕捉像素8邻域信息的的尺寸(理解为中心像素周围有8个像素)。
2、使用1x1的卷积核目的是在不影响输入输出的维度情况下,对输入进行形变,再通过ReLU进行非线性处理,提高决策函数的非线性。
3、2个3x3卷积堆叠等于1个5x5卷积,3个3x3堆叠等于1个7x7卷积,感受野大小不变,而采用更多层、更小的卷积核可以引入更多非线性(更多的隐藏层,从而带来更多非线性函数),提高决策函数判决力,并且带来更少参数。
4、每个VGG网络都有3个FC层,5个池化层,1个softmax层。
5、在FC层中间采用dropout层,防止过拟合,如下图:
左边的图为一个完全的全连接层,右边为应用dropout后的全连接层。
我们知道,典型的神经网络其训练流程是将输入通过网络进行正向传导,然后将误差进行反向传播。dropout就是针对这一过程之中,随机地删除隐藏层的部分单元,进行上述过程。步骤为:
(1)、随机删除网络中的一些隐藏神经元,保持输入输出神经元不变;
(2)、将输入通过修改后的网络进行前向传播,然后将误差通过修改后的网络进行反向传播;
(3)、对于另外一批的训练样本,重复上述操作(1)。
dropout可以有效防止过拟合,原因是:
(1)、达到了一种vote的作用。对于单个神经网络而言,将其进行分批,即使不同的训练集可能会产生不同程度的过拟合,但是我们如果将其公用一个损失函数,相当于对其同时进行了优化,取了平均,因此可以较为有效地防止过拟合的发生。
(2)、减少神经元之间复杂的共适应性。当隐藏层神经元被随机删除之后,使得全连接网络具有了一定的稀疏化,从而有效地减轻了不同特征的协同效应。也就是说,有些特征可能会依赖于固定关系的隐含节点的共同作用,而通过dropout的话,就有效地组织了某些特征在其他特征存在下才有效果的情况,增加了神经网络的鲁棒性。
6、如今用得最多的是VGG16(13层conv + 3层FC)和VGG19(16层conv + 3层FC),注意算层数时不算maxpool层和softmax层,只算conv层和fc层。
VGGNet的卷积层有一个显著的特点:特征图的空间分辨率单调递减,特征图的通道数单调递增。这样做是合理的。对于卷积神经网络而言,输入图像的维度是HxWx3(彩色图)或者是HxWx1(灰度图),而最后的全连接层的输出是一个1x1xC的向量,C等于分类的类别数(例如ImageNet中的1000类)。如何从一个HxWx3或HxWx1的图像转换到1x1xC的向量呢?上文所说的VGGNet的特点就是答案:特征图的空间分辨率单调递减,特征图的通道数单调递增,使得输入图像在维度上流畅地转换到分类向量。用于相同ImageNet图像分类任务的AlexNet的通道数无此规律,VGGNet后续的GoogLeNet和Resnet均遵循此维度变化的规律。
训练采用多尺度训练(Multi-scale),将原始图像缩放到不同尺寸 S,然后再随机裁切224x224的图片,并且对图片进行水平翻转和随机RGB色差调整,这样能增加很多数据量,对于防止模型过拟合有很不错的效果。
初始对原始图片进行裁剪时,原始图片的最小边不宜过小,这样的话,裁剪到224x224的时候,就相当于几乎覆盖了整个图片,这样对原始图片进行不同的随机裁剪得到的图片就基本上没差别,就失去了增加数据集的意义,但同时也不宜过大,这样的话,裁剪到的图片只含有目标的一小部分,也不是很好。
针对上述裁剪的问题,提出的两种解决办法:
(1) 、固定最小边的尺寸为256;
(2) 、随机从[256,512]的确定范围内进行抽样,这样原始图片尺寸不一,有利于训练,这个方法叫做尺度抖动(scale jittering),有利于训练集增强。
将全连接层等效替换为卷积层进行测试,原因是:
卷积层和全连接层的唯一区别就是卷积层的神经元和输入是局部联系的,并且同一个通道(channel)内的不同神经元共享权值(weight)。卷积层和全连接层的计算实际上相同,因此可以将全连接层转换为卷积层,只要将卷积核大小设置为输入空间大小即可:例如输入为7x7x512,第一层全连接层输出4096;我们可以将其看作卷积核大小为7x7,步长为1,没有填充,输出为1x1x4096的卷积层。这样的好处在于输入图像的大小不再受限制,因此可以高效地对图像作滑动窗式预测;而且全连接层的计算量比较大,等效卷积层的计算量减小了,这样既达到了目的又十分高效。
拓展:
为什么卷积层可以“代替”全连接层?
卷积和全连接的区别大致在于:卷积是局部连接,计算局部信息;全连接是全局连接,计算全局信息。(但二者都是采用的点积运算)
但如果卷积核的kernel_size和输入feature maps的size一样,那么相当于该卷积核计算了全部feature maps的信息,则相当于是一个kernel_size∗1的全连接。在全连接层上,相当于是n∗m
(其中n是输入的维度,m是输出的维度)的全连接,其计算是通过一次导入到内存中计算完成;如果是在最后一个feature maps上展开后进行的全连接,这里若不进行展开,直接使用output_size的卷积核代替,则相当于是n∗1的全连接(这里的n就是feature maps展开的向量大小,也就是卷积核的大小kernel_size∗kernel_size),使用m个卷积核则可以相当于n∗m的全连接层。
但用卷积层代替全连接层的方式,其卷积核的计算是并行的,不需要同时读入内存中,所以使用卷积层的方式代替全连接层可以加开模型的优化。
为什么不能用卷积层代替全连接层的方式,使得模型处理不同大小的输入?
因为卷积层的运算是通过卷积核,说到底也就是点积运算,是需要事先设定参数的大小。
但如果这种操作用于处理不同size的输入,则实际上每次训练时,该层的参数size是不一样的,也就是模型不能得到训练。
虽然使用卷积层代替全连接层来处理不同大小输入的模型在整个流程上看起来没什么问题,但根本上,该模型是不能得到良好训练的。(从代替的那层卷积层开始,其后的每一层得到的输入分布其实是一直在变化的,所以波动会比较大。)
1、虽然 VGGNet 减少了卷积层参数,但实际上其参数空间比 AlexNet 大,其中绝大多数的参数都是来自于第一个全连接层,耗费更多计算资源。在随后的 NIN 中发现将这些全连接层替换为全局平均池化,对于性能影响不大,同时显著降低了参数数量。
2、采用 Pre-trained 方法训练的 VGG model(主要是 D 和 E),相对其他的方法参数空间很大,所以训练一个 VGG 模型通常要花费更长的时间,所幸有公开的 Pre-trained model 让我们很方便的使用。
拓展:
全局池化(GAP)替代全连接层的分析
首先我们来看一下全连接层的缺点:
在AlexNet及其之前,大抵所有的基于神经网络的机器学习算法都要在卷积层之后添加上全连接层来进行特征的向量化,此外出于神经网络黑盒子的考虑,有时设计几个全连接网络还可以提升卷积神经网络的分类性能,一度成为神经网络使用的标配。
一般情况下,在全连接层之前,我们会把池化的feature map进行flatten,比如200个3x3,会拉成1800x1的列向量,而后如果设置了50个神经元,则系统会生成50个1x1800的矩阵跟你的feature map进行矩阵乘法运算
——>>> 50 x (1x1800x1800x1) ——>>> 变成一个50个元素的列向量
最后如果你要分成10类,则在最后的连接层设置10个神经元,即完成分类的全连接层设计等等。
但是,我们同时也注意到,全连接层有一个非常致命的弱点就是参数量过大,特别是与最后一个卷积层相连的全连接层。一方面增加了Training以及testing的计算量,降低了速度;另外一方面参数量过大容易过拟合。虽然使用了类似dropout等手段去处理,但是毕竟dropout是hyper-parameter, 不够优美也不好实践。
那么我们有没有办法将其替代呢?
当然有,就是GAP(Global Average Pooling)。
全局池化(以平均池化为例),则完全抛弃全连接层,在无数个卷积以及池化层后,比如,最后我形成了200个3x3的feature map,但是我需要10个分类就行,则需要进行一次10个卷积核的卷积操作,形成10x3x3,然后进行全局平均池化。该过程会对每一个feature map进行求均值操作(也可以理解为一个与其等大的卷积核进行卷积),形成一个10个元素的列向量。
我们要明确以下,全连接层将卷积层展开成向量之后不还是要针对每个feature map进行分类嘛,GAP的思路就是将上述两个过程合二为一,一起做了。如图所示:
由此就可以比较直观地说明了。这两者合二为一的过程我们可以探索到GAP的真正意义是:对整个网路在结构上做正则化防止过拟合。其直接剔除了全连接层中黑箱的特征,直接赋予了每个channel实际的类别意义。做法是在最后卷积层输出多少类别就多少map,然后直接分别对map进行平均值计算得到结果最后用softmax进行分类。
实践证明其效果还是比较可观的,同时GAP可以实现任意图像大小的输入。但是值得我们注意的是,使用gap可能会造成收敛速度减慢。
全连接层等效替换为卷积层,NIN 中发现将全连接层替换为全局平均池化。二者的区别是:全连接层替换为全局平均池化比全连接层等效替换为卷积层多了一层全局池化运算,本质上两者都是利用卷积来代替全连接层。