第1关:实现卷积层的反向传播
任务描述
本关任务:实现卷积层的反向传播。
相关知识
为了完成本关任务,你需要掌握:卷积层的反向传播。
本实训内容可参考《深度学习入门——基于 Python 的理论与实现》一书中第5章的内容。
卷积层的反向传播
在之前的实训中,我们学习了卷积层的前向传播。我们知道,卷积层的前向传播通常先通过 im2col 操作将输入特征图转化成一个矩阵,其中矩阵的每一行对应于输入特征图在一个卷积窗口的所有通道内的数据,这样,卷积操作就被转化成了矩阵乘法。忽略掉偏置的计算(因为偏置的计算非常简单),卷积计算可以用下面的公式表示:
y^=x^×W^
这里,x^是输入x经过 im2col 计算后的结果。因为卷积层的权重W的形状通常是(C′,C,Kh,Kw),为了匹配上面矩阵乘法的形式,需要通过 reshape 和 transpose 操作将W转化为(C⋅Kh⋅Kw,C′)的形状,这里记这个矩阵为W^。得到的结果y^的形状是(B⋅H′⋅W′,C′),通过 reshape 和 transpose 操作将其变换成(B,C′,H′,W′)就是我们想要的结果了。
对于这个形式,你是否感觉有一点熟悉呢?没错,这与我们之前学习的全连接层的计算形式如出一辙,套用全连接层的反向传播公式:
∂W^∂l∂x^∂l=∂y^∂l⋅∂W^∂y^=x^×(∂y^∂l)T=∂y^∂l⋅∂x^∂y^=W^×∂y^∂l
最后,我们需要做的就是把∂l/∂x^变换为∂l/∂x,同时把把∂l/∂W^变换为∂l/∂W。对于后者,只要通过 transpose 和 reshape 操作还原为原来的形状即可。对于前者,我们需要通过 im2col 的逆运算——col2im——来降其转换为∂l/∂x。
卷积层反向传播的实现
实训拓展了在之前的实训定义的Convolution
类,实训已经给出了forward(x)
的实现,并针对反向传播的需要对其进行了一定的修改。你需要实现该类的反向传播函数backward(dout)
,dout
是损失函数相对卷积层输出的梯度,即之前公式中的∂y∂l,是一个形状为(B,C′,H′,W′)的numpy.ndarray
。实训已经提供了一个col2im
的实现,其可以将一个(B×H′×W′,C×Kh×Kw)的矩阵转化成(B,C,H,W)的特征图。
实训提供的col2im
函数的定义如下:col2im(col, input_shape, filter_h, filter_w, stride=1, pad=0)
,对应参数的含义分别为:
col
:变换后的矩阵;input_shape
:输入特征图的形状;filter_h
和filter_w
:池化窗口的宽和高;stride
:池化的步长;pad
:池化的填充。
编程要求
根据提示,在右侧编辑器 Begin 和 End 之间补充代码,实现上述卷积层的前向传播。
测试说明
平台会对你编写的代码进行测试,测试方法为:平台会随机产生输入x
、权重W
、偏置b
和输出梯度dout
,然后根据你的实现代码,创建一个Convolution
类的实例,然后利用该实例先进行前向传播计算,再进行反向传播计算。你的答案将并与标准答案进行比较。因为浮点数的计算可能会有误差,因此只要你的答案与标准答案之间的误差不超过10−5即可。
样例输入:
x:
[[[[0.11 0.65 0.08 0.28 0.77]
[0.12 0.29 0.77 0.58 0.11]
[0.44 0.43 0.4 0.28 0.87]
[0.52 0.78 0.99 0.58 0.13]
[0.46 0.31 0.9 0.19 0.3 ]]
[[0.12 0.65 0.58 0.44 0.9 ]
[0.23 0.34 0.96 0.94 0.37]
[0.63 0.17 0.61 0.22 0.98]
[0.91 0.32 0.78 0.61 0.42]
[0.21 0.01 0.9 0.06 0.2 ]]]
[[[0.79 0.36 0.39 0.6 0.12]
[0.84 0.62 0.32 0.84 0.69]
[0.34 0.21 0.03 0.17 0.22]
[0.6 0.19 0.4 1. 0.93]