CNN经典模型:GoogLeNet(从Inception v1到v4的演进)

      GoogLeNet和VGG是2014年ImageNet挑战赛(ILSVRC14)的双雄,GoogLeNet获得第一名、VGG获得第二名,这两类模型结构的共同特点是层次更深了。VGG继承了LeNet以及AlexNet的一些框架结构,(大话CNN经典模型:VGGNet)而GoogLeNet则做了更加大胆的网络结构尝试,虽然深度只有22层,但大小却比AlexNet和VGG小很多,GoogleNet参数为500万个,AlexNet参数个数是GoogleNet的12倍,VGGNet参数又是AlexNet的3倍,因此在内存或计算资源有限时,GoogleNet是比较好的选择;从模型结果来看,GoogLeNet的性能却更加优越。其主要贡献是开发了一个 Inception 模块,该模块大大减少了网络中的参数数量(4M,与带有 60M 的 AlexNet 相比)。另外,这个论文在卷积神经网络的顶部使用平均池化(Average Pooling)而不是完全连接层(Fully Connected layers),从而消除了大量似乎并不重要的参数。 

那么,GoogLeNet是如何进一步提升性能的呢?

    一般来说,提升网络性能最直接的办法就是增加网络深度和宽度,深度指网络层次数量、宽度指神经元数量。但这种方式存在以下问题:
(1)参数太多,如果训练数据集有限,很容易产生过拟合;
(2)网络越大、参数越多,计算复杂度越大,难以应用;
(3)网络越深,容易出现梯度弥散问题(梯度越往后穿越容易消失),难以优化模型。

 googlenet的主要思想就是围绕这两个思路去做的:

1.深度,层数更深,文章采用了22层,为了避免上述提到的梯度消失问题,googlenet巧妙的在不同深度处增加了两个辅助分类器来保证梯度回传消失的现象。

2.宽度,增加了多种核 1x1,3x3,5x5,还有直接max pooling的,但是如果简单的将这些应用到feature map上的话,concat起来的feature map厚度将会很大,所以在googlenet中为了避免这一现象提出的inception具有如下结构,在3x3前,5x5前,max pooling后分别加上了1x1的卷积核起到了降低feature map厚度的作用。

因此,GoogLeNet团队提出了Inception网络结构,就是构造一种“基础神经元”结构,来搭建一个稀疏性、高计算性能的网络结构。

具体网络配置如链接:https://github.com/BVLC/caffe/blob/master/models/bvlc_googlenet/train_val.prototxt

综上googlent有两个最重要的创新点分别是为了解决深度和宽度受限来设计的,由于googlenet的两个辅助loss的限制,很多文章拿base model的时候比较偏向于vgg

优点:

  1. 宽度。总共是9个Inception的模块,每个模块除了num_output的个数不一样之外,其他的都是相同的。每一个卷积后都要做relu操作。
  2. 深度。除了在最后的全连接计算了loss和top_1,top_5的准确率之外,还在inception_4a/output和inception_4d/output之后进行池化卷积全连接,最后计算loss和top_1,top_5。

这种方式,一方面可以比较不同深度下的loss和准确率,同时,这些中间层的backward computation会对整个起到调整梯度的作用,这样防止当层次过深时的梯度消失的问题。


Inception历经了V1、V2、V3、V4等多个版本的发展,不断趋于完善,下面一一进行介绍

一、Inception V1

通过设计一个稀疏网络结构,但是能够产生稠密的数据,既能增加神经网络表现,又能保证计算资源的使用效率。谷歌提出了最原始Inception的基本结构:
                                
       该结构将CNN中常用的卷积(1x1,3x3,5x5)、池化操作(3x3)堆叠在一起(卷积、池化后的尺寸相同,将通道相加),一方面增加了网络的宽度,另一方面也增加了网络对尺度的适应性。网络卷积层中的网络能够提取输入的每一个细节信息,同时5x5的滤波器也能够覆盖大部分接受层的的输入。还可以进行一个池化操作,以减少空间大小,降低过度拟合。在这些层之上,在每一个卷积层后都要做一个ReLU操作,以增加网络的非线性特征。

        然而这个Inception原始版本,所有的卷积核都在上一层的所有输出上来做,而那个5x5的卷积核所需的计算量就太大了,造成了特征图的厚度很大,为了避免这种情况,在3x3前、5x5前、max pooling后,分别加上了1x1的卷积核,以起到了降低特征图厚度的作用,这也就形成了Inception v1的网络结构,如下图所示:

                      

