KongDeqiang
KongDeqiang

Reputation: 183

Tensorflow conv2d_transpose output_shape

I want to implement a Generative adversarial network (GAN) with unfixed input size, like 4-D Tensor (Batch_size, None, None, 3).

But when I use conv2d_transpose, there is a parameter output_shape, this parameter must pass the true size after deconvolution opeartion.

For example, if the size of batch_img is (64, 32, 32, 128), w is weight with (3, 3, 64, 128) , after

deconv = tf.nn.conv2d_transpose(batch_img, w, output_shape=[64, 64, 64, 64],stride=[1,2,2,1], padding='SAME')

So, I get deconv with size (64, 64, 64, 64), it's ok if I pass the true size of output_shape.

But, I want to use unfixed input size (64, None, None, 128), and get deconv with (64, None, None, 64).

But, it raises an error as below.

TypeError: Failed to convert object of type <type'list'> to Tensor...

So, what can I do to avoid this parameter in deconv? or is there another way to implement unfixed GAN?

Upvotes: 3

Views: 2135

Answers (3)

Jai
Jai

Reputation: 3310

  • The output shape list does not accept to have None in the list because the None object can not be converted to a Tensor Object
  • None is only allowed in shapes of tf.placeholder
  • for varying size output_shape instead of None try -1 for example you want size(64, None, None, 128) so try [64, -1, -1, 128]... I am not exactly sure whether this will work... It worked for me for batch_size that is my first argument was not of fixed size so I used -1
  • How ever there is also one high level api for transpose convolution tf.layers.conv2d_transpose()
  • I am sure the high level api tf.layers.conv2d_transpose() will work for you because it takes tensors of varying inputs
  • You do not even need to specify the output-shape you just need to specify the output_channel and the kernel to be used
  • For more details : https://www.tensorflow.org/api_docs/python/tf/layers/conv2d_transpose... I hope this helps

Upvotes: 2

Geralt Xu
Geralt Xu

Reputation: 41

I find a solution to use tf.shape for unspecified shape and get_shape() for specified shape.

def get_deconv_lens(H, k, d):
    return tf.multiply(H, d) + k - 1

def deconv2d(x, output_shape, k_h=2, k_w=2, d_h=2, d_w=2, stddev=0.02, name='deconv2d'):
    # output_shape: the output_shape of deconv op
    shape = tf.shape(x)
    H, W = shape[1], shape[2]
    N, _, _, C = x.get_shape().as_list()
    H1 = get_deconv_lens(H, k_h, d_h)
    W1 = get_deconv_lens(W, k_w, d_w)

    with tf.variable_scope(name):
        w = tf.get_variable('weights', [k_h, k_w, C, x.get_shape()[-1]], initializer=tf.random_normal_initializer(stddev=stddev))
        biases = tf.get_variable('biases', shape=[C], initializer=tf.zeros_initializer())

    deconv = tf.nn.conv2d_transpose(x, w, output_shape=[N, H1, W1, C], strides=[1, d_h, d_w, 1], padding='VALID')
    deconv = tf.nn.bias_add(deconv, biases)

    return deconv

Upvotes: 0

Nobody
Nobody

Reputation: 152

I ran into this problem too. Using -1, as suggested in the other answer here, doesn't work. Instead, you have to grab the shape of the incoming tensor and construct the output_size argument. Here's an excerpt from a test I wrote. In this case it's the first dimension that's unknown, but it should work for any combination of known and unknown parameters.

output_shape = [8, 8, 4] # width, height, channels-out. Handle batch size later
xin = tf.placeholder(dtype=tf.float32, shape = (None, 4, 4, 2), name='input')
filt = tf.placeholder(dtype=tf.float32, shape = filter_shape, name='filter')

## Find the batch size of the input tensor and add it to the front
## of output_shape
dimxin = tf.shape(xin)
ncase = dimxin[0:1]
oshp = tf.concat([ncase,output_shape], axis=0)

z1 = tf.nn.conv2d_transpose(xin, filt, oshp, strides=[1,2,2,1], name='xpose_conv')

Upvotes: 0

Related Questions