笔记参考和图片来源@hanbingtao:零基础入门深度学习(4) - 卷积神经网络

ReLU函数

卷积神经网络往往不选择Sigmoid\text{Sigmoid}tanh\tanh函数作为激活函数,而是选择**ReLU\text{ReLU}**函数:

f(x)=max(0,x)f(x)=\max(0,x)

ReLU函数的优势:

  • 速度快 和Sigmoid函数需要计算指数和导数相比,ReLU函数计算代价小很多

  • 减轻梯度消失问题

    对于梯度公式=σδx\nabla=\sigma'\delta x,其中σ\sigma'是Sigmoid函数的导数。每经过一层神经元,梯度就要乘一个σ\sigma',而σ\sigma'的最大值是14\frac14。因此梯度会越来越小。而ReLU函数的导数是1,不会导致梯度变小。使用ReLU函数可以训练更深的网络

  • 稀疏性

全连接网络和卷积网络

全连接网络参数数量太多,也并没有利用像素之间的位置信息,还容易受到网络层数限制,所以不太适合图像识别任务。卷积神经网络主要通过以下三个方面解决这些问题:

  • 局部连接 每个神经元不再和上一层的所有神经元相连,而是只和一小部分神经元相连,这样减少了很多参数
  • 权值共享 一组连接可以共享同一个权重,这样又减少很多参数
  • 下采样 通过Pooling来减少每层的样本数,进一步减少参数数量,同时提升模型的鲁棒性

卷积神经网络尽可能保留重要参数,去掉大量不重要参数,达到更好的学习效果。

卷积神经网络

下面是一个卷积神经网络示意图:

卷积神经网络的结构

一个卷积神经网络由若干卷积层、Pooling层(池化层)、全连接层组成。通常的架构模式:INPUT -> [[CONV]*N (-> POOL)]*M -> [FC]*K

即一个输入层,N个卷积层叠加,可选加一个池化层,重复这个结构M次,最后叠加K个全连接层。上图可按此表示为INPUT -> [[CONV]*1 -> POOL]*2 -> [FC]*2, 即N=1, M=2, K=2.

三维的层结构

全连接神经网络每层的神经元是按照一维排列的,即一条线;而卷积神经网络每层的神经元是三维排列的,即一个长方体的样子,有宽度、高度和深度。

上图所示的流程如下:

  1. 输入层的宽度和高度对应输入图像的宽度和高度,深度为1.
  2. 首先,第一个卷积层对输入层进行了卷积操作,得到三个Feature Map. 这个卷积层包括三个Filter, 也就是三套参数,每个Filter都可以将原始输入图像卷积得到一个Feature Map. 卷积层的Filter个数也是一个超参数。三个Filter对原始图像提取出三组不同的特征,即得到三个Feature Map, 也叫做三个通道(channel)
  3. 第一个卷积层之后的Pooling层对三个Feature Map做了下采样,得到三个更小的Feature Map.
  4. 接着,第二个卷积层有五个Filter, 每个Filter都把前面下采样之后的三个Feature Map卷积在一起,得到一个新的Feature Map. 五个Filter就得到了五个Feature Map.
  5. 第二个Pooling层继续对五个Feature Map进行下采样,得到了五个更小的Feature Map.
  6. 最后,第一个全连接层的每个神经元和上一层五个Feature Map中的每个神经元相连,第二个全连接层(即输出层)的每个神经元和第一个全连接层的每个神经元相连,这样得到了整个网络的输出。

卷积神经网络输出的计算

卷积层输出值的计算

假设有一个5*5的图像,使用一个3*3的Filter进行卷积,得到一个3*3的Feature Map,如图所示:

Feature map

对于图像第iijj列元素xi,jx_{i,j}、Filter第mmnn列权重ωm,n\omega_{m,n}、Filter偏置项ωb\omega_b、Feature Map的第iijj列元素ai,ja_{i,j}

ai,j=f(m=02n=02ωm,nxi+m,j+n+ωb)a_{i,j}=f(\sum_{m=0}^2\sum_{n=0}^2\omega_{m,n}x_{i+m,j+n}+\omega_b)

如下图动画所示进行计算。

上图的步幅(stride)为1. 当步幅为2时计算如下:

步幅为2

此时的Feature Map变为2*2了。于是可得出图像大小,步幅和卷积后的Feature Map大小满足如下关系:

W2=(W1F+2P)/S+1W_2=(W_1-F+2P)/S+1

其中W2W_2是卷积后Feature Map的宽高;W1W_1是卷积前图像的宽高;FF是Filter的宽高;PP是Zero Padding的数量,指在原始图像周围补几圈0;SS是步幅。

当深度大于1的时候如何计算?

