轻松玩转--卷积神经网络(CNN)

第12章 TensorFlow卷积神经网络

12.1 卷积神经网络简介

卷积神经网路(Convolutional Neural Network, CNN)是一种前馈神经网络,对于CNN最早可以追溯到1986年BP算法的提出,1989年LeCun将其用到多层神经网络中,直到1998年LeCun提出LeNet-5模型,神经网络的雏形基本形成。在接下来近十年的时间里,卷积神经网络的相关研究处于低谷,原因有两个:一是研究人员意识到多层神经网络在进行BP训练时的计算量极其之大,当时的硬件计算能力完全不可能实现;二是包括SVM在内的浅层机器学习算法也渐渐开始暂露头脚。
2006年,Hinton终于一鸣惊人,在《科学》上发表文章,CNN再度觉醒,并取得长足发展。2012年,ImageNet大赛上CNN夺冠,2014年,谷歌研发出20层的VGG模型。同年,DeepFace、DeepID模型横空出世,直接将LFW数据库上的人脸识别、人脸认证的正确率刷到99.75%,几乎超越人类。
卷积神经网路由一个或多个卷积层和顶端的全连通层(对应经典的神经网路)组成,同时也包括关联权重和池化层(pooling layer)。这一结构使得卷积神经网路能够利用输入数据的二维结构。与其他深度学习结构相比,卷积神经网路在图像和语音识别方面能够给出更好的结果。这一模型也可以使用反向传播算法进行训练。相比较其他深度、前馈神经网路,卷积神经网路需要考量的参数更少,使之成为一种颇具吸引力的深度学习结构。

12.2卷积的定义

卷积现在可能是深度学习中最重要的概念。正是靠着卷积和卷积神经网络,深度学习才超越了几乎其他所有的机器学习方法。要理解卷积神经网络,首先需要了解卷积的含义,卷积的定义有点抽象,我们先给出一个数学上的定义,然后通过一个简单例子及其物理意义来帮助大家理解。
卷积(Convolution)是一种数学运算,它是通过两个函数f和g生成第三个函数的一种运算或数学操作。卷积的数据定义为:
其离散定义为:

通常把函数g称为输入函数,函数f称为滤波器(Filter),或卷积核(kernel),得到的结果h为特征图或特征映射(feature map)。
数学上的定义有点抽象,下面我通过几个示例来帮助大家理解。
1)小李定期存款示例
小李存入100元钱,年利率是4%,按本息计算(即将每一年所获利息加入本金,以计算下一年的利息),那么在五年之后他能拿到的钱数是:

以此类推,如果小李每年都往银行中存入新的100元钱,那么这个收益表格将是这样的:

在上式中,f(t)为小李的存钱函数,而g(t)为存入银行的每一笔钱的本息计算函数。在这里,小李最终得到的钱就是他的存钱函数和本息计算函数的卷积。
如果我们把这个公式推广到连续的情况,也就是说,小李在从0到x的这一段时间内,每时每刻都往银行里存钱,他的存钱函数为
f(t) (0≤t≤x)
而银行也对他存入的每一笔钱按本息公式计算收益:

通过上面这个例子,大家应该能够很清晰地记住卷积公式了。
如果我们将小李的存款函数视为一个信号发生(也就是激励)的过程,而将本息函数
g(x-t)
视为一个系统对信号的响应函数(也就是响应),那么二者的卷积
(f*g)(x)
就可以看做是在x时刻对系统进行观察,得到的观察结果(也就是输出)将是过去产生的所有信号经过系统的处理后得到的结果的叠加或加权平均,这也就是卷积的物理意义了。
参考了:https://www.zhihu.com/question/21686447
2)两个方形脉冲波的卷积示例
下图为两个方形脉冲波的卷积。其中函数"g"首先对τ=0反射,接着平移"t",成为 g(t-τ)。那么重叠部分的面积就相当于"t"处的卷积,其中横坐标代表待变量τ 以及新函数f*g的自变量"t"。
Convolution_of_box_signal_with_itself2
图1 两个方形脉冲的卷积

下图示方形脉冲波和指数衰退的脉冲波的卷积(后者可能出现于RC电路中),同样地重叠部分面积就相当于"t"处的卷积。注意到因为"g"是对称的,所以在这两张图中,反射并不会改变它的形状。

Convolution_of_spiky_function
图2 一个方形与指数衰退的脉冲波的卷积

该图取自:
https://zh.wikipedia.org/wiki/%E5%8D%B7%E7%A7%AF

12.3卷积运算

上节我们通过一些简单示例介绍了卷积的定义,卷积本质上是一个线性运算,因此卷积操作也被称为线性滤波。卷积如何运算?为提供一个直观印象,我们先看一个简单的二维空间卷积运算示例:

