If we use keras with tensorflow, the output shape of a Conv2DTranspose is undefined even if the input shape is fixed. This problem doesn't happen with Conv2D . This is probably due to a bug in the implementation of Conv2DTranspose.
import tensorflow as tf
config = tf.ConfigProto()
config.gpu_options.allow_growth=True
sess = tf.Session(config=config)
from keras.layers.convolutional import Conv2DTranspose , Conv2D
layer1 = Conv2DTranspose( 8 , (4 , 4) , strides=(1, 1) , data_format='channels_first' , input_shape=(3,64,64) )
layer2 = Conv2D( 8 , (4, 4) , strides=(1, 1), input_shape=(3, 64, 64) , data_format='channels_first' )
BATCH_SIZE = 32
x = tf.placeholder(tf.float32, shape=( BATCH_SIZE , 3, 64 , 64 ))
o1 = layer1( x )
o2 = layer2( x )
print o1.get_shape() # Prints (?, 8, ?, ?) , why???
print o2.get_shape() # Prints (32, 8, 61, 61) , which is correct
I encountered the same issue! I had to use the following to determine the output shape:
shape_o1 = layer1.compute_output_shape(input_shape)
Yes, There is a bug in the implementation on this layer. This is causing other source codes to break.
I add this line print (inputs, input_shape)
at convolutional.py line 765
the output :
(<tf.Tensor 'activation_9/Relu:0' shape=(?, 64, 64, 256) dtype=float32>, <tf.Tensor 'conv2d_transpose_1/Shape:0' shape=(4,) dtype=int32>)
It seems that K.shape(line 742)
cannot get the exact shape of input tensor...
Sorry, I misunderstand the K.shape functionality.
I try to add many breakpoint to see the behavior
outputs = K.conv2d_transpose(
inputs,
self.kernel,
output_shape,
self.strides,
padding=self.padding,
data_format=self.data_format)
print (outputs)
print (self.activation)
if self.bias:
outputs = K.bias_add(
outputs,
self.bias,
data_format=self.data_format)
print (outputs)
if self.activation is not None:
outputs = self.activation(outputs)
# return outputs
print (outputs)
The output:
(<tf.Tensor 'conv2d_transpose_1/conv2d_transpose:0' shape=(?, ?, ?, ?) dtype=float32>)
(<function linear at 0x1328aff50>)
(<tf.Tensor 'conv2d_transpose_1/BiasAdd:0' shape=(?, ?, ?, 128) dtype=float32>)
(<tf.Tensor 'conv2d_transpose_1/BiasAdd:0' shape=(?, ?, ?, 128) dtype=float32>)
Caller:
# nn.get_shape() : (?, 64, 64, 256)
nn = Conv2DTranspose(128, (3, 3), strides=(2, 2), padding='same', activation=None)(nn)
Maybe I'd better trace deeper.
ps. my backend use Tensorflow
Keras (2.0.4), Tensorflow (1.1.0)
This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 30 days if no further activity occurs, but feel free to re-open a closed issue if needed.
Any updates on this issue?
I have also run into this bug. It requires some ugly workarounds. any updates?
I too encoutered this bug.
The following code
from keras.models import Model
from keras.layers import Input, Conv2D, Conv2DTranspose
from keras import backend as K
assert K.image_data_format() == 'channels_last'
inp = Input(shape=(((32, 32, 3))))
out_1 = Conv2D(8, (3, 3), strides=(1, 1), padding='same')(inp)
out_2 = Conv2DTranspose(8, (3, 3), strides=(1, 1), padding='same')(inp)
print(out_1.shape)
print(out_2.shape)
produces this output (Keras Version 2.0.8, TensorFlow 1.3.0)
(?, 32, 32, 8)
(?, ?, ?, 8)
To me it looks like it is caused by this TensorFlow issue.
Just as an update: It still happens with Keras 2.1.1 and TensorFlow 1.4.0. I will check again with the next release of a new TensorFlow version.
I can check the output shape with _keras_shape
property of the layer.
A nasty workaround is to explicitly mention the output shape.
@gdubrg Thanks a lot. Accessing a protected member is not perfect, but it works for my purpose.
Kudos @gdubrg
I have faced the problem too
Same problem for me :-(
Any better workaround?
Changing the imports to the Keras version included in Tensorflow also fixed the problem:
from tensorflow.python import keras
from tensorflow.python.keras.layers import Input, Conv2D, Conv2DTranspose
from tensorflow.python.keras import backend as K
assert K.image_data_format() == 'channels_last'
inp = Input(shape=(((32, 32, 3))))
out_1 = Conv2D(8, (3, 3), strides=(1, 1), padding='same')(inp)
out_2 = Conv2DTranspose(8, (3, 3), strides=(1, 1), padding='same')(inp)
print(out_1.shape)
print(out_2.shape)
(?, 32, 32, 8)
(?, 32, 32, 8)
Closing as this is resolved
@wt-huang Is this really resolved? It seems like the solution above is "abandon Keras and use tf.keras", which isn't ideal.
@wt-huang This isn't solved! Keras from TF and vanilla keras is not compatible. A project should use either tf.keras or just keras and not both. Changing the whole project to use tf.keras is a huge job.
I also don't like it, but the notes of the latest vanilla Keras release even state:
This is also the last major release of multi-backend Keras. Going forward, we recommend that users consider switching their Keras code to tf.keras in TensorFlow 2.0. It implements the same Keras 2.3.0 API (so switching should be as easy as changing the Keras import statements), but it has many advantages for TensorFlow users, such as support for eager execution, distribution, TPU training, and generally far better integration between low-level TensorFlow and high-level concepts like Layer and Model. It is also better maintained.
Development will focus on tf.keras going forward. We will keep maintaining multi-backend Keras over the next 6 months, but we will only be merging bug fixes. API changes will not be ported.
:cry:
(edit: I used the cry-emoji because I'm also somewhat suffering by these things when maintaining this library.)
I suppose that's that, then. Still pretty annoying since, a) TF 2.0 is still in beta, and b) tf.keras is _not_ a drop-in replacement, as evidenced by the week or so of work I had to put in switching over to get around this bug.
(The latter point may now be true with the 2.3.0 update, but I think that also points towards the high volatility in machine learning libraries.)
My latest pull request fixes this issue: #13778
Most helpful comment
I can check the output shape with
_keras_shape
property of the layer.