Saltar al contenido

Keras reemplazando la capa de entrada

Solución:

Cuando guardó su modelo usando:

old_model.save('my_model.h5')

guardará lo siguiente:

  1. La arquitectura del modelo, que permite crear el modelo.
  2. Los pesos del modelo.
  3. La configuración de entrenamiento del modelo (pérdida, optimizador).
  4. 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)
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *