前面已经推导学习了卷积神经网络之前向传播算法,本篇文章将推导卷积神经网络之反向传播算法。在学习卷积神经网络算法之前,希望你对深度神经网络有一定程度的了解,我在之前也有写过相关的文章,包括深度神经网络之前向传播算法、深度神经网络之反向传播算法、深度神经网络之损失函数和激活函数、深度神经网络之正则化,可以先看一下再学习卷积神经网络。
1.DNN反向传播算法
学习CNN(卷积神经网络)反向传播算法之前,我们先回顾下DNN(深度神经网络)反向传播算法。DNN之中,我们是首先计算出输出层的 δ L \delta^L δL
δ L = ∂ J ( W , b ) ∂ z L = ∂ J ( W , b ) a L ⊙ σ ′ ( z L ) \delta^L = \frac{\partial J(W,b)}{\partial z^L} = \frac{\partial J(W,b)}{a^L} \odot {\sigma}'(z^L) δL=∂zL∂J(W,b)=aL∂J(W,b)⊙σ′(zL)
然后利用数学归纳法,用 δ l + 1 \delta^{l+1} δl+1的值向前求出第 l l l层的 δ l \delta ^{l} δl,表达式为
δ l = δ l + 1 ∂ z l + 1 ∂ z l = ( W l + 1 ) T δ l + 1 ⊙ σ ′ ( z l ) \delta^{l}= \delta^{l+1}\frac{\partial z^{l+1}}{\partial z^l}=(W^{l+1})^T\delta^{l+1}\odot {\sigma}'(z^l) δl=δl+1∂zl∂zl+1=(Wl+1)Tδl+1⊙σ′(zl)
有了 δ l \delta^l δl表达式,便能够求出 W , b W,b W,b的梯度表达式
∂ J ( W , b ) ∂ W l = ∂ J ( W , b , x , y ) ∂ z l ∂ z l ∂ W l = δ l ( a l − 1 ) T \frac{\partial J(W,b)}{\partial W^l} = \frac{\partial J(W,b,x,y)}{\partial z^l}\frac{\partial z^l}{\partial W^l}=\delta^l(a^{l-1})^T ∂Wl∂J(W,b)=∂zl∂J(W,b,x,y)∂Wl∂zl=δl(al−1)T
∂ J ( W , b ) ∂ b l = ∂ J ( W , b , x , y ) ∂ z l ∂ z l ∂ b l = δ l \frac{\partial J(W,b)}{\partial b^l} = \frac{\partial J(W,b,x,y)}{\partial z^l}\frac{\partial z^l}{\partial b^l}=\delta^l ∂bl∂J(W,b)=∂zl∂J(W,b,x,y)∂bl∂zl=δl
有了 W , b W,b W,b梯度表达式,便可利用梯度下降法来优化 W , b W,b W,b,最终求出所有的 W , b W,b W,b。了解DNN深度神经网络反向传播算法之后,下面来看下卷积神经网络算法如何求解 W , b W,b W,b。
2.CNN反向传播算法
对比深度神经网络反向传播算法,卷积神经网络反向传播算法需要解决以下几个问题。
- 池化层没有激活函数,因此令池化层的激活函数为 σ ( z ) = z \sigma(z)=z σ(z)=z,即激活后便是本身,这样池化层激活函数的导数为1。另池化层在前向传播算法之中,对输入进行了压缩,那么现在反向推倒 δ l − 1 \delta ^{l-1} δl−1,如何求解呢。
- 卷积层是通过张量进行卷积,而DNN的全连接层是直接进行矩阵乘法计算,然后得到当前层的输出,那么卷积层进行反向传播时如何推导 δ l − 1 \delta^{l-1} δl−1呢。
- 对于卷积层,由于和 W W W的运算是卷积,那么从 δ l \delta ^l δl推导出当前层卷积的 W , b W,b W,b方式也不同,针对卷积神经网络如何求解 W , b W,b W,b呢。
由于卷积层可以有多个卷积核,各个卷积核之间的处理方式是完全相同的,为了简化算法公式的复杂度,下面推导时只针对卷积层中若干卷积核中的一个。
3.已知池化层 δ l \delta^l δl,推导上一隐藏层 δ l − 1 \delta^{l-1} δl−1
针对上述问题1,CNN前向传播算法时,池化层一般会采用Max或Average对输入进行池化,池化的区域大小已知。现在我们反过来,从缩小后的误差 δ l \delta^l δl,还原前一次较大区域对应的误差。
反向传播时,首先会把 δ l \delta^l δl的所有子矩阵大小还原到池化之前的大小。如果是Max方法池化,则把 δ l \delta^l δl的所有子矩阵的各个池化区域的值,放在之前做前向传播算法得到最大值的位置。如果是Average方法池化,则把 δ l \delta^l δl的所有子矩阵的各个池化区域的值,取平均后放在还原后的子矩阵位置,上述过程一般叫做upsample。
下面我们通过一个简单例子来表示upsample,假设我们池化后的区域大小是2*2, δ l \delta^l δl的第k个子矩阵为
δ k l = [ 2 8 4 6 ] \delta_k^l = \begin{bmatrix} 2&8 \\ 4&6 \end{bmatrix} δkl=[2486]
由于池化区域为2*2,首先将 δ k l \delta ^l _k δkl进行还原
[ 0 0 0 0 0 2 8 0 0 4 6 0 0 0 0 0 ] \begin{bmatrix} 0 &0 &0 &0 \\ 0 &2 &8 &0 \\ 0 &4 &6 &0 \\ 0 &0 &0 &0 \end{bmatrix} ⎣⎢⎢⎡0000024008600000⎦⎥⎥⎤
如果是Max方法,假设之前在前向传播算法记录的最大值位置分别是左上、右下、右上、左下,则转换后的矩阵为
[ 2 0 0 0 0 0 0 8 0 4 0 0 0 0 6 0 ] \begin{bmatrix} 2 &0 &0 &0 \\ 0 &0 &0 &8 \\ 0 &4 &0 &0 \\ 0 &0 &6 &0 \end{bmatrix} ⎣⎢⎢⎡2000004000060800⎦⎥⎥⎤
如果是Average方法,则进行平均化,转化后的矩阵为
[ 0.5 0.5 2 2 0.5 0.5 2 2 1 1 1.5 1.5 1 1 1.5 1.5 ] \begin{bmatrix} 0.5 &0.5 &2 &2 \\ 0.5 &0.5 &2 &2 \\ 1 &1 &1.5 &1.5 \\ 1 &1 &1.5 &1.5 \end{bmatrix} ⎣⎢⎢⎡0.50.5110.50.511221.51.5221.51.5⎦⎥⎥⎤
至此我们便能够得到上一层 ∂ J ( W , b ) ∂ a k l − 1 \frac{\partial J(W,b)}{\partial a^{l-1}_k} ∂akl−1∂J(W,b),通过下式便能得到 δ k l − 1 \delta ^{l-1}_k δkl−1,其中upsample函数完成池化误差矩阵放大于误差重新分配的逻辑
δ k l − 1 = ∂ J ( W , b ) ∂ a k l − 1 ∂ a k l − 1 ∂ z k l − 1 = u p s a m p l e ( δ k l ) ⊙ σ ′ ( z k l − 1 ) \delta_k ^{l-1} = \frac{\partial J(W,b)}{\partial a_k^{l-1}}\frac{\partial a_k^{l-1}}{\partial z_k^{l-1}} = upsample(\delta_k ^l)\odot {\sigma}'(z_k^{l-1}) δkl−1