这个二维空间的卷积运算对两个输入张量(即输入和卷积核)进行卷积,并把结果输出。
接下来再看一个二维卷积详细运算过程,以便于大家对卷积运算有个更全面的了解。
saddle_point_evaluation_optimizers

图3 卷积运算
该图取自:https://www.zybuluo.com/hanbingtao/note/485480
在以上计算中,输入为一个5x5的矩阵,移动窗口为3x3矩阵,又称为卷积矩阵或卷积核,这个矩阵值为共享参数,移动步长或步幅(stride)为1,当然这个值可以大于1,如2或3等。小窗口移动过程中,其中的值是保持不变的:

图4 卷积核
这就是参数共享的说法,这些参数就决定一个卷积核,每个卷积核能够提取某一部分的特征。一般情况下,只有一个卷积核是不够的,在实际处理中,往往通过多个卷积核来提取多重特征,每一个卷积核与原始输入数据执行卷积操作后得到一个特征映射,如下图:

上图中,最右边,特征映射矩阵中的4,具体计算公式如下:

上图中,最右边特征映射矩阵中的3,具体计算公式如下:

其他以此类推,最后输出结果为:

图5 输出结果
以上介绍了一个输入,通过一个卷积核后,得到一个特征映射。如果输入有多个,卷积核也有多个情况又如何呢?另外,步幅也可以是大于1的整数,如为2,如果原来的输入为5*5的矩阵,卷积核还是3*3的矩阵,那么卷积核小窗口按步幅2从左到右,从上到下移动过程中,可能导致卷积核窗口部分在输入矩阵之外,如下图:

当卷积窗口在3这个位置时,它只覆盖输入矩阵的一列,这个时候该如何处理呢?为防止信息丢失,我们采用边界外面补0(Zero padding)策略。下面的动画显示了包含两个卷积核的卷积层的计算。我们可以看到7*7*3输入,经过两个3*3*3的卷积(步幅为2),得到了3*3*2的输出。另外我们也会看到下图的Zero padding是1,也就是在输入元素的周围补了一圈0。Zero padding对于图像边缘部分的特征提取是很有帮助的,可以防止信息丢失。

图6 多个输入及卷积核的卷积计算

以上就是卷积层的计算方法。这里面体现了局部连接和权值共享:每层神经元只和上一层部分神经元相连(卷积计算规则),且卷积核的权值对于上一层所有神经元都是一样的。对于包含两个3*3*3的卷积核的卷积层来说,其参数数量仅有(3*3*3+1)*2=56个,且参数数量与上一层神经元个数无关。与全连接神经网络相比,其参数数量大大减少了。

这是通常的卷积运算,此外,还有多种卷积运算,如空洞卷积、分离卷积等等,这里我们介绍一下空洞卷积(atrous convolutions),空洞卷积又称为扩张卷积(dilated convolutions),向卷积层引入了一个称为 “扩张率(dilation rate)”的新参数,该参数定义了卷积核处理数据时各值的间距。

卷积核为3、扩张率为2和无边界扩充的二维空洞卷积
一个扩张率为2的3×3卷积核,感受野与5×5的卷积核相同,而且仅需要9个参数。你可以把它想象成一个5×5的卷积核,每隔一行或一列删除一行或一列。
在相同的计算条件下,空洞卷积提供了更大的感受野。空洞卷积经常用在实时图像分割中。当网络层需要较大的感受野,但计算资源有限而无法提高卷积核数量或大小时,可以考虑空洞卷积。

卷积核,从这个名字可以看出它的重要性,它是整个卷积过程的核心。比较简单的卷积核或过滤器有Horizontalfilter、Verticalfilter、Sobel filter等。这些过滤器能够检测图像的水平边缘、垂直边缘、增强图片中心区域权重等。

12.4 卷积网络结构

卷积神经网络到底啥样?为获取一个感性认识,我们先看一下卷积神经网络的示意图。