1x1的卷积核有什么用呢?

      1x1卷积的主要目的是为了减少维度,还用于修正线性激活(ReLU)。比如,上一层的输出为100x100x128,经过具有256个通道的5x5卷积层之后(stride=1,pad=2),输出数据为100x100x256,其中,卷积层的参数为128x5x5x256= 819200。而假如上一层输出先经过具有32个通道的1x1卷积层,再经过具有256个输出的5x5卷积层,那么输出数据仍为为100x100x256,但卷积参数量已经减少为128x1x1x32 + 32x5x5x256= 204800,大约减少了4倍。

基于Inception构建了GoogLeNet的网络结构如下(共22层):            

对上图说明如下:
(1)GoogLeNet采用了模块化的结构(Inception结构),方便增添和修改;
(2)网络最后采用了average pooling(平均池化)来代替全连接层,该想法来自NIN(Network in Network),事实证明这样可以将准确率提高0.6%。但是,实际在最后还是加了一个全连接层,主要是为了方便对输出进行灵活调整;
(3)虽然移除了全连接,但是网络中依然使用了Dropout ; 
(4)为了避免梯度消失,网络额外增加了2个辅助的softmax用于向前传导梯度(辅助分类器)。辅助分类器是将中间某一层的输出用作分类,并按一个较小的权重(0.3)加到最终分类结果中,这样相当于做了模型融合,同时给网络增加了反向传播的梯度信号,也提供了额外的正则化,对于整个网络的训练很有裨益。而在实际测试的时候,这两个额外的softmax会被去掉。

辅助分类器的具体细节: 

1.均值pooling层滤波器大小为5x5,步长为3,(4a)的输出为4x4x512,(4d)的输出为4x4x528; 
2.1x1的卷积有用于降维的128个滤波器和修正线性激活; 
3.全连接层有1024个单元和修正线性激活; 
4.dropout层的dropped的输出比率为70%; 
5.线性层将softmax损失作为分类器(和主分类器一样预测1000个类,但在inference时移除)。

GoogLeNet的网络结构图细节如下:
CNN经典模型:GoogLeNet(从Inception v1到v4的演进)_第1张图片
注:上表中的“#3x3 reduce”,“#5x5 reduce”表示在3x3,5x5卷积操作之前使用了1x1卷积的数量。 


我们看一下辅助分类器的结构,prototxt文件:https://github.com/BVLC/caffe/blob/master/models/bvlc_googlenet/train_val.prototxt

layer {
  name: "inception_4a/output"
#拼接 type: "Concat"
  bottom: "inception_4a/1x1"
  bottom: "inception_4a/3x3"
  bottom: "inception_4a/5x5"
  bottom: "inception_4a/pool_proj"
  top: "inception_4a/output"
  }
平均池化 layer {
  name: "loss1/ave_pool"
  type: "Pooling"
  bottom: "inception_4a/output"
  top: "loss1/ave_pool"
  pooling_param {
  pool: AVE
  kernel_size: 5
  stride: 3}
  }
卷积减少通道 layer {
  name: "loss1/conv"
  type: "Convolution"
  bottom: "loss1/ave_pool"
  top: "loss1/conv"
  param {
  lr_mult: 1
  decay_mult: 1}
  param {
  lr_mult: 2
  decay_mult: 0}
  convolution_param {
  num_output: 128
  kernel_size: 1
  weight_filler {
  type: "xavier"}
  bias_filler {
  type: "constant"
  value: 0.2}
  }
  }
  layer {
  name: "loss1/relu_conv"
  type: "ReLU"
  bottom: "loss1/conv"
  top: "loss1/conv"
  }
全连接1024个输出 layer {
  name: "loss1/fc"
  type: "InnerProduct"
  bottom: "loss1/conv"
  top: "loss1/fc"
  param {
  lr_mult: 1
  decay_mult: 1
  }
  param {
  lr_mult: 2
  decay_mult: 0
  }
  inner_product_param {
  num_output: 1024
  weight_filler {
  type: "xavier"}
  bias_filler {
  type: "constant"
  value: 0.2}
  }
  }
  layer {
  name: "loss1/relu_fc"
  type: "ReLU"
  bottom: "loss1/fc"
  top: "loss1/fc"
  }
全连接层应用dropout layer {
  name: "loss1/drop_fc"
  type: "Dropout"
  bottom: "loss1/fc"
  top: "loss1/fc"
  dropout_param {
  dropout_ratio: 0.7
  }
  }
