TensorFlow Using transposed convolution layers

From WikiOD

Using tf.nn.conv2d_transpose for arbitary batch sizes and with automatic output shape calculation.[edit | edit source]

Example of how to calculate the output shape and overcome the difficulties of using tf.nn.conv2d_transpose with unknown batch size (when input.get_shape() is (?, H, W, C) or (?, C, H, W)).

def upconvolution (input, output_channel_size, filter_size_h, filter_size_w,
                   stride_h, stride_w, init_w, init_b, layer_name, 
                   dtype=tf.float32, data_format="NHWC", padding='VALID'):
    with tf.variable_scope(layer_name):
      #calculation of the output_shape:
      if data_format == "NHWC":
        input_channel_size = input.get_shape().as_list()[3]
        input_size_h = input.get_shape().as_list()[1]
        input_size_w = input.get_shape().as_list()[2]
        stride_shape = [1, stride_h, stride_w, 1]
        if padding == 'VALID':
          output_size_h = (input_size_h - 1)*stride_h + filter_size_h
          output_size_w = (input_size_w - 1)*stride_w + filter_size_w
        elif padding == 'SAME':
          output_size_h = (input_size_h - 1)*stride_h + 1
          output_size_w = (input_size_w - 1)*stride_w + 1
        else:
          raise ValueError("unknown padding")
        output_shape = tf.stack([tf.shape(input)[0], 
                                output_size_h, output_size_w, 
                                output_channel_size])
      elif data_format == "NCHW":
        input_channel_size = input.get_shape().as_list()[1]
        input_size_h = input.get_shape().as_list()[2]
        input_size_w = input.get_shape().as_list()[3]
        stride_shape = [1, 1, stride_h, stride_w]
        if padding == 'VALID':
          output_size_h = (input_size_h - 1)*stride_h + filter_size_h
          output_size_w = (input_size_w - 1)*stride_w + filter_size_w
        elif padding == 'SAME':
          output_size_h = (input_size_h - 1)*stride_h + 1
          output_size_w = (input_size_w - 1)*stride_w + 1
        else:
          raise ValueError("unknown padding")
        output_shape = tf.stack([tf.shape(input)[0], 
                                output_channel_size, 
                                output_size_h, output_size_w])
      else:
        raise ValueError("unknown data_format")

      #creating weights:
      shape = [filter_size_h, filter_size_w, 
               output_channel_size, input_channel_size]
      W_upconv = tf.get_variable("w", shape=shape, dtype=dtype,
                                 initializer=init_w)

      shape=[output_channel_size]
      b_upconv = tf.get_variable("b", shape=shape, dtype=dtype, 
                                 initializer=init_b)

      upconv = tf.nn.conv2d_transpose(input, W_upconv, output_shape, stride_shape,
                                      padding=padding,
                                      data_format=data_format)
      output = tf.nn.bias_add(upconv, b_upconv, data_format=data_format)

      #Now output.get_shape() is equal (?,?,?,?) which can become a problem in the 
      #next layers. This can be repaired by reshaping the tensor to its shape:
      output = tf.reshape(output, output_shape)
      #now the shape is back to (?, H, W, C) or (?, C, H, W)

      return output

This article is an extract of the original Stack Overflow Documentation created by contributors and released under CC BY-SA 3.0. This website is not affiliated with Stack Overflow