卷积神经网络
前言
卷积神经网络(Convolutional Neural Networks,CNN)是一种神经网络模型,是深度学习的代表算法之一。它广泛应用于计算机视觉、语音处理等领域,在图像处理,语音识别方面具有非常强大的性能。针对计算机视觉任务,卷积神经网络能够很好的从大量的数据中做到特征的提取,并且降低网络的复杂度。
概述
卷积神经网络在各个领域得到广泛的应用,但就其本质来说,卷积神经网络只是一个特征提取器,它通过强大的特征学习能力,进行不断的特征提取,通过不断地卷积、池化等操作,过滤掉无用的信息,最终将一幅图像转化为特征图,通过提取出来的特征进行图像分类,边缘检测等任务,卷积神经网络的应用,都建立在特征图之上。
术语解释
在 CNN 中,主要的参数有下面几个:
- 卷积核(kernel)
- 步长(stride)
- 填充(padding)
- 通道数(channel)
卷积核
卷积核无疑是 CNN 中最重要的一个部分,那么什么是卷积核呢?
或者说,什么是卷积?
( f ⋅ g ) ( n ) = ∫ − ∞ ∞ f ( τ ) g ( n − τ ) d τ (f \cdot g)(n) = \int_{-\infty}^{\infty}f(\tau)g(n-\tau) \mathrm{d}\tau (f⋅g)(n)=∫−∞∞f(τ)g(n−τ)dτ
首先上来就扔个公式出来,这不是一看就懂?🙈
还是从下面这张图来说起,其实下面这张图就描述了卷积的过程。
首先我们有一个 7×7
大小的矩阵(被卷积图片),以及一个 3×3
大小的矩阵(卷积核)
我们拿着卷积核,从被卷积图片的左上角开始不断进行平移,并且进行对应位置的乘法(图中灰色部分),可以想象每平移一个单位,我们就可以计算出一个值,最后得到所谓的特征图,也就是卷积之后的图像。
整个过程其实也就是特征提取的过程,你可以把卷积核矩阵上面的参数理解为不同大小的权重,分别对应到原始图像上的每一块(区域),对每一块进行评估,最后也就得到特征图。
步长
步长(stride) 同样很好理解,在上面的平移过程中,我们可以移动任意个单位,也就是 stride。
很明显,一旦步长改变,那么最后得到的特征图大小也会随着改变。
填充
填充(padding) 同样也是一个值得关注的方面。你可能已经发现了,在原始图像周围,有一圈 0,这就是填充。
那么问题来了,为什么要在原始图像周围加一圈 0 呢?
让我们来关注一下元素图像中的每个像素被卷积层“关照”了几次
假设周围没有一圈 0 ,位于中心的元素 4
会被扫描到 9 次,四个角落里的元素只会被扫描到 1 次。
你也应该发现了,卷积核从左上角开始对原始图像进行卷积,那么势必会导致边缘、角落里的元素被扫描到的次数少于位于图像中心的元素。
为了“平等对待”,我们在原始图像周围加上一圈 0,这样可以尽可能多的提取边缘信息,至于为什么填充 0,当然是因为 0 对最后计算出来的结果没有影响。
卷积图像大小计算
通过上面的讨论我们不难发现,卷积核大小,步长,填充都会影响输出图像的大小。
更进一步,我们有下面的公式:
{ h o u t = h i n − h k e r n e l + 2 ∗ p a d d i n g s t r i d e + 1 w o u t = w i n − w k e r n e l + 2 ∗ p a d d i n g s t r i d e + 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} {hout=stridehin−hkernel+2∗padding+1wout=stridewin−wkernel+2∗padding+1
其中, h i n , w i n , h o u t , w o u t h_{in}, w_{in}, h_{out}, w_{out} hin,win,hout,wout 分别为输入/输出图像的长宽, h k e r n e l , w k e r n e l h_{kernel}, w_{kernel} hkernel,wkernel 分别为卷积核长宽
通道数
通道数(channel) 非常简单,对于单通道和多通道,你可以理解为灰度图像和彩色 RGB 图像。
值得注意的是,为了处理多个维度的输入图像,就需要对卷积核进行调整,卷积核必须与被卷积图像有相同维度。
卷积神经网络的结构
卷积神经网络通常包含:输入层、卷积层、池化层、全连接层和输出层,如图 1 所示。
下面对各层网络进行简单说明:
(1)输入层
作为输入,通常为 RGB 彩色图像,每个像素点的范围为[0,255]。为了方便运算,通常进行归一化操作。
(2)卷积层
卷积层作为卷积神经网络最核心的部分,主要负责卷积操作,进行特征提取的任务。从数学上讲,卷积就是一种运算,其连续形式定义为:
( f ⋅ g ) ( n ) = ∫ − ∞ ∞ f ( τ ) g ( n − τ ) d τ (f \cdot g)(n) = \int_{-\infty}^{\infty}f(\tau)g(n-\tau) \mathrm{d}\tau (f⋅g)(n)=∫−∞∞f(τ)g(n−τ)dτ
其离散形式定义为:
( f ⋅ g ) ( n ) = ∑ τ = − ∞ ∞ f ( τ ) g ( n − τ ) (f \cdot g)(n) = \sum_{\tau=-\infty}^{\infty}f(\tau)g(n-\tau) (f⋅g)(n)=τ=−∞∑∞f(τ)g(n−τ)
卷积神经网络属于离散形式的卷积操作,但不同的是卷积神经网络中的卷积,是二维卷积,通过卷积核对原始图像进行卷积操作。对于一幅 m × n m\times n m×n大小的图像,给定一个 3 × 3 3\times3 3×3大小的卷积核,二维离散形式的卷积公式:
f = [ a 0 , 0 a 0 , 1 a 1 , 0 a 1 , 1 ⋯ a 0 , n a 1 , n ⋮ ⋱ ⋮ a m , 0 a m , 1 ⋯ a m , 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] f=⎣⎢⎢⎢⎡a0,0a1,0a0,1a1,1⋮am,0am,1⋯⋱⋯a0,na1,n⋮am,n⎦⎥⎥⎥⎤
g = [ 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 ] 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] g=⎣⎡b0,0b1,0b2,0b0,1b1,1b2,1b0,2b1,2b2,2⎦⎤
( f ⋅ g ) ( u , v ) = ∑ i ∑ j f ( i , j ) g ( u − i , v − j ) = ∑ i ∑ j a i , j b u − i , v − j \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}} (f⋅g)(u,v)=i∑j∑f(i,j)g(u−i,v−j)=i∑j∑ai,jbu−i,v−j
图 2 展示了卷积操作的基本方法。将一个 3 × 3 3\times3 3×3 的卷积核不断在原始图像上平移(步幅为 1,填充为 1),将卷积核与被卷积图像的对应位置相乘并相加,最终可以得到卷积之后的特征图。卷积核在这里作为权重表来使用。
彩色图像的每个像素通常是由红(R)、绿(G)、蓝(B)三个分量来表示的,由于每个像素有 R、G、B 三个通道,因此在计算机中,一幅 RGB 图像就是大小为 m × n × 3 m\times n\times3 m×n×3 的矩阵。为了处理多个维度的输入图像,就需要对卷积核进行调整,卷积核必须与被卷积图像有相同维度。如图 3 所示。另一方面,可以通过设置多个卷积核,从而获得多个特征图,对于同一幅被卷积图片,获得不同角度的特征,从而加强卷积神经网络的特征提取能力。
(3)池化层
池化层也称为下采样,主要负责数据的降维,常见的有最大池化层与平均池化层。在对图像进行卷积处理之后,虽然通过卷积减少了参数,但仍然面临着庞大的计算量,随着现代传感器的进步,计算机获取的图像尺寸往往非常大,对于这样的大尺寸图像来说,虽然有着丰富的特征,但是不可避免地导致网络训练速度变慢。
池化层在缩小维度的同时,尽可能地保留重要特征,减少运算地数据量。除此之外,池化层也可以在一定程度上降低过拟合的风险,改善网络的性能。图 4 是一个 2×2 的最大池化层,步长为 2。通过在窗口内选取最大值对特征图进行降维,减少数据量。
(4)全连接层
全连接层与常规神经网络相同,通过若干次卷积、池化等操作之后,将最终得到的特征图作为输入进行全连接操作,连接所有的神经元,根据特征图进行分类器的工作。
(5)输出层
最后的输出层输出所需的图像,其具体输出根据不同的任务也会有所不同。
激活函数
激活函数的本质就是一个函数,它的目的是将神经网络非线性化,通过加入激活函数,提高神经网络的非线性能力,解决线性模型所不能解决的问题。下面是两种常用的激活函数:
Sigmoid 函数
f ( x ) = 1 1 + e − x f(x)=\frac{1}{1+e^{-x}} f(x)=1+e−x1
Sigmoid 函数可以将元素的值变换到 0 和 1 之间,早期的神经网络主要采用 Sigmoid 函数作为激活函数,但也随之而来引发了一系列问题,如梯度消失问题,当 Sigmoid 函数趋近于 0 和 1 的时候,其导数也趋近于 0,从而无法很好地进行反向传播。
ReLU 函数
R e L U = max ( 0 , x ) ReLU=\max{(0,x)} ReLU=max(0,x)
相较于 Sigmoid 函数,ReLU 函数很好地解决了 Sigmoid 函数引发的梯度消失问题,能够使网络更快地收敛。并且得益于 ReLU 函数简单的表达形式,它的计算效率也很高。因此,现在大多数深度学习模型都放弃了 Sigmoid 函数转而使用 ReLU 函数。
正向传播与反向传播
正向传播
正向传播就是按照从输入层到输出层的顺序,由输入层开始,经过卷积层,池化层等一直到输出层得到结果 z z z 的过程。如图 5 所示,正向传播使用输入 x x x 和 y y y 通过 f ( x , y ) f(x,y) f(x,y)计算 z z z
在模型训练过程中,需要衡量价格预测值与真实值之间的误差,误差越小代表模型的可靠性越强。在深度学习中,将衡量误差的函数称为损失函数。通过将一次正向传播得到的结果 z z z,与真实值 z ^ \hat{z} z^作差来计算损失,用于反向传播。
反向传播
与正向传播相反,反向传播按照从输出层开始经过隐藏层最后到输入层的顺序,进行反向传播的根本目的是为了减小神经网络的误差,更新参数权值,提高可靠性。在正向传播结束之后,计算当前值与真实值之间的误差,之后通过梯度下降法,以一定的学习率对网络中所有参数权值进行更新。如图 5 所示,反向传播在获得 d L / d z dL/dz dL/dz 后,通过链式法则计算 d L / d x dL/dx dL/dx 和 d L / d y dL/dy dL/dy,以此达到修正的目的。
d L d x = d L d z ⋅ d z d x \frac{dL}{dx}=\frac{dL}{dz}\cdot\frac{dz}{dx} dxdL=dzdL⋅dxdz
d L d y = d L d z ⋅ d z d y \frac{dL}{dy}=\frac{dL}{dz}\cdot\frac{dz}{dy} dydL=dzdL⋅dydz
就神经网络的整个传播过程概况来说,首先通过输入值进行正向传播获得误差,之后根据获得的误差反向传播更新参数权值,往复循环,对网络进行修正。
卷积神经网络的优点
由于卷积神经网络强大的特征学习能力,使用它可以有效减少开销。对于一个图像任务,如果使用神经网络直接进行特征提取,这时的开销往往是巨大的,特别是对于较大的输入图像来说,可能达到亿万个参数,过拟合的风险难以避免,另外巨大的内存需求也难以接受。同时由于图像中可能包含许多无用的信息,检测效果也可能下降。面对这样的问题,卷积神经网络给出了一个较好的解决方案,通过不断地卷积进行特征提取,在抽取图像特征信息的同时,有效减少了训练参数的数量。具体来说:
参数共享
对于使用全连接的普通神经网络来说,如图 6 所示特征图上的每个像素与输入图像的每个像素全部相关,对于一幅 m × n m\times n m×n 大小的图像,生成一幅 p × q p\times q p×q 大小的特征图,需要 m × n × p × q m\times n\times p\times q m×n×p×q 个参数。但对于卷积神经网络来说,由于卷积核的存在,每一次卷积操作只需要卷积核的一组参数即可。参数共享的机制,很好的解决了神经网络参数过多的问题,可以有效避免过拟合。
局部感受野
正如前面提到的,普通神经网络使用全连接方式,一个神经元与输入图像上的每个像素都相关,而卷积神经网络中,每个神经元只需要对局部图像进行感知,如图 6 所示。这样做同样可以减少参数个数,加快训练的速度。