LeNet-5:是Yann LeCun在1998年设计的用于手写数字识别的卷积神经网络,当年美国大多数银行就是用它来识别支票上面的手写数字的,它是早期卷积神经网络中最有代表性的实验系统之一。
LenNet-5共有7层(不包括输入层),每层都包含不同数量的训练参数,如下图所示。
LeNet-5中主要有2个卷积层、2个下抽样层(池化层)、3个全连接层3种连接方式
卷积层
卷积层采用的都是5x5大小的卷积核/过滤器(kernel/filter),且卷积核每次滑动一个像素(stride=1),一个特征图谱使用同一个卷积核.
每个上层节点的值乘以连接上的参数,把这些乘积及一个偏置参数相加得到一个和,把该和输入激活函数,激活函数的输出即是下一层节点的值
LeNet-5的下采样层(pooling层)
下抽样层采用的是2x2的输入域,即上一层的4个节点作为下一层1个节点的输入,且输入域不重叠,即每次滑动2个像素,下抽样节点的结构如下:
每个下抽样节点的4个输入节点求和后取平均(平均池化),均值乘以一个参数加上一个偏置参数作为激活函数的输入,激活函数的输出即是下一层节点的值。
卷积后输出层矩阵宽度的计算:
Outlength=
(inlength-fileterlength+2*padding)/stridelength+1
Outlength:输出层矩阵的宽度
Inlength:输入层矩阵的宽度
Padding:补0的圈数(非必要)
Stridelength:步长,即过滤器每隔几步计算一次结果
LeNet-5第一层:卷积层C1
C1层是卷积层,形成6个特征图谱。卷积的输入区域大小是5x5,每个特征图谱内参数共享,即每个特征图谱内只使用一个共同卷积核,卷积核有5x5个连接参数加上1个偏置共26个参数。卷积区域每次滑动一个像素,这样卷积层形成的每个特征图谱大小是(32-5)/1+1=28x28。C1层共有26x6=156个训练参数,有(5x5+1)x28x28x6=122304个连接。C1层的连接结构如下所示。
LeNet-5第二层:池化层S2
S2层是一个下采样层(为什么是下采样?利用图像局部相关性的原理,对图像进行子抽样,可以减少数据处理量同时保留有用信息)。C1层的6个28x28的特征图谱分别进行以2x2为单位的下抽样得到6个14x14((28-2)/2+1)的图。每个特征图谱使用一个下抽样核。5x14x14x6=5880个连接。S2层的网络连接结构如下右图
LeNet-5第三层:卷积层C3
C3层是一个卷积层,卷积和和C1相同,不同的是C3的每个节点与S2中的多个图相连。C3层有16个10x10(14-5+1)的图,每个图与S2层的连接的方式如下表 所示。C3与S2中前3个图相连的卷积结构见下图.这种不对称的组合连接的方式有利于提取多种组合特征。该层有(5x5x3+1)x6 + (5x5x4 + 1) x 3 + (5x5x4 +1)x6 + (5x5x6+1)x1 = 1516个训练参数,共有1516x10x10=151600个连接。
这16张图片的每一张,是通过S2的6张图片进行加权组合得到的:
前6个feature map与S2层相连的3个feature map相连接,后面6个feature map与S2层相连的4个feature map相连接,后面3个feature map与S2层部分不相连的4个feature map相连接,最后一个与S2层的所有feature map相连。卷积核大小依然为5x5。
LeNet-5第四层:池化层S4
S4是一个下采样层。C3层的16个10x10的图分别进行以2x2为单位的下抽样得到16个5x5的图。5x5x5x16=2000个连接。连接的方式与S2层类似,如下所示。
LeNet-5第五层:全连接层C5
C5层是一个全连接层。由于S4层的16个图的大小为5x5,与卷积核的大小相同,所以卷积后形成的图的大小为1x1。这里形成120个卷积结果。每个都与上一层的16个图相连。所以共有(5x5x16+1)x120 = 48120个参数,同样有48120个连接。C5层的网络结构如下所示。
LeNet-5第六层:全连接层F6
F6层是全连接层。F6层有84个节点,对应于一个7x12的比特图,该层的训练参数和连接数都是(120 + 1)x84=10164.
F6相当于MLP中的隐含层,F6层采用了正切函数。
LeNet-5第七层:全连接层Output
Output层也是全连接层,共有10个节点,分别代表数字0到9,如果节点i的输出值为0,则网络识别的结果是数字i。采用的是径向基函数(RBF)的网络连接方式。假设x是上一层的输入,y是RBF的输出,则RBF输出的计算方式是:
yi的值由i的比特图编码(即参数Wij)确定。yi越接近于0,则标明输入越接近于i的比特图编码,表示当前网络输入的识别结果是字符i。该层有84x10=840个设定的参数和连接。连接的方式如上图.
以上是LeNet-5的卷积神经网络的完整结构,共约有60,840个训练参数,340,908个连接。一个数字识别的效果如图所示
LeNet-5的训练算法
训练算法与传统的BP算法差不多。主要包括4步,这4步被分为两个阶段:
第一阶段,向前传播阶段:
a)从样本集中取一个样本(X,Yp),将X输入网络;
b)计算相应的实际输出Op。
在此阶段,信息从输入层经过逐级的变换,传送到输出 层。这个过程也是网络在完成训练后正常运行时执行的过程。在此过程中,网络执行的是计算(实际上就是输入与每层的权值矩阵相点乘,得到最后的输出结果):
Op=Fn(…(F2(F1(XpW(1))W(2))…)W(n))
第二阶段,向后传播阶段
a)算实际输出Op与相应的理想输出Yp的差;
b)按极小化误差的方法反向传播调整权矩阵。
卷积神经网络的优点
卷积网络较一般神经网络在图像处理方面有 如下优点
a)输入图像和网络的拓扑结构能很好的吻合;
b)特征提取和模式分类同时进行,并同时在训练中产生;
c)权重共享可以减少网络的训练参数,使神经网络结构变得更简单,适应性更强。
总结
卷积网络在本质上是一种输入到输出的映射,它能够学习大量的输入与输出之间的映射关系,而不需要任何输入和输出之间的精确的数学表达式。
通过对LeNet-5的网络结构的分析,可以直观地了解一个卷积神经网络的构建方法,可以为分析、构建更复杂、更多层的卷积神经网络做准备。
LaNet-5的局限性
CNN能够得出原始图像的有效表征,这使得CNN能够直接从原始像素中,经过极少的预处理,识别视觉上面的规律。然而,由于当时缺乏大规模训练数据,计算机的计算能力也跟不上,LeNet-5 对于复杂问题的处理结果并不理想。
结构:
AlexNet的结构如上图所示,共包含了8个学习层——5个卷积层与3个全连接层,相比于之前的LeNet-5网络,AlexNet有以下几个创新的结构:
也就是现在被广泛使用的ReLU激活函数,在过去,神经网络的激活函数通常是sigmoid或者tanh函数,这两种函数最大的缺点就是其饱和性,当输入的x过大或过小时,函数的输出会非常接近+1与-1,在这里斜率会非常小,那么在训练时引用梯度下降时,其饱和性会使梯度非常小,严重降低了网络的训练速度。
而ReLU的函数表达式为max(0, x),当x>0时输出为x,斜率恒为1,在实际使用时,神经网络的收敛速度要快过传统的激活函数数十倍。
对于一个四层的神经网络,利用CIFAR-10数据集进行训练,使用ReLU函数达到25%错误率需要的迭代数是tanh函数所需迭代数的六分之一。而对于大型的数据集,使用更深的神经网络,ReLU对训练的加速更为明显。
不多说,利用多个GPU进行分布式计算
在使用饱和型的激活函数时,通常需要对输入进行归一化处理,以利用激活函数在0附近的线性特性与非线性特性,并避免饱和,但对于ReLU函数,不需要输入归一化。然而,Alex等人发现通过LRN这种归一化方式可以帮助提高网络的泛化性能。LRN的公式如下:
LRN的作用就是,对位置(x, y)处的像素计算其与几个相邻的kernel maps的像素值的和,并除以这个和来归一化。kernel maps的顺序可以是任意的,在训练开始前确定顺序即可。其中的k, N, α, β都是超参数,论文中给出了所用的值为k=2, N=5, α=10e-4, β=0.75。在AlexNet中,LRN层位于ReLU之后。在论文中,Alex指出应用LRN后top-1与top-5错误率分别提升了1.4%与1.2%。
Hinton等人认为LRN层模仿生物神经系统的侧抑制机制,对局部神经元的活动创建竞争机制,使得响应比较大的值相对更大,提高模型泛化能力。但是,后来的论文比如Very Deep Convolution Networks for Large-Scale Image Recognition(也就是提出VGG网络的文章)中证明,LRN对CNN并没有什么作用,反而增加了计算复杂度,因此,这一技术也不再使用了。
池化层是CNN中非常重要的一层,可以起到提取主要特征,减少特征图尺寸的作用,对加速CNN计算非常重要,然而通常池化的大小与步进被设置为相同的大小,当池化的大小大于步进时,就成为了overlapping pooling,这也是AlexNet中使用的池化技术。论文中提到,使用这种池化可以一定程度上减小过拟合现象。
这部分讲了AlexNet的整体结构,如前图所示。全连接的最后一层是softmax层,共有1000个输出。计算的过程分成两部分是因为这两部分是在两块GTX580上计算的。
ReLU在每个卷积层和全连接层后。LRN层在第一个和第二个卷积层之后。Max-pooling层在两个LRN层与第四个卷积层之后。
卷积的维度不再赘述,看图就好。
AlexNet中有六千万个参数,也非常容易产生过拟合现象,而AlexNet中采用了两种方式来对抗过拟合。
对抗过拟合最简单有效的办法就是扩大训练集的大小,AlexNet中使用了两种增加训练集大小的方式。
Dropout是神经网络中一种非常有效的减少过拟合的方法,对每个神经元设置一个keep_prob用来表示这个神经元被保留的概率,如果神经元没被保留,换句话说这个神经元被“dropout”了,那么这个神经元的输出将被设置为0,在残差反向传播时,传播到该神经元的值也为0,因此可以认为神经网络中不存在这个神经元;而在下次迭代中,所有神经元将会根据keep_prob被重新随机dropout。相当于每次迭代,神经网络的拓扑结构都会有所不同,这就会迫使神经网络不会过度依赖某几个神经元或者说某些特征,因此,神经元会被迫去学习更具有鲁棒性的特征。如下图所示:
在AlexNet中,在训练时,每层的keep_prob被设置为0.5,而在测试时,所有的keep_prob都为1.0,也即关闭dropout,并把所有神经元的输出均乘以0.5,保证训练时和测试时输出的均值接近。当然,dropout只用于全连接层。
没有dropout,AlexNet网络将会遭遇严重的过拟合,加入dropout后,网络的收敛速度慢了接近一倍。
AlexNet使用了mini-batch SGD,batch的大小为128,梯度下降的算法选择了momentum,参数为0.9,加入了L2正则化,或者说权重衰减,参数为0.0005。论文中提到,这么小的权重衰减参数几乎可以说没有正则化效果,但对模型的学习非常重要。
每一层权重均初始化为0均值0.01标准差的高斯分布,在第二层、第四层和第五层卷积的偏置被设置为1.0,而其他层的则为0,目的是为了加速早期学习的速率(因为激活函数是ReLU,1.0的偏置可以让大部分输出为正)。
学习速率初始值为0.01,在训练结束前共减小3次,每次减小都出现在错误率停止减少的时候,每次减小都是把学习速率除以10 。
Alex共在包含120万图片的ImageNet测试集中训练了90个epoch,在2块GTX580 3GB上训练 了5-6天。
1. conv1阶段DFD(data flow diagram):
第一层输入数据为原始的227*227*3的图像(输入图像的尺寸是224*224,在进行第一次卷积的时候会padding 3个像素变成227*227),这个图像被11*11*3的卷积核进行卷积运算,卷积核对原始图像的每次卷积都生成一个新的像素。卷积核沿原始图像的x轴方向和y轴方向两个方向移动,移动的步长是4个像素。因此,卷积核在移动的过程中会生成(227-11)/4+1=55个像素(227个像素减去11,正好是54,即生成54个像素,再加上被减去的11也对应生成一个像素),行和列的55*55个像素形成对原始图像卷积之后的像素层。共有96个卷积核,会生成55*55*96个卷积后的像素层。96个卷积核分成2组,每组48个卷积核。对应生成2组55*55*48的卷积后的像素层数据。这些像素层经过relu1单元的处理,生成激活像素层,尺寸仍为2组55*55*48的像素层数据。
这些像素层经过pool运算(池化运算)的处理,池化运算的尺度为3*3,运算的步长为2,则池化后图像的尺寸为(55-3)/2+1=27。 即池化后像素的规模为27*27*96;然后经过归一化处理,归一化运算的尺度为5*5;第一卷积层运算结束后形成的像素层的规模为27*27*96。分别对应96个卷积核所运算形成。这96层像素层分为2组,每组48个像素层,每组在一个独立的GPU上进行运算。
反向传播时,每个卷积核对应一个偏差值。即第一层的96个卷积核对应上层输入的96个偏差值。
2. conv2阶段DFD(data flow diagram):
第二层输入数据为第一层输出的27*27*96的像素层,为便于后续处理,每幅像素层的左右两边和上下两边都要填充2个像素;27*27*96的像素数据分成27*27*48的两组像素数据,两组数据分别再两个不同的GPU中进行运算。每组像素数据被5*5*48的卷积核进行卷积运算,卷积核对每组数据的每次卷积都生成一个新的像素。卷积核沿原始图像的x轴方向和y轴方向两个方向移动,移动的步长是1个像素。因此,卷积核在移动的过程中会生成(27-5+2*2)/1+1=27个像素。(27个像素减去5,正好是22,在加上上下、左右各填充的2个像素,即生成26个像素,再加上被减去的5也对应生成一个像素),行和列的27*27个像素形成对原始图像卷积之后的像素层。共有256个5*5*48卷积核;这256个卷积核分成两组,每组针对一个GPU中的27*27*48的像素进行卷积运算。会生成两组27*27*128个卷积后的像素层。这些像素层经过relu2单元的处理,生成激活像素层,尺寸仍为两组27*27*128的像素层。
这些像素层经过pool运算(池化运算)的处理,池化运算的尺度为3*3,运算的步长为2,则池化后图像的尺寸为(27-3)/2+1=13。 即池化后像素的规模为2组13*13*128的像素层;然后经过归一化处理,归一化运算的尺度为5*5;第二卷积层运算结束后形成的像素层的规模为2组13*13*128的像素层。分别对应2组128个卷积核所运算形成。每组在一个GPU上进行运算。即共256个卷积核,共2个GPU进行运算。
反向传播时,每个卷积核对应一个偏差值。即第一层的96个卷积核对应上层输入的256个偏差值。
3. conv3阶段DFD(data flow diagram):
第三层输入数据为第二层输出的2组13*13*128的像素层;为便于后续处理,每幅像素层的左右两边和上下两边都要填充1个像素;2组像素层数据都被送至2个不同的GPU中进行运算。每个GPU中都有192个卷积核,每个卷积核的尺寸是3*3*256。因此,每个GPU中的卷积核都能对2组13*13*128的像素层的所有数据进行卷积运算。卷积核对每组数据的每次卷积都生成一个新的像素。卷积核沿像素层数据的x轴方向和y轴方向两个方向移动,移动的步长是1个像素。因此,运算后的卷积核的尺寸为(13-3+1*2)/1+1=13(13个像素减去3,正好是10,在加上上下、左右各填充的1个像素,即生成12个像素,再加上被减去的3也对应生成一个像素),每个GPU中共13*13*192个卷积核。2个GPU中共13*13*384个卷积后的像素层。这些像素层经过relu3单元的处理,生成激活像素层,尺寸仍为2组13*13*192像素层,共13*13*384个像素层。
4. conv4阶段DFD(data flow diagram):
第四层输入数据为第三层输出的2组13*13*192的像素层;为便于后续处理,每幅像素层的左右两边和上下两边都要填充1个像素;2组像素层数据都被送至2个不同的GPU中进行运算。每个GPU中都有192个卷积核,每个卷积核的尺寸是3*3*192。因此,每个GPU中的卷积核能对1组13*13*192的像素层的数据进行卷积运算。卷积核对每组数据的每次卷积都生成一个新的像素。卷积核沿像素层数据的x轴方向和y轴方向两个方向移动,移动的步长是1个像素。因此,运算后的卷积核的尺寸为(13-3+1*2)/1+1=13(13个像素减去3,正好是10,在加上上下、左右各填充的1个像素,即生成12个像素,再加上被减去的3也对应生成一个像素),每个GPU中共13*13*192个卷积核。2个GPU中共13*13*384个卷积后的像素层。这些像素层经过relu4单元的处理,生成激活像素层,尺寸仍为2组13*13*192像素层,共13*13*384个像素层。
5. conv5阶段DFD(data flow diagram):
第五层输入数据为第四层输出的2组13*13*192的像素层;为便于后续处理,每幅像素层的左右两边和上下两边都要填充1个像素;2组像素层数据都被送至2个不同的GPU中进行运算。每个GPU中都有128个卷积核,每个卷积核的尺寸是3*3*192。因此,每个GPU中的卷积核能对1组13*13*192的像素层的数据进行卷积运算。卷积核对每组数据的每次卷积都生成一个新的像素。卷积核沿像素层数据的x轴方向和y轴方向两个方向移动,移动的步长是1个像素。因此,运算后的卷积核的尺寸为(13-3+1*2)/1+1=13(13个像素减去3,正好是10,在加上上下、左右各填充的1个像素,即生成12个像素,再加上被减去的3也对应生成一个像素),每个GPU中共13*13*128个卷积核。2个GPU中共13*13*256个卷积后的像素层。这些像素层经过relu5单元的处理,生成激活像素层,尺寸仍为2组13*13*128像素层,共13*13*256个像素层。
2组13*13*128像素层分别在2个不同GPU中进行池化(pool)运算处理。池化运算的尺度为3*3,运算的步长为2,则池化后图像的尺寸为(13-3)/2+1=6。 即池化后像素的规模为两组6*6*128的像素层数据,共6*6*256规模的像素层数据。
6. fc6阶段DFD(data flow diagram):
第六层输入数据的尺寸是6*6*256,采用6*6*256尺寸的滤波器对第六层的输入数据进行卷积运算;每个6*6*256尺寸的滤波器对第六层的输入数据进行卷积运算生成一个运算结果,通过一个神经元输出这个运算结果;共有4096个6*6*256尺寸的滤波器对输入数据进行卷积运算,通过4096个神经元输出运算结果;这4096个运算结果通过relu激活函数生成4096个值;并通过drop运算后输出4096个本层的输出结果值。
由于第六层的运算过程中,采用的滤波器的尺寸(6*6*256)与待处理的feature map的尺寸(6*6*256)相同,即滤波器中的每个系数只与feature map中的一个像素值相乘;而其它卷积层中,每个滤波器的系数都会与多个feature map中像素值相乘;因此,将第六层称为全连接层。
第五层输出的6*6*256规模的像素层数据与第六层的4096个神经元进行全连接,然后经由relu6进行处理后生成4096个数据,再经过dropout6处理后输出4096个数据。
7. fc7阶段DFD(data flow diagram):
第六层输出的4096个数据与第七层的4096个神经元进行全连接,然后经由relu7进行处理后生成4096个数据,再经过dropout7处理后输出4096个数据。
8. fc8阶段DFD(data flow diagram):
第七层输出的4096个数据与第八层的1000个神经元进行全连接,经过训练后输出被训练的数值。
Alexnet网络中各个层发挥的作用如下表所述:
在学习过程中,我们使用随机梯度下降法和一批大小为128、动力为0.9、权重衰减为0.0005的样例来训练我们的网络。我们发现,这少量的权重衰减对于模型学习是重要的。换句话说,这里的权重衰减不仅仅是一个正则化矩阵:它减少了模型的训练误差。对于权重w的更新规则为:
其中i是迭代指数,v是动力变量,ε是学习率,是目标关于w、对求值的导数在第i批样例上的平均值。我们用一个均值为0、标准差为0.01的高斯分布初始化了每一层的权重。我们用常数1初始化了第二、第四和第五个卷积层以及全连接隐层的神经元偏差。该初始化通过提供带正输入的ReLU来加速学习的初级阶段。我们在其余层用常数0初始化神经元偏差。
对于所有层都使用了相等的学习率,这是在整个训练过程中手动调整的。我们遵循的启发式是,当验证误差率在当前学习率下不再提高时,就将学习率除以10。学习率初始化为0.01,在终止前降低三次。
VGGNet是牛津大学计算机视觉组和DeepMind公司共同研发一种深度卷积网络,并且在2014年在ILSVRC比赛上获得了分类项目的第二名和定位项目的第一名,VggNet一共有六种不同的网络结构,但是每种结构都有含有5组卷积,每组卷积都使用3x3的卷积核,每组卷积后进行一个2x2最大池化,接下来是三个全连接层.在训练高级别的网络时,可以先训练低级别的网络,用前者获得的权重初始化高级别的网络,可以加速网络的收敛.
网络的几种不同配置
在这篇论文中分别使用了A、A-LRN、B、C、D、E这6种网络结构进行测试,这6种网络结构相似,都是由5层卷积层、3层全连接层组成,其中区别在于每个卷积层的子层数量不同,从A至E依次增加(子层数量从1到4),总的网络深度从11层到19层(添加的层以粗体显示),表格中的卷积层参数表示为“conv〈感受野大小〉-通道数〉”,例如con3-128,表示使用3x3的卷积核,通道数为128。为了简洁起见,在表格中不显示ReLU激活功能。
其中,网络结构D就是著名的VGG16,网络结构E就是著名的VGG19。
C级别的网络增加了1x1的卷积核,它的作用主要是对像素进行线性变换,不改变输入出通道,和大小.
网络的参数
在有些卷积组中会出现连续的几个卷积层堆叠,使用3x3的卷积核,这样的设计,既可以保证感受视野,有能减少卷基层的参数,
例如:两个3x3的卷积层叠加,等价于一个5x5的卷积核的效果,3个3x3的卷积核的叠加相当于一个7x7的卷积核,而且参数更少.大约是7x7卷积核卷积层的(3*3*3)/(7*7)=0.55.而且拥有和7x7卷积核一样的感受视野,三个卷积层的叠加,经过了更多次的非线性变换,对特征的学习能力更强.
VGGNet探索了卷积神经网络的深度与其性能之间的关系,通过反复堆叠3*3的小型卷积核和2*2的最大池化层,VGGNet成功地构筑了16~19层深的卷积神经网络。VGGNet相比之前state-of-the-art的网络结构,错误率大幅下降,并取得了ILSVRC 2014比赛分类项目的第2名和定位项目的第1名。同时VGGNet的拓展性很强,迁移到其他图片数据上的泛化性非常好。VGGNet的结构非常简洁,整个网络都使用了同样大小的卷积核尺寸(3*3)和最大池化尺寸(2*2)。到目前为止,VGGNet依然经常被用来提取图像特征。VGGNet训练后的模型参数在其官方网站上开源了,可用来在特定的图像分类任务上进行再训练(相当于提供了非常好的初始化权重),因此被用在了很多地方。
VGGNet论文中全部使用了3*3的卷积核和2*2的池化核,通过不断加深网络结构来提升性能。图1所示为VGGNet各级别的网络结构图,图2所示为每一级别的参数量,从11层的网络一直到19层的网络都有详尽的性能测试。虽然从A到E每一级网络逐渐变深,但是网络的参数量并没有增长很多,这是因为参数量主要都消耗在最后3个全连接层。前面的卷积部分虽然很深,但是消耗的参数量不大,不过训练比较耗时的部分依然是卷积,因其计算量比较大。这其中的D、E也就是我们常说的VGGNet-16和VGGNet-19。C很有意思,相比B多了几个1*1的卷积层,1*1卷积的意义主要在于线性变换,而输入通道数和输出通道数不变,没有发生降维。
训练时,输入是大小为224*224的RGB图像,预处理只有在训练集中的每个像素上减去RGB的均值。
VGGNet在训练时有一个小技巧,先训练级别A的简单网络,再复用A网络的权重来初始化后面的几个复杂模型,这样训练收敛的速度更快。在预测时,VGG采用Multi-Scale的方法,将图像scale到一个尺寸Q,并将图片输入卷积网络计算。然后在最后一个卷积层使用滑窗的方式进行分类预测,将不同窗口的分类结果平均,再将不同尺寸Q的结果平均得到最后结果,这样可提高图片数据的利用率并提升预测准确率。在训练中,VGGNet还使用了Multi-Scale的方法做数据增强,将原始图像缩放到不同尺寸S,然后再随机裁切224´224的图片,这样能增加很多数据量,对于防止模型过拟合有很不错的效果。实践中,作者令S在[256,512]这个区间内取值,使用Multi-Scale获得多个版本的数据,并将多个版本的数据合在一起进行训练。图4所示为VGGNet使用Multi-Scale训练时得到的结果,可以看到D和E都可以达到7.5%的错误率。最终提交到ILSVRC 2014的版本是仅使用Single-Scale的6个不同等级的网络与Multi-Scale的D网络的融合,达到了7.3%的错误率。不过比赛结束后作者发现只融合Multi-Scale的D和E可以达到更好的效果,错误率达到7.0%,再使用其他优化策略最终错误率可达到6.8%左右,非常接近同年的冠军Google Inceptin Net。同时,作者在对比各级网络时总结出了以下几个观点:(1)LRN层作用不大(VGGNet不使用局部响应标准化(LRN),这种标准化并不能在ILSVRC数据集上提升性能,却导致更多的内存消耗和计算时间。);(2)越深的网络效果越好;(3)1*1的卷积也是很有效的,但是没有3*3的卷积好,大一些的卷积核可以学习更大的空间特征。
图4 各级别VGGNet在使用Multi-Scale训练时的top-5错误率
在训练的过程中,比AlexNet收敛的要快一些,原因为:(1)使用小卷积核和更深的网络进行的正则化;(2)在特定的层使用了预训练得到的数据进行参数的初始化。
对于较浅的网络,如网络A,可以直接使用随机数进行随机初始化,而对于比较深的网络,则使用前面已经训练好的较浅的网络中的参数值对其前几层的卷积层和最后的全连接层进行初始化。
VGGNet探索了卷积神经网络的深度与其性能之间的关系,成功地构筑了16~19层深的卷积神经网络,证明了增加网络的深度能够在一定程度上影响网络最终的性能,使错误率大幅下降,同时拓展性又很强,迁移到其它图片数据上的泛化性也非常好。到目前为止,VGG仍然被用来提取图像特征。
一、VGG的特点
先看一下VGG的结构图
1、结构简洁
VGG由5层卷积层、3层全连接层、softmax输出层构成,层与层之间使用max-pooling(最大化池)分开,所有隐层的激活单元都采用ReLU函数。
2、小卷积核和多卷积子层
VGG使用多个较小卷积核(3x3)的卷积层代替一个卷积核较大的卷积层,一方面可以减少参数,另一方面相当于进行了更多的非线性映射,可以增加网络的拟合/表达能力。
小卷积核是VGG的一个重要特点,虽然VGG是在模仿AlexNet的网络结构,但没有采用AlexNet中比较大的卷积核尺寸(如7x7),而是通过降低卷积核的大小(3x3),增加卷积子层数来达到同样的性能(VGG:从1到4卷积子层,AlexNet:1子层)。
VGG的作者认为两个3x3的卷积堆叠获得的感受野大小,相当一个5x5的卷积;而3个3x3卷积的堆叠获取到的感受野相当于一个7x7的卷积。这样可以增加非线性映射,也能很好地减少参数(例如7x7的参数为49个,而3个3x3的参数为27),如下图所示:
3、小池化核
相比AlexNet的3x3的池化核,VGG全部采用2x2的池化核。
4、通道数多
VGG网络第一层的通道数为64,后面每层都进行了翻倍,最多到512个通道,通道数的增加,使得更多的信息可以被提取出来。
5、层数更深、特征图更宽
由于卷积核专注于扩大通道数、池化专注于缩小宽和高,使得模型架构上更深更宽的同时,控制了计算量的增加规模。
6、全连接转卷积(测试阶段)
这也是VGG的一个特点,在网络测试阶段将训练阶段的三个全连接替换为三个卷积,使得测试得到的全卷积网络因为没有全连接的限制,因而可以接收任意宽或高为的输入,这在测试阶段很重要。
如本节第一个图所示,输入图像是224x224x3,如果后面三个层都是全连接,那么在测试阶段就只能将测试的图像全部都要缩放大小到224x224x3,才能符合后面全连接层的输入数量要求,这样就不便于测试工作的开展。
而“全连接转卷积”,替换过程如下:
例如7x7x512的层要跟4096个神经元的层做全连接,则替换为对7x7x512的层作通道数为4096、卷积核为1x1的卷积。
这个“全连接转卷积”的思路是VGG作者参考了OverFeat的工作思路,例如下图是OverFeat将全连接换成卷积后,则可以来处理任意分辨率(在整张图)上计算卷积,这就是无需对原图做重新缩放处理的优势。
以网络结构D(VGG16)为例,介绍其处理过程如下,请对比上面的表格和下方这张图,留意图中的数字变化,有助于理解VGG16的处理过程:
1、输入224x224x3的图片,经64个3x3的卷积核作两次卷积+ReLU,卷积后的尺寸变为224x224x64
2、作max pooling(最大化池化),池化单元尺寸为2x2(效果为图像尺寸减半),池化后的尺寸变为112x112x64
3、经128个3x3的卷积核作两次卷积+ReLU,尺寸变为112x112x128
4、作2x2的max pooling池化,尺寸变为56x56x128
5、经256个3x3的卷积核作三次卷积+ReLU,尺寸变为56x56x256
6、作2x2的max pooling池化,尺寸变为28x28x256
7、经512个3x3的卷积核作三次卷积+ReLU,尺寸变为28x28x512
8、作2x2的max pooling池化,尺寸变为14x14x512
9、经512个3x3的卷积核作三次卷积+ReLU,尺寸变为14x14x512
10、作2x2的max pooling池化,尺寸变为7x7x512
11、与两层1x1x4096,一层1x1x1000进行全连接+ReLU(共三层)
12、通过softmax输出1000个预测结果
以上就是VGG16(网络结构D)各层的处理过程,A、A-LRN、B、C、E其它网络结构的处理过程也是类似。
从上面的过程可以看出VGG网络结构还是挺简洁的,都是由小卷积核、小池化核、ReLU组合而成。其简化图如下(以VGG16为例):
A、A-LRN、B、C、D、E这6种网络结构的深度虽然从11层增加至19层,但参数量变化不大,这是由于基本上都是采用了小卷积核(3x3,只有9个参数),这6种结构的参数数量(百万级)并未发生太大变化,这是因为在网络中,参数主要集中在全连接层。
从上表可以看出:
1、LRN层无性能增益(A-LRN)
VGG作者通过网络A-LRN发现,AlexNet曾经用到的LRN层(local response normalization,局部响应归一化)并没有带来性能的提升,因此在其它组的网络中均没再出现LRN层。
2、随着深度增加,分类性能逐渐提高(A、B、C、D、E)
从11层的A到19层的E,网络深度增加对top1和top5的错误率下降很明显。
3、多个小卷积核比单个大卷积核性能好(B)
VGG作者做了实验用B和自己一个不在实验组里的较浅网络比较,较浅网络用conv5x5来代替B的两个conv3x3,结果显示多个小卷积核比单个大卷积核效果要好。
最后进行个小结:
1、通过增加深度能有效地提升性能;
2、最佳模型:VGG16,从头到尾只有3x3卷积与2x2池化,简洁优美;
3、卷积可代替全连接,可适应各种尺寸的图片
GoogLeNet的思想动机也是增加模型的规模:深度,和宽度。同样的是,更大的模型意味着更多的参数,计算资源的消耗增加,模型也更容易过拟合,因此并不能盲目的增加模型的规模。
深度,必须增加。那么为了较少模型复杂度,就只能在模型的宽度上做文章。VGG的做法是将每一层的滤波器尺寸都换成3×3 来减少模型的宽度,也证明具有很好的效果。Inception的做法就是将卷积层的完全连接变成稀疏连接,而且受到生物神经学的启发,利用多个大小不一致的滤波器,在多个尺度上来提取特征,然后再连接到一个共同的输出,这样一方面在不增加参数量的前提下增加了网络的宽度,另一方面也增加了网络对多个尺度的适应性。通过对Inception进行堆叠,构成了一个含有22个权重层的GoogLeNet。
对于每一个Inception模块,包含有1×1、3×3和5×5的三个滤波器,以及一个并行的最大池化层,最后在将输出连接成一个输出向量。模块构成如下:
随着层数的加深,feature map中特征的空间集中度会下降,因此需要更多的3×3和5×5的滤波器,而这样会导致参数量变得非常大。
下图是优化前后两种方案的乘法次数比较,同样是输入一组有192个特征、32x32大小,输出256组特征的数据,第一张图直接用3x3卷积实现,需要192x256x3x3x32x32=452984832次乘法;第二张图先用1x1的卷积降到96个特征,再用3x3卷积恢复出256组特征,需要192x96x1x1x32x32+96x256x3x3x32x32=245366784次乘法,使用1x1卷积降维的方法节省了一半的计算量。有人会问,用1x1卷积降到96个特征后特征数不就减少了么,会影响最后训练的效果么?答案是否定的,只要最后输出的特征数不变(256组),中间的降维类似于压缩的效果,并不影响最终训练的结果。
因而作者提出了一种新的结构,在3×3和5×5的滤波器前使用1×1的滤波器来进行降维,例如,假设原始结构为1×1×192×64+3×3×192×128+5×5×192×32(height×width×input×output),而在3×3和5×5卷积层前分别加入了通道数为96和16的1×1卷积层,这样卷积核参数就变成了1×1×192×64+(1×1×192×96+3×3×96×128)+(1×1×192×16+5×5×16×32),这样就将模型参数减少到原来的三分之一左右。同样的为了减少维度,在pooling层之后也使用1×1的滤波器来进行降维。并且除了降维的功能,1×1的滤波器还可以用来进行修正线性激活。因此改进后的Inception模块如下:
整个GoogLeNet的框架如下:
模型的参数如下:
我们发现在Inception4(a)和Inception4(d)中,使用了辅助分类器,作者希望利用中间层的特征来增加底层的判别性,利用辅助分类器来增加反向传播的信号,来增加额外的正则化(辅助分类器在测试阶段并不使用)。
GoogLeNet网络结构中有3个LOSS单元,这样的网络设计是为了帮助网络的收敛。在中间层加入辅助计算的LOSS单元,目的是计算损失时让低层的特征也有很好的区分能力,从而让网络更好地被训练。在论文中,这两个辅助LOSS单元的计算被乘以0.3,然后和最后的LOSS相加作为最终的损失函数来训练网络。
GoogLeNet还有一个闪光点值得一提,那就是将后面的全连接层全部替换为简单的全局平均pooling,在最后参数会变的更少。而在AlexNet中最后3层的全连接层参数差不多占总参数的90%,使用大网络在宽度和深度允许GoogleNet移除全连接层,但并不会影响到结果的精度,在ImageNet中实现93.3%的精度,而且要比VGG还要快
对于整个GoogLeNet模型,虽然总共有22层,但是参数数量却只是8层的AlexNet的十二分之一。
分类任务上与state of the art的比较
GoogLeNet 不同版本的性能:
检测任务上与state of the art的比较:
单模型检测的性能:
本文在模型结构上进行了非常大胆新颖的尝试,在提高模型层次的基础上,使用稀疏结构来减少模型复杂度,以提高模型的性能。结果也证明了这个方法是非常具有研究价值的。
对于传统的深度学习网络应用来说,我们都有这样一种体会,那就是网络越深所能学到的东西就越多。当然收敛速度同时也就越慢,训练时间越长,然而深度到了一定程度之后就会发现有一些越往深学习率越低的情况。深度残差网络的设计就是为了克服这种由于网络深度加深而产生的学习率变低,准确率无法有效提升的问题,也称作网络的退化问题。甚至在一些场景下,网络层数的增加反而会降低正确率。
关于深度残差网络的介绍资料不算多,至少比起传统的BP、CNN、RNN网络的介绍资料就少得多了,我这边参考的是何恺明先生在网上公开的一个介绍性资料“Deep Residual Networks——Deep Learning Gets Way Deeper”。
说到对比传统的卷积神经网络在做分类器的时候,在加深网络层数的过程中是会观察到一些出出乎意料的现象的。例如在CIFAR-10项目上使用56层的3×3卷积核的网络其错误率无论是训练集上还是验证集上,都高于20层的卷积网络,这就尴尬了。通常为了让网络学到更多的东西,是可以通过加深网络的层数,让网络具备更高的VC维这样的手段来实现的。但眼前的事实就是这样,加到56层的时候其识别错误率是要比在20层的时候更加糟糕。
这种现象的本质问题是由于出现了信息丢失而产生的过拟合问题。这些图片在经过多层卷积的采样后在较深的网络层上会出现一些奇怪的现象,就是明明是不同的图片类别,但是却产生了看上去比较近似的对网络的刺激效果。这种差距的减小也就使得最后的分类效果不会太理想,所以解决思路应该是尝试着使它们的引入这些刺激的差异性和解决泛化能力为主。所以才会考虑较大尺度地改变传统CNN网络的结构,而结果也没有让我们失望,新型的深度残差网络在图像处理方面表现出来的优秀特性确实令我们眼前一亮。
到目前为止,在图像分类(Image Classification)、对象检测(Object Detection)、语义分割(Semantic Segmentation)等领域的应用中,深度残差网络都表现出了良好的效果。上面这几张图都是尝试用深度残差网络在一张图片中去识别具体的一个目标,每个目标的属性标注是基于微软的COCO数据集 的数据标识。物品(人)的框图上还标注了一个小数,这个数字就是概率(或者称确信度Precision),指模型识别这个物体种类的确信度。我们能看到,在这个图片中大部分物体的识别还是非常准确的。
深度网络有个巨大的问题,那就是随着深度的加深,很容易出现梯度弥散和梯度爆炸的问题。
前面我们也提过这个问题,因为网络深度太大所以残差传播的过程在层与层之间求导的过程中会进行相乘叠加,一个小于1或一个大于1的数字在经过150层的指数叠加就会变得很大或者很小,我们自己手算一下也能算出来,0.8的150次方大约是2.9 x 10-15 ,1.2的150次方大约是7.5 x 1011,这两种情况都是极为严重的灾难,任何一种都会导致训练劳而无功。
在传统的平网络(Plain Network)中,一层的网络的数据来源只能是前一层网络,就像上图这样,数据一层一层向下流。对于卷积神经网络来说,每一层在通过卷积核后都会产生一种类似有损压缩的效果,可想而知在有损压缩到一定程度以后,分不清楚原本清晰可辨的两张照片并不是什么意外的事情。这种行为叫有损压缩其实并不合适,实际在工程上我们称之为降采样(Downsampling)——就是在向量通过网络的过程中经过一些滤波器(filters)的处理,产生的效果就是让输入向量在通过降采样处理后具有更小的尺寸,在卷积网络中常见的就是卷积层和池化层,这两者都可以充当降采样的功能属性。主要目的是为了避免过拟合,以及有一定的减少运算量的副作用。在深度残差网络中,结构出现了比较明显的变化。
在这种情况下,会引入这种类似“短路”式的设计,将前若干层的数据输出直接跳过多层而引入到后面数据层的输入部分,如图所示。这会产生什么效果呢?简单说就是前面层的较为“清晰”一些的向量数据会和后面被进一步“有损压缩”过的数据共同作为后面的数据输入。而对比之前没有加过这个“短路”设计的平网络来说,缺少这部分数据的参考,本身是一种信息缺失丢失的现象本质。本来一个由2层网络组成的映射关系我们可以称之为F(x)的这样一个期望函数来拟合,而现在我们期望用H(x)=F(x)+x来拟合,这本身就引入了更为丰富的参考信息或者说更为丰富的维度(特征值)。这样网络就可以学到更为丰富的内容。
这张图比较了三种网络的深度和结构特点,VGG-19、34层的“平网络”——也就是普通34层的CNN网络,还有34层的深度残差网络。
在深度残差网络的设计中通常都是一种“力求简洁”的设计方式,只是单纯加深网络,所有的卷积层几乎都采用3×3的卷积核,而且绝不在隐藏层中设计任何的全连接层,也不会在训练的过程中考虑使用任何的DropOut机制。以2015年的ILSVRC & COCO Copetitions为例,以分类为目的深度残差网络“ImageNet Classfication”居然能够达到152层之深,也算是破了纪录了。
这种短路层引入后会有一种有趣的现象,就是会产生一个非常平滑的正向传递过程。我们看xl+1和其前面一层xl的关系是纯粹一个线性叠加的关系。如果进一步推导xl+2及其以后层的输出会发现展开后是这样一个表达式:
也就是后面的任何一层xL向量的内容会有一部分由其前面的某一层xl线性贡献。
好,现在看反向的残差传递,也是一个非常平滑的过程。这是刚才我们看到的某层输出xL的函数表达式
那么残差我们定义为E(就是Loss),应该有
后面的xlable表示的是在当前样本和标签给定情况下某一层xL所对应的理想向量值,这个残差就来表示它就可以了。下面又是老生常谈的求导过程了,这里就是用链式法则可以直接求出来的,很简单
注意这个地方,用白话解释一下就是任意一层上的输出xL所产生的残差可以传递回其前面的任意一层的xl上,这个传递的过程是非常“快”或者说“直接”的,那么它在层数变多的时候也不会出现明显的效率问题。而且还有一个值得注意的地方,后面这项
它可以使得
是一个线性叠加的过程而非连乘,所以它自然也不太可能出现梯度消失现象。这些就是从数学推导层面来解释为什么深度残差网络的深度可以允许那么深,并且还没有出现令人恐惧的梯度消失问题和训练效率问题。
补充说明一下,
中的E和xL在这里泛指某两个不同层之间的关系,指代他们的残差和输出值。大家请注意,在一个多层的网络中,每一层我们都可以认为是一种分类器模型,只不过每一层分类器的具体分类含义人类很难找到确切的并且令人信服的物理解释。然而每一层的各种神经元在客观上确实充当着分类器的功能,它将前面一层输入的向量进行采样并映射为新的向量空间分布。所以从这个角度去解释的话,
可以看成指代任何一个“断章取义”的网络片段也没问题,也就不强调这个损失函数一定是由最后一层传到前面某一层去的了。
除了前面我们提到的这种基于网络各层函数表达式的解释以外,深度残差网络的学习能力强,有好的性能表现还有一种解释,我们把这种解释可视化一下。
短路项相当于像上图这样把所有的一个一个网络短接了过去,而这些短接过去的部分其实形成了新的拓扑结构。
例如刚刚的f1、f2、f3这三个网络通过短接之后其实就演变成了右边这样一个拓扑结构,我们可以清楚地看到,这相当于是多个不同的网络模型做了融合或并联。将前面的向量信息通过多个不同的分类器模型将结构反馈到后面去。而没变化之前只有最下面的一条串联结构,这两种模型的不同正是造成它们学习能力不同的关键。
残差网络中的特殊点就在于刚刚的这个结构就是将这样一个一个的带有ShortCut部分的单元头尾相接连在一起。笔者在Keras这种框架中发现它提供出来两种不同的ShortCut单元以供使用,一种是带有卷积项的,一种是不带有卷积项的。
这里提一句Keras,Keras也是一个非常好的深度学习框架,或者说“壳子”更合适。它提供了更为简洁的接口格式,能够让使用者再非常非常短的代码中实现很多模型描述信息。它的后端支持TensorFlow和Theano两种框架作为后台实现(Backend)。在TensorFlow中描述很复杂的过程,可以在Keras里封装地非常好,所以在实际工作中笔者也经常使用Keras“包裹”着TensorFlow去做工程,代码可读性会好很多。大家有兴趣可以去试一下,本书的后面的附录也提供了Keras的安装文档以供参考。
关于深度残差网络的实现在Github上有很多人都上传过,这里我们也尝试过一些版本,例如:
https://github.com/ry/tensorflow-resnet
https://github.com/raghakot/keras-resnet/blob/master/resnet.py
前者还可以从网上下载一个Pretrained Model,都是模型制作人自己使用一些数据集训练的一些模型状态。我们可以认为它算是具备一定识别能力的“半成品”。
在自己应用的场景中,可以根据需要在将这些“半成品”初始化后继续用一些数据集训练,使其更能适配自己所指派的场景。这种方式在工程中也很多见,毕竟要得到人家这个“半成品”的水平也要自己花费极多的人力成本和时间成本。
何恺明先生自己也公开了一种实现方式,地址在https://github.com/KaimingHe/deep-residual-networks,不过是在Caffe上实现的,有兴趣的读者朋友如果想要研究Caffe框架的可以做个参考。具体的代码我们就不展开细讲了。
应该说,残差网络的发明是对网络连接结构的又一种有益的尝试,而且实际效果还确实不错。曾经有人问过我,如果深度残差网络中不是用一个ShortCut跳过两个卷积层,而是跳过1个或者3个或者其他数量会有什么结果。
这个问题很难回答,但是问题本身并非没有意义。
首先,跳过1个也好3个也罢,每一种不同的链接方式都是一种新的网络拓扑结构,有着不同的分类能力。由于神经网络本身的构造就非常复杂,经过这样的拓扑结构改变后直接讨论两种具备不同拓扑结构网络的学习能力也就比较困难。不过有一点可以确定,那就是网络发生类似“并联”的情况是会提高网络本身学习的容纳能力的。至于在哪个场景,有多大程度的能力提高,需要在实验中不断尝试和对比,从而总结归纳出一些新的理论成果。所以其实理论上确实不能排除跳过1个或者3个层来做短接在其它一些分类领域会有更好的效果,这需要具体的实验和论证过程。现在国际上每年出现的一些新的关于网络结构调整的论文也都是基于一些实验而归纳出来的理论,虽然大部分谈不上什么重大突破,不过科研这种东西总要有一个积量变为质变的过程。
我倒是认为,大家在工作的过程中,一方面多关注国际上最新的一些论文和实验成果,一方面也可以在自己掌握的理论基础上大胆提出一些新的观点并进行论证尝试。这同样是一种值得鼓励的科研态度,也是得到经验的好方法。