图7 卷积神经网络
由图7可知,一个卷积神经网络由若干卷积层(Convolution)、池化层(Pooling)、全连接层(fully connected)组成。
从图7我们可以发现卷积神经网络的层结构和全连接神经网络的层结构有很大不同。全连接神经网络每层的神经元是按照一维排列的,也就是排成一条线的样子;而卷积神经网络每层的神经元是按照三维排列的,也就是排成一个长方体的样子,有宽度、高度和深度。
对于图7展示的神经网络,我们看到输入层的宽度和高度对应于输入图像的宽度和高度,而它的深度为1。接着,第一个卷积层对这幅图像进行了卷积操作,得到了三个特征映射。这里的"3"可能是让很多初学者迷惑的地方,实际上,就是这个卷积层包含三个卷积核,也就是三套参数(或共享参数),每个卷积核都可以把原始输入图像卷积得到一个特征映射,三个卷积核就可以得到三个特征映射。至于一个卷积层可以有多少个卷积核,那是可以自由设定的。也就是说,卷积层的卷积核个数也是一个超参数。我们可以把特征映射可以看做是通过卷积变换提取到的图像特征,三个卷积核就对原始图像提取出三组不同的特征,也就是得到了三个特征映射,也称做三个通道(channel)。
继续观察图7,在第一个卷积层之后,Pooling层对三个特征映射做了下采样,得到了三个更小的特征映射。接着,是第二个卷积层,它有5个卷积核。每个卷积核都把前面下采样之后的3个**特征映射卷积在一起,得到一个新的特征映射。这样,5个卷积核就得到了5个特征映射。接着,是第二个Pooling,继续对5个特征映射进行下采样,得到了5个更小的特征映射。
图7所示网络的最后两层是全连接层。第一个全连接层的每个神经元,和上一层5个特征映射中的每个神经元相连,第二个全连接层(也就是输出层)的每个神经元,则和第一个全连接层的每个神经元相连,这样得到了整个网络的输出。
至此,我们对卷积神经网络有了最基本的感性认识。接下来,我们将介绍卷积神经网络中各种层的计算和训练。

12.4.1卷积层

我们知道一般神经网络没有卷积层,深度学习中的卷积层能解决哪些问题?
神经网络在处理图像时数据量太大,例如一个输入1000*1000像素的图片(一百万像素,现在已经不能算大图了),输入层有1000*1000=100万节点。假设第一个隐藏层有100个节点(这个数量并不多),那么仅这一层就有(1000*1000+1)*100=1亿参数,这实在是太多了!神经网络训练本来就慢,这么多数据是不合理的。我们看卷积如何解决这个问题。
主要从三个方面:
局部连接
这个是最容易想到的,每个神经元不再和上一层的所有神经元相连,而只和一小部分神经元相连。这样就减少了很多参数。
权值共享
一组连接可以共享同一个权重,而不是每个连接有一个不同的权重,这样又减少了很多参数。
池化或下采样
可以使用Pooling来减少每层的样本数,进一步减少参数数量,同时还可以提升模型的鲁棒性。
对于图像识别任务来说,卷积神经网络通过尽可能保留重要的参数,去掉大量不重要的参数,来达到更好的学习效果
卷积核对图片进行卷积操作就得到的卷积层的输出,卷积核的大小是人为设定的,比如可以设置成3×3或其他尺寸,卷积核的个数也是人为设定,太多太少都不合适,卷积核的内容是训练的时候学习得来的,学习方法一般也是梯度下降法。
由上节内容可知,卷积操作,其实就是卷积核在输入的二维数据面上每次移动一个步长,进行乘法运算再除以卷积核的元素个数。
我们通常会使用多层卷积层来得到更深层次的特征图。如下:

12.4.2激活函数

为增强各层的表现力,各层的输出往往使用激活函数来生成特征映射或特征图,并以此来加入非线性因素的,因为线性模型的表达力不够。
在具体处理图像的时候,如何处理呢?我们知道在神经网络中,对于图像,我们主要采用了卷积的方式来处理,也就是对每个像素点赋予一个权值,这个操作显然就是线性的。但是样本不一定是线性可分的,为了解决这个问题,我们可以进行线性变化,或者我们引入非线性因素,解决线性模型所不能解决的问题。
在选择激活函数时应该满足注意哪些方面呢?
首先,我们知道神经网络的数学基础是处处可微的,所以选取的激活函数要能保证数据输入与输出也是可微的,运算特征是不断进行循环计算,所以在每代循环过程中,每个神经元的值也是在不断变化的。 这就导致了tanh特征相差明显时的效果会很好,在循环过程中会不断扩大特征效果显示出来,但有时,在特征相差比较复杂或是相差不是特别大时,需要更细微的分类判断的时候,sigmoid效果就好了。
其次,sigmoid 和 tanh作为激活函数的话,一定要注意一定要对 input 进行归一话,否则激活后的值都会进入平坦区,使隐层的输出全部趋同,但是 ReLU 并不需要输入归一化来防止它们达到饱和。
此外,对稀疏矩阵,也就是大多数为0的稀疏矩阵来表示。这个特性矩阵比较适合采用于Relu激活函数,Relu就是取的max(0,x),因为神经网络是不断反复计算,实际上变成了它在尝试不断试探如何用一个大多数为0的矩阵来尝试表达数据特征,结果因为稀疏特性的存在,反而这种方法变得运算得又快效果又好了。所以我们可以看到目前大部分的卷积神经网络中,基本上都是采用了ReLU 函数。
常用的激活函数
激活函数应该具有的性质:
(1)非线性。线性激活层对于深层神经网络没有作用,因为其作用以后仍然是输入的各种线性变换。。
(2)连续可微。梯度下降法的要求。
(3)范围最好不饱和,当有饱和的区间段时,若系统优化进入到该段,梯度近似为0,网络的学习就会停止。
(4)单调性,当激活函数是单调时,单层神经网络的误差函数是凸的,好优化。
(5)在原点处近似线性,这样当权值初始化为接近0的随机值时,网络可以学习的较快,不用可以调节网络的初始值。
目前常用的激活函数都只拥有上述性质的部分,没有一个拥有全部。
下面介绍几种常用的激活函数。

