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

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

我们首先回顾DNN的反向传播算法。在DNN中,我们是首先计算出输出层的手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别:手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_02

利用数学归纳法,用手写反向传播网络 识别 反向传播神经网络_DNN_03的值一步步的向前求出第l层的手写反向传播网络 识别 反向传播神经网络_反向传播算法_04,表达式为:手写反向传播网络 识别 反向传播神经网络_DNN_05

有了手写反向传播网络 识别 反向传播神经网络_反向传播算法_04的表达式,从而求出手写反向传播网络 识别 反向传播神经网络_反向传播算法_07的梯度表达式:手写反向传播网络 识别 反向传播神经网络_DNN_08手写反向传播网络 识别 反向传播神经网络_反向传播算法_09

有了手写反向传播网络 识别 反向传播神经网络_反向传播算法_07梯度表达式,就可以用梯度下降法来优化手写反向传播网络 识别 反向传播神经网络_反向传播算法_07,求出最终的所有手写反向传播网络 识别 反向传播神经网络_反向传播算法_07的值。

现在我们想把同样的思想用到CNN中,很明显,CNN有些不同的地方,不能直接去套用DNN的反向传播算法的公式。

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

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

1)池化层没有激活函数,这个问题倒比较好解决,我们可以令池化层的激活函数为手写反向传播网络 识别 反向传播神经网络_卷积_13,即激活后就是自己本身。这样池化层激活函数的导数为1.

2)池化层在前向传播的时候,对输入进行了压缩,那么我们现在需要向前反向推导手写反向传播网络 识别 反向传播神经网络_反向传播算法_14,这个推导方法和DNN完全不同。

3)卷积层是通过张量卷积,或者说若干个矩阵卷积求和而得的当前层的输出,这和DNN很不相同,DNN的全连接层是直接进行矩阵乘法得到当前层的输出。这样在卷积层反向传播的时候,上一层的手写反向传播网络 识别 反向传播神经网络_反向传播算法_14递推计算方法肯定有所不同。

4)对于卷积层,由于手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_16使用的运算是卷积,那么从手写反向传播网络 识别 反向传播神经网络_反向传播算法_04推导出该层的所有卷积核的手写反向传播网络 识别 反向传播神经网络_反向传播算法_07的方式也不同。

从上面可以看出,问题1比较好解决,但是问题2,3,4就需要好好的动一番脑筋了,而问题2,3,4也是解决CNN反向传播算法的关键所在。另外大家要注意到的是,DNN中的手写反向传播网络 识别 反向传播神经网络_反向传播算法_19都只是一个向量,而我们CNN中的手写反向传播网络 识别 反向传播神经网络_反向传播算法_19都是一个张量,这个张量是三维的,即由若干个输入的子矩阵组成。

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

在研究过程中,需要注意的是,由于卷积层可以有多个卷积核,各个卷积核的处理方法是完全相同且独立的,为了简化算法公式的复杂度,我们下面提到卷积核都是卷积层中若干卷积核中的一个。

3. 已知池化层的手写反向传播网络 识别 反向传播神经网络_反向传播算法_04,推导上一隐藏层的手写反向传播网络 识别 反向传播神经网络_反向传播算法_14

我们首先解决上面的问题2,如果已知池化层的手写反向传播网络 识别 反向传播神经网络_反向传播算法_04,推导出上一隐藏层的手写反向传播网络 识别 反向传播神经网络_反向传播算法_14

在前向传播算法时,池化层一般我们会用MAX或者Average对输入进行池化,池化的区域大小已知。现在我们反过来,要从缩小后的误差手写反向传播网络 识别 反向传播神经网络_反向传播算法_04,还原前一次较大区域对应的误差。

在反向传播时,我们首先会把手写反向传播网络 识别 反向传播神经网络_反向传播算法_04的所有子矩阵矩阵大小还原成池化之前的大小,然后如果是MAX,则把手写反向传播网络 识别 反向传播神经网络_反向传播算法_04的所有子矩阵的各个池化局域的值放在之前做前向传播算法得到最大值的位置。如果是Average,则把手写反向传播网络 识别 反向传播神经网络_反向传播算法_04的所有子矩阵的各个池化局域的值取平均后放在还原后的子矩阵位置。这个过程一般叫做upsample。