ai,j(k)=f(d=0D1m=0F1n=0F1ωd,m,n(k)xd,i+m,j+n+ωb(k))a_{i,j}^{(k)}=f(\sum_{d=0}^{D-1}\sum_{m=0}^{F-1}\sum_{n=0}^{F-1}\omega_{d,m,n}^{(k)}x_{d,i+m,j+n}+\omega_b^{(k)})

其中kk为输出通道数(Feature Map的深度、Filter的个数),dd为输入通道数(Image的深度、每个Filter的深度)

下图是一个包含两个Filter的卷积层的计算。其中k=2k=2,k=2k=2d=3d=3,Zero padding为1,步幅为2.

可以看到,卷积层的输入是一个深度为dd的立方体,每个Filter是一个深度也为dd的立方体,卷积层有kk个这样的Filter,最终输出kk张二维的Feature Map,这些Feature Map在深度方向叠加,形成一个深度为kk的立方体

以上就是卷积层的计算方法,体现了局部连接权值共享的特点。

Pooling层输出值的计算

Pooling层主要作用是下采样,通过去掉Feature Map中不重要的样本,进一步减少参数数量。

最常用的方法就是Max Pooling,也就是取n*n样本中的最大值。也有Mean Pooling等其他方法。Pooling不改变Feature Map的深度,因为每层是独立做Pooling操作的。

下采样

全连接层输出值的计算

上一章中全连接神经网络的计算方法。

用卷积公式进行计算

对于矩阵Ama×naA_{m_a\times n_a},Bmb×nbB_{m_b\times n_b}二维卷积公式如下:

Cs,t=m=0ma1n=0na1Am,nBsm,tnC_{s,t}=\sum_{m=0}^{m_a-1}\sum_{n=0}^{n_a-1}A_{m,n}B_{s-m,t-n}

其中s,ts,t满足条件0s<ma+mb10\le s<m_a+m_b-1,0t<na+nb10\le t<n_a+n_b-1.

这样,上式可以写成:

C=AB=conv(A,B)C=A*B=conv(A,B)

对于超出边界的元素取0. 称之为互相关操作

卷积神经网络的训练

卷积神经网络的训练原理同全连接神经网络:利用链式求导计算损失函数对每个权重的梯度,根据梯度下降公式更新权重。训练算法依然是反向传播算法。

卷积层的训练

卷积层误差项的传递

当步幅为1、输入深度为1、Filter数为1的简单情况:

netnet是卷积加偏置后还没有通过激活函数的值,aa是通过激活函数后的输出

netl=conv(Wl,al1)+ωbai,jl1=fl1(neti,jl1)\begin{aligned}net^l&=conv(W^l,a^{l-1})+\omega_b\\a_{i,j}^{l-1}&=f^{l-1}(net_{i,j}^{l-1})\end{aligned}

那么对于误差项δi,jl1\delta_{i,j}^{l-1},

δi,jl1=Edneti,jl1=Edai,jl1ai,jl1neti,jl1\begin{aligned}\delta_{i,j}^{l-1}&=\frac{\partial E_d}{\partial net_{i,j}^{l-1}}\\&=\frac{\partial E_d}{\partial a_{i,j}^{l-1}}\frac{\partial a_{i,j}^{l-1}}{\partial net_{i,j}^{l-1}}\end{aligned}

很明显,

ai,jl1neti,jl1=f(neti,jl1)\frac{\partial a_{i,j}^{l-1}}{\partial net_{i,j}^{l-1}}=f'(net^{l-1}_{i,j})

现在来求Edai,jl1\frac{\partial E_d}{\partial a_{i,j}^{l-1}}

