看见很多教学对于CNN的反向传播好像都是一笔带过,因为在反向传播首次出现一般在普通神经网络,讲解完普通神经网络之后,对于CNN的反向传播就忽略了,不过CNN的反向传播依旧有非常多的细节,今天我就带大家将这些细节一一梳理。
1.损失如何传回特征图?
假设我们的特征图是由5X5输入图,经过3x3的卷积核,步幅为二得到的特征图:

这一步暂时不用深究卷积怎么算的,后面会讲到
然后我们展平Z:

所以:Z = 0,1,1,2,
Flatten 没有进行乘法或加法,只是重新排列。
为什么要这样做?因为后面要接一个全连接层,它需要把这四个数字当作四个输入。
继续
请看下图:

我们现在有四个输入:
给了一个权重矩阵:
先别被矩阵吓到。
它的意思就是:每一个输入都会通过不同权重,连接到两个输出神经元。第一列就是Y1对于Z的权重,第二列就是Y2对于Z的权重
将Z与V_flat进行乘积,得到Y = 2,-2,也就是Y1与Y2
你看,四个输入就这样变成了两个输出。
这是理解后面反向传播的关键。
我们继续
现在模型预测的是:
Y=2,-2
但我们的真实目标是:
T=1,0
也就是模型希望第一个输出是 1,第二个输出是 0。
可是它实际输出了 2 和 -2,所以预测有误差。
使用平方误差损失:
代入刚才算出的结果:
这个 2.5 就是总损失。
接下来分别对两个输出求偏导数。
第一个输出:

第二个输出:

所以:

这里的 就是损失对两个输出的梯度。
它表示:
-
第一个输出
增加一点,损失倾向于增加,所以希望它减小。
-
第二个输出
增加一点,损失倾向于减小,所以希望它从 -2 往 0 靠近。
因此,梯度既告诉我们方向,也告诉我们损失对变化有多敏感。
刚才我们已经知道,两个输出收到的梯度是:

现在的问题是:
两个输出的梯度,怎么传回四个输入 呢?
答案是:沿着原来的连接往回走,每条梯度乘以对应的连接权重。

Z1对于Y1的权重连接为0,所以Z1只能影响到Y2,如果Z1和Y1之间有权重连接,也要计算其数值后再与Z1对于Y2的梯度相加
根据链式法则:

于是我们得到Z1的梯度为2
同理得到

再提醒一个容易混淆的地方: 是输入数值,
是它们对应的梯度,二者不是同一个东西。
现在恢复形状:

于是最终得到:

2.特征图梯度传回卷积核权重怎么传?
先回顾上一节的结果。
我们有一张 5×5 的输入图像 ,一个 3×3 的卷积核
经过卷积,得到 2×2 的特征图
G是我们特征图的梯度,并非参与了前向传播

现在我们要继续求:

什么意思?
就是想知道,卷积核 W 里面的 9 个权重,每一个应该怎样改变,才能让损失减小。

这一节的核心就是:用已经知道的四个梯度,计算卷积核九个权重的梯度。
卷积核可以理解为一个 3×3 的小窗口,每次从输入图像中取出 3×3 的区域。
由于步幅是 2,所以窗口每次往右或者往下移动两格。

这样就得到四个输入窗口,分别叫:

它们分别对应特征图的左上、右上、左下、右下四个输出位置。
注意:这里的下标从 0 开始,例如 表示右下角的输入窗口。
非常重要:四个窗口使用的是同一个卷积核 W,而不是四个不同的卷积核。
这就叫权重共享。

卷积到底是怎么算的?我再重复一下吧
拿右下角的窗口 来举例。

卷积核仍然是:

卷积的计算方法非常直接:
对应位置相乘,再把九个结果加起来。
W乘以P11 = 2
于是得到:

继续:
现在我们得到了特征图的梯度:

我们要求损失函数对于卷积核W的梯度,现在我们只知道Z的梯度,如何知道W的梯度呢?
我们拆开来看,假设我们要求卷积核中心的梯度,也就是1所在的位置,其余位置同理:
我们的问题是:

卷积核中间的 1,如果变大一点,最终损失 L 会怎样变化?
这就是在求卷积核中心权重的梯度。
这个卷积核在输入图像上移动了四次。产生四个输出。

现在只盯住这四个橙色数字:

为什么要看它们?
因为我们要求的是卷积核中心权重的梯度。
卷积是对应位置相乘的,所以卷积核中心权重每次都和输入窗口的中心数值相乘。
上一节已经算出:

它告诉我们每个特征图位置发生微小变化时,对最终损失的影响。
例如,右上角的梯度为 2,意思是右上角输出增加很小的一点,损失的变化量大约是它的 2 倍。
现在我们把刚才四个位置的变化和梯度结合起来。

所以中心权重的梯度就是:

刚才我们做的是:

其实对于每一个权重,都要做同样的事情。
不过有一个更方便的方法:
把特征图的每个梯度,乘以它对应的整个 3×3 输入窗口。
例如右下角:

