TF - Transpose convolution

2019-01-17  本文已影响0人  大地瓜_
  1. 反卷积经常被翻译为deconvolution layer,但是实际上我们应该称为transposed convolution layer

  2. 在讨论二维反卷积的时候,其实就是就是一个卷积的过程

如图看下面的卷积过程。设置输入为[4 4]的块,[3 3]的卷积核,卷积步长为2,周围不补0。

conv

上图中的卷积过程的输出为2*2的图像块。

现在我们将输入图像块shape = [ 4, 4], 然后将修改为[ 16, 1]向量X,同理输出输出也可以定义[4,1]向量Y,则卷积过程为 Y = C X 其中C为权重组成的矩阵, shape = [4, 16], 其实实现了一个矩阵的变换,其中参数和卷积核中参数对应。

  1. 反卷积对应相同的过程,其中C矩阵也是需要训练的矩阵

这种可以理解为一种反卷积的理解

deconv

具体的tensorflow实现 - tf.nn.conv2d_transpose & tf.layer.conv2d_transpose

tf.nn.conv2d_transpose(value, filter, output_shape, strides, padding="SAME", data_format="NHWC", name=None)

* 第一个参数value:指需要做反卷积的输入图像,它要求是一个Tensor
* 第二个参数filter:卷积核,它要求是一个Tensor,具有[filter_height, filter_width, out_channels, in_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,卷积核个数,图像通道数]
* 第三个参数output_shape:反卷积操作输出的shape,细心的同学会发现卷积操作是没有这个参数的,那这个参数在这里有什么用呢?下面会解释这个问题
* 第四个参数strides:反卷积时在图像每一维的步长,这是一个一维的向量,长度4
* 第五个参数padding:string类型的量,只能是"SAME","VALID"其中之一,这个值决定了不同的卷积方式
* 第六个参数data_format:string类型的量,'NHWC'和'NCHW'其中之一
   这是tensorflow新版本中新加的参数,它说明了value参数的数据格式。  
   'NHWC'指tensorflow标准的数据格式[batch, height, width, in_channels]
   'NCHW'指Theano的数据格式[batch, in_channels,height, width]
   当然默认值是'NHWC'

需要注意的地方如下

* tf.nn.conv2d中的filter参数,是[filter_height, filter_width, in_channels, out_channels]的形式
* tf.nn.conv2d_transpose中的filter参数,是[filter_height, filter_width, out_channels,in_channels]的形式
注意in_channels和out_channels反过来了!因为两者互为反向,所以输入输出要调换位置

# 确定输入图像的大小 https://blog.csdn.net/wuzqchom/article/details/74785643
# W为输入图像的size, F为核的size, S为步长
# valid mode 
new_height = new_width = floor((W-F+1) / S)  
# same mode
new_height = new_width = floor(W / S) 

举例说明

x1 = tf.constant(1.0, shape=[1,3,3,1])
kernel = tf.constant(1.0, shape=[3,3,3,1])
x2 = tf.constant(1.0, shape=[1,6,6,3])
x3 = tf.constant(1.0, shape=[1,5,5,3])

y2 = tf.nn.conv2d(x3, kernel, strides=[1,2,2,1], padding="SAME")
# 1,3,3,1]的Tensor 
# same 周围补0

y3 = tf.nn.conv2d_transpose(y2,kernel,output_shape=[1,5,5,3], strides=[1,2,2,1],padding="SAME")
# [1,5,5,3]的Tensor

tf.nn.conv2d_transpose的output_shape 因为知道了原图,卷积核,步长显然是可以推出输出图像大小的,那为什么要指定output_shape呢?

y4 = tf.nn.conv2d(x2, kernel, strides=[1,2,2,1], padding="SAME")
# [1,3,3,1] tensor
# [1,6,6,3]和[1,5,5,3]的图经过卷积得到了相同的大小,[1,3,3,1]
# 产生了两种情况。所以这里指定output_shape是有意义

# 随意指定output_shape是不允许的,如下情况程序会报错
y5 = tf.nn.conv2d_transpose(x1, kernel,output_shape=[1,10,10,3],strides=[1,2,2,1],padding="SAME")

tf.layers.conv2d_transpose(inputs, filters, kernel_size, strides, padding)
参数意义
1. inputs是输入的tensor;
2. filters是反卷积后得到的特征图数量;
3. kernel_size是卷积核大小;
4. strides是移动步长;
5. padding是填充方式;

把卷积操作conv2d视为一个正操作和conv2d_transpose视为一个反操作。求conv2d_transpose操作得到的特征图维度,我们可以通过卷积正操作来反推

具体的例子如下

import tensorflow as tf  

x1 = tf.ones(shape=[64,7,7,256])  

y1 = tf.layers.conv2d_transpose(x1, 128, [3, 3], strides=1, padding='valid')  

with tf.Session() as sess:  

    sess.run(tf.global_variables_initializer())  
    y1_value=sess.run([y1])
    print("y1_value.shape:",y1_value[0].shape)

## y1_value.shape: (64, 9, 9, 128)

解释说明
经过的反卷积操作得的特征图大小为99,而特征图大小为99经过卷积正操作(卷积参数大小与反卷积的参数相同 如kernel_size,strides,padding)会得到7*7大小的特征图跟x1是一样,也就是与反卷积的输入尺寸是一致。若卷积和反卷积的参数相同(主要是kernel_size,strides,padding),反卷积得到的输出维度等于正卷积的输入维度。

import tensorflow as tf  

x1 = tf.ones(shape=[64,7,7,256])  

y1 = tf.layers.conv2d_transpose(x1, 128, [3, 3], strides=1, padding='same')  

with tf.Session() as sess:  

    sess.run(tf.global_variables_initializer())  
    y1_value=sess.run([y1])
    print("y1_value.shape:",y1_value[0].shape)

## y1_value.shape: (64, 7, 7, 128)
上一篇下一篇

猜你喜欢

热点阅读