目前已被淘汰 ,其主要缺点:
饱和时梯度值非常小。由于BP算法反向传播的时候后层的梯度是以乘性方式传递到前层,因此当层数比较多的时候,传到前层的梯度就会非常小,网络权值得不到有效的更新,即梯度消失。如果该层的权值初始化使得f(x) 处于饱和状态时,网络基本上权值无法更新。
Tanh函数
Tanh和Sigmoid是有异曲同工之妙的,它的图形如上图右所示,不同的是它把实值得输入压缩到-1~1的范围,因此它基本是0均值的,也就解决了上述Sigmoid缺点中的第二个,所以实际中tanh会比sigmoid更常用。但是它还是存在梯度饱和的问题。Tanh是sigmoid的变形:

 

Alex在2012年提出的一种新的激活函数。该函数的提出很大程度的解决了BP算法在优化深层神经网络时的梯度耗散问题 。
优点:
(1) x>0 时,梯度恒为1,无梯度耗散问题,收敛快;
(2)增大了网络的稀疏性。当x (3)运算量很小;
缺点:
如果后层的某一个梯度特别大,导致W更新以后变得特别大,导致该层的输入<0,输出为0,这时该层就会‘die’,没有更新。当学习率比较大时可能会有40%的神经元都会在训练开始就‘die’,因此需要对学习率进行一个好的设置。
由优缺点可知max(0,x) 函数为一个双刃剑,既可以形成网络的稀疏性,也可能造成有很多永远处于‘die’的神经元,需要tradeoff。

改善了ReLU的死亡特性,但是也同时损失了一部分稀疏性,且增加了一个超参数,目前来说其好处不太明确


根据一定的概率(可配置)将输出设置为0,当引入少量随机性将有助于训练时,这个层有很好的表现,它是防止过拟合的一种策略,Dropout在训练的时候有,但在测试的时候是不能有Dropout的,毕竟只有在训练学习的时候才才担心过拟合。
简单讲,Dropout就是在按梯度下降法求网络参数的时候,每一次迭代都随机删掉一些隐含神经元,注意删掉之后会再次放回,下次迭代继续在所有隐含神经元存在的情况下随机删除。
解决过拟合的方法还有在代价函数添加正则项的方法,L1是添加绝对值,L2是添加二次方差。这两个正则项在数学上是可以证明的,能防止参数w过大。
那Dropout为什么有助于防止过拟合呢?可以简单地这样解释,运用了dropout的训练过程,相当于训练了很多个只有半数隐层单元的神经网络(后面简称为“半数网络”),每一个这样的半数网络,都可以给出一个分类结果,这些结果有的是正确的,有的是错误的。随着训练的进行,大部分半数网络都可以给出正确的分类结果,那么少数的错误分类结果就不会对最终结果造成大的影响。实际上dropout不一定非要在全连接层隐含层,卷积似乎也可以dropout。
如何选择激活函数?
通常来说,很少会把各种激活函数串起来在一个网络中使用的。
如果使用 ReLU,那么一定要小心设置 learning rate,而且要注意不要让你的网络出现很多 “dead” 神经元,如果这个问题不好解决,那么可以试试 Leaky ReLU、PReLU 或者 Maxout.
最好不要用 sigmoid,可以试试 tanh,不过可以预期它的效果会比不上 ReLU 和 Maxout。
实际使用的时候最常用的还是ReLU函数,注意学习率的设置以及死亡节点所占的比例即可。

12.4.3池化层(Pooling)

