J'ai un modèle keras 3D / 2D. Dans ce modèle, un calque 3D a la forme [Aucun, Aucun, 4, 32]. Je veux remodeler cela en [Aucun, Aucun, 128]. Cependant, si je fais simplement ce qui suit:
reshaped_layer = Remodeler ((- 1, 128)) (mon_couche)
my_layer a une forme de [None, 128] et je ne peux donc pas appliquer par la suite une convolution 2D, comme:
conv_x = Conv2D (16, (1,1)) (reshaped_layer)
J'ai essayé d'utiliser tf.shape (my_layer) et tf.reshape, mais je n'ai pas pu compiler le modèle car tf.reshape n'est pas une couche Keras.
Juste pour clarifier, j'utilise les canaux en dernier; ce n'est pas tf.keras, c'est juste Keras. Ici, j'envoie un débogage de la fonction reshape: Reshape in keras
C'est ce que je fais en ce moment, en suivant les conseils d'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)
J'obtiens l'erreur suivante: ValueError: La dimension de canal des entrées doit être définie. Trouvé Aucun
3 Réponses :
Vous pouvez utiliser K.shape
pour obtenir la forme de votre entrée (en tant que tenseur) et envelopper le remodelage dans une couche Lambda comme suit:
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)
Cela remodèlera un tenseur avec la forme (Aucun, Aucun, a, b)
en (Aucun, Aucun, a * b)
.
J'ai essayé votre solution mais, remodelé a une forme de [Aucun, Aucun, Aucun] et quand je fais un Conv2D de remodelé, j'obtiens l'erreur suivante: ValueError: La dimension de canal des entrées doit être définie. Trouvé Aucun
.
Essayez d'ajouter reshaped.set_shape ([None, None, 128])
avant de le transmettre à la couche Conv2D
Même si cela semble fonctionner: remodelé est Aucun
.
Utilisez-vous les canaux en premier ou les canaux en dernier dans votre couche Conv2D? Pour moi, cela fonctionne (avec les chaînes en dernier, qui est la valeur par défaut). Je suppose que vous obtenez l'erreur en premier à cause des canaux, et vos données ont en effet None comme première dimension. D'où vient ce None? Vous voudrez peut-être vous demander si votre architecture a du sens
Je viens de publier une capture d'écran de débogage. J'utilise les canaux en dernier, mon modèle fonctionnait correctement lorsque la forme d'entrée a été définie (128, 128, 10, 1). Cependant, lorsque j'essaie de développer un modèle avec une forme d'entrée de (None, None, 10, 1), cela se brise.
En creusant dans le fichier base_layer.py, j'ai découvert que remodelé est un
En creusant dans le fichier base_layer.py, j'ai trouvé que remodelé est:
tf.Tensor 'lambda_1 / Reshape: 0' shape = (?,?,?, 128) dtype = float32.
Cependant, son attribut "_keras_shape" est (None, None, None, None) même après la set_shape. Par conséquent, la solution est de définir cet attribut:
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)
Puisque vous remodelez, le meilleur que vous pouvez obtenir de (4,32), sans perdre de dimensions, est soit (128, 1) ou (1, 128). Ainsi, vous pouvez faire ce qui suit:
# 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]