Kendall Weihe Kendall Weihe - 5 months ago 433
Python Question

Tensorflow conv2d_transpose (deconv) Number of rows of out_backprop doesn't match computed

EDIT My issue is the width and height of my filter, I misunderstood the API doc... working on correction now

SOLUTION Follow deconvolution from here slide 53




I have a similar issue as here but it's a little funkier.

My error is
Conv2DBackpropInput: Number of rows of out_backprop doesn't match computed: actual = 25, computed = 26
at the time of the optimizer initialization.

...so it's off by 1?

Some background...

I have a conv layer with dimensions
<tf.Tensor 'MaxPool_2:0' shape=(?, 25, 25, 128) dtype=float32>


The input image is 200x200, and I have 3 maxpool layers -- thus the h = w = 25. I want to add 3 deconv layers so that I return the original resolution (I'm doing image segmentation).

The deconv code looks like:

temp_batch_size = tf.shape(x)[0]
# output_shape = tf.pack([temp_batch_size, 50, 50, 64])
output_shape = [temp_batch_size, 50, 50, 64]
conv4 = tf.nn.conv2d_transpose(conv3, weights['wdc1'], output_shape=output_shape, strides=[1,1,1,1], padding="VALID")
# conv4 = tf.nn.local_response_normalization(conv4)

# output_shape = tf.pack([temp_batch_size, 100, 100, 32])
output_shape = [temp_batch_size, 100, 100, 32]
conv5 = tf.nn.conv2d_transpose(conv4, weights['wdc2'], output_shape=output_shape, strides=[1,1,1,1], padding="VALID")
# conv5 = tf.nn.local_response_normalization(conv5)

# output_shape = tf.pack([temp_batch_size, 200, 200, 1])
output_shape = [temp_batch_size, 200, 200, 1]
conv6 = tf.nn.conv2d_transpose(conv5, weights['wdc3'], output_shape=output_shape, strides=[1,1,1,1], padding="VALID")
# conv6 = tf.nn.local_response_normalization(conv6)


(You can see I tried to
tf.pack()
to no success -- as recommended here) Where the weights are:

'wdc1' : tf.Variable(tf.random_normal([25, 25, 64,128])),

'wdc2' : tf.Variable(tf.random_normal([50, 50, 32,64])),

'wdc3' : tf.Variable(tf.random_normal([100, 100, 1,32])),


Some debugging looks like this:

(Pdb) conv3
<tf.Tensor 'MaxPool_2:0' shape=(?, 25, 25, 128) dtype=float32>
(Pdb) conv4
<tf.Tensor 'conv2d_transpose:0' shape=(?, ?, ?, ?) dtype=float32>
(Pdb) conv5
<tf.Tensor 'conv2d_transpose_1:0' shape=(?, ?, ?, ?) dtype=float32>
(Pdb) conv6
<tf.Tensor 'conv2d_transpose_2:0' shape=(?, ?, ?, ?) dtype=float32>


I find it odd that because I have the line
temp_batch_size = tf.shape(x)[0]
(as recommended here), the last 3 dimensions are also question marks? If I change the first dimension to a constant (such as 10) I get
<tf.Tensor 'conv2d_transpose:0' shape=(10, 50, 50, 64) dtype=float32>


So maybe that is part of my issue? If I change it back to a constant
batch_size
then I get the error
ValueError: Shapes (10, 101, 101, 32) and (10, 100, 100, 32) are not compatible
at the time of the optimizer initialization. Once again, off by one.

Debugging with this configuration...

(Pdb) conv4
<tf.Tensor 'conv2d_transpose:0' shape=(10, 50, 50, 64) dtype=float32>
(Pdb) conv5
<tf.Tensor 'conv2d_transpose_1:0' shape=(10, 100, 100, 32) dtype=float32>
(Pdb) conv6
<tf.Tensor 'conv2d_transpose_2:0' shape=(10, 200, 200, 1) dtype=float32>


Is the issue my number of strides? What should they be (I've tried different variations to no success)

Answer

When using transposed convolutions, you need to think backwards: how would you get your input (conv3 of shape [batch_size, 25, 25, 128]) given the output (of shape [batch_size, 200, 200, 1])?

You would do a succession of 3x3 convolutions and max pooling. Unfortunately, unpooling is not yet available in TensorFlow, so you will just have transposed convolutions.

The filters should have normal CNN shapes: like 3x3 convolutions, or 5x5. If you want to increase the output size, you need to use strided transpose convolutions.

weights = {
  'wdc1' : tf.Variable(tf.random_normal([3, 3, 64, 128])),
  'wdc2' : tf.Variable(tf.random_normal([3, 3, 32, 64])),
  'wdc3' : tf.Variable(tf.random_normal([3, 3, 1, 32]))
}

And the code (don't forget the stride = 2):

temp_batch_size = 10

conv3 = tf.zeros([temp_batch_size, 25, 25, 128])
output_shape = [temp_batch_size, 50, 50, 64]
conv4 = tf.nn.conv2d_transpose(conv3, weights['wdc1'], output_shape=output_shape, strides=[1,2,2,1], padding="SAME")

output_shape = [temp_batch_size, 100, 100, 32]
conv5 = tf.nn.conv2d_transpose(conv4, weights['wdc2'], output_shape=output_shape, strides=[1,2,2,1], padding="SAME")

output_shape = [temp_batch_size, 200, 200, 1]
conv6 = tf.nn.conv2d_transpose(conv5, weights['wdc3'], output_shape=output_shape, strides=[1,2,2,1], padding="SAME")

EDIT:

Just saw your edit. The slides from CS231n are a very good illustration of how to use transposed convolutions, it's even better with the video !

Comments