I want to mimic this paper where they use fully connected upsampling layers. I'm using the contributed conv3d_transpose
but the concept should be the same as 2D version.
I have an output from a convolutional layer [6,6,6,256]
being fed into an upsampling layer that is supposed to output [13,13,13,128]
. Since the layer should be fully connected, the filter should be [13,13,13,128]
right? (reducing feature map size)
Furthermore, the stride should be 1
correct?
Maybe I am thinking of this backwards, let me explain. The filter defines that size of the inverted receptive field (totally made that up) -- the size of the weight matrix located on the output layer (thus the full [13,13,13,128]
). EDIT INCORRECT [ The strides are the length of strides the single window moves on the input image.] --> I now understand that the strides are also in relation to the output layer. For example a filter size 2 with a stride 2, will double the output dimension.
This means that for a fully connected layer, the stride should be 0
, but that isn't possible...
The code for my upsampling is here:
temp_batch_size = tf.shape(x)[0] #batch_size shape
with tf.name_scope("deconv6") as scope:
output_shape = [temp_batch_size, (n_input_z / 4), n_input_x / 4, n_input_y / 4, 128]
strides = [1,1,1,1,1]
conv7 = deconv3d(conv6, weights['wdc1'], biases['bdc1'], output_shape, strides, padding=1)
conv7 = tf.reshape(conv7, [-1, n_input_x / 4, n_input_y / 4, (n_input_z / 4) * 128])
conv7 = tf.contrib.layers.batch_norm(conv7)
conv7 = tf.reshape(conv7, [-1, (n_input_z / 4), n_input_x / 4, n_input_y / 4, 128])
The deconv
function looks like this:
def deconv3d(prev_layer, w, b, output_shape, strides, padding=0):
# Deconv layer
if padding == 0:
deconv = tf.nn.conv3d_transpose(prev_layer, w, output_shape=output_shape, strides=strides, padding="SAME")
else:
deconv = tf.nn.conv3d_transpose(prev_layer, w, output_shape=output_shape, strides=strides, padding="VALID")
deconv = tf.nn.bias_add(deconv, b)
deconv = tf.nn.relu(deconv)
return deconv
The weights and biases are here:
'wdc1' : tf.get_variable("weights_7", shape=[13, 13, 13, 128, 256],
initializer=tf.contrib.layers.xavier_initializer(), dtype=tf.float32),
...
'bdc1': tf.Variable(tf.zeros([128], dtype=tf.float32), name="biases_7", dtype=tf.float32),
From debugging I can verify input and output dimensions:
(Pdb) conv6
<tf.Tensor 'conv5_1/Reshape_1:0' shape=(?, 6, 6, 6, 256) dtype=float32>
(Pdb) output_shape
[<tf.Tensor 'strided_slice:0' shape=() dtype=int32>, 13, 13, 13, 128]
When I run this code, I get the following error:
tensorflow.python.framework.errors.InvalidArgumentError: Conv3DBackpropInput: Number of planes of out_backprop doesn't match computed: actual = 6, computed = 1
[[Node: deconv6/conv3d_transpose = Conv3DBackpropInputV2[T=DT_FLOAT, padding="VALID", strides=[1, 1, 1, 1, 1], _device="/job:localhost/replica:0/task:0/gpu:0"](deconv6/conv3d_transpose/output_shape, weights_7/read, conv5_1/Reshape_1)]]
[[Node: deconv8/BatchNorm/moments/sufficient_statistics/Shape/_39 = _Recv[client_terminated=false, recv_device="/job:localhost/replica:0/task:0/cpu:0", send_device="/job:localhost/replica:0/task:0/gpu:0", send_device_incarnation=1, tensor_name="edge_3797_deconv8/BatchNorm/moments/sufficient_statistics/Shape", tensor_type=DT_INT32, _device="/job:localhost/replica:0/task:0/cpu:0"]()]]
I assumed from the first Node
line the problem was in deconv6
, but I'll post the code if you think it's actually in deconv8
.