-
反卷积经常被翻译为
deconvolution layer
,但是实际上我们应该称为transposed convolution layer
-
在讨论二维反卷积的时候,其实就是就是一个卷积的过程
如图看下面的卷积过程。设置输入为[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], 其实实现了一个矩阵的变换,其中参数和卷积核中参数对应。
- 反卷积对应相同的过程,其中C矩阵也是需要训练的矩阵
这种可以理解为一种反卷积的理解
deconv具体的tensorflow
实现 - tf.nn.conv2d_transpose & tf.layer.conv2d_transpose
- tf.nn.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
和上文提到的tf.nn.conv2d_transpose
有明显的区别,设置也相对比较简单
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)
网友评论