卷积神经网络(CNN)反向传播算法

    在卷积神经网络(CNN)前向传播算法中,咱们对CNN的前向传播算法作了总结,基于CNN前向传播算法的基础,咱们下面就对CNN的反向传播算法作一个总结。在阅读本文前,建议先研究DNN的反向传播算法:深度神经网络(DNN)反向传播算法(BP)html

1. 回顾DNN的反向传播算法

    咱们首先回顾DNN的反向传播算法。在DNN中,咱们是首先计算出输出层的$\delta^L$:$$\delta^L = \frac{\partial J(W,b)}{\partial z^L} = \frac{\partial J(W,b)}{\partial a^L}\odot \sigma^{'}(z^L)$$git

    利用数学概括法,用$\delta^{l+1}$的值一步步的向前求出第l层的$\delta^l$,表达式为:$$\delta^{l} = (\frac{\partial z^{l+1}}{\partial z^{l}})^T\delta^{l+1} = (W^{l+1})^T\delta^{l+1}\odot \sigma^{'}(z^l)$$github

    有了$\delta^l$的表达式,从而求出$W,b$的梯度表达式:$$\frac{\partial J(W,b)}{\partial W^l}  = \delta^{l}(a^{l-1})^T$$$$\frac{\partial J(W,b,x,y)}{\partial b^l} = = \delta^{l}$$算法

    有了$W,b$梯度表达式,就能够用梯度降低法来优化$W,b$,求出最终的全部$W,b$的值。网络

    如今咱们想把一样的思想用到CNN中,很明显,CNN有些不一样的地方,不能直接去套用DNN的反向传播算法的公式。函数

2. CNN的反向传播算法思想

    要套用DNN的反向传播算法到CNN,有几个问题须要解决:post

    1)池化层没有激活函数,这个问题倒比较好解决,咱们能够令池化层的激活函数为$\sigma(z) = z$,即激活后就是本身自己。这样池化层激活函数的导数为1.优化

    2)池化层在前向传播的时候,对输入进行了压缩,那么咱们如今须要向前反向推导$\delta^{l-1}$,这个推导方法和DNN彻底不一样。htm

    3) 卷积层是经过张量卷积,或者说若干个矩阵卷积求和而得的当前层的输出,这和DNN很不相同,DNN的全链接层是直接进行矩阵乘法获得当前层的输出。这样在卷积层反向传播的时候,上一层的$\delta^{l-1}$递推计算方法确定有所不一样。blog

    4)对于卷积层,因为$W$使用的运算是卷积,那么从$\delta^l$推导出该层的全部卷积核的$W,b$的方式也不一样。

    从上面能够看出,问题1比较好解决,可是问题2,3,4就须要好好的动一番脑筋了,而问题2,3,4也是解决CNN反向传播算法的关键所在。另外你们要注意到的是,DNN中的$a_l,z_l$都只是一个向量,而咱们CNN中的$a_l,z_l$都是一个张量,这个张量是三维的,即由若干个输入的子矩阵组成。

    下面咱们就针对问题2,3,4来一步步研究CNN的反向传播算法。

    在研究过程当中,须要注意的是,因为卷积层能够有多个卷积核,各个卷积核的处理方法是彻底相同且独立的,为了简化算法公式的复杂度,咱们下面提到卷积核都是卷积层中若干卷积核中的一个。

3. 已知池化层的$\delta^l$,推导上一隐藏层的$\delta^{l-1}$   

    咱们首先解决上面的问题2,若是已知池化层的$\delta^l$,推导出上一隐藏层的$\delta^{l-1}$。

    在前向传播算法时,池化层通常咱们会用MAX或者Average对输入进行池化,池化的区域大小已知。如今咱们反过来,要从缩小后的偏差$\delta^l$,还原前一次较大区域对应的偏差。

    在反向传播时,咱们首先会把$\delta^l$的全部子矩阵矩阵大小还原成池化以前的大小,而后若是是MAX,则把$\delta^l$的全部子矩阵的各个池化局域的值放在以前作前向传播算法获得最大值的位置。若是是Average,则把$\delta^l$的全部子矩阵的各个池化局域的值取平均后放在还原后的子矩阵位置。这个过程通常叫作upsample。

    用一个例子能够很方便的表示:假设咱们的池化区域大小是2x2。$\delta^l$的第k个子矩阵为:$$\delta_k^l =
