卷积神经网络

前言

卷积神经网络(Convolutional Neural Networks,CNN)是一种神经网络模型,是深度学习的代表算法之一。它广泛应用于计算机视觉、语音处理等领域,在图像处理,语音识别方面具有非常强大的性能。针对计算机视觉任务,卷积神经网络能够很好的从大量的数据中做到特征的提取,并且降低网络的复杂度。

概述

卷积神经网络在各个领域得到广泛的应用,但就其本质来说,卷积神经网络只是一个特征提取器,它通过强大的特征学习能力,进行不断的特征提取,通过不断地卷积、池化等操作,过滤掉无用的信息,最终将一幅图像转化为特征图,通过提取出来的特征进行图像分类,边缘检测等任务,卷积神经网络的应用,都建立在特征图之上。

术语解释

在 CNN 中,主要的参数有下面几个:

  • 卷积核(kernel)
  • 步长(stride)
  • 填充(padding)
  • 通道数(channel)

卷积核

卷积核无疑是 CNN 中最重要的一个部分,那么什么是卷积核呢?

或者说,什么是卷积?

(fg)(n)=f(τ)g(nτ)dτ(f \cdot g)(n) = \int_{-\infty}^{\infty}f(\tau)g(n-\tau) \mathrm{d}\tau

首先上来就扔个公式出来,这不是一看就懂?🙈

还是从下面这张图来说起,其实下面这张图就描述了卷积的过程。

首先我们有一个 7×7 大小的矩阵(被卷积图片),以及一个 3×3 大小的矩阵(卷积核)

我们拿着卷积核,从被卷积图片的左上角开始不断进行平移,并且进行对应位置的乘法(图中灰色部分),可以想象每平移一个单位,我们就可以计算出一个值,最后得到所谓的特征图,也就是卷积之后的图像。

整个过程其实也就是特征提取的过程,你可以把卷积核矩阵上面的参数理解为不同大小的权重,分别对应到原始图像上的每一块(区域),对每一块进行评估,最后也就得到特征图。

步长

步长(stride) 同样很好理解,在上面的平移过程中,我们可以移动任意个单位,也就是 stride。

很明显,一旦步长改变,那么最后得到的特征图大小也会随着改变。

填充

填充(padding) 同样也是一个值得关注的方面。你可能已经发现了,在原始图像周围,有一圈 0,这就是填充。

那么问题来了,为什么要在原始图像周围加一圈 0 呢?

让我们来关注一下元素图像中的每个像素被卷积层“关照”了几次

假设周围没有一圈 0 ,位于中心的元素 4 会被扫描到 9 次,四个角落里的元素只会被扫描到 1 次。

你也应该发现了,卷积核从左上角开始对原始图像进行卷积,那么势必会导致边缘、角落里的元素被扫描到的次数少于位于图像中心的元素。

为了“平等对待”,我们在原始图像周围加上一圈 0,这样可以尽可能多的提取边缘信息,至于为什么填充 0,当然是因为 0 对最后计算出来的结果没有影响。

卷积图像大小计算

通过上面的讨论我们不难发现,卷积核大小,步长,填充都会影响输出图像的大小。

更进一步,我们有下面的公式:

