conv2d_transpose()只是将权重转置并将其翻转180度。然后,它应用标准的conv2d()。 “转置”实际上意味着它会更改权重张量中“列”的顺序。请检查以下示例。
这里有一个使用stride = 1和padding ='SAME'的卷积的例子。这是一个简单的案例,但其他案例也可以采用相同的推理。
说我们有:
- 输入:28x28x1的MNIST图像,形状= [28,28,1]
- 卷积层:32个7x7的滤镜,权重形状= [7,7,1,32],名称= W_conv1
如果我们对输入进行卷积,则的激活将具有以下形状:[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]中,我们将获得一个张量,其形状为= [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')
结果显示在这里:
测试conv2d(),conv2d_tranposed()和conv2d_backprop_input()
我们可以看到结果是相同的。要以更好的方式查看它,请在以下位置查看我的代码:
https://github.com/simo23/conv2d_transpose
在这里,我使用标准conv2d()复制conv2d_transpose()函数的输出。
0
conv2d_transpose()
操作的文档没有明确说明其作用:我浏览了文档所指向的论文,但没有帮助。
该操作有什么作用,为什么要使用它呢?