卷积神经网络入门篇

 

1 引言

 

卷积神经网络(Convolutional Neural Networks),通常我们将之简称为ConvNets或者CNN,它是一种在图像识别和分类领域十分流行且行之有效的神经网络。目前,CNN网络已经作为一种非常重要且实用的工具成功应用于人脸识别、机器人和自动驾驶中的目标识别、信号灯识别等应用中。因此,学习卷积神经网络是以前十分有必要的事情。

然而,理解CNNs网络并且学会怎么使用CNN网络却不是一件容易的事情。本篇博客正是作为入门篇,对CNN网络如何针对图片进行工作展开介绍。不过,如果你刚开始接触神经网络算法,那我建议你还是先理解一下多层感知机是如何工作的,你可以参考这篇博客

本文写作的初衷是看了一篇关于CNN网络的外文博客,感觉写的真的很不错,但毕竟是外文,感觉思维方式,行文习惯看着别扭,于是就打算翻译出来,在翻译过程中添加了很多自己的理解,如有误解,还请指出。

 

2 关于图像

 

从本质上说,每一张图片都可以表示为像素值构成的矩阵:

 

图1
 

通道是一个常规术语,用于指代图像的特定组成部分。一张标准的图像一般具有三个通道:红色,绿色和蓝色。所以,对于图像,我们可以将它们想象成三个彼此堆叠的2d矩阵(每种颜色一个),每个像素值的范围为0到255。当然,如果是灰度图像,那么就只会有一个通道,也就只有一个2d矩阵,矩阵中每一个值元素值都在0到255之间,0代表黑色,255代表白色。

 

3 LeNet网络——最早的CNN网络

 

3.1 从LeNet开始

 

LeNet是最早提出的一类CNN网络,它的提出极大推进了深度学习的发展。1988年,经过多次迭代更新之后,LeNet的开拓者将他研究的这种神经网络结构命名为LeNet5。在那段时间,LeNet架构主要是被用来做字符识别,例如识别邮编和数字。

 

接下来,我们结合图3来对LeNet网络结构如何进行图像识别进行分析。近几年,有很多在LeNet结构基础上优化改进而来的网络结构被相继提出,这些网络的主要概念源自于LeNet,所以,理解LeNet网络是很有必要的,这将会使我们理解其他网络更加轻松。

 

图2 Lenet 网络图像分类
 

图1所展示的卷积神经网络结构与最初的LeNet网络结构非常相似,它可以将输入的图像划分为四类:狗、猫、船、鸟(最初的LeNet网络主要是用来完成字符识别)。从图2可以明显看出,当输入一张包含船的图像时,网络可以正确得进行分类(判断为船的概率高达94%,其他3类概率就要低得多,概率总和为1)。

 

图1所示的CNN网络主要完成了4种操作:
(1)卷积
(2)非线性变化(relu))
(3)池化(或者说下采样)
(4)分类

 

这四种操作是每一个CNN网络的基础结构,所以,理解这四种操作对于整体理解CNN网络非常有必要。

 

3.2 卷积层

 

卷积层通过输入的方块数据对图像进行“扫描”,能够在保留像素空间关系的同时对输入图像展开学习,从而达到提取特征的目的。在上文中我们讨论过,每一张图像都可以看做是像素值组成的矩阵,我们通常用$w \times h \times c$的方式来描述输入矩阵size,其中$w$和$h$表示图像的长和宽,$c$表示通道数,有时候为了描述方便,当通道数为1时可以省略描述通道数。现在,假设有一张$5 \times 5 \times 1$的输入图像,为方便介绍,我们姑且假设该图像像素值只取0或1,如图3所示。

 

图3 输入图像
 

进行卷积运算时,需要初始化一个$n \times n \times c$的矩阵,这个矩阵称为滤波器或者卷积核(本文以滤波器称呼),如图4所示为一个$3 \times 3 \times 1$的滤波器。在大多数情况下,滤波器的长和宽是相等的,这么设置的原因是为了描述方面,实现起来也更加简单。另外,滤波器的通道数$c$必须与输入图像的通道数对应,卷积过程中,输入层有多少个通道,滤波器就要有多少个通道,但是滤波器的数量是任意的,滤波器的数量决定了卷积后特征图的通道数。滤波器中的各参数值会在网络训练过程中通过反向传播算法自行优化。

 

图4 滤波器
 

图2中$5 \times 5 \times 1$的输入图像与图3所示的$3 \times 3 \times 1$滤波器进行卷积运算过程如下图5动画所示。我们在绿色图像中滑动滤波器,每次滑动1像素的距离,这个距离我们称之为步长(stride),每一次滑动后,都计算滤波器每个元素与对应所覆盖位置像素值的乘积,然后将获得的9个乘积相加求和就是这一次滑动覆盖区域卷积运算的输出,当滤波器滑动到最右侧后,往下滑动一个步长,并回到最左侧继续从左往右滑动依次进行卷积运算,直到绿色图像中所有像素都被覆盖参与了卷积运算,最终,每一步的输出共同组成了右侧粉红色的矩阵。这个粉色矩阵就是完成的卷积操作后提取到的特征,通常,我们称之为特征图。

 

image

图5 卷积运算过程
 