它对应的输入窗口是:

因此,这个输出位置对整个卷积核梯度的贡献是:


类似地:

-
左上角:
-
右上角:
-
左下角:
-
右下角:
得到:

最后得到:

所以你可以把整个过程理解为:

注意:不是把 2×2 的梯度直接变形成 3×3,而是借助四个输入窗口,通过链式法则算出 3×3 的权重梯度。
最终的更新:

3.均匀池化和最大池化如何传递梯度?
先带大家回顾一下池化操作
上一节卷积后,我们得到了特征图:

现在池化(Pooling)要做的事,就是把这四个数变成一个数。
池化有两种方式:

注意,池化和卷积不一样。这里的池化操作没有需要学习的卷积核权重,只是按照固定规则选最大值或者计算平均值。
我们先来看最大池化,请看下图:

大家发现只有当前右下角的输入发生微小变化时,池化输出才会跟着发生变化。
我们把这种关系写成局部导数:

你可以这样理解:
-
0:这个位置稍微变化,不影响池化输出。
-
1:这个位置增加一点,池化输出就增加同样多。
这个矩阵叫 MAX 池化的局部掩码(Mask)。
我们继续,池化后依旧要连接两个输出神经元

连接权重是:

因此:

MAX 池化得到 ,所以:

真实目标仍是:1,0
平方误差损失求导后,两个输出的梯度为:

现在把这两个梯度传回 F。
第一条连接权重是 1,第二条连接权重是 -1,所以:

这一步和上一节全连接层反向传播的计算方法完全一样。
接下来,才轮到 MAX 池化发挥作用。
因为 MAX 的局部导数是:

所以让收到的梯度 3 乘上这个掩码:

最终:


所以,MAX 池化不是把梯度分给所有人,而是谁在前向传播时被选中,反向传播时谁收到梯度。
本例的最大值是唯一的。如果出现多个并列最大值,梯度的具体分配取决于实现方式。
现在换成平均池化。
还是这四个数字:

前向过程:

和 MAX 最大池化不同,AVG 的输出是四个数字共同计算得到的。
我们还是用刚才的方法来理解导数。
假设只把左上角的 0 增加 0.04:


因此:

这就是该位置的局部导数:

其他三个位置的计算方法完全相同,因为平均池化对每个位置都乘了四分之一。
所以:

现在你应该能看到两个池化的根本区别:
-
MAX 只依赖当前最大的那个数字。
-
AVG 同时依赖所有四个数字,而且每个位置的局部导数一样。
我们刚才知道 MAX 收到的上游梯度是 3。
但是 AVG 收到的上游梯度不是 3,而是 1!
为什么?
因为 AVG 的前向输出与 MAX 不同。
AVG输入两个输出神经元的数值是1,MAX输入两个神经元的数值是2,由于我们固定了输入到输出的权重,所以在这个例子里面就会导致两个输出神经元的值不一样,实际上这里的权重依旧会进行更新与训练。
由于 AVG 收到的上游梯度是 1。
接下来再乘每个位置的局部导数 1/4:

得到:


这里要区分两件事:
局部传播规则取决于 MAX 或 AVG 的运算方式;而实际收到的上游梯度还取决于前向输出和后面的损失函数。
所以这份案例中,MAX 收到 3,而 AVG 收到 1。
4.池化的梯度怎样继续传到卷积核?
记得上一节的规则吗?

简单说:
每个特征图位置的梯度,乘它对应的 3×3 输入窗口,然后全部相加。
对于 MAX:

只有右下角的梯度非零,所以:

右下角输入窗口为:

得到:

请注意:MAX 只让特征图中的一个位置收到梯度,但这个位置仍然可以影响卷积核里的多个权重。
对于 AVG:

所以四个窗口都需要参与:

得到:

这样我们就从池化一路传到了卷积核。
来个小题:


番外:1X1卷积核梯度传递
有个特别重要的知识点,也是很多人第一次学反向传播时容易搞混的地方:
同一层收到梯度后,需要计算两种不同的梯度:
-
传给上一层输入的梯度。
-
传给本层权重参数的梯度。
这两个梯度不是一回事,计算方法也不一样。
前面我们学过 3×3 卷积,它每次取 3×3 的输入区域,逐格相乘,再加起来。
但 1×1 卷积更简单。
在这份单通道例子里,1×1 卷积就是每个位置乘同一个权重 q。

与之前的全连接层反向传播完全相同。

经过 Flatten 和全连接层,得到:

沿着原来的全连接权重反向传播。
得到 H 的梯度:

接下来把梯度传回输入 Z
我们有一个最简单的关系:

链式法则:

于是

这是我们要回传的梯度,同时我们还要更新1x1卷积核自己的梯度
还是从:

因此:

右下角 H 收到的梯度为 3,所以这个位置对 q 的梯度贡献为:2x3 = 6

于是我们可以得到总结:
