4.2 CNN基础知识与PyTorch实战部分
卷积神经网络的模型架构在近年来经过了研究人员广泛的研究,发展出了适合各种任务的模型架构,涌现出一些系统性的设计思想,本章对卷积神经网络的经典模型和背后的设计思想进行详细的介绍。
4.2.1 什么是卷积神经网络
1.什么是卷积?
卷积在工程和数学上有非常多的应用,在信号处理领域中,任意一个线性系统的输出,就是输入信号和系统激励函数的卷积。放到数字图像处理领域,卷积操作一般指图像领域的二维卷积,如图4-3所示。
图4-3 卷积操作
一个二维卷积的案例如上,在图像上滑动,取与卷积核大小相等的区域,逐像素做乘法然后相加。例如原始图像大小是5×5,卷积核大小是3×3。首先卷积核与原始图像左上角3×3对应位置的元素相乘求和,得到的数值作为结果矩阵第一行第一列的元素值,然后卷积核向右移动一个单位(即步长stride为1),与原始图像前三行第2、3、4列所对应位置的元素分别相乘并求和,得到的数值作为结果矩阵第一行第二列的元素值,以此类推。
故卷积就是:一个核矩阵在一个原始矩阵上从上往下、从左往右扫描,每次扫描都得到一个结果,将所有结果组合到一起得到一个新的结果矩阵。
注意,这里不区分卷积和互相关,它们的区别只在于权重算子是否进行了翻转。之所以不重视,是因为在机器学习中,卷积核是否翻转,并不影响算法学习。
在卷积神经网络中,有几个重要的基本概念是需要注意的,这在网络结构的设计中至关重要。
2.感受野
直观上讲,感受野就是视觉感受区域的大小。在卷积神经网络中,感受野是CNN中的某一层输出结果的一个元素对应输入层的一个映射,即feature map上的一个点所对应的输入图上的区域,具体示例如图4-4所示。
图4-4 感受野
如果一个神经元的大小是受到上层N×N的神经元的区域的影响,那么就可以说,该神经元的感受野是N×N,因为它反映了N×N区域的信息。在图4-4conv2中的像素点5,是由conv1的2×2的区域计算得来,而该2×2区域,又是由raw image中5×5的区域计算而来,所以,该像素的感受野是5×5。可以看出感受野越大,得到的全局信息越多。在物体分割和目标检测中,这是非常重要的一个参数。
3.池化
了解感受野后再来解释池化(pooling)也很简单,图4-4的raw image到conv1,再到conv2,图像越来越小。每过一级就相当于一次降采样,这就是池化。池化可以通过步长不为1的卷积实现,也可以通过pool直接插值采样实现,本质上没有区别,只是权重不同。
通过卷积获得了特征之后,下一步则是用这些特征去做分类。理论上讲,人们可以把所有解析出来的特征关联到一个分类器,例如softmax分类器,但计算量非常大,并且极易出现过度拟合(over-fitting)。而池化层则可以对输入的特征图进行压缩,一方面使特征图变小,简化网络计算复杂度;另一方面进行特征压缩,提取主要特征。
一般而言池化操作的池化窗口都是不重叠的,所以池化窗口的大小等于步长stride。如图4-5所示,采用一个大小为2×2的池化窗口,max pooling是在每一个区域中寻找最大值,这里的stride=2,最终在原特征图中提取主要特征得到右图。具体操作可如图4-5所示。
4.2.2 卷积神经网络的优点是什么
前面介绍了全连接神经网络的原理和结构上的缺陷,而这正好是卷积的优势。
图4-5 池化操作
首先是学习原理上的改进,卷积神经网络不再是有监督学习了,不需要从图像中提取特征,而是直接从原始图像数据进行学习,这样可以最大程度防止信息在还没有进入网络之前就丢失。
另一方面是学习方式的改进。前面说了全连接神经网络一层的结果是与上一层的结点全部连接的,如100×100像素的图像,如果隐藏层也是同样大小(100×100个)的神经元,光是一层网络,就已经有108个参数。要优化和存储这样的参数量,是无法想象的,所以经典的神经网络,基本上隐藏层在一两层左右。而卷积神经网络某一层的结点,只与上一层的一个图像块相连。而用于产生同一个图像中各个空间位置像素的卷积核是同一个,这就是所谓的权值共享。对于与全连接层同样多的隐藏层,假如每个神经元只和输入10×10的局部patch相连接,且卷积核移动步长为10,则参数为:100×100×10×10,降低了两个数量级。
局部感知就是上一小节说的感受野,实际上就是卷积核和图像卷积的时候,每次卷积核所覆盖的像素只是一小部分,是局部特征,所以说是局部感知。CNN是一个从局部到整体的过程,而传统的神经网络是整体的过程。
概括下来CNN主要有3个特点:局部感受野、权值共享和时间或空间子采样。
4.2.3 什么是LeNet5网络
从1989年开始,Yann LeCun和Y. Bengio等人开始认真研究卷积神经网络。在后来10年的时间里,LeNet系列网络开始迭代,直到最后1998年的LeNet5问世。
下面就先说一下LeNet1,其实LeNet1之前还有一个网络,使用的输入大小为16×16,有9298个样本,网络结构共包含3个隐藏层,分别是H1、H2、H3。
LeNet1的结构如图4-6所示,与LeNet5非常的像,差别就是输入图像大小、网络宽度和深度的不同,这其实反映了当时束缚神经网络发展的一个关键,硬件计算能力,因为反向传播理论早已成熟。
图4-6 LeNet1结构
在1998年,LeNet网络系列迭代到了LeNet5。
LeNet系列最终稳定的版本就是LeNet5,这是一个7层的卷积网络,后来被用于美国银行的手写数字识别。
LeNet5有3个卷积层,2个池化层,2个全连接层。卷积层的卷积核都为5×5,步长stride=1,池化方法都为Max pooling,激活函数为Sigmoid,具体网络结构如图4-7所示。
图4-7 LeNet5结构
下面详细解读网络结构,先约定一些称呼。featuremap就是特征图,stride即卷积核的步长,C1的特征图大小为28×28×6,卷积参数大小为(5×5×1)×6。其中28×28是特征图的高度×宽度,6是特征图的通道数。(5×5×1)×6表示卷积核尺寸为5×5×1,依次是高度×宽度×通道数,共6个卷积核。可以把(5×5×1)想象成一个厚度为1,高度、宽度各为5的卷积块,以下依此类推。
首先是输入层,输入图像统一归一化为32×32。
然后是第一个卷积层C1,经过(5×5×1)×6卷积核,stride=1,生成特征图为28×28×6。输入的图像是一个单通道的图像,所以这里特征图的数量,就等于卷积核的数量,每一个输入通道都与一个输入通道相连。C1层包含了156个可训练的参数,122304个连接。
接着是S2池化层,这是一个(2×2)的采样核,stride=2,生成特征图为14×14×6。注意这里的池化层虽然没有卷积核,但是也有训练参数,即偏移量。所以包括了12个训练参数,5880个连接。
然后是C3卷积层,经过(5×5×6)×16卷积核,stride=1,生成特征图为10×10×16。输入是6个通道,输出是16个通道,这里经过了一个编码,编码表见表4-2。
表4-2:编码表
C3的前6个feature map与S2层相邻的3个feature map相连接,后面6个feature map与S2层相邻的4个feature map相连接,后面3个feature map与S2层部分不相邻的4个feature map相连接,最后一个与S2层的所有feature map相连。
这其实是一个非常主观的设定,输出的16个通道并没有跟输入的每一个通道相连。它的设计初衷有两个:第一个是减小了计算量;第二个为了打破对称性。实际上在往后的网络设计中,很少会遵循这样的设计准则。C3层共包含了1516个可训练参数,151600个连接。
紧接着是S4池化层,经过(2×2)采样核,stride=2,生成特征图为5×5×16。S4层有32个可训练参数,2000个连接。
然后就是C5卷积层,经过(5×5×16)×120卷积核,stride=1,生成特征图为1×1×120,这就是一个全连接层了,所以输出的每一个通道都会跟输入的所有通道相连。C5层有48120个可训练的连接。
然后是F6全连接层,依然是一个全连接层,输入为1×1×120,输出为1×1×84,总参数量为120×84。F6层有10164个可训练的连接,84这个数字有当时的设计背景。7表示6种笔触类型加1,这6种笔触分别是vertical line、horizontal line、diagonal line、closed curve、curve open to left、curve open to right。12是10种数字加正负两种数值方向。
最后是输出全连接层,输入为1×1×84,输出为1×1×10,总参数量为84×10,10就是分类的类别数。
注意,这里虽然是分类任务,但是并没有采用现在广泛使用的softmax loss,即交叉熵,而是一个欧式距离,在原文中被描述为gaussian connect,其实就等价于一个全连接层加上一个欧式损失层。
LeNet5网络是早期非常经典的卷积神经网络,也是成功商业的代表,虽然它的网络深度只有7层,再加上数据的不足,但在早期并没有在手写数字识别之外的其他计算机视觉任务上仍取得重大的突破。
LeNet5代码展示如下:
4.2.4 为什么卷积核一般都是3×3而不是更大
主要有两点原因:第一,相对于用较大的卷积核,使用多个较小的卷积核可以获得相同的感受野和能获得更多的特征信息,同时使用小的卷积核参数更少,计算量更小;第二,用户可以使用更多的激活函数,有更多的非线性,使得在用户的CNN模型中的判决函数有更有判决性。
4.2.5 为什么不使用全连接神经网络,而是使用卷积神经网络
最重要的原因是结构上的缺陷:参数很多,丢失空间信息。全连接神经网络从BP算法提出开始,发展于20世纪90年代,那时候的计算机属于CPU时代,根本就无法撑起海量参数的计算。如果一个隐藏层特征图像大小为100×100,输入层的特征图像大小为100×100,这意味着学习这一层需要100×100×100×100=10^8的参数。如果以32位的浮点数进行存储,就需要4×108的字节的存储量,约等于400MB的参数量。仅仅这样的一个网络层,其模型参数量已经超过了AlexNet网络的参数量,而100×100的特征图像分辨率,已经低于很多任务能够成功解决的下限。除了计算过程中需要存储的海量的参数,还有海量的计算,这些都超过了当时硬件的计算能力,因此大大限制了网络的大小,尤其是对于一些大的图像输入。
4.2.6 什么是AlexNet
ImageNet竞赛是由斯坦福大学计算机科学家李飞飞组织的年度机器学习竞赛。在每年的比赛中,参赛者都会得到超过一百万张图像的训练数据集,每张图像都被手工标记一个标签。参赛者的软件根据其对未被包含在训练集的其他图像进行分类的能力进行评判。如果前五次猜测中有一次与人类选择的标签相匹配,则被认为识别成功。
这项竞赛始于2010年,前两年的结果相当平庸。2010年获胜的团队的top-5错误率高达28%。2011年,这个错误率为25%。2012年来自多伦多大学的一个团队提交了参赛作品:AlexNet击败了所有竞争者。由于该团队使用深度神经网络,该团队得到了16%的top-5错误率。
训练这种规模的网络需要大量的计算能力,而AlexNet被设计利用现代GPU提供的大量并行计算能力。研究人员想出了如何在两个GPU之间分配网络训练的工作,从而给了它们两倍的计算能力。不过,尽管进行了积极的优化,在2012年可用的硬件条件下(两个Nvidia GTX 580GPU,每个3GB内存),网络训练进行了5~6天。
Alex Krizhevsky正式提出了AlexNet网络,取得了2012年ImageNet分类任务的冠军,并取得了比第二名低10%的误差,奠定了深度学习在图像识别领域的优势地位。
AlexNet网络包含了8个网络层,其中5个卷积层,3个全连接层。由于当时硬件水平的限制,采用了两个GPU分别进行训练。
它的网络结构示意图如图4-8所示。
图4-8 AlexNet网络结构配置示意图
AlexNet网络的输入图像为224×224×3,这远远大于MNIST和CIFAR数据集中样本的大小。一般来说,越大的输入意味着信息的完整性越高。
AlexNet网络的具体结构配置如下。
第一个卷积层是conv1,使用了11×11大小的卷积核,输出96个通道,stride=4,输出特征图边长大小等于(224-11)/4+2=55,输出为55×55×96。
第一个池化层pool1,经过3×3的最大池化核,stride=2,输出特征图边长大小等于(55-3)/2+1=27,输出为27×27×96。
第一个LRN层norm1,local_size=5,输出为27×27×96。
第二个卷积层conv2,使用5×5的卷积核,输出256个通道,pad=2,group=2,stride=1,输出特征图边长大小为(27+2×2-5)/1+1=27,输出为27×27×256。
第二个池化层pool2,经过3×3的最大池化核,stride=2,输出特征图边长大小为(27-3)/2+1=13,输出为13×13×256。
第二个归一化层norm2,local_size=5, 输出为13×13×256。
第三个卷积层conv3,使用3×3的卷积核,输出384个通道,pad=1,stride=1,输出特征图边长大小等于(13+1×2-3)/1+1=13,输出为13×13×384。
第四个卷积层conv4,使用3×3的卷积核,输出384个通道,pad=1,stride=1,输出特征图边长大小等于(13+1×2-3)/1+1=13,输出为13×13×384。
第五个卷积层conv5,使用3×3的卷积核,输出256个通道,pad=1,stride=1,输出特征图边长大小等于(13+1×2-3)/1+1=13,输出为13×13×256。
第三个池化层pool5,经过(3×3)的最大池化核,stride=2,输出特征图边长大小等于(13-3)/2+1=6,输出为6×6×256。
第一个全连接层fc6,包含(6×6×256)×4096个全连接,输出为1×1×4096。
第一个dropout层为dropout6,在训练的时候以1/2概率使得隐藏层的某些神经元的输出为0,这样就丢掉了一半结点的输出,BP的时候也不更新这些结点,以下droupout同理。
第二个全连接层fc7,输入为1×1×4096,输出为1×1×4096,总参数量为4096×4096。
第二个dropout层为dropout7,输出为1×1×4096。
第三个全连接层fc8,输入为1×1×4096,输出为1000,总参数量为4096×1000。
总结AlexNet网络的结构如下:
1)网络比LeNet5更深,包括5个卷积层和3个全连接层,最终AlexNet总体的数据参数大概为240MB。
2)使用ReLU激活函数,收敛很快,解决了Sigmoid在网络较深时出现的梯度弥散问题。
3)加入了dropout层,防止过拟合。在训练的时候,dropout会随机丢弃神经元的输出,即设定对应的权重参数都为0。在测试的时候,则会将所有神经元的输出,乘以0.5来进行近似。
4)使用了LRN归一化层,对局部神经元的活动创建竞争机制,抑制反馈较小的神经元放大反应大的神经元,增强了模型的泛化能力。
5)使用了新型的数据增强方式,使用裁剪、翻转等操作做让数据增强,增强了模型的泛化能力。预测时使用提取图片4个角加中间5个位置并进行左右翻转一共十幅图片的方法求取平均值,这也是后面刷比赛的基本使用技巧。
6)分块训练,当年的GPU是GTX 580,显存只有3GB,限制了网络的规模,AlexNet创新地将图像分为上下两块分别训练,然后在全连接层合并在一起。
这里的并行除了将模型的神经元进行了并行,还使得通信被限制在了某些网络层。比如第三层卷积要使用第二层所有的特征图,但是第四层却只需要同一块GPU中的第三层的特征图,如何去进行这样的选择方案的设定,需要进行多次实验的交叉验证。与只使用一个GPU,也就是通道减半的网络相比,性能提升了不少。不过,如今这样的方案已经不需要了,因为GPU的显存越来越大,而神经网络的参数量和结构也得到了更好的优化,可以说,AlexNet网络的成功是大数据,网络深度增加以及使用了若干新的训练技巧的共同结果。
AlexNet代码展示:
4.2.7 什么是VGG16
VGG16是牛津大学VGG组提出的。VGG16相比AlexNet的一个改进是采用连续的几个3×3的卷积核代替AlexNet中的较大卷积核(11×11,5×5)。对于给定的感受野(与输出有关的输入图片的局部大小),采用堆积的小卷积核是优于采用大的卷积核,因为多层非线性层可以增加网络深度来保证学习更复杂的模式,而且代价还比较小(参数更少)。
AlexNet是一个8层的神经网络,在2012年以前8层是一个很深的网络,但是现在看来是一个很浅的网络,在两年后VGGNet直接将网络的深度提升了一倍,性能也大幅度提升。
AlexNet使用了11×11的卷积核和大小等于4的步长,Zeiler和Fergus在zfnet中对其进行了改进,卷积大小变为了7×7,获得了更好的性能。
研究表明使用更小的卷积是有利的,在这样的背景下2014年牛津大学视觉组提出了VGGNet,分别在ImageNet的定位和分类任务中取得第一名和第二名。
VGG网络结构中全部卷积核大小为3×3,通过对逐渐加深的网络进行评估,结果表明加深网络深度至16~19层可以极大地改进前人的网络结构。
VGG使用了更小的卷积核和更小的stride,不仅可以增加网络的非线性表达能力,还可以减小计算量。
下面以VGG16的网络结构为例进行详细介绍,它共有13个卷积层,3个全连接层,全部采用3×3大小的卷积核,步长为1,和2×2大小的最大池化核,步长为2。
首先是输入层,输入图片为224×224×3,在这一层进行了减均值预处理,减去均值可以一定程度上加速网络的训练,对于16层的标准VGG16,接下来的网络配置依次为:
CONV3-64,经过(3×3×3)×64次卷积,生成featuremap为224×224×64。
CONV3-64,经过(3×3×64)×64次卷积,生成featuremap为224×224×64。
Max pool,经过(2×2)的max pool,生成featuremap为112×112×64。
CONV3-128,经过(3×3×64)×128次卷积,生成featuremap为112×112×128。
CONV3-128,经过(3×3×128)×128次卷积,生成featuremap为112×112×128。
Max pool,经过(2×2)的maxpool,生成featuremap为56×56×128。
CONV3-256,经过(3×3×128)×256次卷积,生成featuremap为56×56×256。
CONV3-256,经过(3×3×256)×256次卷积,生成featuremap为56×56×256。
CONV3-256,经过(3×3×256)×256次卷积,生成featuremap为56×56×256。
Max pool,经过(2×2)的maxpool,生成featuremap为28×28×256
CONV3-512,经过(3×3×256)×512次卷积,生成featuremap为28×28×512
CONV3-512,经过(3×3×512)×512次卷积,生成featuremap为28×28×512。
CONV3-512,经过(3×3×512)×512次卷积,生成featuremap为28×28×512。
Max pool,经过(2×2)的maxpool,生成featuremap为14×14×512。
CONV3-512,经过(3×3×512)×512次卷积,生成featuremap为14×14×512。
CONV3-512,经过(3×3×512)×512次卷积,生成featuremap为14×14×512。
CONV3-512,经过(3×3×512)×512次卷积,生成featuremap为14×14×512。
Max pool,经过(2×2)的maxpool,生成featuremap为7×7×512。
FC-4096,输入为7×7×512,输出为1×1×4096,总参数量为7×7×512×4096。
FC-4096,输入为1×1×4096,输出为1×1×4096,总参数量为4096×4096。
FC-1000,输入为1×1×4096,输出为1000,总参数量为4096×1000。整个的VGG网络共包含参数约为550M,全部使用3×3的卷积核和2×2的最大池化核,简化了卷积神经网络的结构。
与AlexNet网络结构相比,VGG有几点重大的不同。
(1)卷积核
VGG网络相比于AlexNet网络,只使用了3×3的卷积,网络的结构更加简单。相比于AlexNet第一个卷积层输出96维,卷积大小为11×11,VGG第一个卷积层的参数量和计算量都要小很多。AlexNet参数量为96×3×11×11,VGG参数量为64×3×3×3,64×3×3×3/(96×3×11×11)=0.05,即VGG第一层卷积的参数量只有AlexNet的1/20不到,计算量也差不多。这样一来,虽然网络的深度增加了很多,但是模型参数却不比有较大的卷积感受野和较多特征图的浅层网络多。
(2)池化
在VGG网络中,池化的核大小为2×2,步长为2,而AlexNet中采用的是重叠池化方案,核大小为3×3,步长为2。至于是重叠池化好还是不重叠池化好,在AlexNet中观测到,有重叠的池化相比不重叠池化能够降低过拟合问题,不过不重叠池化计算量低一些。
(3)数据增强
在VGG中使用了比AlexNet更复杂的多尺度增强方案,即Scale Jittering。先固定一种裁剪的尺寸为m×m,比如通常为224×224,然后把图片短边缩放到一个大于m的值,比如[256,288],最后再裁剪出m×m。相对于先把图片缩放到固定的大小,这个能操作的空间更大,不过也可能裁剪掉了重要的区域。
下面这段代码即展示了VGG16网络的实现过程,代码中共有13个卷积层,3个全连接层,全部采用3×3大小的卷积核2×2大小的最大池化核。