{hout=hinhkernel+2paddingstride+1wout=winwkernel+2paddingstride+1\begin{cases} h_{out} =\frac{h_{in} - h_{kernel} + 2 * padding}{stride} + 1 \\ w_{out} =\frac{w_{in} - w_{kernel} + 2 * padding}{stride} + 1 \end{cases}

其中,hin,win,hout,wouth_{in}, w_{in}, h_{out}, w_{out} 分别为输入/输出图像的长宽,hkernel,wkernelh_{kernel}, w_{kernel} 分别为卷积核长宽

通道数

通道数(channel) 非常简单,对于单通道和多通道,你可以理解为灰度图像和彩色 RGB 图像。

值得注意的是,为了处理多个维度的输入图像,就需要对卷积核进行调整,卷积核必须与被卷积图像有相同维度。

卷积神经网络的结构

卷积神经网络通常包含:输入层、卷积层、池化层、全连接层和输出层,如图 1 所示。

图 1 卷积神经网络结构

下面对各层网络进行简单说明:

(1)输入层

作为输入,通常为 RGB 彩色图像,每个像素点的范围为[0,255]。为了方便运算,通常进行归一化操作。

(2)卷积层

卷积层作为卷积神经网络最核心的部分,主要负责卷积操作,进行特征提取的任务。从数学上讲,卷积就是一种运算,其连续形式定义为:

(fg)(n)=f(τ)g(nτ)dτ(f \cdot g)(n) = \int_{-\infty}^{\infty}f(\tau)g(n-\tau) \mathrm{d}\tau

其离散形式定义为:

(fg)(n)=τ=f(τ)g(nτ)(f \cdot g)(n) = \sum_{\tau=-\infty}^{\infty}f(\tau)g(n-\tau)

卷积神经网络属于离散形式的卷积操作,但不同的是卷积神经网络中的卷积,是二维卷积,通过卷积核对原始图像进行卷积操作。对于一幅m×nm\times n大小的图像,给定一个3×33\times3大小的卷积核,二维离散形式的卷积公式:

f=[a0,0a0,1a1,0a1,1a0,na1,nam,0am,1am,n]f=\left[\begin{matrix}\begin{matrix}a_{0,0}&a_{0,1}\\a_{1,0}&a_{1,1}\\\end{matrix}&\cdots&\begin{matrix}a_{0,n}\\a_{1,n}\\\end{matrix}\\\vdots&\ddots&\vdots\\\begin{matrix}a_{m,0}&a_{m,1}\\\end{matrix}&\cdots&a_{m,n}\\\end{matrix}\right]

g=[b0,0b0,1b0,2b1,0b1,1b1,2b2,0b2,1b2,2]g=\left[\begin{matrix}b_{0,0}&b_{0,1}&b_{0,2}\\b_{1,0}&b_{1,1}&b_{1,2}\\b_{2,0}&b_{2,1}&b_{2,2}\\\end{matrix}\right]

(fg)(u,v)=ijf(i,j)g(ui,vj)=ijai,jbui,vj\left(f\cdot g\right)\left(u,v\right)=\sum_{i}\sum_{j}{f\left(i,j\right)g\left(u-i,v-j\right)=}\sum_{i}\sum_{j}{a_{i,j}b_{u-i,v-j}}

图 2 展示了卷积操作的基本方法。将一个 3×33\times3 的卷积核不断在原始图像上平移(步幅为 1,填充为 1),将卷积核与被卷积图像的对应位置相乘并相加,最终可以得到卷积之后的特征图。卷积核在这里作为权重表来使用。

图 2 卷积运算基本方法

彩色图像的每个像素通常是由红(R)、绿(G)、蓝(B)三个分量来表示的,由于每个像素有 R、G、B 三个通道,因此在计算机中,一幅 RGB 图像就是大小为 m×n×3m\times n\times3 的矩阵。为了处理多个维度的输入图像,就需要对卷积核进行调整,卷积核必须与被卷积图像有相同维度。如图 3 所示。另一方面,可以通过设置多个卷积核,从而获得多个特征图,对于同一幅被卷积图片,获得不同角度的特征,从而加强卷积神经网络的特征提取能力。

图 3 多通道多卷积核

(3)池化层

池化层也称为下采样,主要负责数据的降维,常见的有最大池化层与平均池化层。在对图像进行卷积处理之后,虽然通过卷积减少了参数,但仍然面临着庞大的计算量,随着现代传感器的进步,计算机获取的图像尺寸往往非常大,对于这样的大尺寸图像来说,虽然有着丰富的特征,但是不可避免地导致网络训练速度变慢。

图 4 池化操作

池化层在缩小维度的同时,尽可能地保留重要特征,减少运算地数据量。除此之外,池化层也可以在一定程度上降低过拟合的风险,改善网络的性能。图 4 是一个 2×2 的最大池化层,步长为 2。通过在窗口内选取最大值对特征图进行降维,减少数据量。

(4)全连接层

全连接层与常规神经网络相同,通过若干次卷积、池化等操作之后,将最终得到的特征图作为输入进行全连接操作,连接所有的神经元,根据特征图进行分类器的工作。

(5)输出层

最后的输出层输出所需的图像,其具体输出根据不同的任务也会有所不同。

激活函数

激活函数的本质就是一个函数,它的目的是将神经网络非线性化,通过加入激活函数,提高神经网络的非线性能力,解决线性模型所不能解决的问题。下面是两种常用的激活函数:

Sigmoid 函数

f(x)=11+exf(x)=\frac{1}{1+e^{-x}}

Sigmoid 函数可以将元素的值变换到 0 和 1 之间,早期的神经网络主要采用 Sigmoid 函数作为激活函数,但也随之而来引发了一系列问题,如梯度消失问题,当 Sigmoid 函数趋近于 0 和 1 的时候,其导数也趋近于 0,从而无法很好地进行反向传播。

ReLU 函数

ReLU=max(0,x)ReLU=\max{(0,x)}

相较于 Sigmoid 函数,ReLU 函数很好地解决了 Sigmoid 函数引发的梯度消失问题,能够使网络更快地收敛。并且得益于 ReLU 函数简单的表达形式,它的计算效率也很高。因此,现在大多数深度学习模型都放弃了 Sigmoid 函数转而使用 ReLU 函数。

正向传播与反向传播

正向传播

正向传播就是按照从输入层到输出层的顺序,由输入层开始,经过卷积层,池化层等一直到输出层得到结果 zz 的过程。如图 5 所示,正向传播使用输入 xxyy 通过 f(x,y)f(x,y)计算 zz

在模型训练过程中,需要衡量价格预测值与真实值之间的误差,误差越小代表模型的可靠性越强。在深度学习中,将衡量误差的函数称为损失函数。通过将一次正向传播得到的结果zz,与真实值z^\hat{z}作差来计算损失,用于反向传播。

图 5 正向传播和反向传播

反向传播

与正向传播相反,反向传播按照从输出层开始经过隐藏层最后到输入层的顺序,进行反向传播的根本目的是为了减小神经网络的误差,更新参数权值,提高可靠性。在正向传播结束之后,计算当前值与真实值之间的误差,之后通过梯度下降法,以一定的学习率对网络中所有参数权值进行更新。如图 5 所示,反向传播在获得 dL/dzdL/dz 后,通过链式法则计算 dL/dxdL/dxdL/dydL/dy,以此达到修正的目的。

dLdx=dLdzdzdx\frac{dL}{dx}=\frac{dL}{dz}\cdot\frac{dz}{dx}

dLdy=dLdzdzdy\frac{dL}{dy}=\frac{dL}{dz}\cdot\frac{dz}{dy}

就神经网络的整个传播过程概况来说,首先通过输入值进行正向传播获得误差,之后根据获得的误差反向传播更新参数权值,往复循环,对网络进行修正。

卷积神经网络的优点

由于卷积神经网络强大的特征学习能力,使用它可以有效减少开销。对于一个图像任务,如果使用神经网络直接进行特征提取,这时的开销往往是巨大的,特别是对于较大的输入图像来说,可能达到亿万个参数,过拟合的风险难以避免,另外巨大的内存需求也难以接受。同时由于图像中可能包含许多无用的信息,检测效果也可能下降。面对这样的问题,卷积神经网络给出了一个较好的解决方案,通过不断地卷积进行特征提取,在抽取图像特征信息的同时,有效减少了训练参数的数量。具体来说:

参数共享

对于使用全连接的普通神经网络来说,如图 6 所示特征图上的每个像素与输入图像的每个像素全部相关,对于一幅 m×nm\times n 大小的图像,生成一幅 p×qp\times q 大小的特征图,需要 m×n×p×qm\times n\times p\times q 个参数。但对于卷积神经网络来说,由于卷积核的存在,每一次卷积操作只需要卷积核的一组参数即可。参数共享的机制,很好的解决了神经网络参数过多的问题,可以有效避免过拟合。

图 6 神经网络与卷积神经网络

局部感受野

正如前面提到的,普通神经网络使用全连接方式,一个神经元与输入图像上的每个像素都相关,而卷积神经网络中,每个神经元只需要对局部图像进行感知,如图 6 所示。这样做同样可以减少参数个数,加快训练的速度。