Eda2,2l1\frac{\partial E_d}{\partial a_{2,2}^{l-1}}为例,(提示:

net1,1l=w1,1a1,1l1+w1,2a1,2l1+w2,1a2,1l1+w2,2a2,2l1+wbnet^l_{1,1} = w_{1,1} a^{l-1}_{1,1} + w_{1,2} a^{l-1}_{1,2} + w_{2,1} a^{l-1}_{2,1} + w_{2,2} a^{l-1}_{2,2} + w_b

Eda2,2l1=Ednet1,1lnet1,1la2,2l1+Ednet1,2lnet1,2la2,2l1+Ednet2,1lnet2,1la2,2l1+Ednet2,2lnet2,2la2,2l1=δ1,1lw2,2+δ1,2lw2,1+δ2,1lw1,2+δ2,2lw1,1\begin{aligned}\frac{\partial E_d}{\partial a^{l-1}_{2,2}}&= \frac{\partial E_d}{\partial net^l_{1,1}} \frac{\partial net^l_{1,1}}{\partial a^{l-1}_{2,2}}+ \frac{\partial E_d}{\partial net^l_{1,2}} \frac{\partial net^l_{1,2}}{\partial a^{l-1}_{2,2}}+ \frac{\partial E_d}{\partial net^l_{2,1}} \frac{\partial net^l_{2,1}}{\partial a^{l-1}_{2,2}}+ \frac{\partial E_d}{\partial net^l_{2,2}} \frac{\partial net^l_{2,2}}{\partial a^{l-1}_{2,2}}\\&= \delta^l_{1,1} w_{2,2} + \delta^l_{1,2} w_{2,1} + \delta^l_{2,1} w_{1,2} + \delta^l_{2,2} w_{1,1}\end{aligned}

那么可以推出,计算Edal1\frac{\partial E_d}{\partial a^{l-1}}, 相当于把第ll层的Sensitive Map(δ\delta矩阵)周围补一圈0,在与180°\degree旋转后的Filter进行互相关操作,即可得到结果。

因此,Edal\frac{\partial E_d}{\partial a^l}可以被表示为:

Edal=δlWl\frac{\partial E_d}{\partial a^l}=\delta^l*W^l

最终,我们得到:

δl1=δlWlf(netl1)\delta^{l-1}=\delta^l*W^l\circ f'(net^{l-1})

其中\circ代表对应元素相乘。

当步幅为SS时:

当我们反向计算误差项时,只需要对Sensitive Map的对应位置进行补0,将其还原为步幅为1的情况即可求解。

当输入层深度为DD时,Filter的深度也必须为DDl1l-1层的did_i通道只与Filter的did_i通道的权重进行计算。因此反向计算误差项时,用Filter得第did_i通道权重对第ll层Sensitive Map进行卷积,得到第l1l-1did_i通道的Sensitive Map.

当有NN个Filter时,输出层的深度也为NN,第ii个Filter卷积产生输出层的第ii个Feature Map. 由于第l1l-1层每个加权输入netd,i,jl1net_{d,i,j}^{l-1}都影响了第ll层所有Feature Map的输出,因此反向计算误差项需要使用全导数公式。

δl1=d=0DδdlWdlf(netl1)\delta^{l-1}=\sum_{d=0}^D\delta_d^l*W_d^l\circ f'(net^{l-1})

卷积层Filter权重梯度的计算

现在已经得到第ll层Sensitivity Map,要计算Filter权重的梯度。

由于权值共享,每一个ωi,j\omega_{i,j}对所有的neti,jlnet_{i,j}^l都有影响。(提示:

net1,1l=w1,1a1,1l1+w1,2a1,2l1+w2,1a2,1l1+w2,2a2,2l1+wbnet^l_{1,1} = w_{1,1} a^{l-1}_{1,1} + w_{1,2} a^{l-1}_{1,2} + w_{2,1} a^{l-1}_{2,1} + w_{2,2} a^{l-1}_{2,2} + w_b

所以可以得出:

Edωi,j=mnEdnetm,nnetm,nωi,j=mnδm,nai+m,j+nl1\begin{aligned}\frac{\partial E_d}{\partial\omega_{i,j}}&=\sum_m\sum_n\frac{\partial E_d}{\partial net_{m,n}}\frac{\partial net_{m,n}}{\partial\omega_{i,j}}\\&=\sum_m\sum_n\delta_{m,n}a_{i+m,j+n}^{l-1}\end{aligned}

也就是用Sensitivity Map作为卷积核,在input上进行互相关操作:

偏置项的梯度Edωb\frac{\partial E_d}{\partial\omega_b}是Sensitivity Map所有误差项之和。

流程总结

利用已有的al1a^{l-1},WW,进行第ll层的计算:

  1. 前向计算:滑动卷积核,对输入做卷积,每个卷积输出加一个偏置ωb\omega_b,将卷积结果通过激活函数得到输出ala^l

  2. 反向传播:从下一层(或损失函数)得到本层误差项δl\delta^l,将其补0扩展,将卷积核旋转180°\degree,再将二者卷积,乘以上一层激活函数的导数f(netl1)f'(net^{l-1}),得到上一层误差项δl1\delta^{l-1}

  3. 计算梯度:利用本层误差项δl\delta ^lδl\delta^lal1a^{l-1}δl\delta^lEdωi,j=δlal1\frac{\partial E_d}{\partial\omega_{i,j}}=\sum\delta^la^{l-1}

  4. 参数更新:

    ωωηEdωi,jbbηEdωb\omega \leftarrow \omega - \eta \frac{\partial E_d}{\partial \omega_{i,j}}\\ b \leftarrow b - \eta \frac{\partial E_d}{\partial \omega_b}

别忘了最后一层的δ\delta,也就是反向传播的起点。

δL=(yt)f(netL)\delta^L = (y - t) \cdot f'(net^L)

Pooling层的训练

对于Pooling层,没有要学习的参数,仅仅是将误差项传递到上一层。

Max Pooling层误差项的传递

对于max pooling,下一层的误差项的值会原封不动的传递到上一层对应区块中的最大值所对应的神经元,而其他神经元的误差项的值都是0。

Mean Pooling层误差项的传递

对于mean pooling,下一层的误差项的值会平均分配到上一层对应区块中的所有神经元。