Solución:
Cuando guardó su modelo usando:
old_model.save('my_model.h5')
guardará lo siguiente:
- La arquitectura del modelo, que permite crear el modelo.
- Los pesos del modelo.
- La configuración de entrenamiento del modelo (pérdida, optimizador).
- El estado del optimizador, que permite que el entrenamiento se reanude desde donde lo dejó antes.
Entonces, cuando cargas el modelo:
res50_model = load_model('my_model.h5')
debe recuperar el mismo modelo, puede verificar el mismo usando:
res50_model.summary()
res50_model.get_weights()
Ahora puede, hacer estallar la capa de entrada y agregar la suya propia usando:
res50_model.layers.pop(0)
res50_model.summary()
agregar nueva capa de entrada:
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()
La solución de @MilindDeore no funcionó para mí, desafortunadamente. Si bien puedo imprimir el resumen del nuevo modelo, recibo un error de “Tamaño de matriz incompatible” en la predicción. Supongo que esto tiene sentido, ya que la nueva forma de entrada de la capa densa no coincide con la forma de los pesos de la capa densa anterior.
Por tanto, aquí hay otra solución. La clave para mí fue usar “_layers” en lugar de “capas”. Este último solo parece devolver una copia.
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)
Layers.pop (0) o algo por el estilo no funciona.
Tienes dos opciones que puedes probar:
1.
Puede crear un nuevo modelo con las capas necesarias.
Una forma relativamente fácil de hacer esto es i) extraer la configuración json del modelo, ii) cambiarla apropiadamente, iii) crear un nuevo modelo a partir de ella y luego iv) copiar los pesos. Solo mostraré la idea básica.
i) extraer la configuración
model_config = model.get_config()
ii) cambiar la configuración
input_layer_name = model_config['layers'][0]['name']
model_config['layers'][0] = {
'name': 'new_input',
'class_name': 'InputLayer',
'config': {
'batch_input_shape': (None, 300, 300),
'dtype': 'float32',
'sparse': False,
'name': 'new_input'
},
'inbound_nodes': []
}
model_config['layers'][1]['inbound_nodes'] = [[['new_input', 0, 0, {}]]]
model_config['input_layers'] = [['new_input', 0, 0]]
ii) crear un nuevo modelo
new_model = model.__class__.from_config(model_config, custom_objects={}) # change custom objects if necessary
ii) pesos de copia
# iterate over all the layers that we want to get weights from
weights = [layer.get_weights() for layer in model.layers[1:]]
for layer, weight in zip(new_model.layers[1:], weights):
layer.set_weights(weight)
2.
Puede probar una biblioteca como kerassurgeon (estoy vinculando a una bifurcación que funciona con la versión de keras de tensorflow). Tenga en cuenta que las operaciones de inserción y eliminación solo funcionan en determinadas condiciones, como dimensiones compatibles.
from kerassurgeon.operations import delete_layer, insert_layer
model = delete_layer(model, layer_1)
# insert new_layer_1 before layer_2 in a model
model = insert_layer(model, layer_2, new_layer_3)