Guardar y cargar los resultados del modelo de Tensorflow en el error de Keras

Aug 20 2020

Para un proyecto en el que estoy trabajando, he creado un modelo simple en TensorFlow que consta de una capa de características densas seguida de tres capas densas.

def build_model(arguments):
    model = tf.keras.Sequential([
        tf.keras.layers.DenseFeatures(arguments),
        tf.keras.layers.Dense(128, activation='relu'),
        tf.keras.layers.Dense(128, activation='relu'),
        tf.keras.layers.Dense(5, activation='sigmoid')
    ])
    
    return model

No puedo entrar en más detalles sobre el parámetro arguments, pero la función del modelo anterior funciona perfectamente bien y puede entrenar y guardar un .h5archivo perfectamente usando el código a continuación.

    # Create a path for the saving location of the model
    model_dir = log_dir + "\model.h5"

    # Save the model
    model.save(model_dir)

Sin embargo, cuando intento volver a cargar el modelo desde el .h5archivo,

model = tf.keras.models.load_model(model_path)

Recibo el siguiente mensaje de error.

  File "sampleModel.py", line 342, in <module>
    model = tf.keras.models.load_model(model_path)
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\keras\saving\save.py", line 1
82, in load_model
    return hdf5_format.load_model_from_hdf5(filepath, custom_objects, c
ompile)
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\keras\saving\hdf5_format.py",
 line 178, in load_model_from_hdf5
    custom_objects=custom_objects)
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\keras\saving\model_config.py"
, line 55, in model_from_config
    return deserialize(config, custom_objects=custom_objects)
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\keras\layers\serialization.py
", line 175, in deserialize
    printable_module_name='layer')
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\keras\utils\generic_utils.py"
, line 358, in deserialize_keras_object
    list(custom_objects.items())))
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\keras\engine\sequential.py",
line 487, in from_config
    custom_objects=custom_objects)
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\keras\layers\serialization.py
", line 175, in deserialize
    printable_module_name='layer')
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\keras\utils\generic_utils.py"
, line 358, in deserialize_keras_object
    list(custom_objects.items())))
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\keras\feature_column\base_fea
ture_layer.py", line 141, in from_config
    config['feature_columns'], custom_objects=custom_objects)
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\feature_column\serialization.
py", line 186, in deserialize_feature_columns
    for c in configs
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\feature_column\serialization.
py", line 186, in <listcomp>
    for c in configs
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\feature_column\serialization.
py", line 138, in deserialize_feature_column
    columns_by_name=columns_by_name)
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\feature_column\feature_column
_v2.py", line 2622, in from_config
    config['normalizer_fn'], custom_objects=custom_objects)
  File "C:\WINDOWS\system32\config\systemprofile\AppData\Roaming\Python
\Python37\site-packages\tensorflow\python\feature_column\serialization.
py", line 273, in _deserialize_keras_object
    obj = module_objects.get(object_name)
AttributeError: 'NoneType' object has no attribute 'get'

Mirando a mi alrededor, sospecho que tiene algo que ver con la custom_objectsetiqueta de la load_modelfunción, pero no estoy 100% seguro de cómo implementarlo.

Respuestas

John Aug 21 2020 at 20:55

Prueba este enlace https://github.com/keras-team/keras/issues/11418

Hay una respuesta de ethanfowler que parece resolver el problema usando custom_objects

AaronJones Sep 05 2020 at 01:54

Después de mirar un poco más y investigar algunos problemas de Github, creo que he resuelto el problema. Para mi situación específica, no necesitaba guardar todo el modelo, en lugar de solo los pesos. Para mi configuración estoy usando Tensorflow 2.3.0 y Keras 2.4.3.

RESPUESTA CORTA:

Ajuste su modelo durante al menos una época, luego cargue los pesos.

RESPUESTA LARGA:

Para guardar los pesos, utilizo la siguiente función adjunta con la ruta del archivo de mi modelo encima.

# Create a path for the saving location of the model
model_dir = dir_path + '/model.h5'

# Save the model
model.save_weights(model_dir)

Primero construyo mi modelo a partir de mi pregunta anterior y lo almaceno en un objeto modelo

model = build_model(arguments)

Agrego mi función de pérdida y optimizador, luego compilo mi modelo para asegurarme de que tenga todas las características relevantes antes de cargar los pesos.

loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
    
#Declare and set the parametors of the optimizer
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001, decay=0.001)
    
#Compile the model
model.compile(loss=loss_object, optimizer=optimizer, metrics=['accuracy'])

Encontré mi respuesta de esta línea aquí , pero en la parte inferior dice que se ajuste al modelo durante 1 época antes de cargar los pesos.

history = model.fit(test_data, batch_size=1, epochs=1)

Luego, debería poder cargar bien los pesos usando la función a continuación.

model.load_weights(model_path)