卷积神经网络是一种带有卷积结构的深度神经网络,卷积结构可以减少深层网络占用的内存量,其三个关键的操作,其一是局部感受野,其二是权值共享,其三是pooling层,有效的减少了网络的参数个数,缓解了模型的过拟合问题。
卷积神经网络结构包括:卷积层,下采样层,全连接层。以此来达到简化网络参数并使得网络具有一定程度的位移、尺度、缩放、非线性形变稳定性。
每一层有多个特征图,每个特征图通过一种卷积滤波器提取输入的一种特征,每个特征图有多个神经元。
通常将输入层到隐藏层的映射称为一个特征映射,也就是通过卷积层得到特征提取层,经过pooling之后得到特征映射层。
全连接层:采用softmax全连接,得到的激活值即卷积神经网络提取到的图片特征。
卷积层:因为通过卷积运算我们可以提取出图像的特征,通过卷积运算可以使得原始信号的某些特征增强,并且降低噪声。
用一个可训练的滤波器fx去卷积一个输入的图像(第一阶段是输入的图像,后面的阶段就是卷积特征map了),然后加一个偏置bx,得到卷积层Cx。
目的:进行图像特征提取
卷积及特性:
1.拥有局部感知机制
2.权值共享
1.卷积核的channel(深度)与输入特征层的channel相同
2.输出的特征矩阵的channel与卷积核个数相同
池化:取区域平均或最大
下采样层:因为对图像进行下采样,可以减少数据处理量同时保留有用信息,采样可以混淆特征的具体位置,因为某个特征找出来之后,其它的位置已经不重要了,我们只需要这个特征和其他特征的相对位置,可以应对形变和扭曲带来的同类物体的变化。
每邻域四个像素求和变为一个像素,然后通过标量Wx+1加权,再增加偏置bx+1,然后通过一个sigmoid激活函数,产生一个大概缩小四倍的特征映射图Sx+1。
目的:对特征图进行稀疏处理,减少数据运算量。
1.没有训练参数
2.只改变特征矩阵的w和h,不改变channel
3.一般poolsize和stride相同
参考博客:
参考一
参考二
C1层是一个卷积层,由6个特征图Feature
Map构成。特征图中每个神经元与输入为5×5的邻域相连。特征图的大小为28×28,这样能防止输入的连接掉到边界之外(32-5+1=28)。C1有156个可训练参数(每个滤波器5×5=25个unit参数和一个bias参数,一共6个滤波器,共(5×5+1)6=156个参数),共156(28*28)=122,304个连接。
S2层是一个下采样层,有6个14×14的特征图。特征图中的每个单元与C1中相对应特征图的2×2邻域相连接。S2层每个单元的4个输入相加,乘以一个可训练参数,再加上一个可训练偏置。每个单元的2×2感受野并不重叠,因此S2中每个特征图的大小是C1中特征图大小的1/4(行和列各1/2)。S2层有12(6(1+1)=12)个可训练参数和5880(14×14(2*2+1)*6=5880)个连接。
C3层也是一个卷积层,它同样通过5x5的卷积核去卷积层S2,然后得到的特征map就只有10x10个神经元,但是它有16种不同的卷积核,所以就存在16个特征map了。C3中每个特征图由S2中所有6个或者几个特征map组合而成。为什么不把S2中的每个特征图连接到每个C3的特征图呢?原因有2点。第一,不完全的连接机制将连接的数量保持在合理的范围内。第二,也是最重要的,其破坏了网络的对称性。由于不同的特征图有不同的输入,所以迫使他们抽取不同的特征(希望是互补的)。
例如,存在的一个方式是:C3的前6个特征图以S2中3个相邻的特征图子集为输入。接下来6个特征图以S2中4个相邻特征图子集为输入。然后的3个以不相邻的4个特征图子集为输入。最后一个将S2中所有特征图为输入。这样C3层有1516(6*(325+1)+6(425+1)+3(425+1)+(256+1)=1516)个可训练参数和151600(10101516=151600)个连接。
S4层是一个下采样层,由16个5×5大小的特征图构成。特征图中的每个单元与C3中相应特征图的2×2邻域相连接,跟C1和S2之间的连接一样。S4层有32个可训练参数(每个特征图1个因子和一个偏置16*(1+1)=32)和2000(16*(2*2+1)5×5=2000)个连接。
C5层是一个卷积层,有120个特征图。每个单元与S4层的全部16个单元的5×5邻域相连。由于S4层特征图的大小也为5×5(同滤波器一样),故C5特征图的大小为1×1(5-5+1=1):这构成了S4和C5之间的全连接。之所以仍将C5标示为卷积层而非全相联层,是因为如果LeNet-5的输入变大,而其他的保持不变,那么此时特征图的维数就会比1×1大。C5层有48120(120*(1655+1)=48120由于与全部16个单元相连,故只加一个偏置)个可训练连接。
F6层有84个单元(之所以选这个数字的原因来自于输出层的设计),与C5层全相连。有10164(84*(120*(1*1)+1)=10164)个可训练参数。如同经典神经网络,F6层计算输入向量和权重向量之间的点积,再加上一个偏置。然后将其传递给sigmoid函数产生单元i的一个状态。
最后,输出层由欧式径向基函数(Euclidean Radial Basis Function)单元组成,每类一个单元,每个有84个输入。
1、输入层:N个32x32的训练样本
输入图像大小为32x32,比MNIST数据库中的字母大,这样做的原因是希望潜在的明显特征,如笔画断点或角点能够出现在最高层特征监测子感受野的中心。
2、C1层
输入图像大小:32x32
卷积核大小:5x5
卷积核个数:6
输出特征图数量:6
输出特征图大小:28x28(32-5+1)
神经元数量:4707(28x28x6)
连接数:122304((28x28x5x5x6)+(28x28x6))
可训练参数:156(5x5x6+6,权值+偏置)
3、S2层
输入图像大小:(28x28x6)
卷积核大小:2x2
卷积核个数:6
输出特征图数量:6
输出特征图大小:14x14(28/2,28/2)
神经元数量:1176(14x14x6)
连接数:5880((2x2x14x14x6)+(14x14x6))
可训练参数:12(1x6+6,权值+偏置)
备注:S2层每个单元的4个输入相加,乘以一个可训练参数,再加上一个可训练偏置。结果通过sigmoid函数计算。可训练系数和偏置控制着sigmoid函数的非线性程度。
如果系数比较小,那么运算近似于线性运算,下采样相当于模糊图像。
如果系数比较大,根据偏置的大小下采样可以被看成是有噪声的“或”运算或者有噪声的“与”运算。
每个单元的2*2感受野并不重叠,因此S2中每个特征图的大小是C1中特征图大小的1/4(行和列各1/2)。
4、C3层输入图像大小:(14x14x6)
卷积核大小:5x5
卷积核个数:16
输出特征图数量:16
输出特征图大小:10x10(14-5+1)
神经元数量:1600(10x10x16)
连接数:151600(1516x10x10)
可训练参数:1516
备注:C3层也是一个卷积层,通过5x5的卷积核去卷积S2层,然后得到的特征图map就有10x10个神经元,但是有16种不同的卷积核,就存在16个不同的特征map。
C3中每个特征图由S2中的所有6个或几个特征图组合而成,为什么不把S2中的所有特征图都连接到C3的特征图呢:
第一,不完全的连接机制将连接的数量保持在合理的范围内
第二,也是最重要的,这样一来就可以破坏网络的对称性,由于不同的特征图有不同的输入,所以迫使他们抽取不同的特征。
5、S4层
输入图像大小:(10x10x16)
卷积核大小:2x2
卷积核个数:16
输出特征图数量:16
输出特征图大小:5x5x16
神经元数量:400(5x5x16)
连接数:2000((2x2x5x5x16)+(5x5x16))
可训练参数:32((1+1)x16)
备注:S4是一个下采样层,由16个5x5大小的特征图构成,特征图的每个单元与C3中相应的特征图的2x2邻域相连,S4层有32个可训练参数(每个特征图1个因子和一个偏置)和2000个连接。
6、C5层
输入图像大小:5x5x16
卷积核大小:5x5
卷积核个数:120
输出特征图数量:120
输出特征图大小:1X1(5-5+1)
神经元数量:120(1x120)
连接数:48120(5x5x16x120x1+120x1)
可训练参数:48120(5x5x16x120+120)
备注:C5层是一个卷积层,有120个特征图,每个单元与S4层的全部16个单元的5x5邻域相连,构成了S4和C5的全连接,之所以仍将C5标识为卷积层而非全连接层是因为如果LeNet-5的输入变大,而其他的保持不变,那么此时特征图的维数就会比1x1大。
7、F6层
输入图像大小:(1x1x120)
卷积核大小:1x1
卷积核个数:84
输出特征图数量:1
输出特征图大小:84
神经元数量:84
连接数:10164(120x84+84)
可训练参数:10164(120x84+84)
备注:F6有84个单元(之所以选择84是源于输出层的设计),与C5层相连,有10164个可训练参数,类似经典的全连接神经网络,F6层计算输入向量和权重向量之间的点积,再加上一个偏置,之后将其传递给sigmoid函数产生一个单元i的状态。
8、output层
输入图像大小:1x84
输出特征图数量:1x10
python代码实现
代码中需要理解的函数:
一、torch.nn.Conv2d( in_channels , out_channels , kernel_size , stride = 1 , padding = 0 , dilation = 1 , groups = 1 ,
bias = True , padding_mode = 'zeros' , device = None , dtype = None )
参数:
in_channels ( int ) – 输入图像中的通道数
out_channels ( int ) – 卷积产生的通道数
kernel_size ( int or tuple ) – 卷积核的大小
stride ( int or tuple , optional ) -- 卷积的步幅。默认值:1
padding ( int , tuple或str , optional ) – 添加到输入的所有四个边的填充。默认值:0
padding_mode (字符串,可选) – 'zeros', 'reflect', 'replicate'或'circular'. 默认:'zeros'
dilation ( int or tuple , optional ) -- 内核元素之间的间距。默认值:1
groups ( int , optional ) -- 从输入通道到输出通道的阻塞连接数。默认值:1
bias ( bool , optional ) – If True,向输出添加可学习的偏差。默认:True
二、torch.nn.MaxPool2d( kernel_size , stride = None , padding = 0 , dilation = 1 , return_indices = False , ceil_mode = False )
参数:
kernel_size – 最大的窗口大小
stride:步幅——窗口的步幅。默认值为kernel_size
padding – 要在两边添加隐式零填充
dilation – 控制窗口中元素步幅的参数
return_indices - 如果True,将返回最大索引以及输出。torch.nn.MaxUnpool2d以后有用
ceil_mode – 如果为 True,将使用ceil而不是floor来计算输出形状
卷积结果计算公式:
输入图像的大小为nxn,卷积核的大小为mxm,步长为s, 为输入图像两端填补p个零(zero padding),那么卷积操作之后输出的大小为(n-m+2p)/s + 1
网络包含8个带权重的层;前5层是卷积层,剩下的3层是全连接层。最后一层全连接层的输出是1000维softmax的输入,softmax会产生1000类标签的分布。
卷积层C1:该层的处理流程是: 卷积–>ReLU–>池化–>归一化。
卷积层C2:该层的处理流程是:卷积–>ReLU–>池化–>归一化
卷积层C3:该层的处理流程是: 卷积–>ReLU
卷积层C4:该层的处理流程是: 卷积–>ReLU。该层和C3类似。
卷积层C5:该层处理流程为:卷积–>ReLU–>池化
全连接层FC6:该层的流程为:(卷积)全连接 -->ReLU -->Dropout
全连接层FC7:流程为:全连接–>ReLU–>Dropout
输出层
Alexnet网络中各个层发挥的作用如下表所述:
算法 | 作用 |
---|---|
ReLu、多个CPU | 提高训练速度 |
重叠pool池化 | 提高精度、不容易产生过拟合 |
局部响应归一化 | 提高精度 |
数据增益、Droupout | 减少过拟合 |
超详解AlexNet见此博文
python代码实现
论文参考:https://arxiv.org/pdf/1409.1556.pdf
python代码实现
VGGNet探索了CNN的深度及其性能之间的关系,通过反复堆叠33的小型卷积核和22的最大池化层,VGGNet成功的构筑了16-19层深的CNN。
创新点
VGGNet全部使用33的卷积核和22的池化核,通过不断加深网络结构来提升性能。网络层数的增长并不会带来参数量上的爆炸,因为参数量主要集中在最后三个全连接层中。同时,两个33卷积层的串联相当于1个55的卷积层,3个33的卷积层串联相当于1个77的卷积层,即3个33卷积层的感受野大小相当于1个77的卷积层。但是3个33的卷积层参数量只有77的一半左右,同时前者可以有3个非线性操作,而后者只有1个非线性操作,这样使得前者对于特征的学习能力更强。
使用11的卷积层来增加线性变换,输出的通道数量上并没有发生改变。这里提一下11卷积层的其他用法,11的卷积层常被用来提炼特征,即多通道的特征组合在一起,凝练成较大通道或者较小通道的输出,而每张图片的大小不变。有时11的卷积神经网络还可以用来替代全连接层。
其他小技巧。VGGNet在训练的时候先训级别A的简单网络,再复用A网络的权重来初始化后面的几个复杂模型,这样收敛速度更快。VGGNet作者总结出LRN层作用不大,越深的网络效果越好,11的卷积也是很有效的,但是没有33的卷积效果好,因为3*3的网络可以学习到更大的空间特征。
VGGNet结构
VGGNet有A-E七种结构,从A-E网络逐步变深,但是参数量并没有增长很多,原因为:参数量主要消耗在最后3个全连接层,而前面的卷积层虽然层数多,但消耗的参数量不大。不过,卷积层的训练比较耗时,因为其计算量大。
其中,D和E是常说的VGGNet-16和VGGNet-19。C很有意思,相比于B多了几个11的卷积层,11卷积的意义在于线性变换,而输入的通道数和输出的通道数不变,没有发生降维。
VGGNet网络特点:
- VGGNet拥有5段卷积,每段卷积内有2-3个卷积层,同时每段尾部都会连接一个最大池化层(用来缩小图片)。
- 每段内的卷积核数量一样,越后边的段内卷积核数量越多,依次为:64-128-256-512-512
- 越深的网络效果越好。(图6-9)
- LRN层作用不大(作者结论)
- 11的卷积也是很有效的,但是没有33的卷积好,大一些的卷积核可以学习更大的空间特征。
为什么一个段内有多个3*3的卷积层堆叠?
这是个非常有用的设计。2个33的卷积层串联相当于1个55的卷积层,即一个像素会跟周围55的像素产生关联,可以说感受野大小为55。而3个33的卷积层相当于1个77的卷积层。并且,两个33的卷积层的参数比1个55的更少,前者为233=18,后者为155=25。
更重要的是,2个33的卷积层比1个55的卷积层有更多的非线性变换(前者可使用2次ReLu函数,后者只有两次),这使得CNN对特征的学习能力更强。
所以3*3的卷积层堆叠的优点为:
(1)参数量更小
(2)小的卷积层比大的有更多的非线性变换,使得CNN对特征的学习能力更强。
ImageNet 2014比赛分类任务的冠军,将错误率降低到了6.656%,突出的特点是大大增加了卷积神经网络的深度。
将最后的全连接层都换成了1x1的卷积层,大大加速了训练速率。
有没有一种方法,既能保持网络结构的稀疏性,又能利用密集矩阵的高计算性能。大量的文献表明可以将稀疏矩阵聚类为较为密集的子矩阵来提高计算性能,据此论文提出了名为Inception 的结构来实现此目的。
2012年AlexNet做出历史突破以来,直到GoogLeNet出来之前,主流的网络结构突破大致是网络更深(层数),网络更宽(神经元数)。所以大家调侃深度学习为“深度调参”,但是纯粹的增大网络的缺点:
那么解决上述问题的方法当然就是增加网络深度和宽度的同时减少参数,Inception就是在这样的情况下应运而生。
网络结构
Inception 结构的主要思路是怎样用密集成分来近似最优的局部稀疏结构,基本结构如下:
上图说明:
但是使用5x5的卷积核仍然会带来巨大的计算量,为此文章借鉴NIN,采用1x1的卷积核来进行降维。
例如:上一层的输出为100x100x128,经过具有256个输出的5x5卷积层之后(stride=1,pad=2),输出数据为100x100x256。其中,卷积层的参数为128x5x5x256。假如上一层输出先经过具有32个输出的1x1卷积层,再经过具有256个输出的5x5卷积层,那么最终的输出数据仍为为100x100x256,但卷积参数量已经减少为128x1x1x32 + 32x5x5x256,大约减少了4倍。
例如:上一层的输出为100x100x128,经过具有256个输出的5x5卷积层之后(stride=1,pad=2),输出数据为100x100x256。其中,卷积层的参数为128x5x5x256。假如上一层输出先经过具有32个输出的1x1卷积层,再经过具有256个输出的5x5卷积层,那么最终的输出数据仍为为100x100x256,但卷积参数量已经减少为128x1x1x32 + 32x5x5x256,大约减少了4倍。
卷积层参数数量计算:
输入通道数为K,输出通道数为L,那么卷积核个数为K*L。因为高维卷积计算是多个通道与多个卷积核分别进行二维计算,
所以K个通道会需要K个卷积核,计算之后,合并也就是相加得到一个通道,又因为输出通道为L,所以需要K*L个卷积核。
然后就是如何求解参数数量?
其实很简单,就是卷积核个数乘以卷积核尺寸,para=I*J*K*L。
GoogLeNet Incepetion V1比AlexNet的8层或者VGGNet的19层还要更深。但其计算量只有15亿次浮点运算,同时只有500万的参数量,仅为AlexNet参数量(6000万)的1/12,却可以达到远胜于AlexNet的准确率,可以说是非常优秀并且非常实用的模型。
Inception V1降低参数量的目的有两点:
第一,参数越多模型越庞大,需要供模型学习的数据量就越大,而目前高质量的数据非常昂贵;
第二,参数越多,耗费的计算资源也会更大。
Inception V1参数少但效果好的原因除了模型层数更深、表达能力更强外,还有两点:
其一,去除了最后的全连接层,用全局平均池化层(即将图片尺寸变为1*1)来取代它。全连接层几乎占据了AlexNet或VGGNet中90%的参数量,而且会引起过拟合,去除全连接层后模型训练更快并且减轻了过拟合。
其二,Inception V1中精心设计的Inception Module提高了参数的利用效率,其结构如上图所示。这一部分也借鉴了Network In Network的思想,形象的解释就是Inception Module本身如同大网络中的一个小网络,其结构可以反复堆叠在一起形成大网络。
Inception Module的基本结构:其中有4个分支:
第一个分支,对输入进行1×1的卷积,这其实也是NIN中提出的一个重要结构。1×1的卷积是一个非常优秀的结构,它可以跨通道组织信息,提高网络的表达能力,同时可以对输出通道升维和降维。
Inception Module的4个分支都用到了1x1的卷积,来进行低成本(计算量比3x3小很多)的跨通道的特征变换
第二个分支,先使用了1x1卷积,然后连接3x3卷积,相当于进行了两次特征变换
第三个分支,先使用1x1卷积,然后连接5x5卷积
第四个分支,3x3最大池化后直接使用1x1卷积
四个分支在最后通过一个聚合操作合并,在输出通道这个维度上聚合。
V2和V1的最大的不同就是,V2增加了Batch Normalization。《Batch Normalization:Accelerating Deep Network Training by Reducing Internal CovariateShift》
Inception V2学习了VGGNet,用两个3x3的卷积代替5x5的卷积,用以降低参数量并减轻过拟合,还提出了著名的Batch Normalization方法,该方法是一个很有效的正则化的方法,可以让大型卷积网络的训练速度加快很多倍,同时收敛后的分类准确率也可以得到大幅度的提高。
BN在用于神经网络某层时,会对每一个mini-batch数据的内部进行标准化(normalization)处理,使输出规范化到N(0,1)的正态分布,减少了Internal Covariate Shift(内部神经元分布的改变)。
BN的论文指出,传统的深度神经网络在训练时,每一层的输入的分布都在变化,导致训练变得困难,我们只能使用一个很小的学习速率解决这个问题。而对每一层使用BN之后,我们就可以有效地解决这个问题,学习速率可以增大很多倍,达到之前的准确率所需要的迭代次数只有1/14,训练时间大大缩短。
一般在训练网络时会对数据进行预处理,包括去掉均值、白化操作等,目的是为了加快训练:
去均值化:
去均值是一种常用的数据处理方式,它是将各个特征值减去其均值,几何上的展现是可以将数据的中心移到坐标原点,python代码为X=X-np.mean(X,axis=0)
,对于图像来说,就是对每个像素的值都要减去平均值。
白化:
白化的方式有很多种,常用的有PCA白化(PCA主成分分析),就是对数据进行PCA操作之后,再进行方差归一化,这样数据基本满足0均值、单位方差、弱相关性。
BN算法:Batch Normalization:批量归一化详解
BN的意义:解决的问题是梯度消失和梯度爆炸的问题
学习Factorization into small convolutions的思想,在Inception V2的基础上,将一个二维卷积拆分成两个较小卷积,例如将7×7卷积拆成1×7卷积和7×1卷积,这样做的好处是降低参数量。该paper中指出,通过这种非对称的卷积拆分比对称的拆分为几个相同的小卷积效果更好,可以处理更多,更丰富的空间特征,这就是Inception V3网络结构。
论文链接:https://arxiv.org/abs/1409.4842
python代码实现
网络主要结构:
GoogLeNet网络有22层深(包括pool层,有27层深),在分类器之前,采用Network in Network中用Averagepool(平均池化)来代替全连接层的思想,而在avg pool之后,还是添加了一个全连接层,是为了大家做finetune(微调)。而无论是VGG还是LeNet、AlexNet,在输出层方面均是采用连续三个全连接层,全连接层的输入是前面卷积层的输出经过reshape得到。据发现,GoogLeNet将fully-connected layer用avg pooling layer代替后,top-1 accuracy 提高了大约0.6%;然而即使在去除了fully-connected layer后,依然必须dropout。
由于全连接网络参数多,计算量大,容易过拟合,所以GoogLeNet没有采用VGG、LeNet、AlexNet三层全连接结构,直接在Inception模块之后使用Average Pool和Dropout方法,不仅起到降维作用,还在一定程度上防止过拟合。
在Dropout层之前添加了一个7×7的Average Pool,一方面是降维,另一方面也是对低层特征的组合。我们希望网络在高层可以抽象出图像全局的特征,那么应该在网络的高层增加卷积核的大小或者增加池化区域的大小,GoogLeNet将这种操作放到了最后的池化过程,前面的Inception模块中卷积核大小都是固定的,而且比较小,主要是为了卷积时的计算方便。
用表格的形式表示GoogLeNet的网络结构如下所示:
上述就是GoogLeNet的结构,可以看出,和AlexNet统一使用5个卷积层、VGG统一使用5个卷积块不同,GoogLeNet在主体卷积部分是卷积层与Inception块混合使用。另外,需要注意一下,在输出层GoogleNet采用全局平均池化,得到的是高和宽均为1的卷积层,而不是通过reshape得到的全连接层。
需要注意的是,上图中 “#3×3reduce” 和 “#5×5reduce” 表示在3×3和5×5卷积之前,使用的降维层中的1×1滤波器的数量。pool proj代表max-pooling后的投影数量(即先max-pooling,再PW降维),所有的reductions(降维)和projections(投影)也都使用激活函数ReLU。
下面就来详细介绍一下GoogLeNet的模型结构。
输入
原始输入图像为224x224x3,且都进行了零均值化的预处理操作(图像每个像素减去均值)
第一模块
第一模块采用的是一个单纯的卷积层紧跟一个最大池化层。
卷积层:卷积核大小7×7,步长为2,padding为3,输出通道数64,输出特征图尺寸为(224-7+3*2)/2+1=112.5(向下取整)=112,输出特征图维度为112x112x64,卷积后进行ReLU操作。
池化层:窗口大小3×3,步长为2,输出特征图尺寸为((112 -3)/2)+1=55.5(向上取整)=56,输出特征图维度为56x56x64。
关于卷积和池化中的特征图大小计算方式,可以参考神经网络之多维卷积的那些事
第二模块
池化层: 窗口大小3×3,步长为2,输出通道数192,输出为((56 - 3)/2)+1=27.5(向上取整)=28,输出特征图维度为28x28x192。
第三模块(Inception 3a层)
Inception 3a层,分为四个分支,采用不同尺度,图示如下:
再看下表格结构,来分析和计算吧:
1*1*192*64=12288
1*1*192*96+3*3*96*128=129024
1*1*192*16+5*5*16*32=15872
1*1*192*32=6144
将四个结果进行连接,对这四部分输出结果的第三维并联,即64+128+32+32=256,最终输出28x28x256。总的参数量是12288+129024+15872+6144=163328,即163328/1024=159.5K
,约等于159K。
第三模块(Inception 3b层)
Inception 3b层,分为四个分支,采用不同尺度。
将四个结果进行连接,对这四部分输出结果的第三维并联,即128+192+96+64=480,最终输出输出为28x28x480。
第四模块(Inception 4a、4b、4c、4e)
与Inception3a,3b类似
第五模块(Inception 5a、5b)
与Inception3a,3b类似
输出层
前面已经多次提到,在输出层GoogLeNet与AlexNet、VGG采用3个连续的全连接层不同,GoogLeNet采用的是全局平均池化层,得到的是高和宽均为1的卷积层,然后添加丢弃概率为40%的Dropout,输出层激活函数采用的是softmax。
激活函数
GoogLeNet每层使用的激活函数为ReLU激活函数。
辅助分类器
根据实验数据,发现神经网络的中间层也具有很强的识别能力,为了利用中间层抽象的特征,在某些中间层中添加含有多层的分类器。如下图所示,红色边框内部代表添加的辅助分类器。GoogLeNet中共增加了两个辅助的softmax分支,作用有两点,一是为了避免梯度消失,用于向前传导梯度。反向传播时如果有一层求导为0,链式求导结果则为0。二是将中间某一层输出用作分类,起到模型融合作用。最后的loss=loss_2 + 0.3 * loss_1 + 0.3 * loss_0
。实际测试时,这两个辅助softmax分支会被去掉。
参考:
参考一
论文见:https://arxiv.org/pdf/1512.03385.pdf
python代码实现
在ResNet网络中有如下几个亮点:
在ResNet网络提出之前,传统的卷积神经网络都是通过将一系列卷积层与下采样层进行堆叠得到的。但是当堆叠到一定网络深度时,就会出现两个问题。
在ResNet论文中说通过数据的预处理以及在网络中使用BN(Batch Normalization)层能够解决梯度消失或者梯度爆炸问题。如果不了解BN层可参考这个链接。但是对于退化问题(随着网络层数的加深,效果还会变差,如下图所示)并没有很好的解决办法。
所以ResNet论文提出了residual结构(残差结构)来减轻退化问题。下图是使用residual结构的卷积网络,可以看到随着网络的不断加深,效果并没有变差,反而变的更好了。
残差结构(residual)
残差指的是什么?
其中ResNet提出了两种mapping:一种是identity mapping,指的就是下图中”弯弯的曲线”,另一种residual mapping,指的就是除了”弯弯的曲线“那部分,所以最后的输出是 y=F(x)+x
下图是论文中给出的两种残差结构。
左边的残差结构是针对层数较少网络,例如ResNet18层和ResNet34层网络。
右边是针对网络层数较多的网络,例如ResNet101,ResNet152等。
为什么深层网络要使用右侧的残差结构呢。
因为,右侧的残差结构能够减少网络参数与运算量。同样输入一个channel为256的特征矩阵,如果使用左侧的残差结构需要大约1170648个参数,但如果使用右侧的残差结构只需要69632个参数。明显搭建深层网络时,使用右侧的残差结构更合适。
对左侧的残差结构(针对ResNet18/34)进行分析。
如下图所示,该残差结构的主分支是由两层3x3的卷积层组成,而残差结构右侧的连接线是shortcut分支也称捷径分支(注意为了让主分支上的输出矩阵能够与我们捷径分支上的输出矩阵进行相加,必须保证这两个输出特征矩阵有相同的shape)。仔细观察了ResNet34网络结构图,应该能够发现图中会有一些虚线的残差结构。在原论文中作者只是简单说了这些虚线残差结构有降维的作用,并在捷径分支上通过1x1的卷积核进行降维处理。而下图右侧给出了详细的虚线残差结构,注意下每个卷积层的步距stride,以及捷径分支上的卷积核的个数(与主分支上的卷积核个数相同)。
下面这幅图是原论文给出的不同深度的ResNet网络结构配置,注意表中的残差结构给出了主分支上卷积核的大小与卷积核个数,表中的×N
表示将该残差结构重复N次。
可见,ResNet-18/34是进行两层卷积的残差,ResNet-50/101/152是进行三层卷积的残差。ResNet-18/34对应的每个残差块的卷积kernel大小依次是33、33,ResNet-50/101/152对应的每个残差块的卷积kernel大小依次是11、33、1*1。
18、34层等数字是如何计算出来的:以34层为例,1个卷积(conv1)+3残差块×2个卷积(conv2_x)+4个残差块×2个卷积(conv3_x)+6个残差块×2个卷积(conv4_x)+3个残差块×2个卷积(conv5_x)+最后的1个全连接层=34。这里的层仅指卷积层和全连接层,其它类型的层并没有计算在内。
论文中给出了层数为34的ResNet网络结构,论文截图如下所示:
左侧为VGG-19网络结构;中间为34层的普通网络结构;在此基础上,在层与层之间加入shortcut connections,就将普通网络转换为对应的ResNet网络,即右侧网络结构。与上表中ResNet-34一致。
右侧ResNet网络,曲线有实线和虚线两种。虚线表示恒等映射x输出的feature map数、width、height与残差F(x)的输出不一致时,x需要进行卷积kernel大小为1*1的运算操作,因为最终F(x)与x要执行”+”操作,即Eltwise操作。GoogLeNet中使用Concat操作。