tf.layers.conv2d_transpose
参数
conv2d_transpose(
inputs,
filters,
kernel_size,
strides=(1, 1),
padding=’valid’,
data_format=’channels_last’,
activation=None,
use_bias=True,
kernel_initializer=None,
bias_initializer=tf.zeros_initializer(),
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
trainable=True,
name=None,
reuse=None
)
比较关注的参数:
- inputs: 输入的张量
- filters: 输出卷积核的数量
- kernel_size : 在卷积操作中卷积核的大小
- strides: (不太理解,我直接理解成放大的倍数)
- padding : ‘valid’ 或者 ‘same’。
反卷积的过程
- Step 1 扩充: 将 inputs 进行填充扩大。扩大的倍数与strides有关。扩大的方式是在元素之间插strides - 1 个 0
- Step 2 卷积: 对扩充变大的矩阵,用大小为kernel_size卷积核做卷积操作,这样的卷积核有filters个,并且这里的步长为1(与参数strides无关,一定是1)
举个例子:
- inputs:[ [1, 1], [2,2] ]
- strides = 2(扩大2倍)
- filters = 1
- kernel_size = 3(假设核的值都是1)
- padding = ‘same’
Step 1:[2,2] 扩大至 [4,4]
- 问题描述:一个矩阵
X
,通过 3*3 大小的卷积核,以 ‘same’的padding形式,步长为2做卷积,得到 [[1,1],[2,2]],问
X 长啥样
[1212]→⎡⎣⎢⎢⎢0000010200000102⎤⎦⎥⎥⎥
通过填充,让原来2*2的矩阵变成4*4。填充的方式是我自己根据代码给出的结果猜的,大概就是先在元素之间插strides - 1个0,然后在填充边缘使矩阵达到目标尺寸。
目标尺寸可以根据下面的公式来求:
⌊(x−k+2∗p)/s⌋+1=o(1)
其中 x 为目标尺寸,k 是卷积核的尺寸, p 表示填充的个数,o 表示输出的尺寸, s 表示步长。
在这里,k,p,s,o 都是已知的,求 x 即可。但是因为有取整操作,实际上会有两个值符合x ,似乎是取大的那个。
在这个例子中 k=3,p=1,s=2,o=2 ,得到 x=4或x=3 ,取大的那个,所以 x=4
Step 2 : 做卷积,卷积核大小3*3, 步长为1
⎡⎣⎢⎢⎢0000010200000102⎤⎦⎥⎥⎥→⎡⎣⎢⎢⎢1132113222641132⎤⎦⎥⎥⎥
这一步就是普通的做卷积操作。
上代码
a = np.array([[1,1],[2,2]], dtype=np.float32)
# [[1,1],
# [2,2]]
# tf.layers.conv2d_transpose 要求输入是4维的
a = np.reshape(a, [1,2,2,1])
# 定义输入
x = tf.constant(a,dtype=tf.float32)
# 进行tf.layers.conv2d_transpose
upsample_x = tf.layers.conv2d_transpose(x, 1, 3, strides=2, padding='same', kernel_initializer=tf.ones_initializer())
with tf.Session() as sess:
tf.global_variables_initializer().run()
print(sess.run(upsample_x))
# [[[[1],[1],[2],[1]],
# [[1],[1],[2],[1]],
# [[3],[3],[6],[3]],
# [[2],[2],[4],[2]]]]