Affine层(仿射变换)的误差反向传播图如下:
image.png
正向传播的公式:
Y = X * W + B
这里X, W均为矩阵,其中X为输入数据,W为权重值, B为偏置值且是一个行向量。对上述公式的python代码如下:
X = np.array([[0, 0, 0], [10, 10, 10]])
B = np.array([1, 2, 3])
print(X_dot_W)
print(X_dot_W + B)
结果为
[[ 0 0 0]
[10 10 10]]
[[ 1 2 3]
[11 12 13]]
可以看到,X * W中的两个数据的每一个元素都被加上了偏置。正向传播的时候,偏置会被加到每一个数据上。因此,反向传播的时候,各个数据的反向传播的值需要汇总为偏置的元素。python代码如下所示:
dY = np.array([[1, 2, 3], [4, 5, 6]])
dB = np.sum(dY, axis=0)
print(dB)
结果为:
[5 7 9]
可能你不懂该代码上面的一行是什么意思,也不懂代码是什么意思。但是我们需要明白的一点是,任何参数的偏导数都与该参数的矩阵形状一致。比如,反向传播时候我们求X,W的偏导数都与X,W的形状一致。因此,我们很容易得出偏置B的偏导数也应该是一个形状为1*3的行向量。接下来我们分析这句话“反向传播的时候,各个数据的反向传播的值需要汇总为偏置的元素”,看似很难理解,我们再看与它对应的代码:
dB = np.sum(dY, axis=0) #axis=0 表示将向量沿y=0方向相加(纵向)
该代码的含义有两点:
- 将这个矩阵纵向按行相加
- 去掉np.array最外层的[ ]
第二点我在上面已经解释清楚就是偏导数和变量要在矩阵形状上保持一致,对于第一点,为什么我们要将向量纵向相加呢?让我们好好思考一下dB的含义:它是表示偏置的返回量。我们在做正向传播的时候,偏置加到的是每一个向量上,也就是说每一幅图片,在其中三个元素表示的位置上,都增加了偏置,所以反向传播的时候,返回的应该是这三个位置的偏执的总和。所以第一个偏置的和为1+4=5,第二个为2+5=7,第三个为3+6=9,因此我们就可以理解了在仿射变化的误差反向传播中,关于偏置的反向传播的计算问题。