GoogLeNet网络结构学习
1.背景介绍
GoogLeNet, 一个22层的深度网络,2014年ILSVRC挑战赛冠军,将Top5 的错误率降低到6.67%。论文地址:Going deeper with convolutions。
据说起名为“GoogLeNet”而非“GoogleNet”,是为了向早期的LeNet致敬。
2.网络结构
GoogLeNet网络的整体结构如下:
3.主要创新点
一般来说,提升网络性能最直接的办法就是增加网络深度和宽度,但是这样会带来一些缺陷:
- 参数太多,容易过拟合
- 网络越大计算复杂度越大,难以应用
- 网络越深,梯度越往后越容易消失
于是GoogLeNet针对这些问题给出了两个解决方案:
深度方面:层数更深,文章采用了22层,为了避免上述提到的梯度消失问题,GoogLeNet巧妙的在不同深度处增加了两个loss来保证梯度回传消失的现象。
宽度方面:采用了Inception结构,这是一种网中网(Network In Network)的结构,即原来的结点也是一个网络。
不同size的卷积核的目的
采用不同大小的卷积核意味着不同大小的感受野,最后拼接意味着不同尺度特征的融合;
之所以卷积核大小采用1、3和5,主要是为了方便对齐。设定卷积步长stride=1之后,只要分别设定pad=0、1、2,那么卷积之后便可以得到相同维度的特征,然后这些特征就可以直接拼接在一起了;
但是,使用3x3,5x5的卷积核参数大小仍然过于巨大
- 为此为了降维改进如下:
1x1卷积层
- 对特征降维,一方面可以解决计算瓶颈,同时限制网络的参数大小,可以将网络做的更「宽」和更「深」。如何降维,本文后面解释。
4.维度计算
注:#3×3 reduce,#5x5 reduce等表示在这之前使用了 1×1 的卷积核降维之后输出宽度。
第一层 convolution层
- 输入(data):224×224×3
- 卷积核size:7×7,滑动步长(stride)为 2,padding为 3
- 输出维度:112×112×64,计算方式:(224 + 2×3 − 7 + 1) / 2 = 112 ,kernel size = 64
第 二 层 max pool层
- 输入维度:112×112×64
- pooling size:3×3,滑动步长(stride)为 2,padding为 1
- 输出维度:56×56×64,计算方式:(112 + 2×1 − 3 +1 ) / 2 = 56
第三层 convolution层
- 输入维度:56x56x64
- 卷积核size:3x3,滑动步长(stride)为1,padding为1
- 输出维度:56x56x192,计算方式:(56 + 2x1 - 3 + 1)/ 1 = 56,kernel size = 192
第四层 max pool层
- 输入维度:56x56x192
- pooling size: 3x3,滑动步长(stride)为2,padding为1
- 输出维度:28x28x192,计算方式:(56 + 2x1 - 3 + 1)/ 2 = 28
第五层 Inception层
分为4条通道,每条通道的输入均为第四层的输出(28 x 28 x 192):
通道1:1×1 卷积层,64个卷积核,输出大小为 28×28×64;
通道2:1×1 卷积层,96个卷积核,输出大小为 28×28×96;作为输入进入 3×3 卷积层,输出大小为 28×28×128;
通道3:1×1 卷积层,32个卷积核,输出大小为 28×28×32;作为输入进入 3×3 卷积层,输出大小为 28×28×32;
通道4:3×3 的 pooling 层,输出大小为28×28×192;作为输入进入 1x1卷积层,输出大小为28×28×32;
Inception层的输出为这四个通道的输出和:64 + 128 + 32 + 32 = 256
这就是GoogLeNet增加宽度的方式
如何降维,以第五层第二个通道为例:
如果没有那个 1×1卷积层,参数个数为 3×3×192×128=221,184 个;
如果加了一个 1×1卷积层,参数个数为 1×1×192×96+3×3×96×128=129,024 个;
由此可以看出,这一通道节约了大于一半参数,其他的类似。