用一个例子可以很方便的表示:假设我们的池化区域大小是2x2。手写反向传播网络 识别 反向传播神经网络_反向传播算法_04的第k个子矩阵为:手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_30

由于池化区域为2x2,我们先讲手写反向传播网络 识别 反向传播神经网络_反向传播算法_31做还原,即变成:手写反向传播网络 识别 反向传播神经网络_卷积_32

如果是MAX,假设我们之前在前向传播时记录的最大值位置分别是左上,右下,右上,左下,则转换后的矩阵为:手写反向传播网络 识别 反向传播神经网络_DNN_33

如果是Average,则进行平均:转换后的矩阵为:手写反向传播网络 识别 反向传播神经网络_DNN_34

这样我们就得到了上一层手写反向传播网络 识别 反向传播神经网络_DNN_35的值,要得到手写反向传播网络 识别 反向传播神经网络_反向传播算法_36手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_37

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

我们概括下,对于张量手写反向传播网络 识别 反向传播神经网络_反向传播算法_14,我们有:手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_39

4. 已知卷积层的手写反向传播网络 识别 反向传播神经网络_反向传播算法_04,推导上一隐藏层的手写反向传播网络 识别 反向传播神经网络_反向传播算法_14

对于卷积层的反向传播,我们首先回忆下卷积层的前向传播公式:手写反向传播网络 识别 反向传播神经网络_卷积_42

其中手写反向传播网络 识别 反向传播神经网络_DNN_43为上一隐藏层的输入子矩阵个数。

在DNN中,我们知道手写反向传播网络 识别 反向传播神经网络_反向传播算法_14手写反向传播网络 识别 反向传播神经网络_DNN_45的递推关系为:手写反向传播网络 识别 反向传播神经网络_反向传播算法_46

因此要推导出手写反向传播网络 识别 反向传播神经网络_反向传播算法_14手写反向传播网络 识别 反向传播神经网络_DNN_45的递推关系,必须计算手写反向传播网络 识别 反向传播神经网络_DNN_49的梯度表达式。

注意到手写反向传播网络 识别 反向传播神经网络_反向传播算法_50手写反向传播网络 识别 反向传播神经网络_卷积_51的关系为:手写反向传播网络 识别 反向传播神经网络_卷积_52

因此我们有:手写反向传播网络 识别 反向传播神经网络_DNN_53

这里的式子其实和DNN的类似,区别在于对于含有卷积的式子求导时,卷积核被旋转了180度。即式子中的手写反向传播网络 识别 反向传播神经网络_卷积_54,翻转180度的意思是上下翻转一次,接着左右翻转一次。在DNN中这里只是矩阵的转置。那么为什么呢?由于这里都是张量,直接推演参数太多了。我们以一个简单的例子说明为啥这里求导后卷积核要翻转。

假设我们手写反向传播网络 识别 反向传播神经网络_DNN_55层的输出手写反向传播网络 识别 反向传播神经网络_卷积_56是一个3x3矩阵,第手写反向传播网络 识别 反向传播神经网络_卷积_57层的卷积核手写反向传播网络 识别 反向传播神经网络_卷积_58是一个2x2矩阵,采用1像素的步幅,则输出手写反向传播网络 识别 反向传播神经网络_反向传播算法_50是一个2x2的矩阵。我们简化手写反向传播网络 识别 反向传播神经网络_反向传播算法_60,则有手写反向传播网络 识别 反向传播神经网络_DNN_61

我们列出手写反向传播网络 识别 反向传播神经网络_反向传播算法_62的矩阵表达式如下:手写反向传播网络 识别 反向传播神经网络_DNN_63

利用卷积的定义,很容易得出:手写反向传播网络 识别 反向传播神经网络_反向传播算法_64手写反向传播网络 识别 反向传播神经网络_DNN_65手写反向传播网络 识别 反向传播神经网络_DNN_66手写反向传播网络 识别 反向传播神经网络_DNN_67