\left( \begin{array}{ccc}
2& 8 \\
4& 6 \end{array} \right)$$

    因为池化区域为2x2,咱们先讲$\delta_k^l$作还原,即变成:$$
\left( \begin{array}{ccc}
0&0&0&0 \\ 0&2& 8&0 \\ 0&4&6&0 \\
0&0&0&0 \end{array} \right)$$

     若是是MAX,假设咱们以前在前向传播时记录的最大值位置分别是左上,右下,右上,左下,则转换后的矩阵为:$$
\left( \begin{array}{ccc}
2&0&0&0 \\ 0&0& 0&8 \\ 0&4&0&0 \\
0&0&6&0 \end{array} \right)$$

    若是是Average,则进行平均:转换后的矩阵为:$$
\left( \begin{array}{ccc}
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{array} \right)$$

    这样咱们就获得了上一层 $\frac{\partial J(W,b)}{\partial a_k^{l-1}} $的值,要获得$\delta_k^{l-1}$:$$\delta_k^{l-1} = (\frac{\partial  a_k^{l-1}}{\partial z_k^{l-1}})^T\frac{\partial J(W,b)}{\partial a_k^{l-1}}  = upsample(\delta_k^l) \odot \sigma^{'}(z_k^{l-1})$$

    其中,upsample函数完成了池化偏差矩阵放大与偏差从新分配的逻辑。

    咱们归纳下,对于张量$\delta^{l-1}$,咱们有:$$\delta^{l-1} =  upsample(\delta^l) \odot \sigma^{'}(z^{l-1})$$

4. 已知卷积层的$\delta^l$,推导上一隐藏层的$\delta^{l-1}$  

    对于卷积层的反向传播,咱们首先回忆下卷积层的前向传播公式:$$  a^l= \sigma(z^l) = \sigma(a^{l-1}*W^l +b^l) $$

    其中$n\_in$为上一隐藏层的输入子矩阵个数。

    在DNN中,咱们知道$\delta^{l-1}$和$\delta^{l}$的递推关系为:$$\delta^{l} = \frac{\partial J(W,b)}{\partial z^l} =(\frac{\partial z^{l+1}}{\partial z^{l}})^T \frac{\partial J(W,b)}{\partial z^{l+1}} =(\frac{\partial z^{l+1}}{\partial z^{l}})^T\delta^{l+1}$$

    所以要推导出$\delta^{l-1}$和$\delta^{l}$的递推关系,必须计算$\frac{\partial z^{l}}{\partial z^{l-1}}$的梯度表达式。

    注意到$z^{l}$和$z^{l-1}$的关系为:$$z^l = a^{l-1}*W^l +b^l =\sigma(z^{l-1})*W^l +b^l  $$

    所以咱们有:$$\delta^{l-1} =  (\frac{\partial z^{l}}{\partial z^{l-1}})^T\delta^{l} = \delta^{l}*rot180(W^{l}) \odot  \sigma^{'}(z^{l-1}) $$

    这里的式子其实和DNN的相似,区别在于对于含有卷积的式子求导时,卷积核被旋转了180度。即式子中的$rot180()$,翻转180度的意思是上下翻转一次,接着左右翻转一次。在DNN中这里只是矩阵的转置。那么为何呢?因为这里都是张量,直接推演参数太多了。咱们以一个简单的例子说明为啥这里求导后卷积核要翻转。

    假设咱们$l-1$层的输出$a^{l-1}$是一个3x3矩阵,第$l$层的卷积核$W^l$是一个2x2矩阵,采用1像素的步幅,则输出$z^{l}$是一个2x2的矩阵。咱们简化$b^l都是0$,则有$$a^{l-1}*W^l = z^{l}$$

    咱们列出$a,W,z$的矩阵表达式以下:$$
\left( \begin{array}{ccc}
a_{11}&a_{12}&a_{13} \\ a_{21}&a_{22}&a_{23}\\
a_{31}&a_{32}&a_{33} \end{array} \right)    *  \left( \begin{array}{ccc}
w_{11}&w_{12}\\
w_{21}&w_{22} \end{array} \right) = \left( \begin{array}{ccc}
z_{11}&z_{12}\\
z_{21}&z_{22} \end{array} \right)$$

    利用卷积的定义,很容易得出:$$z_{11} = a_{11}w_{11} + a_{12}w_{12} + a_{21}w_{21} +   a_{22}w_{22} $$$$z_{12} = a_{12}w_{11} + a_{13}w_{12} + a_{22}w_{21} +   a_{23}w_{22} $$$$z_{21} = a_{21}w_{11} + a_{22}w_{12} + a_{31}w_{21} +   a_{32}w_{22} $$$$z_{22} = a_{22}w_{11} + a_{23}w_{12} + a_{32}w_{21} +   a_{33}w_{22} $$

    接着咱们模拟反向求导:$$\nabla a^{l-1} = \frac{\partial J(W,b)}{\partial a^{l-1}} = ( \frac{\partial z^{l}}{\partial a^{l-1}})^T\frac{\partial J(W,b)}{\partial z^{l}} =(\frac{\partial z^{l}}{\partial a^{l-1}})^T \delta^{l} $$

    从上式能够看出,对于$a^{l-1}$的梯度偏差$\nabla a^{l-1}$,等于第$l$层的梯度偏差乘以$\frac{\partial z^{l}}{\partial a^{l-1}}$,而$\frac{\partial z^{l}}{\partial a^{l-1}}$对应上面的例子中相关联的$w$的值。假设咱们的$z$矩阵对应的反向传播偏差是$\delta_{11}, \delta_{12}, \delta_{21}, \delta_{22}$组成的2x2矩阵,则利用上面梯度的式子和4个等式,咱们能够分别写出$\nabla a^{l-1}$的9个标量的梯度。

    好比对于$a_{11}$的梯度,因为在4个等式中$a_{11}$只和$z_{11}$有乘积关系,从而咱们有:$$ \nabla a_{11} = \delta_{11}w_{11}$$

    对于$a_{12}$的梯度,因为在4个等式中$a_{12}$和$z_{12},z_{11}$有乘积关系,从而咱们有:$$ \nabla a_{12} = \delta_{11}w_{12} + \delta_{12}w_{11}$$

    一样的道理咱们获得:$$ \nabla a_{13} = \delta_{12}w_{12} $$$$\nabla a_{21} = \delta_{11}w_{21} + \delta_{21}w_{11}$$$$\nabla a_{22} = \delta_{11}w_{22} + \delta_{12}w_{21} + \delta_{21}w_{12} + \delta_{22}w_{11}  $$$$ \nabla a_{23} = \delta_{12}w_{22} + \delta_{22}w_{12}$$$$ \nabla a_{31} = \delta_{21}w_{21}$$$$ \nabla a_{32} = \delta_{21}w_{22} + \delta_{22}w_{21}$$$$ \nabla a_{33} = \delta_{22}w_{22} $$  

    这上面9个式子其实能够用一个矩阵卷积的形式表示,即:$$
\left( \begin{array}{ccc}
0&0&0&0 \\ 0&\delta_{11}& \delta_{12}&0 \\ 0&\delta_{21}&\delta_{22}&0 \\
0&0&0&0 \end{array} \right) * \left( \begin{array}{ccc}
w_{22}&w_{21}\\
w_{12}&w_{11} \end{array} \right)  = \left( \begin{array}{ccc}
\nabla a_{11}&\nabla a_{12}&\nabla a_{13} \\ \nabla a_{21}&\nabla a_{22}&\nabla a_{23}\\
\nabla a_{31}&\nabla a_{32}&\nabla a_{33} \end{array} \right)$$

     为了符合梯度计算,咱们在偏差矩阵周围填充了一圈0,此时咱们将卷积核翻转后和反向传播的梯度偏差进行卷积,就获得了前一次的梯度偏差。这个例子直观的介绍了为何对含有卷积的式子反向传播时,卷积核要翻转180度的缘由。

    以上就是卷积层的偏差反向传播过程。

5. 已知卷积层的$\delta^l$,推导该层的$W,b$的梯度    

    好了,咱们如今已经能够递推出每一层的梯度偏差$\delta^l$了,对于全链接层,能够按DNN的反向传播算法求该层$W,b$的梯度,而池化层并无$W,b$,也不用求$W,b$的梯度。只有卷积层的$W,b$须要求出。

    注意到卷积层$z$和$W,b$的关系为:$$z^l = a^{l-1}*W^l +b$$

    所以咱们有:$$\frac{\partial J(W,b)}{\partial W^{l}}=a^{l-1} *\delta^l$$

    注意到此时卷积核并无反转,主要是此时是层内的求导,而不是反向传播到上一层的求导。具体过程咱们能够分析一下。

    和第4节同样的一个简化的例子,这里输入是矩阵,不是张量,那么对于第l层,某个个卷积核矩阵W的导数能够表示以下:$$\frac{\partial J(W,b)}{\partial W_{pq}^{l}} = \sum\limits_i\sum\limits_j(\delta_{ij}^la_{i+p-1,j+q-1}^{l-1})$$

    假设咱们输入$a$是4x4的矩阵,卷积核$W$是3x3的矩阵,输出$z$是2x2的矩阵,那么反向传播的$z$的梯度偏差$\delta$也是2x2的矩阵。

    那么根据上面的式子,咱们有:$$\frac{\partial J(W,b)}{\partial W_{11}^{l}} = a_{11}\delta_{11} + a_{12}\delta_{12} + a_{21}\delta_{21} +  a_{22}\delta_{22}$$

$$\frac{\partial J(W,b)}{\partial W_{12}^{l}} = a_{12}\delta_{11} + a_{13}\delta_{12} + a_{22}\delta_{21} +  a_{23}\delta_{22}$$

$$\frac{\partial J(W,b)}{\partial W_{13}^{l}} = a_{13}\delta_{11} + a_{14}\delta_{12} + a_{23}\delta_{21} +  a_{24}\delta_{22}$$

$$\frac{\partial J(W,b)}{\partial W_{21}^{l}} = a_{21}\delta_{11} + a_{22}\delta_{12} + a_{31}\delta_{21} +  a_{32}\delta_{22}$$

    最终咱们能够一共获得9个式子。整理成矩阵形式后可得:

$$\frac{\partial J(W,b)}{\partial W^{l}} =\left( \begin{array}{ccc} a_{11}&a_{12}&a_{13}&a_{14} \\ a_{21}&a_{22}&a_{23}&a_{24} \\ a_{31}&a_{32}&a_{33}&a_{34} \\
a_{41}&a_{42}&a_{43}&a_{44} \end{array} \right) * \left( \begin{array}{ccc}
\delta_{11}& \delta_{12} \\ \delta_{21}&\delta_{22} \end{array} \right)  $$

    从而能够清楚的看到此次咱们为何没有反转的缘由。

    而对于b,则稍微有些特殊,由于$\delta^l$是高维张量,而$b$只是一个向量,不能像DNN那样直接和$\delta^l$相等。一般的作法是将$\delta^l$的各个子矩阵的项分别求和,获得一个偏差向量,即为$b$的梯度:$$\frac{\partial J(W,b)}{\partial b^{l}} = \sum\limits_{u,v}(\delta^l)_{u,v}$$

6. CNN反向传播算法总结

    如今咱们总结下CNN的反向传播算法,以最基本的批量梯度降低法为例来描述反向传播算法。

    输入:m个图片样本,CNN模型的层数L和全部隐藏层的类型,对于卷积层,要定义卷积核的大小K,卷积核子矩阵的维度F,填充大小P,步幅S。对于池化层,要定义池化区域大小k和池化标准(MAX或Average),对于全链接层,要定义全链接层的激活函数(输出层除外)和各层的神经元个数。梯度迭代参数迭代步长$\alpha$,最大迭代次数MAX与中止迭代阈值$\epsilon$

    输出:CNN模型各隐藏层与输出层的$W,b$

    1) 初始化各隐藏层与输出层的各$W,b$的值为一个随机值。

      2)for iter to 1 to MAX:

    2-1) for i =1 to m:

      a) 将CNN输入$a^1$设置为$x_i$对应的张量

      b) for $l$=2 to L-1,根据下面3种状况进行前向传播算法计算:

      b-1) 若是当前是全链接层:则有$a^{i,l} = \sigma(z^{i,l}) = \sigma(W^la^{i,l-1} + b^{l})$

      b-2) 若是当前是卷积层:则有$a^{i,l} = \sigma(z^{i,l}) = \sigma(W^l*a^{i,l-1} + b^{l})$

      b-3) 若是当前是池化层:则有$ a^{i,l}= pool(a^{i,l-1})$, 这里的pool指按照池化区域大小k和池化标准将输入张量缩小的过程。

      c) 对于输出层第L层: $ a^{i,L}= softmax(z^{i,L}) = softmax(W^{L}a^{i,L-1} +b^{L})$

      c) 经过损失函数计算输出层的$\delta^{i,L}$

      d) for $l$= L-1 to 2, 根据下面3种状况进行进行反向传播算法计算:

      d-1)  若是当前是全链接层:$\delta^{i,l} =  (W^{l+1})^T\delta^{i,l+1}\odot \sigma^{'}(z^{i,l})$

      d-2) 若是当前是卷积层:$\delta^{i,l} = \delta^{i,l+1}*rot180(W^{l+1}) \odot  \sigma^{'}(z^{i,l}) $

      d-3) 若是当前是池化层:$\delta^{i,l} =  upsample(\delta^{i,l+1}) \odot \sigma^{'}(z^{i,l})$

    2-2) for $l$ = 2 to L,根据下面2种状况更新第$l$层的$W^l,b^l$:

      2-2-1) 若是当前是全链接层:$W^l = W^l -\alpha \sum\limits_{i=1}^m \delta^{i,l}(a^{i, l-1})^T $, $b^l = b^l -\alpha \sum\limits_{i=1}^m \delta^{i,l}$

      2-2-2) 若是当前是卷积层,对于每个卷积核有:$W^l = W^l -\alpha \sum\limits_{i=1}^m \delta^{i,l}*a^{i, l-1} $, $b^l = b^l -\alpha \sum\limits_{i=1}^m \sum\limits_{u,v}(\delta^{i,l})_{u,v}$

    2-3) 若是全部$W,b$的变化值都小于中止迭代阈值$\epsilon$,则跳出迭代循环到步骤3。

    3) 输出各隐藏层与输出层的线性关系系数矩阵$W$和偏倚向量$b$。

 

(欢迎转载,转载请注明出处。欢迎沟通交流: liujianping-ok@163.com) 

参考资料:

1) Neural Networks and Deep Learning by By Michael Nielsen

2) Deep Learning, book by Ian Goodfellow, Yoshua Bengio, and Aaron Courville

3) UFLDL Tutorial

4)CS231n Convolutional Neural Networks for Visual Recognition, Stanford

相关文章
相关标签/搜索