池化(Pooling)又称为下采样,通过卷积层获得了图像的特征之后,理论上我们可以直接使用这些特征训练分类器(如softmax),但是这样做将面临巨大的计算量的挑战,而且容易产生过拟合的现象。为了进一步降低网络训练参数及模型的过拟合程度,对卷积层进行池化/采样(Pooling)处理。池化/采样的方式通常有以下两种:
最大池化(Max Pooling: 选择Pooling窗口中的最大值作为采样值;
均值池化(Mean Pooling): 将Pooling窗口中的所有值相加取平均,以平均值作为采样值
高斯池化:借鉴高斯模糊的方法。不常用。
图像经过池化后,得到的是一系列的特征图,而多层感知器接受的输入是一个向量。因此需要将这些特征图中的像素依次取出,排列成一个向量。各种池化方法可用如下图来表示:

12.4.4归一化层

对于归一化我们应该不陌生,在线性回归和逻辑回归中经常使用,而且很有效。因为输入层的输入值的大小变化不剧烈,那么输入也不会。但是,对于一个可能有很多层的深度学习模型来说,情况可能会比较复杂。
举个例子,随着第一层和第二层的参数在训练时不断变化,第三层所使用的激活函数的输入值可能由于乘法效应而变得极大或极小,例如和第一层所使用的激活函数的输入值不在一个数量级上。这种在训练时可能出现的情况会造成模型训练的不稳定性。例如,给定一个学习率,某次参数迭代后,目标函数值会剧烈变化或甚至升高。数学的解释是,如果把目标函数 f根据参数 w迭代进行泰勒展开,有关学习率 η 的高阶项的系数可能由于数量级的原因(通常由于层数多)而不容忽略。然而常用的低阶优化算法(如梯度下降)对于不断降低目标函数的有效性通常基于一个基本假设:在以上泰勒展开中把有关学习率的高阶项通通忽略不计。
为了应对上述这种情况,Sergey Ioffe和Christian Szegedy在2015年提出了批量归一化(Batch Normalization, BN)的方法。简而言之,在训练时给定一个批量输入,批量归一化试图对深度学习模型的某一层所使用的激活函数的输入进行归一化:使批量呈标准正态分布(均值为0,标准差为1)。
批量归一化通常应用于输入层或任意中间层

12.4.5全连接层

全连接层(fully connected layers,FC)在整个卷积神经网络中起到“分类器”的作用。如果说卷积层、池化层和激活函数层等操作是将原始数据映射到隐层特征空间的话,全连接层则起到将学到的“分布式特征表示”映射到样本标记空间的作用。在实际使用中,全连接层可由卷积操作实现:对前层是全连接的全连接层可以转化为卷积核为1x1的卷积;而前层是卷积层的全连接层可以转化为卷积核为hxw的全局卷积,h和w分别为前层卷积结果的高和宽。
目前由于全连接层参数冗余(仅全连接层参数就可占整个网络参数80%左右),近期一些性能优异的网络模型如ResNet和GoogLeNet等均用全局平均池化(global average pooling,GAP)取代FC来融合学到的深度特征,最后仍用softmax等损失函数作为网络目标函数来指导学习过程。需要指出的是,用GAP替代FC的网络通常有较好的预测性能。
近期的研究(In Defense of Fully Connected Layers in Visual Representation Transfer)发现,FC可在模型表示能力迁移过程中充当“防火墙”的作用。具体来讲,假设在ImageNet上预训练得到的模型为 ,则ImageNet可视为源域(迁移学习中的source domain)。微调(fine tuning)是深度学习领域最常用的迁移学习技术。针对微调,若目标域(target domain)中的图像与源域中图像差异巨大(如相比ImageNet,目标域图像不是物体为中心的图像,而是风景照,见下图),不含FC的网络微调后的结果要差于含FC的网络。因此FC可视作模型表示能力的“防火墙”,特别是在源域与目标域差异较大的情况下,FC可保持较大的模型capacity从而保证模型表示能力的迁移。

12.4.6几种经典的CNN

这里介绍几种经典的CNN,如LeNet5、AlexNet、VGGNet、Google Inception Net、ResNet等。

12.4.6.1 LeNet5

LeNet5 诞生于 1994 年,是最早的卷积神经网络之一,并且推动了深度学习领域的发展。自从 1988 年开始,在许多次成功的迭代后,这项由 Yann LeCun 完成的开拓性成果被命名为 LeNet5(参见:Gradient-Based Learning Applied to Document Recognition)。

图1

LeNet5 的架构基于这样的观点:(尤其是)图像的特征分布在整张图像上,以及带有可学习参数的卷积是一种用少量参数在多个位置上提取相似特征的有效方式。在那时候,没有 GPU 帮助训练,甚至 CPU 的速度也很慢。因此,能够保存参数以及计算过程是一个关键进展。这和将每个像素用作一个大型多层神经网络的单独输入相反。LeNet5 阐述了那些像素不应该被使用在第一层,因为图像具有很强的空间相关性,而使用图像中独立的像素作为不同的输入特征则利用不到这些相关性。
LeNet5特征能够总结为如下几点:
1)卷积神经网络使用三个层作为一个系列: 卷积,池化,非线性
2) 使用卷积提取空间特征
3)使用映射到空间均值下采样(subsample)
4)双曲线(tanh)或S型(sigmoid)形式的非线性
5)多层神经网络(MLP)作为最后的分类器
6)层与层之间的稀疏连接矩阵避免大的计算成本
总体看来,这个网络是最近大量神经网络架构的起点,并且也给这个领域带来了许多灵感。