接着我们模拟反向求导:手写反向传播网络 识别 反向传播神经网络_DNN_68

从上式可以看出,对于手写反向传播网络 识别 反向传播神经网络_卷积_56的梯度误差手写反向传播网络 识别 反向传播神经网络_反向传播算法_70,等于第手写反向传播网络 识别 反向传播神经网络_卷积_57层的梯度误差乘以手写反向传播网络 识别 反向传播神经网络_卷积_72,而手写反向传播网络 识别 反向传播神经网络_卷积_72对应上面的例子中相关联的手写反向传播网络 识别 反向传播神经网络_卷积_74的值。假设我们的手写反向传播网络 识别 反向传播神经网络_卷积_75矩阵对应的反向传播误差是手写反向传播网络 识别 反向传播神经网络_卷积_76组成的2x2矩阵,则利用上面梯度的式子和4个等式,我们可以分别写出手写反向传播网络 识别 反向传播神经网络_反向传播算法_70的9个标量的梯度。

比如对于手写反向传播网络 识别 反向传播神经网络_卷积_78的梯度,由于在4个等式中手写反向传播网络 识别 反向传播神经网络_卷积_78只和手写反向传播网络 识别 反向传播神经网络_DNN_80有乘积关系,从而我们有:手写反向传播网络 识别 反向传播神经网络_卷积_81

对于手写反向传播网络 识别 反向传播神经网络_反向传播算法_82的梯度,由于在4个等式中手写反向传播网络 识别 反向传播神经网络_反向传播算法_82手写反向传播网络 识别 反向传播神经网络_DNN_84有乘积关系,从而我们有:手写反向传播网络 识别 反向传播神经网络_DNN_85

同样的道理我们得到:手写反向传播网络 识别 反向传播神经网络_DNN_86手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_87手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_88手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_89手写反向传播网络 识别 反向传播神经网络_反向传播算法_90手写反向传播网络 识别 反向传播神经网络_卷积_91手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_92

这上面9个式子其实可以用一个矩阵卷积的形式表示,即:手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_93

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

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

5. 已知卷积层的手写反向传播网络 识别 反向传播神经网络_反向传播算法_04,推导该层的手写反向传播网络 识别 反向传播神经网络_反向传播算法_07的梯度

好了,我们现在已经可以递推出每一层的梯度误差手写反向传播网络 识别 反向传播神经网络_反向传播算法_04了,对于全连接层,可以按DNN的反向传播算法求该层手写反向传播网络 识别 反向传播神经网络_反向传播算法_07的梯度,而池化层并没有手写反向传播网络 识别 反向传播神经网络_反向传播算法_07,也不用求手写反向传播网络 识别 反向传播神经网络_反向传播算法_07的梯度。只有卷积层的手写反向传播网络 识别 反向传播神经网络_反向传播算法_07需要求出。

注意到卷积层手写反向传播网络 识别 反向传播神经网络_卷积_75手写反向传播网络 识别 反向传播神经网络_反向传播算法_07的关系为:手写反向传播网络 识别 反向传播神经网络_卷积_103

因此我们有:手写反向传播网络 识别 反向传播神经网络_反向传播算法_104

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

和第4节一样的一个简化的例子,这里输入是矩阵,不是张量,那么对于第l层,某个个卷积核矩阵W的导数可以表示如下:手写反向传播网络 识别 反向传播神经网络_反向传播算法_105

假设我们输入手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_106是4x4的矩阵,卷积核手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_16是3x3的矩阵,输出手写反向传播网络 识别 反向传播神经网络_卷积_75是2x2的矩阵,那么反向传播的手写反向传播网络 识别 反向传播神经网络_卷积_75的梯度误差手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_110也是2x2的矩阵。

那么根据上面的式子,我们有:手写反向传播网络 识别 反向传播神经网络_DNN_111

手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_112

手写反向传播网络 识别 反向传播神经网络_DNN_113

手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_114

最终我们可以一共得到9个式子。整理成矩阵形式后可得:

手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_115

从而可以清楚的看到这次我们为什么没有反转的原因。

而对于b,则稍微有些特殊,因为手写反向传播网络 识别 反向传播神经网络_反向传播算法_04是高维张量,而手写反向传播网络 识别 反向传播神经网络_反向传播算法_117只是一个向量,不能像DNN那样直接和手写反向传播网络 识别 反向传播神经网络_反向传播算法_04相等。通常的做法是将手写反向传播网络 识别 反向传播神经网络_反向传播算法_04的各个子矩阵的项分别求和,得到一个误差向量,即为手写反向传播网络 识别 反向传播神经网络_反向传播算法_117的梯度:手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_121

6. CNN反向传播算法总结

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

输入:m个图片样本,CNN模型的层数L和所有隐藏层的类型,对于卷积层,要定义卷积核的大小K,卷积核子矩阵的维度F,填充大小P,步幅S。对于池化层,要定义池化区域大小k和池化标准(MAX或Average),对于全连接层,要定义全连接层的激活函数(输出层除外)和各层的神经元个数。梯度迭代参数迭代步长手写反向传播网络 识别 反向传播神经网络_卷积_122,最大迭代次数MAX与停止迭代阈值手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_123

输出:CNN模型各隐藏层与输出层的手写反向传播网络 识别 反向传播神经网络_反向传播算法_07

  • 1)初始化各隐藏层与输出层的各手写反向传播网络 识别 反向传播神经网络_反向传播算法_125的值为一个随机值。
  • 2)for iter to 1 to MAX:

2-1) for i =1 to m:

a) 将CNN输入手写反向传播网络 识别 反向传播神经网络_DNN_126设置为手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_127对应的张量

b) for手写反向传播网络 识别 反向传播神经网络_卷积_57=2 to L-1,根据下面3种情况进行前向传播算法计算:

b-1) 如果当前是全连接层:则有手写反向传播网络 识别 反向传播神经网络_反向传播算法_129

b-2) 如果当前是卷积层:则有手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_130

b-3) 如果当前是池化层:则有手写反向传播网络 识别 反向传播神经网络_反向传播算法_131, 这里的pool指按照池化区域大小k和池化标准将输入张量缩小的过程。

c) 对于输出层第L层:手写反向传播网络 识别 反向传播神经网络_DNN_132

c) 通过损失函数计算输出层的手写反向传播网络 识别 反向传播神经网络_卷积_133

d) for手写反向传播网络 识别 反向传播神经网络_卷积_57= L-1 to 2, 根据下面3种情况进行进行反向传播算法计算:

d-1) 如果当前是全连接层:手写反向传播网络 识别 反向传播神经网络_卷积_135

d-2) 如果当前是卷积层:手写反向传播网络 识别 反向传播神经网络_卷积_136

d-3) 如果当前是池化层:手写反向传播网络 识别 反向传播神经网络_DNN_137

  • 2-2) for手写反向传播网络 识别 反向传播神经网络_DNN_138= 2 to L,根据下面2种情况更新第手写反向传播网络 识别 反向传播神经网络_DNN_138层的手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_140:

2-2-1) 如果当前是全连接层:手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_141手写反向传播网络 识别 反向传播神经网络_反向传播算法_142

2-2-2) 如果当前是卷积层,对于每一个卷积核有:手写反向传播网络 识别 反向传播神经网络_DNN_143手写反向传播网络 识别 反向传播神经网络_DNN_144

  • 2-3) 如果所有手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_145的变化值都小于停止迭代阈值手写反向传播网络 识别 反向传播神经网络_手写反向传播网络 识别_146,则跳出迭代循环到步骤3。
  • 3) 输出各隐藏层与输出层的线性关系系数矩阵手写反向传播网络 识别 反向传播神经网络_卷积_147和偏倚向量手写反向传播网络 识别 反向传播神经网络_DNN_148

参考资料:

1) Neural Networks and Deep Learning

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

3) UFLDL Tutorial

4)CS231n Convolutional Neural Networks for Visual Recognition, Stanford