首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >TensorFlow的`conv2d_transpose()`操作是做什么的?

TensorFlow的`conv2d_transpose()`操作是做什么的?
EN

Stack Overflow用户
提问于 2016-09-07 22:55:19
回答 6查看 33.8K关注 0票数 45

conv2d_transpose()操作的文档没有清楚地解释它的作用:

conv2d的转置。

这种操作有时被称为Deconvolutional Networks之后的“反卷积”,但实际上是conv2d的转置(梯度),而不是实际的反卷积。

我看了医生所指的那篇论文,但没有帮助。

这个操作是做什么的,你为什么想要使用它的例子有哪些?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2016-09-07 23:13:05

这是我在网上看到的最好的解释,卷积转置是如何工作的here

我将给出我自己的简短描述。它以分数步长应用卷积。换句话说,将输入值(用零)隔开,以便在可能小于过滤器大小的区域上应用过滤器。

至于为什么人们会想要使用它。它可以用作一种具有学习权重的上采样,而不是双线性插值或其他固定形式的上采样。

票数 48
EN

Stack Overflow用户

发布于 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:的

代码语言:javascript
复制
# 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_xd_w,它们是梯度w.r.t。xw

为了便于讨论,我们假设:

所有的步长大小都是1

  • All填充和奇数都是1

  • Use out_channels VALID

  • 奇数过滤器大小,这避免了一些不对称的形状问题

简短的回答

从概念上讲,在上述假设下,我们有以下关系:

代码语言:javascript
复制
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_xd_w。这显示了conv2dconv2d_backprop_filterconv2d_backprop_inputconv2d_transpose是如何相互关联的。Please find the full scripts here

以4种不同的方式计算d_x

代码语言:javascript
复制
# 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

代码语言:javascript
复制
# 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_rot180tf_pad_to_full_conv2dtf_NHWC_to_HWIO的实现请参考full scripts。在脚本中,我们检查不同方法的最终输出值是否相同;也可以使用numpy实现。

票数 29
EN

Stack Overflow用户

发布于 2017-07-14 23:01:55

conv2d_transpose()简单地将权重转置并翻转180度。然后它应用标准的conv2d()。“转置”实际上意味着它改变了权重张量中“列”的顺序。请检查下面的示例。

这里有一个使用卷积的示例,其中stride=1和padding=‘相同’。这是一个简单的情况,但同样的推理也可以应用于其他情况。

假设我们有:

权重输入: MNIST图像28x28x1,shape = 28,28,1

  • Convolutional layer: 32个滤镜,7x7,
  • = 7,7,1,32,name = W_conv1

如果我们对输入进行卷积,那么将的激活具有以下形状: 1,28,28,32。

代码语言:javascript
复制
 activations = sess.run(h_conv1,feed_dict={x:np.reshape(image,[1,784])})

其中:

代码语言:javascript
复制
 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():

代码语言:javascript
复制
  deconv = conv2d_transpose(activations,W_conv1, output_shape=[1,28,28,1],padding='SAME')

或者使用conv2d(),我们需要转置和翻转权重:

代码语言:javascript
复制
  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的张量。然后我们反转权重:

代码语言:javascript
复制
  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()计算卷积如下:

代码语言:javascript
复制
  strides = [1,1,1,1]
  deconv = conv2d(activations,transposed_and_flipped_weights,strides=strides,padding='SAME')

我们会得到和以前一样的结果。使用conv2d_backprop_input()也可以获得完全相同的结果:

代码语言:javascript
复制
   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()函数的输出。

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39373230

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档