conv2d_transpose()
操作的文档没有清楚地解释它的作用:
conv2d的转置。
这种操作有时被称为Deconvolutional Networks之后的“反卷积”,但实际上是conv2d的转置(梯度),而不是实际的反卷积。
我看了医生所指的那篇论文,但没有帮助。
这个操作是做什么的,你为什么想要使用它的例子有哪些?
发布于 2016-09-07 23:13:05
这是我在网上看到的最好的解释,卷积转置是如何工作的here。
我将给出我自己的简短描述。它以分数步长应用卷积。换句话说,将输入值(用零)隔开,以便在可能小于过滤器大小的区域上应用过滤器。
至于为什么人们会想要使用它。它可以用作一种具有学习权重的上采样,而不是双线性插值或其他固定形式的上采样。
发布于 2017-06-04 12:33:10
这是从“梯度”角度的另一个观点,也就是为什么TensorFlow文档说conv2d_transpose()
“实际上是conv2d的转置(gradient),而不是实际的反卷积”。有关在此conv2d_transpose
**,中完成的实际计算的更多详细信息,我强烈建议从第19页开始使用[]。**
四个相关函数
在tf.nn
中,有4个密切相关且相当混乱的二维卷积函数:
tf.nn.conv2d
tf.nn.conv2d_backprop_filter
tf.nn.conv2d_backprop_input
tf.nn.conv2d_transpose
一句话总结:它们都是二维卷积。它们的不同之处在于输入参数排序、输入旋转或转置、步长(包括分数步长)、填充等。有了tf.nn.conv2d
,可以通过转换输入和更改conv2d
参数来实现所有其他3个操作。
问题设置
向前和向后computations:的
# forward
out = conv2d(x, w)
# backward, given d_out
=> find d_x?
=> find d_w?
在正演计算中,我们用滤波器w
计算输入图像x
的卷积,结果是out
。在反向计算中,假设我们给定了d_out
,它是梯度w.r.t。out
。我们的目标是找到d_x
和d_w
,它们是梯度w.r.t。x
和w
。
为了便于讨论,我们假设:
所有的步长大小都是1
1
out_channels
VALID
简短的回答
从概念上讲,在上述假设下,我们有以下关系:
out = conv2d(x, w, padding='VALID')
d_x = conv2d(d_out, rot180(w), padding='FULL')
d_w = conv2d(x, d_out, padding='VALID')
其中rot180
是旋转180度的2d矩阵(左右翻转和自上而下翻转),FULL
的意思是“在与输入部分重叠的地方应用滤波器”(参见theano docs)。请注意,这仅适用于上述假设,但是,可以更改conv2d参数以对其进行泛化。
关键要点:
输入梯度d_x
是输出梯度d_out
和权重w
的卷积,具有一定的权值梯度d_w
是输入x
和输出梯度d_out
的卷积,具有一定的权重
长长的答案
现在,让我们给出一个实际的工作代码示例,说明如何使用上面的4个函数在给定d_out
的情况下计算d_x
和d_w
。这显示了conv2d
、conv2d_backprop_filter
、conv2d_backprop_input
和conv2d_transpose
是如何相互关联的。Please find the full scripts here。
以4种不同的方式计算d_x
:
# Method 1: TF's autodiff
d_x = tf.gradients(f, x)[0]
# Method 2: manually using conv2d
d_x_manual = tf.nn.conv2d(input=tf_pad_to_full_conv2d(d_out, w_size),
filter=tf_rot180(w),
strides=strides,
padding='VALID')
# Method 3: conv2d_backprop_input
d_x_backprop_input = tf.nn.conv2d_backprop_input(input_sizes=x_shape,
filter=w,
out_backprop=d_out,
strides=strides,
padding='VALID')
# Method 4: conv2d_transpose
d_x_transpose = tf.nn.conv2d_transpose(value=d_out,
filter=w,
output_shape=x_shape,
strides=strides,
padding='VALID')
以三种不同的方式计算d_w
:
# Method 1: TF's autodiff
d_w = tf.gradients(f, w)[0]
# Method 2: manually using conv2d
d_w_manual = tf_NHWC_to_HWIO(tf.nn.conv2d(input=x,
filter=tf_NHWC_to_HWIO(d_out),
strides=strides,
padding='VALID'))
# Method 3: conv2d_backprop_filter
d_w_backprop_filter = tf.nn.conv2d_backprop_filter(input=x,
filter_sizes=w_shape,
out_backprop=d_out,
strides=strides,
padding='VALID')
tf_rot180
、tf_pad_to_full_conv2d
、tf_NHWC_to_HWIO
的实现请参考full scripts。在脚本中,我们检查不同方法的最终输出值是否相同;也可以使用numpy实现。
发布于 2017-07-14 23:01:55
conv2d_transpose()简单地将权重转置并翻转180度。然后它应用标准的conv2d()。“转置”实际上意味着它改变了权重张量中“列”的顺序。请检查下面的示例。
这里有一个使用卷积的示例,其中stride=1和padding=‘相同’。这是一个简单的情况,但同样的推理也可以应用于其他情况。
假设我们有:
权重输入: MNIST图像28x28x1,shape = 28,28,1
如果我们对输入进行卷积,那么将的激活具有以下形状: 1,28,28,32。
activations = sess.run(h_conv1,feed_dict={x:np.reshape(image,[1,784])})
其中:
W_conv1 = weight_variable([7, 7, 1, 32])
b_conv1 = bias_variable([32])
h_conv1 = conv2d(x, W_conv1, strides=[1, 1, 1, 1], padding='SAME') + b_conv1
为了获得“反卷积”或“转置卷积”,我们可以这样对卷积激活使用conv2d_transpose():
deconv = conv2d_transpose(activations,W_conv1, output_shape=[1,28,28,1],padding='SAME')
或者使用conv2d(),我们需要转置和翻转权重:
transposed_weights = tf.transpose(W_conv1, perm=[0, 1, 3, 2])
在这里,我们将“列”的顺序从0, 1,2,3改为0,1,3,2。因此,我们将从7,7,1,32获得一个带有shape=7,7,32,1的张量。然后我们反转权重:
for i in range(n_filters):
# Flip the weights by 180 degrees
transposed_and_flipped_weights[:,:,i,0] = sess.run(tf.reverse(transposed_weights[:,:,i,0], axis=[0, 1]))
然后我们可以用conv2d()计算卷积如下:
strides = [1,1,1,1]
deconv = conv2d(activations,transposed_and_flipped_weights,strides=strides,padding='SAME')
我们会得到和以前一样的结果。使用conv2d_backprop_input()也可以获得完全相同的结果:
deconv = conv2d_backprop_input([1,28,28,1],W_conv1,activations, strides=strides, padding='SAME')
结果如下所示:
Test of the conv2d(), conv2d_tranposed() and conv2d_backprop_input()
我们可以看到结果是一样的。要以更好的方式查看它,请查看我的代码:
https://github.com/simo23/conv2d_transpose
在这里,我使用标准的conv2d()复制conv2d_transpose()函数的输出。
https://stackoverflow.com/questions/39373230
复制相似问题