1. 前言
如果读者详细的了解了DNN神经网络的反向更新,那对我们今天的学习会有很大的帮助。我们的CNN卷机网络中有3种网络结构。1. 卷积层,2.池化层,3.全连接层。全连接层的反向传播的方式和DNN的反向传播的方式是一样的,因为DNN的所有层都是全连接的结构。卷机层和池化层下文会继续讲解。
2. 全连接反向更新
这里先回顾下DNN的反向更新,我们进行反向更新主要是计算每一层的\(W,b\)的梯度。
\[\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
\]
\[\frac{\partial J(W,b,x,y)}{\partial b^l} = \frac{\partial J(W,b)}{\partial z^l} \frac{\partial z^l}{\partial b^l} = \delta^{l}
\]
我们现在的目标只要计算每层的\(\delta\),就可以算出每层的\(W,b\)的梯度。最后一层的\(\delta\)很好计算,即
\[\delta^L = \frac{\partial J(W,b,x,y)}{\partial z^L} = (a^L-y)\odot \sigma^{'}(z^L)
\]
如果我们能够通过后一层的\(\delta\)推算出前一层的\(\delta\)那就把问题完全解决了。
\[\delta^{l} = \delta^{l+1}\frac{\partial z^{l+1}}{\partial z^{l}} = (W^{l+1})^T\delta^{l+1}\odot \sigma^{'}(z^l)
\]
以上就是全连接层的反向更新的过程。需要明确的一点是以上的推到是有一个前提的:
\[a^l = \sigma(z^l) = \sigma(W^la^{l-1} + b^l)
\]
这个是前向传播的公式。所以卷积层和池化层的前向传播的公式不一样,那在对反向更新中的参数求导的过程也会变化。
3. 卷积层的反向传播
首先我们看下卷积层的前向传播公式:
\[a^l = \sigma(z^l) = \sigma(a^{l-1}*W^l + b)
\]
其中的\(W^l\)是不是一个矩阵,矩阵的定义是2维的,而我们的\(W^l\)是一个张量,可以理解为多个矩阵的组合,或者理解为矩阵的数组。
由于前向传播公式的改变,卷积层求每层的\(\delta^{l}\)递推方法肯定有所不同。又由于\(W\)用的运算是卷积,那么计算卷积核的\(W,b\)的方式也不同。
3.1 求\(\delta^l\)的递推公式
我们先求\(\delta^l\),它的递推公式还是DNN中的那个。
\[\delta^{l} = \frac{\partial J(W,b)}{\partial z^l} = \frac{\partial J(W,b)}{\partial z^{l+1}}\frac{\partial z^{l+1}}{\partial z^{l}} = \delta^{l+1}\frac{\partial z^{l+1}}{\partial z^{l}}\;\;\;\;\;\;(1)
\]
因此和DNN一样,计算\(\delta^l\)的任务就转化成了计算\(\frac{\partial z^{l+1}}{\partial z^{l}}\),那卷积层中的\(\frac{\partial z^{l+1}}{\partial z^{l}}\)怎么计算呢?
\[z^l = a^{l-1}*W^l +b^l =\sigma(z^{l-1})*W^l +b^l
\]
所以有
\[\delta^{l-1} = \delta^{l}\frac{\partial z^{l}}{\partial z^{l-1}} = \delta^{l}*rot180(W^{l}) \odot \sigma^{'}(z^{l-1})
\]
这里的式子其实和DNN的类似,区别在于对于含有卷积的式子求导时,卷积核被旋转了180度。即式子中的\(rot180()\),翻转180度的意思是上下翻转一次,接着左右翻转一次。在DNN中这里只是矩阵的转置。
3.2 已知\(\delta^l\),求\(W,b\)的梯度
卷积层\(z\)和\(W,b\)的关系为:
\[z^l = a^{l-1}*W^l +b
\]
则有带入(1)中得到:
\[\frac{\partial J(W,b)}{\partial W^{l}} = \frac{\partial J(W,b)}{\partial z^{l}}\frac{\partial z^{l}}{\partial W^{l}} =a^{l-1} *\delta^l
\]
其中的运算符\(*\)和前向传播公式是一样的,是卷积的过程。可以把张量展开。
\[\frac{\partial J(W,b)}{\partial W^{l}} =\left( \begin{array}{ccc} a^{l-1}_{11}&a^{l-1}_{12}&a^{l-1}_{13}&a^{l-1}_{14} \\ a^{l-1}_{21}&a^{l-1}_{22}&a^{l-1}_{23}&a^{l-1}_{24} \\ a^{l-1}_{31}&a^{l-1}_{32}&a^{l-1}_{33}&a^{l-1}_{34} \\ a^{l-1}_{41}&a^{l-1}_{42}&a^{l-1}_{43}&a^{l-1}_{44} \end{array} \right) * \left( \begin{array}{ccc} \delta^{l}_{11}& \delta^{l}_{12} \\ \delta^{l}_{21}&\delta^{l}_{22} \end{array} \right)
\]
把\(\delta^l\)当作卷积核,去扫描\(a^{l-1}\)的张量,就得出了\(\frac{\partial J(W,b)}{\partial W^{l}}\)的梯度。
而对于\(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}
\]
4. 池化层的反向更新
在前向传播算法时,池化层一般我们会用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^l_k\)做还原,即变成
\[\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}}\)的值:
\[\frac{\partial J(W,b)}{\partial a_k^{l-1}}= upsample(\delta_k^l)
\]
所以\(\delta_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})
\]
5. 总结
以上就是CNN卷积网络的反向更新的过程,CNN卷积网络的更新和DNN还是有很大的不同,需要读者仔细思考这个过程,最好找个简单的例子能够手推一下整个过程,能够对整个过程有更深刻的理解。