全连接层,1000类输出 layer {
  name: "loss1/classifier"
  type: "InnerProduct"
  bottom: "loss1/fc"
  top: "loss1/classifier"
  param {
  lr_mult: 1
  decay_mult: 1}
  param {
  lr_mult: 2
  decay_mult: 0}
  inner_product_param {
  num_output: 1000
  weight_filler {
  type: "xavier"}
  bias_filler {
  type: "constant"
  value: 0}
  }
  }
softmax,计算交叉熵损失 layer {
  name: "loss1/loss"
  type: "SoftmaxWithLoss"
  bottom: "loss1/classifier"
  bottom: "label"
  top: "loss1/loss1"
  loss_weight: 0.3
  }
  layer {
top1精度 name: "loss1/top-1"
  type: "Accuracy"
  bottom: "loss1/classifier"
  bottom: "label"
  top: "loss1/top-1"
  include {
  phase: TEST}
  }
  layer {
top5精度 name: "loss1/top-5"
  type: "Accuracy"
  bottom: "loss1/classifier"
  bottom: "label"
  top: "loss1/top-5"
  include {
  phase: TEST}
  accuracy_param {
  top_k: 5}
  }

     分类问题中,如果有10个类,那网络最终会给出10个值,分别代表样例是对应类的几率,最终将几率按从大到小排序。
我们一般认为,样例对应的类的几率最大,则认为网络对该样例的分类是正确的,即top 1accuracy;而top 5 accuracy则放宽了要求,如果 网络对该样例的分类是排在前5个几率之内,就认为分类是正确的 

GoogLeNet网络结构明细表解析如下:

0、输入

原始输入图像为224x224x3,且都进行了零均值化的预处理操作(图像每个像素减去均值)。
1、第一层(卷积层)

使用7x7的卷积核(滑动步长2,padding为3),64通道,输出为112x112x64,卷积后进行ReLU操作
经过3x3的max pooling(步长为2),输出为((112 - 3+1)/2)+1=56,即56x56x64,再进行ReLU操作
2、第二层(卷积层)

使用3x3的卷积核(滑动步长为1,padding为1),192通道,输出为56x56x192,卷积后进行ReLU操作
经过3x3的max pooling(步长为2),输出为((56 - 3+1)/2)+1=28,即28x28x192,再进行ReLU操作
3a、第三层(Inception 3a层)

分为四个分支,采用不同尺度的卷积核来进行处理
(1)64个1x1的卷积核,然后RuLU,输出28x28x64
(2)96个1x1的卷积核,作为3x3卷积核之前的降维,变成28x28x96,然后进行ReLU计算,再进行128个3x3的卷积(padding为1),输出28x28x128
(3)16个1x1的卷积核,作为5x5卷积核之前的降维,变成28x28x16,进行ReLU计算后,再进行32个5x5的卷积(padding为2),输出28x28x32
(4)pool层,使用3x3的核(padding为1),输出28x28x192,然后进行32个1x1的卷积,输出28x28x32。
将四个结果进行连接,对这四部分输出结果的第三维并联,即64+128+32+32=256,最终输出28x28x256

3b、第三层(Inception 3b层)

(1)128个1x1的卷积核,然后RuLU,输出28x28x128
(2)128个1x1的卷积核,作为3x3卷积核之前的降维,变成28x28x128,进行ReLU,再进行192个3x3的卷积(padding为1),输出28x28x192
(3)32个1x1的卷积核,作为5x5卷积核之前的降维,变成28x28x32,进行ReLU计算后,再进行96个5x5的卷积(padding为2),输出28x28x96
(4)pool层,使用3x3的核(padding为1),输出28x28x256,然后进行64个1x1的卷积,输出28x28x64。
将四个结果进行连接,对这四部分输出结果的第三维并联,即128+192+96+64=480,最终输出输出为28x28x480

第四层(4a,4b,4c,4d,4e)、第五层(5a,5b)……,与3a、3b类似,在此就不再重复。

从GoogLeNet的实验结果来看,效果很明显,差错率比MSRA、VGG等模型都要低,对比结果如下表所示:  
                                 CNN经典模型:GoogLeNet(从Inception v1到v4的演进)_第2张图片

二、Inception V2

     GoogLeNet设计的初衷就是要又准又快,而如果只是单纯的堆叠网络虽然可以提高准确率,但是会导致计算效率有明显的下降,所以如何在不增加过多计算量的同时提高网络的表达能力就成为了一个问题。