如果图像存在多个通道,例如最常见的的3通道图像(RGB通道),滤波器也必须有3个通道与图像的3个通道对应地进行卷积运算,每个通道都将产生一个矩阵,将三个矩阵相加输出才是最终的特征图。
在整个卷积运算过程中,有必要注意一下卷积操作的两大特征:局部连接和权值共享
局部连接是指每一次卷积操作都只会对图片的一小部分局部区域进行卷积运算,这部分区域的大小称为感受野,感受野与滤波器大小是相对应的。例如用一个$3 \times 3 \times 1$的滤波器对一张$100 \times 100 \times 1$的图片进行卷积,那么感受野就是$3 \times 3$,每次只会对图片中的一个$3 \times 3$的区域进行卷积运算。
权值共享是指整张图片的所有区域都使用同一个滤波器进行卷积运算去生成一个新的特征,例如用一个$3 \times 3 \times 1$的滤波器对一张$100 \times 100 \times 1$的图片进行卷积,在图片内任意一个3*3的区域内都使用既定的9个卷积权值,不会去改变,这就是权值共享。如果要生成不同的特征,则使用不同的滤波器即可。
局部连接和权值共享操作生成新的特征时很好的利用了图片的局部相关性,同时也大大减少了参数量,降低过拟合风险,同时也提高了训练速度——这也是为什么在图像识别、目标识别等应用中卷积神经网络会这么盛行的原因。

 

另外,需要注意的是,对同一张图像,经过使用不同的滤波器进行卷积运算后输出的特征图也是有差别的。例如如图6所示的一张图像经过不同的滤波器进行卷积运算后的输出大相径庭:

 

 

图6 不同滤波器卷积运算
 

下图7动画更加生动地展示了CNN网络是如何工作的:一个滤波器在一张图片上滑动进行卷积操作,结束所有滑动之后将会产生一个特征图;当用另一个滤波器进行滑动后,将会产生一个不一样的特征图,在我理解看来,这相当于用不同的角度对图像进行观察,产生不同视角下的特征图,获得的信息更加丰富(记得小学的时候学过一篇课文叫《画核桃》,说的是全班同学在不同的角度观察讲台上的核桃然后画出来,最终大家针对同一个核桃却画出来不一样的样子,我想CNN网络就是这个思想,从不同的角度观察输入图像,然后综合多个角度观察结果获得更加丰富的特征,所以性能更好),而且卷及操作也保留了原始图像像素在空间上的局部依存关系,在肉眼直观感受上我们可能觉得产生的特征图相比原图像更加模糊,但事实上,这种运算对于计算机来说可能确实十分有意义的。而且,一般来说,卷积层越多,网络提取复杂特征的能力就越强,例如在图像分类任务重,CNN网络可以通过第一次卷积进行边缘检测,然后在边缘检测基础上第二次卷积可以进行简单的形状检测,更进一步的,后续的卷积可以形状检测基础上进行一些更高层次的特征提取,例如人脸识别。

 

image

图7 多核卷积
 

卷积层输出的特征图的大小由卷积深度、步长和padding三个参数决定,这三个参数都需要我们在构建网络之前确定好。

深度(Depth):深度是指在在一个卷积层中滤波器的数量。如图8所示,我们使用了3个不同的过滤器,因此卷积操作后将产生3个不同的特征图。我们可以将3个特征图看做是多个2d矩阵的堆叠,所以在这个卷积网络中,特征图的深度是3。

 

图8 深度为3的卷积
 

步长(Stride):步长是过滤器每一次在图像中滑动时跨过的像素数量,当步长为1时,每一每次只向右滑动一个像素,当一行卷积运算结束时,也只向下滑动一个像素。注意,步长越大,最终产生的特征图就越小。

Padding:当没有进行padding操作时,我们是不能以图像边缘像素为中心进行卷积运算的,为了解决这一问题,如图9所示,我们可以在图像的外围填充0,这相当于扩充了图像的size,这个填充0的操作就叫做padding。padding操作还有一个好处就是允许我们对特征图的大小进行控制。在实际应用中,也可以填充0以外的其它值,只不过应用的不多。

 

图9 padding——最外围填充0
 

在滤波器size设置上,size也就越大,意味着一次卷积运算能够感知到的信息就越多,但参数量越大,模型越复杂。对于这个问题,我们可以用小滤波器做多次卷积运算来替代一次大滤波器的卷积运算。例如两次$3 \times 3$大小的卷积运算对用$3 \times 3$的滤波器产生一个特征图在进行一次卷积运算等价于一次$5 \times 5$的卷积运算但是参数量从25个降低到18个,3次$3 \times 3$的卷积运算等价于一次$7 \times 7$的卷积运算参数量从49个降低到27个。
多卷积运算多次卷积操作是通过连续多层卷积来完成的,而且在卷积层之间可以添加非线性操作层,增强模型的非线性表达能力,所以,通过多次小卷积运算来代替一次大卷积运算的方法是非常推荐的,也是目前的常用操作。

 

3.3 非线性变换

 

必须承认,在现实世界中绝大部分需要使用卷积神经网络去解决的问题都是非线性的,但是,我们在上文中介绍的所有有关的卷积操作无非都是矩阵的相加或相乘运算,都是线性运算,所以为进一步增强卷积网络拟合能力,需要在上文介绍的卷积操作的基础上添加非线性变化。在卷积神经网络中,进行非线性变换大多是通过引入relu函数实现的。relu函数会对卷积后输出的特征图中每一个元素进行非线性变换:对所有大于等于0的元素保持原样输出,对所有小于零的元素转换为0输出。relu函数图像如下图10所示。下图9所示是对上文图6中一特征图使用relu函数进行非线性变换。除了relu函数外,也可以通过tanh或sigmod等函数来进行非线性变换,但是却用得不多,且被证实,relu函数的性能是最好的。图11所示为上图3中输出的特征图使用relu函数进行非线性变换效果。

对于非线性变换操作,通常不会当做单独一层来处理,而是作为层与层(卷积层与卷积层、卷积层与池化层)之间的连接关节,在很多网络结构可视化图片中,并不会直接画出非线性变化,但是我们要明白,层与层都有必要存在非线性变化。

 

图10 relu函数图像