概述
(一)Inception结构的来源与演变
Inception(盗梦空间结构)是经典模型GoogLeNet中最核心的子网络结构,GoogLeNet是Google团队提出的一种神经网络模型,并在2014年ImageNet挑战赛(ILSVRC14)上获得了冠军,关于GoogLeNet模型详细介绍,可以参考博主的另一篇博客 GoogLeNet网络详解与模型搭建GoogLeNet网络详解与模型搭建。Google团队在随后2年里不断改进,相继提出了v1-v4和xcpetion结构,本文对系列模型进行详细介绍。
2014-2016年,谷歌实验室发表了多篇系列经典论文,充实了Inception结构和GoogLeNet模型:
Inception v1(GoogLeNet, 2014) –> Inception v2(BN-Inception) –> Inception v3 –> Inception v4(Inception-ResNet) –> Xception(2016)
- GoogLeNet:《Going deeper with convolutions》, 2014.09
- BN:《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》, 2015.02
- Inception v3:《Rethinking the Inception Architecture for Computer Vision》, 2015.12
- Inception v4:《Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning》, 2016.02
- Xception:《Xception: Deep Learning with Depthwise Separable Convolutions》, 2016.10
(二)什么是Inception结构?
Inception就是将多个卷积或池化操作放在一起组装成一个网络模块,设计神经网络时,以模块为单位去组装整个网络结构。Inception结构设计了一个稀疏网络结构,但是能够产生稠密的数据,既能增加神经网络表现,又能保证计算资源的使用效率。
在GoogLeNet之前的网络中,一层一般只使用一种操作(单个卷积或池化),一层只使用一个操作的弊端是提取出来的特征往往过于单调。在实际情况中,由于图像的不同尺度等原因,需要不同程度的下采样,或者说不同大小的卷积核,我们希望网络代替人手工自己决定到底使用1×11times1,3×33times3,5×55times5以及是否需要max_pooling层,由网络自动去寻找适合的结构。并且节省计算提取更为丰富的特征,Inception结构正好满足了这样的需求,因而获得了更好的表现。
(三)为什么要提出Inception结构?
The most straightforward way of improving the performance of deep neural networks is by increasing their size. This includes both increasing the depth – the number of levels – of the network and its width: the number of units at each level. This is as an easy and safe way of training higher quality models, especially given the availability of a large amount of labeled training data. However this simple solution comes with two major drawbacks.
Bigger size typically means a larger number of parameters, which makes the enlarged network more prone to overfitting, especially if the number of labeled examples in the training set is limited.
Another drawback of uniformly increased network size is the dramatically increased use of computational resources.
The fundamental way of solving both issues would be by ultimately moving from fully connected to sparsely connected architectures, even inside the convolutions.
《Going deeper with convolutions》
文章提出,提升网络性能最直接的办法就是增加网络深度和宽度,深度指网络层次数量、宽度指神经元数量。但这种方式存在以下问题:
- 参数太多,如果训练数据集有限,很容易产生过拟合;
- 网络越大、参数越多,计算复杂度越大,难以应用;
- 网络越深,容易出现梯度弥散问题(梯度越往后穿越容易消失),难以优化模型。
为了解决提出的问题,就要在增加网络深度和宽度的同时减少参数,减少参数自然就想到将全连接变成稀疏连接。但是在实现上,全连接变成稀疏连接后实际计算量并不会有质的提升,因为大部分硬件是针对密集矩阵计算优化的,稀疏矩阵虽然数据量少,但是计算所消耗的时间却很难减少。
那么,有没有一种方法既能保持网络结构的稀疏性,又能利用密集矩阵的高计算性能。大量的文献表明可以将稀疏矩阵聚类为较为密集的子矩阵来提高计算性能,就如人类的大脑是可以看做是神经元的重复堆积,因此,GoogLeNet团队提出了Inception网络结构,就是构造一种“基础神经元”结构,来搭建一个稀疏性、高计算性能的网络结构。
NiN对Inception的启发
Network In Network (NIN)是由MinLinMin Lin等人于2014年提出,其网络结构中通过引入子网络结构代替纯卷积中的线性映射部分(NiN模型的详细介绍可参考博主的另一篇博客 NiN网络详解),这种形式的网络结构激发了更复杂的卷积神经网络的结构设计,Inception结构就是来源于这个思想。从上文图中的native inception结构中可以看出,在相邻的上下2层之间添加多个卷积核池化的并行操作可以提高模型的非线性表达能力。
除此之外,NiN网络中的MLPConv层则提供了1×11times1卷积的思路,1×11times1卷积不仅可以对通道数进行升降维,显著降低参数量,还可以实现信息的跨通道交互与整合。下面理解一下1×11times1卷积过程👇
上图过程为输入大小为56×56×356times56times3的feature map,通过3个1×1×31times1times3卷积核,输出大小为56×56×156times56times1的feature map的卷积过程。当然,以上过程也可以看作是对三个通道进行了线性组合,这几个卷积核可以看成就是一个简单的神经元结构,每个神经元参数数量与前面的通道数量相等。通常在卷积之后会加入非线性激活函数,在这里之后加入激活函数,就可以理解成一个简单的MLP网络了。
那么1×11times1卷积如何实现通道数的改变和降低模型参数的呢?
相信大家在看完下文Inception v1与native inception结构的对比后就会发现答案。
Inception v1
下图中展示了原始Inception(native inception)结构和GoogLeNet中使用的Inception v1结构,使用Inception v1 Module的GoogleNet不仅比Alex深,而且参数比AlexNet足足减少了12倍,网络大小约是VGGNet的1/20。
GoogleNet作者的初始想法是用多个不同类型的卷积核(1×11times1,3×33times3,5×55times5,3×3Pool3times3Pool)堆叠在一起(卷积、池化后的尺寸相同,将通道相加)代替一个3×3的小卷积核(如左图),好处是可以使提取出来的特征具有多样化,并且特征之间的co-relationship不会很大,最后用把feature map都concatenate起来使网络做得很宽,然后堆叠Inception Module将网络变深。但仅仅简单这么做会使一层的计算量爆炸式增长。
native inception中所有的卷积核都在上一层的所有输出上来做,而那个5×5的卷积核所需的计算量就太大了,造成了特征图的厚度很大,为了避免这种情况,在3×3前、5×5前、max pooling后分别加上了1×1的卷积核,以起到了降低特征图厚度的作用,这也就形成了Inception v1的网络结构(右图)。
假设input feature map的size为28×28×25628times28times256,output feature map的size为28×28×48028times28times480,则native Inception Module的计算量有854M。计算过程如下
从上图可以看出,计算量主要来自高维卷积核的卷积操作,因而在每一个卷积前先使用1×11times1卷积核将输入图片的feature map维度先降低,进行信息压缩,在使用3×3卷积核进行特征提取运算,相同情况下,Inception v1的计算量仅为358M。
Inception v1结构总共有4个分支,输入的feature map并行的通过这四个分支得到四个输出,然后在在将这四个输出在深度维度(channel维度)进行拼接(concate)得到我们的最终输出(注意,为了让四个分支的输出能够在深度方向进行拼接,必须保证四个分支输出的特征矩阵高度和宽度都相同),因此inception结构的参数为:
- branch1: Conv1×1 C o n v 1 × 1 , stride=1
- branch2: Conv3×3C o n v 3 × 3, stride=1, padding=1
- branch3: Conv5×5C o n v 5 × 5, stride=1, padding=2
- branch4: MaxPool3×3M a x P o o l 3 × 3, stride=1, padding=1
Inception v2
GoogLeNet凭借其优秀的表现,得到了很多研究人员的学习和使用,因此GoogLeNet团队又对其进行了进一步地发掘改进,继而提出了Inception v2,Inception v2的核心思想来自Google发表的2篇论文《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》和《Rethinking the Inception Architecture for Computer Vision》。第一篇论文的附录里,作者给出了Inception-BN(inception v2)的模型结构,即在v1的基础上于卷积层与激活函数之间插入BN层:Conv-BN-ReLU,并将v1结构中的5×55times5卷积核替换为2个3×33times3卷积核。第二篇论文里,作者给出了inception v2中卷积分解的详细说明。
(一)Batch Normalization
在BN的论文里,作者提出了Internal Covariate Shift这个问题,即在训练神经网络的过程中,因为前一层的参数变化而导致每层的输入分布都在不断变化(the distribution of each layer’s inputs changes during training, as the parameters of the previous layers change)。这使得我们需要更低的学习率和更小心地进行参数初始化,导致我们难以充分构建一个具有饱满地非线性结构的模型,而这个现象就被称作Internal Covariate Shift。为了解决这个问题,Google提出了Batch Normalization(批规范化)。即在每次梯度下降前,对每个mini-batch做归一化操作来降低数据分布的影响。
我们在图像预处理过程中通常会对图像进行标准化处理,这样能够加速网络的收敛,对于输入层来说,其输入数据满足某一分布的特征矩阵,但对于后续层结构而言输入的feature map就不一定满足某一分布规律了。而BN层的目的就是使我们的feature map满足均值为0,方差为1的分布规律。想对BN层进一步了解,推荐阅读原论文。
(二)小卷积核替代大卷积核
在VGGNet中就提出了通过堆叠两层3×33times3的卷积核可以替代一层5×55times 5的卷积核,堆叠三层 3×33times3的卷积核替代一层 7×77times7的卷积核(参考:VGGNet网络详解与模型搭建)。这样的连接方式在保持感受野范围的同时又减少了参数量,并且可以避免表达瓶颈,加深非线性表达能力。基于此,作者通过将inception v1结构中的5×55times5卷积核替换为2个3×33times3卷积核。如下左图为v1结构,右图为v2结构。
Inception v3
Inception v3来自论文《Rethinking the Inception Architecture for Computer Vision》,论文中首先给出了深度网络的通用设计原则,并在此原则上对inception结构进行修改,最终形成Inception v3。
(一)深度网络的通用设计原则
- 避免表达瓶颈,特别是在网络靠前的地方。 信息流前向传播过程中显然不能经过高度压缩的层,即表达瓶颈。从input到output,feature map的宽和高基本都会逐渐变小,但是不能一下子就变得很小。比如你上来就来个kernel = 7, stride = 5 ,这样显然不合适。
另外输出的维度channel,一般来说会逐渐增多(每层的num_output),否则网络会很难训练。(特征维度并不代表信息的多少,只是作为一种估计的手段)。 - 高维特征更易处理。 高维特征更易区分,会加快训练。
- 可以在低维嵌入上进行空间汇聚而无需担心丢失很多信息。 比如在进行3×3卷积之前,可以对输入先进行降维而不会产生严重的后果。假设信息可以被简单压缩,那么训练就会加快。
- 平衡网络的宽度与深度。
上述的这些并不能直接用来提高网络质量,而仅用来在大环境下作指导。
(二)卷积分解(Factorizing Convolutions)
作者将一个大卷积核的操作分解成若干个小卷积核的操作称为卷积分解,并探讨了2种不同的卷积分解方法,即对称卷积分解和不对称卷积空间分解。
- 对称卷积分解
即使用小卷积核串联来替代大卷积核,这在inception v2中已经提到过。同时作者还提出,通过大量实验表明这种替代方案并不会造成表达能力的下降。通过堆叠两层3×33times3的卷积核可以替代一层5×55times 5的卷积核,堆叠三层 3×33times3的卷积核替代一层 7×77times7的卷积核,可以看出,大卷积核完全可以由一系列的3×33times3卷积核来替代,那能不能再分解得更小一点呢?GoogLeNet团队考虑了非对称卷积分解。
- 非对称卷积分解
任意n×nntimes n的卷积都可以通过1×n1times n卷积后接n×1ntimes 1卷积来替代,如下图(右)所示。
实际上,作者发现在网络的前期使用这种分解效果并不好,还有在中度大小的feature map上使用效果才会更好。(对于mxm大小的feature map,建议m在12到20之间)
(三)降低特征图大小
一般情况下,如果想让特征图的通道数,可以有如下两种方式:
先池化再作Inception卷积,或者先作Inception卷积再作池化。但是方法一(左图)先作pooling(池化)会导致特征表示遇到瓶颈(特征缺失),方法二(右图)是正常的缩小,但计算量很大。为了同时保持特征表示且降低计算量,将网络结构改为下图,使用两个并行化的模块来降低计算量(卷积、池化并行执行,再进行合并),即用卷积得到一半的特征图,池化得到一半的特征图,再进行拼接。
Inception v4
2016年ResNet网络的提出解决了随着神经网络的加深,参数越来越多,模型越来越难以训练,训练时间大大增加,容易出现梯度消散问题。为了融合这一重要成果,Google团队在论文《Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning》里提出了第四版模型,Inception v4研究了Inception模块与残差连接(Residual Connection)的结合来改进V3结构。
如图,将残差模块的卷积结构替换为Inception结构,即得到Inception Residual结构。除了上述右图中的结构外,作者通过20个类似的模块进行组合,最后形成了InceptionV4的网络结构,构建了Inception-ResNet模型。
Xception
持续更新中……
总结回顾
- Inception v1主要采用了多尺度卷积核、1×1卷积操作。
- Inception v2在v1的基础上增加了BN层,使用2个3×33times3小卷积核堆叠替换5×55times5大卷积核;
- inception v3进行了卷积分解(将7×77times7分解成两个一维的卷积1×71times7和1×71times7,3×33times3也是一样1×31times3和3×13times1))和特征图降维。
- inception v4在v3的基础上融合了Residual模块。