如何更新反卷积层的权重?

8
我正在尝试开发一个反卷积层(或者更准确地说是转置卷积层)。
在前向传递中,我执行完整的卷积(使用零填充进行卷积)。 在反向传递中,我执行有效的卷积(不使用填充进行卷积)以将误差传递到前一层。
偏差的梯度很容易计算,只需要对超出的维度取平均即可。
问题是我不知道如何更新卷积滤波器的权重。梯度是什么?我确定这是一个卷积操作,但我不知道如何进行。我尝试了输入和误差之间的有效卷积,但没有成功。

你解决了这个问题吗?我遇到了类似的情况 - 在caffe中,反卷积层特征的所有导数始终为0。 - Alex
很遗憾,目前还没有。我一直在使用带填充的标准卷积层,以便它们不改变尺寸,并像这样构建自动编码器。 - Baptiste Wicht
1个回答

2

反卷积解释

首先,反卷积 卷积层,只是用于不同的目的,即上采样(为什么有用在这篇论文中有解释)。

例如,这里有一个2x2的输入图像(蓝色底部图像),将其上采样到4x4(绿色顶部图像):

deconvolution

为了使它成为有效的卷积,首先对输入进行填充,使其变为6x6,然后应用3x3的滤波器而没有步幅。就像在普通的卷积层中一样,您可以选择不同的填充/步幅策略来产生所需的图像大小。

反向传播

现在应该清楚了,反卷积的反向传播是卷积层的反向传播的一个部分情况,具有特定的步幅和填充。我认为您已经完成了它,但这里是一个天真(而不是非常有效)的实现,适用于任何步幅和填充:

# input: x, w, b, stride, pad, d_out
# output: dx, dw, db <- gradients with respect to x, w, and b

N, C, H, W = x.shape
F, C, HH, WW = w.shape
N, C, H_out, W_out = d_out.shape

x_pad = np.pad(x, pad_width=((0, 0), (0, 0), (pad, pad), (pad, pad)), mode='constant', constant_values=0)

db = np.sum(d_out, axis=(0, 2, 3))

dw = np.zeros_like(w)
dx = np.zeros_like(x_pad)
for n in xrange(N):
  for f in xrange(F):
    filter_w = w[f, :, :, :]
    for out_i, i in enumerate(xrange(0, H, stride)):
      for out_j, j in enumerate(xrange(0, W, stride)):
        dw[f, :, :, :] += d_out[n, f , out_i, out_j] * x_pad[n, :, i:i+HH, j:j+WW]
        dx[n, :, i:i+HH, j:j+WW] += filter_w * d_out[n, f, out_i, out_j]
dx = dx[:,:,1:H+1,1:W+1]

同样的操作可以使用im2colcol2im更高效地完成,但这只是一种实现细节。另一个有趣的事实是,卷积操作(对于数据和权重的反向传播)的反向传递再次是卷积,但使用空间翻转的滤波器。
以下是如何应用它(普通的SGD):
# backward_msg is the message from the next layer, usually ReLu
# conv_cache holds (x, w, b, conv_params), i.e. the info from the forward pass
backward_msg, dW, db = conv_backward(backward_msg, conv_cache)
w = w - learning_rate * dW
b = b - learning_rate * db

如您所见,这很简单,只需要理解您正在应用相同的卷积即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接