Le code que j'ai (que je ne peux pas changer) utilise le Resnet avec my_input_tensor
comme capteur d'entrée.
model1 = keras.applications.resnet50.ResNet50(input_tensor=my_input_tensor, weights='imagenet')
En étudiant le code source , la fonction ResNet50 crée une nouvelle couche d'entrée de keras avec my_input_tensor
, puis créez le reste du modèle. C'est le comportement que je veux copier avec mon propre modèle. Je charge mon modèle à partir du fichier h5.
model2 = keras.models.load_model('my_model.h5')
Étant donné que ce modèle possède déjà un calque d'entrée, je souhaite le remplacer par un nouveau calque d'entrée défini par my_input_tensor
.
Comment remplacer une couche d'entrée?
Lorsque vous avez enregistré votre modèle à l'aide de:
old_model.save('my_model.h5')
il sauvera ce qui suit:
Alors, lorsque vous chargez le modèle:
res50_model = load_model('my_model.h5')
vous devriez récupérer le même modèle, vous pouvez le vérifier en utilisant:
res50_model.summary()
res50_model.get_weights()
Maintenant, vous pouvez ouvrir le calque d'entrée et ajouter le vôtre en utilisant:
res50_model.layers.pop(0)
res50_model.summary()
ajouter une nouvelle couche d'entrée:
newInput = Input(batch_shape=(0,299,299,3)) # let us say this new InputLayer
newOutputs = res50_model(newInput)
newModel = Model(newInput, newOutputs)
newModel.summary()
res50_model.summary()
Malheureusement, la solution de @MilindDeore n'a pas fonctionné pour moi. Bien que je puisse imprimer le résumé du nouveau modèle, je reçois une erreur "Matrix size incompatible" lors de la prédiction. Je suppose que cela a du sens, car la nouvelle forme d'entrée de la couche dense ne correspond pas à la forme des anciens poids de couche dense.
Voici donc une autre solution. La clé pour moi était d'utiliser "_layers" au lieu de "couches". Ce dernier ne semble renvoyer qu'une copie.
import keras
import numpy as np
def get_model():
old_input_shape = (20, 20, 3)
model = keras.models.Sequential()
model.add(keras.layers.Conv2D(9, (3, 3), padding="same", input_shape=old_input_shape))
model.add(keras.layers.MaxPooling2D((2, 2)))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(1, activation="sigmoid"))
model.compile(loss='binary_crossentropy', optimizer=keras.optimizers.Adam(lr=0.0001), metrics=['acc'], )
model.summary()
return model
def change_model(model, new_input_shape=(None, 40, 40, 3)):
# replace input shape of first layer
model._layers[1].batch_input_shape = new_input_shape
# feel free to modify additional parameters of other layers, for example...
model._layers[2].pool_size = (8, 8)
model._layers[2].strides = (8, 8)
# rebuild model architecture by exporting and importing via json
new_model = keras.models.model_from_json(model.to_json())
new_model.summary()
# copy weights from old model to new one
for layer in new_model.layers:
try:
layer.set_weights(model.get_layer(name=layer.name).get_weights())
except:
print("Could not transfer weights for layer {}".format(layer.name))
# test new model on a random input image
X = np.random.Rand(10, 40, 40, 3)
y_pred = new_model.predict(X)
print(y_pred)
return new_model
if __name__ == '__main__':
model = get_model()
new_model = change_model(model)