12.4.6.2 AlexNet

2012年,Hinton的学生Alex Krizhevsky提出了深度卷积神经网络模型AlexNet,它可以算是LeNet的一种更深更宽的版本。AlexNet中包含了几个比较新的技术点,也首次在CNN中成功应用了ReLU、Dropout和LRN等Trick。同时AlexNet也使用了GPU进行运算加速,作者开源了他们在GPU上训练卷积神经网络的CUDA代码。AlexNet包含了6亿3000万个连接,6000万个参数和65万个神经元,拥有5个卷积层,其中3个卷积层后面连接了最大池化层,最后还有3个全连接层。AlexNet以显著的优势赢得了竞争激烈的ILSVRC 2012比赛,top-5的错误率降低至了16.4%,相比第二名的成绩26.2%错误率有了巨大的提升。AlexNet可以说是神经网络在低谷期后的第一次发声,确立了深度学习(深度卷积网络)在计算机视觉的统治地位,同时也推动了深度学习在语音识别、自然语言处理、强化学习等领域的拓展。
AlexNet将LeNet的思想发扬光大,把CNN的基本原理应用到了很深很宽的网络中。AlexNet主要使用到的新技术点如下。
(1)成功使用ReLU作为CNN的激活函数,并验证其效果在较深的网络超过了Sigmoid,成功解决了Sigmoid在网络较深时的梯度弥散问题。虽然ReLU激活函数在很久之前就被提出了,但是直到AlexNet的出现才将其发扬光大。
(2)训练时使用Dropout随机忽略一部分神经元,以避免模型过拟合。Dropout虽有单独的论文论述,但是AlexNet将其实用化,通过实践证实了它的效果。在AlexNet中主要是最后几个全连接层使用了Dropout。
(3)在CNN中使用重叠的最大池化。此前CNN中普遍使用平均池化,AlexNet全部使用最大池化,避免平均池化的模糊化效果。并且AlexNet中提出让步长比池化核的尺寸小,这样池化层的输出之间会有重叠和覆盖,提升了特征的丰富性。
(4)提出了LRN层,对局部神经元的活动创建竞争机制,使得其中响应比较大的值变得相对更大,并抑制其他反馈较小的神经元,增强了模型的泛化能力。
(5)使用CUDA加速深度卷积网络的训练,利用GPU强大的并行计算能力,处理神经网络训练时大量的矩阵运算。AlexNet使用了两块GTX 580 GPU进行训练,单个GTX 580只有3GB显存,这限制了可训练的网络的最大规模。因此作者将AlexNet分布在两个GPU上,在每个GPU的显存中储存一半的神经元的参数。因为GPU之间通信方便,可以互相访问显存,而不需要通过主机内存,所以同时使用多块GPU也是非常高效的。同时,AlexNet的设计让GPU之间的通信只在网络的某些层进行,控制了通信的性能损耗。
(6)数据增强,随机地从256 x 256的原始图像中截取224 x 224大小的区域(以及水平翻转的镜像),相当于增加了倍的数据量。如果没有数据增强,仅靠原始的数据量,参数众多的CNN会陷入过拟合中,使用了数据增强后可以大大减轻过拟合,提升泛化能力。进行预测时,则是取图片的四个角加中间共5个位置,并进行左右翻转,一共获得10张图片,对他们进行预测并对10次结果求均值。同时,AlexNet论文中提到了会对图像的RGB数据进行PCA处理,并对主成分做一个标准差为0.1的高斯扰动,增加一些噪声,这个Trick可以让错误率再下降1%。
整个AlexNet有8个需要训练参数的层(不包括池化层和LRN层),前5层为卷积层,后3层为全连接层,如图4所示。AlexNet最后一层是有1000类输出的Softmax层用作分类。 LRN层出现在第1个及第2个卷积层后,而最大池化层出现在两个LRN层及最后一个卷积层后。ReLU激活函数则应用在这8层每一层的后面。因为AlexNet训练时使用了两块GPU,因此这个结构图中不少组件都被拆为了两部分。现在我们GPU的显存可以放下全部模型参数,因此只考虑一块GPU的情况即可。