Inception V2版本的解决方案就是修改Inception的内部计算逻辑,提出了比较特殊的“卷积”计算结构。

2.1、卷积分解(Factorizing Convolutions)

       大尺寸的卷积核可以带来更大的感受野,但也意味着会产生更多的参数,比如5x5卷积核的参数有25个,3x3卷积核的参数有9个,前者是后者的25/9=2.78倍。因此,GoogLeNet团队提出可以用2个连续的3x3卷积层组成的小网络来代替单个的5x5卷积层,即在保持感受野范围的同时又减少了参数量,如下左图: 
               CNN经典模型:GoogLeNet(从Inception v1到v4的演进)_第3张图片                        CNN经典模型:GoogLeNet(从Inception v1到v4的演进)_第4张图片
       通过大量实验表明,这种替代方案不会造成表达能力的下降。3x3卷积之后还要再加激活吗? 作者也做了对比试验,表明添加非线性激活会提高性能。可以看出,大卷积核完全可以由一系列的3x3卷积核来替代,那能不能再分解得更小一点呢?GoogLeNet团队考虑了nx1的卷积核,如上右图所示,用3个3x1取代3x3卷积。
       因此,任意nxn的卷积都可以通过1xn卷积后接nx1卷积来替代。GoogLeNet团队发现在网络的前期使用这种分解效果并不好,在中度大小的特征图(feature map)上使用效果才会更好(特征图大小建议在12到20之间)

   CNN经典模型:GoogLeNet(从Inception v1到v4的演进)_第5张图片  CNN经典模型:GoogLeNet(从Inception v1到v4的演进)_第6张图片     CNN经典模型:GoogLeNet(从Inception v1到v4的演进)_第7张图片

2.2、降低特征图大小

一般情况下,如果想让图像缩小,可以有如下两种方式:
                                       CNN经典模型:GoogLeNet(从Inception v1到v4的演进)_第8张图片

    先池化再作Inception卷积,或者先作Inception卷积再作池化。但是方法一(左图)先作池化会导致特征表示遇到瓶颈(特征缺失),方法二(右图)是正常的缩小,但计算量很大。为了同时保持特征表示且降低计算量,将网络结构改为下图,使用两个并行化的模块来降低计算量(卷积、池化并行执行,再进行合并)

                             

使用Inception V2作改进版的GoogLeNet,网络结构图如下:
                         

注:上表中的Figure 5指没有进化的Inception,Figure 6是指小卷积版的Inception(用3x3卷积核代替5x5卷积核),Figure 7是指不对称版的Inception(用1xn、nx1卷积核代替nxn卷积核)。

 CNN经典模型:GoogLeNet(从Inception v1到v4的演进)_第9张图片

经实验,模型结果与旧的GoogleNet相比有较大提升,如下表所示:
                                         

三、Inception V3

         Inception V3最重要的改进是分解(Factorization),将7x7分解成两个一维的卷积(1x7,7x1),3x3也是一样(1x3,3x1),这样的好处,既可以加速计算,又可以将1个卷积拆成2个卷积,使得网络深度进一步增加,增加了网络的非线性(每增加一层都要进行ReLU)。另外,网络输入从224x224变为了299x299。

四、Inception V4

      Inception V4研究了Inception模块与残差连接的结合。ResNet结构大大地加深了网络深度,还极大地提升了训练速度,同时性能也有提升(ResNet的技术原理介绍:大话深度残差网络ResNet)。
Inception V4主要利用残差连接(Residual Connection)来改进V3结构,得到Inception-ResNet-v1,Inception-ResNet-v2,Inception-v4网络。
      ResNet的残差结构如下:
                                                            
将该结构与Inception相结合,变成下图:
                                     
通过20个类似的模块组合,Inception-ResNet构建如下:

                                                             

       2014至2016年,GoogLeNet团队发表了多篇关于GoogLeNet的经典论文《Going deeper with convolutions》、《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》、《Rethinking the Inception Architecture for Computer Vision》、《Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning》,在这些论文中对Inception v1、Inception v2、Inception v3、Inception v4 等思想和技术原理进行了详细的介绍,建议阅读这些论文以全面了解GoogLeNet。

总结:

v1:引入inception结构
v2:将inception中的3*3,5*5卷积核用n*1,1*n代替
v3:将inception中7*7用7*1,1*7代替
v4:将残差网络引入inception

from:https://my.oschina.net/u/876354/blog/1637819

推荐一个系列博客:https://blog.csdn.net/shuzfan/article/details/50738394

你可能感兴趣的:(神经网络)