问题
I have a keras 3D/2D model. In this model a 3D layer has a shape of [None, None, 4, 32]. I want to reshape this into [None, None, 128]. However, if I simply do the following:
reshaped_layer = Reshape((-1, 128))(my_layer)
my_layer has a shape of [None, 128] and therefore I cannot apply afterwards any 2D convolution, like:
conv_x = Conv2D(16, (1,1))(reshaped_layer)
I've tried to use tf.shape(my_layer) and tf.reshape, but I have not been able to compile the model since tf.reshape is not a Keras layer.
Just to clarify, I'm using channels last; this is not tf.keras, this is just Keras. Here I send a debug of the reshape function: Reshape in keras
This is what I'm doing right now, following the advice of anna-krogager:
def reshape(x):
x_shape = K.shape(x)
new_x_shape = K.concatenate([x_shape[:-2], [x_shape[-2] * x_shape[-1]]])
return K.reshape(x, new_x_shape)
reshaped = Lambda(lambda x: reshape(x))(x)
reshaped.set_shape([None,None, None, 128])
conv_x = Conv2D(16, (1,1))(reshaped)
I get the following error: ValueError: The channel dimension of the inputs should be defined. Found None
回答1:
You can use K.shape
to get the shape of your input (as a tensor) and wrap the reshaping in a Lambda layer as follows:
def reshape(x):
x_shape = K.shape(x)
new_x_shape = K.concatenate([x_shape[:-2], [x_shape[-2] * x_shape[-1]]])
return K.reshape(x, new_x_shape)
reshaped = Lambda(lambda x: reshape(x))(x)
reshaped.set_shape([None, None, None, a * b]) # when x is of shape (None, None, a, b)
This will reshape a tensor with shape (None, None, a, b)
to (None, None, a * b)
.
回答2:
Digging into the base_layer.py, I have found that reshaped is:
tf.Tensor 'lambda_1/Reshape:0' shape=(?, ?, ?, 128) dtype=float32.
However its atribute "_keras_shape" is (None, None, None, None) even after the set_shape. Therefore, the solution is to set this attribute:
def reshape(x):
x_shape = K.shape(x)
new_x_shape = K.concatenate([x_shape[:-2], [x_shape[-2] * x_shape[-1]]])
return K.reshape(x, new_x_shape)
reshaped = Lambda(lambda x: reshape(x))(x)
reshaped.set_shape([None, None, None, 128])
reshaped.__setattr__("_keras_shape", (None, None, None, 128))
conv_x = Conv2D(16, (1,1))(reshaped)
回答3:
Since you are reshaping the best you can obtain from (4,32), without losing dimensions, is either (128, 1) or (1, 128). Thus you can do the following:
# original has shape [None, None, None, 4, 32] (including batch)
reshaped_layer = Reshape((-1, 128))(original) # shape is [None, None, 128]
conv_layer = Conv2D(16, (1,1))(K.expand_dims(reshaped_layer, axis=-2)) # shape is [None, None, 1, 16]
来源:https://stackoverflow.com/questions/54983295/how-to-use-reshape-keras-layer-with-two-none-dimension