How to use Reshape keras layer with two None dimension?

喜你入骨 提交于 2021-02-09 09:35:41

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!