图4
AlexNet每层的超参数如图5所示。其中输入的图片尺寸为224x224,第一个卷积层使用了较大的卷积核尺寸11x11,步长为4,有96个卷积核;紧接着一个LRN层;然后是一个3 x 3的最大池化层,步长为2。这之后的卷积核尺寸都比较小,都是5 x 5或者3 x 3的大小,并且步长都为1,即会扫描全图所有像素;而最大池化层依然保持为3 x 3,并且步长为2。我们可以发现一个比较有意思的现象,在前几个卷积层,虽然计算量很大,但参数量很小,都在1M左右甚至更小,只占AlexNet总参数量的很小一部分。这就是卷积层有用的地方,可以通过较小的参数量提取有效的特征。而如果前几层直接使用全连接层,那么参数量和计算量将成为天文数字。虽然每一个卷积层占整个网络的参数量的1%都不到,但是如果去掉任何一个卷积层,都会使网络的分类性能大幅地下降。

图5

12.4.6.3 VGGNet

VGGNet是牛津大学计算机视觉组(Visual Geometry Group)和Google DeepMind公司的研究员一起研发的的深度卷积神经网络。VGGNet探索了卷积神经网络的深度与其性能之间的关系,通过反复堆叠3x3的小型卷积核和2x2的最大池化层,VGGNet成功地构筑了16~19层深的卷积神经网络。VGGNet相比之前state-of-the-art的网络结构,错误率大幅下降,并取得了ILSVRC 2014比赛分类项目的第2名和定位项目的第1名。同时VGGNet的拓展性很强,迁移到其他图片数据上的泛化性非常好。VGGNet的结构非常简洁,整个网络都使用了同样大小的卷积核尺寸(3x3)和最大池化尺寸(2x2)。到目前为止,VGGNet依然经常被用来提取图像特征。VGGNet训练后的模型参数在其官方网站上开源了,可用来在domain specific的图像分类任务上进行再训练(相当于提供了非常好的初始化权重),因此被用在了很多地方。
VGGNet论文中全部使用了3x3的卷积核和2x2的池化核,通过不断加深网络结构来提升性能。图6所示为VGGNet各级别的网络结构图,图7所示为每一级别的参数量,从11层的网络一直到19层的网络都有详尽的性能测试。虽然从A到E每一级网络逐渐变深,但是网络的参数量并没有增长很多,这是因为参数量主要都消耗在最后3个全连接层。前面的卷积部分虽然很深,但是消耗的参数量不大,不过训练比较耗时的部分依然是卷积,因其计算量比较大。这其中的D、E也就是我们常说的VGGNet-16和VGGNet-19。C很有意思,相比B多了几个1x1的卷积层,1x1卷积的意义主要在于线性变换,而输入通道数和输出通道数不变,没有发生降维。


图6

图7
VGGNet拥有5段卷积,每一段内有2~3个卷积层,同时每段尾部会连接一个最大池化层用来缩小图片尺寸。每段内的卷积核数量一样,越靠后的段的卷积核数量越多:64 – 128 – 256 – 512 – 512。其中经常出现多个完全一样的3x3的卷积层堆叠在一起的情况,这其实是非常有用的设计。如图8所示,两个3x3的卷积层串联相当于1个5x5的卷积层,即一个像素会跟周围5x5的像素产生关联,可以说感受野大小为5x5。而3个3x3的卷积层串联的效果则相当于1个7x7的卷积层。除此之外,3个串联的3x3的卷积层,拥有比1个7x7的卷积层更少的参数量,只有后者的。最重要的是,3个3x3的卷积层拥有比1个7x7的卷积层更多的非线性变换(前者可以使用三次ReLU激活函数,而后者只有一次),使得CNN对特征的学习能力更强。

图8

VGGNet在训练时有一个小技巧,先训练级别A的简单网络,再复用A网络的权重来初始化后面的几个复杂模型,这样训练收敛的速度更快。在预测时,VGG采用Multi-Scale的方法,将图像scale到一个尺寸Q,并将图片输入卷积网络计算。然后在最后一个卷积层使用滑窗的方式进行分类预测,将不同窗口的分类结果平均,再将不同尺寸Q的结果平均得到最后结果,这样可提高图片数据的利用率并提升预测准确率。同时在训练中,VGGNet还使用了Multi-Scale的方法做数据增强,将原始图像缩放到不同尺寸S,然后再随机裁切224x224的图片,这样能增加很多数据量,对于防止模型过拟合有很不错的效果。实践中,作者令S在[256,512]这个区间内取值,使用Multi-Scale获得多个版本的数据,并将多个版本的数据合在一起进行训练。图9所示为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层作用不大。
(2)越深的网络效果越好。
(3)1x1的卷积也是很有效的,但是没有3x3的卷积好,大一些的卷积核可以学习更大的空间特征。

