Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stack multiple layers of conv2d_transpose() of Tensorflow

I'm trying to stack 2 layers of tf.nn.conv2d_transpose() to up-sample a tensor. It works fine during feed forward, but I get an error during backward propagation: ValueError: Incompatible shapes for broadcasting: (8, 256, 256, 24) and (8, 100, 100, 24).

Basically, I've just set the output of the first conv2d_transpose as the input of the second one:

convt_1 = tf.nn.conv2d_transpose(...)
convt_2 = tf.nn.conv2d_transpose(conv_1)

Using just one conv2d_transpose, everything works fine. The error only occurs if multiple conv2d_transpose are stacked together.

I'm not sure of the proper way of implementing multiple layer of conv2d_transpose. Any advice on how to go about this would be very much appreciated.

Here's a small code that replicates the error:

import numpy as np
import tensorflow as tf

IMAGE_HEIGHT = 256
IMAGE_WIDTH = 256
CHANNELS = 1

batch_size = 8
num_labels = 2

in_data = tf.placeholder(tf.float32, shape=(batch_size, IMAGE_HEIGHT, IMAGE_WIDTH, CHANNELS))
labels = tf.placeholder(tf.int32, shape=(batch_size, IMAGE_HEIGHT, IMAGE_WIDTH, 1))

# Variables
w0 = tf.Variable(tf.truncated_normal([3, 3, CHANNELS, 32]))
b0 = tf.Variable(tf.zeros([32]))

# Down sample
conv_0 = tf.nn.relu(tf.nn.conv2d(in_data, w0, [1, 2, 2, 1], padding='SAME') + b0)
print("Convolution 0:", conv_0)


# Up sample 1. Upscale to 100 x 100 x 24
wt1 = tf.Variable(tf.truncated_normal([3, 3, 24, 32]))
convt_1 = tf.nn.sigmoid(
          tf.nn.conv2d_transpose(conv_0, 
                                 filter=wt1, 
                                 output_shape=[batch_size, 100, 100, 24], 
                                 strides=[1, 1, 1, 1]))
print("Deconvolution 1:", convt_1)


# Up sample 2. Upscale to 256 x 256 x 2
wt2 = tf.Variable(tf.truncated_normal([3, 3, 2, 24]))
convt_2 = tf.nn.sigmoid(
          tf.nn.conv2d_transpose(convt_1, 
                                 filter=wt2, 
                                 output_shape=[batch_size, IMAGE_HEIGHT, IMAGE_WIDTH, 2], 
                                 strides=[1, 1, 1, 1]))
print("Deconvolution 2:", convt_2)

# Loss computation
logits = tf.reshape(convt_2, [-1, num_labels])
reshaped_labels = tf.reshape(labels, [-1])
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits, reshaped_labels)
loss = tf.reduce_mean(cross_entropy)

optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss)
like image 392
Pette Avatar asked May 25 '16 18:05

Pette


1 Answers

I guess you need to change your 'stride' paramter in conv2d_transpose. conv2d_transpos is like conv2d but input and output are reversed.

For conv2d, the stride and input shape will decide the output shape. For conv2d_transpose, the stride and output shape will decide the input shape. Now your stride is [1 1 1 1], which means output and input of conv2d_transpose is about same (ignoring boundary effect).

For input H = W = 100, stride = [1 2 2 1], the output of conv2d_tranpose should be 200. (reversed of conv2d), if you set the padding to SAME. In short, input, output and stride need to be compatible.

like image 137
Wei Liu Avatar answered Nov 19 '22 15:11

Wei Liu