Tensorflow——conv2d_transpose反卷积踩坑实录

1. 背景

    对占位符x进行反卷积操作。因为占位符中batch_size设置为None,而tf.nn.conv2d_transpose函数需要指定output_shape, 于是使用tf.shape()函数构建output_shape,让output_shape的batch_size保持与x动态一致。代码如下。

import tensorflow as tf


def unconv(x):
    x= tf.reshape(x, [-1, 32, 1, 64])
    output_shape = [tf.shape(x)[0], tf.shape(x)[1]*2, tf.shape(x)[2], tf.shape(x)[3]]
    batch, h, w, channels = x.get_shape().as_list()

    # 使用tf.shape()得到的是tensor,用于初始化权值变量时,这个维度变量也需要初始化,这时就会
    # 面临占位符没有no feed的问题。
    initial_state = tf.random.uniform([3, 1, tf.shape(x)[3], tf.shape(x)[3]], minval = -1, maxval = 1)

    filter_w = tf.Variable(initial_state)
    return tf.nn.conv2d_transpose(input = x, filters = filter_w, output_shape = output_shape, padding = "SAME", strides = [1,2,1,1])


if __name__ == "__main__":
    
    tf.compat.v1.disable_eager_execution()

    x = tf.compat.v1.placeholder(dtype = tf.float32, shape = [None, 2048])
    y = unconv(x)

    num = 32
    input_list = [[1. for i in range(2048)] for i in range(num)]

    with tf.compat.v1.Session() as sess:
        tf.compat.v1.global_variables_initializer().run()
        y = y.eval(feed_dict = {x: input_list})
        print(tf.shape(y))

2. 现象

    运行上述代码,tensorflow会在变量初始化时报错,说You must feed a value for placeholder tensor 'Placeholder' with dtype float and shape. 哟,这可难为人了。因为变量初始化的时候不需要给占位符赋值的。那这里为什么会报这个错误呢。

Tensorflow——conv2d_transpose反卷积踩坑实录_第1张图片

     这就是因为当我们使用tf.shape()获取x的维度时,返回的是tensor变量。然后我们在创建权值变量时,即下面代码中,把权值变量的维度设定成了一个tensor。变量初始化到这个initial_state的时候便会报错。

initial_state = tf.random.uniform([3, 1, tf.shape(x)[3], tf.shape(x)[3]], minval = -1, maxval = 1)

    这时,我们可以把这段代码进行修改。把它变成下面的样子就能避免错误了:

batch, h, w, channels = x.get_shape().as_list()
initial_state = tf.random.uniform([3, 1, channels , channels], minval = -1, maxval = 1)

    此时修改的完整代码如下。再次运行就不会报错了。

import tensorflow as tf


def unconv(x):
    x= tf.reshape(x, [-1, 32, 1, 64])
    output_shape = [tf.shape(x)[0], tf.shape(x)[1]*2, tf.shape(x)[2], tf.shape(x)[3]]
    batch, h, w, channels = x.get_shape().as_list()

    # 使用tf.shape()得到的是tensor,用于初始化权值变量时,这个维度变量也需要初始化,这时就会
    # 面临占位符没有no feed的问题。
    batch, h, w, channels = x.get_shape().as_list()
    initial_state = tf.random.uniform([3, 1, channels, channels], minval = -1, maxval = 1)

    filter_w = tf.Variable(initial_state)
    return tf.nn.conv2d_transpose(input = x, filters = filter_w, output_shape = output_shape, padding = "SAME", strides = [1,2,1,1])


if __name__ == "__main__":
    
    tf.compat.v1.disable_eager_execution()

    x = tf.compat.v1.placeholder(dtype = tf.float32, shape = [None, 2048])
    y = unconv(x)

    num = 32
    input_list = [[1. for i in range(2048)] for i in range(num)]

    with tf.compat.v1.Session() as sess:
        tf.compat.v1.global_variables_initializer().run()
        y = y.eval(feed_dict = {x: input_list})
        print(tf.shape(y))

3. 结论

    tf.shape()与get_shape()的功能都是获得tensor的维度,但是它们可以使用的场景是完全不同的,所以用起来还是要小心一点儿。

你可能感兴趣的:(tensorflow,网络算法,tensorflow,深度学习)