图9

12.4.6.4Google Inception Net

Google Inception Net首次出现在ILSVRC 2014的比赛中(和VGGNet同年),就以较大优势取得了第一名。那届比赛中的Inception Net通常被称为Inception V1,它最大的特点是控制了计算量和参数量的同时,获得了非常好的分类性能——top-5错误率6.67%,只有AlexNet的一半不到。Inception V1有22层深,比AlexNet的8层或者VGGNet的19层还要更深。但其计算量只有15亿次浮点运算,同时只有500万的参数量,仅为AlexNet参数量(6000万)的1/12,却可以达到远胜于AlexNet的准确率,可以说是非常优秀并且非常实用的模型。Inception V1降低参数量的目的有两点,第一,参数越多模型越庞大,需要供模型学习的数据量就越大,而目前高质量的数据非常昂贵;第二,参数越多,耗费的计算资源也会更大。Inception V1参数少但效果好的原因除了模型层数更深、表达能力更强外,还有两点:一是去除了最后的全连接层,用全局平均池化层(即将图片尺寸变为1x1)来取代它。全连接层几乎占据了AlexNet或VGGNet中90%的参数量,而且会引起过拟合,去除全连接层后模型训练更快并且减轻了过拟合。用全局平均池化层取代全连接层的做法借鉴了Network In Network(以下简称NIN)论文。二是Inception V1中精心设计的Inception Module提高了参数的利用效率,其结构如图10所示。这一部分也借鉴了NIN的思想,形象的解释就是Inception Module本身如同大网络中的一个小网络,其结构可以反复堆叠在一起形成大网络。不过Inception V1比NIN更进一步的是增加了分支网络,NIN则主要是级联的卷积层和MLPConv层。一般来说卷积层要提升表达能力,主要依靠增加输出通道数,但副作用是计算量增大和过拟合。每一个输出通道对应一个滤波器,同一个滤波器共享参数,只能提取一类特征,因此一个输出通道只能做一种特征处理。而NIN中的MLPConv则拥有更强大的能力,允许在输出通道之间组合信息,因此效果明显。可以说,MLPConv基本等效于普通卷积层后再连接1x1的卷积和ReLU激活函数。

我们再来看Inception Module的基本结构,其中有4个分支:第一个分支对输入进行1x1的卷积,这其实也是NIN中提出的一个重要结构。1x1的卷积是一个非常优秀的结构,它可以跨通道组织信息,提高网络的表达能力,同时可以对输出通道升维和降维。可以看到Inception Module的4个分支都用到了1x1卷积,来进行低成本(计算量比3x3小很多)的跨通道的特征变换。第二个分支先使用了1x1卷积,然后连接3x3卷积,相当于进行了两次特征变换。第三个分支类似,先是1x1的卷积,然后连接5x5卷积。最后一个分支则是3x3最大池化后直接使用1x1卷积。我们可以发现,有的分支只使用1x1卷积,有的分支使用了其他尺寸的卷积时也会再使用1x1卷积,这是因为1x1卷积的性价比很高,用很小的计算量就能增加一层特征变换和非线性化。Inception Module的4个分支在最后通过一个聚合操作合并(在输出通道数这个维度上聚合)。Inception Module中包含了3种不同尺寸的卷积和1个最大池化,增加了网络对不同尺度的适应性,这一部分和Multi-Scale的思想类似。早期计算机视觉的研究中,受灵长类神经视觉系统的启发,Serre使用不同尺寸的Gabor滤波器处理不同尺寸的图片,Inception V1借鉴了这种思想。Inception V1的论文中指出,Inception Module可以让网络的深度和宽度高效率地扩充,提升准确率且不致于过拟合。

图10
人脑神经元的连接是稀疏的,因此研究者认为大型神经网络的合理的连接方式应该也是稀疏的。稀疏结构是非常适合神经网络的一种结构,尤其是对非常大型、非常深的神经网络,可以减轻过拟合并降低计算量,例如卷积神经网络就是稀疏的连接。Inception Net的主要目标就是找到最优的稀疏结构单元(即Inception Module),论文中提到其稀疏结构基于Hebbian原理,这里简单解释一下Hebbian原理:神经反射活动的持续与重复会导致神经元连接稳定性的持久提升,当两个神经元细胞A和B距离很近,并且A参与了对B重复、持续的兴奋,那么某些代谢变化会导致A将作为能使B兴奋的细胞。总结一下即“一起发射的神经元会连在一起”(Cells that fire together, wire together),学习过程中的刺