Salvar e carregar resultados do modelo do Tensorflow em erro Keras

Aug 20 2020

Para um projeto no qual estou trabalhando, criei um modelo simples no TensorFlow que consiste em uma camada densa de recursos seguida por três camadas 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

Não consigo entrar em mais detalhes sobre o parâmetro arguments, mas a função de modelo acima funciona perfeitamente e pode treinar e salvar um .h5arquivo perfeitamente usando o código abaixo.

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

    # Save the model
    model.save(model_dir)

No entanto, quando tento carregar o modelo de volta do .h5arquivo,

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

Eu recebi a seguinte mensagem de erro.

  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'

Olhando em volta, suspeito que tenha algo a ver com a custom_objectstag da load_modelfunção, mas não estou 100% certo de como implementá-la.

Respostas

John Aug 21 2020 at 20:55

Tente este link https://github.com/keras-team/keras/issues/11418

Há uma resposta de ethanfowler que parece resolver o problema usando custom_objects

AaronJones Sep 05 2020 at 01:54

Depois de dar uma olhada mais um pouco e cavar em alguns problemas do Github, acredito que descobri o problema. Para minha situação específica, não precisei salvar o modelo inteiro, em vez de apenas os pesos. Para minha configuração, estou usando Tensorflow 2.3.0 e Keras 2.4.3.

RESPOSTA CURTA:

Ajuste seu modelo por pelo menos uma época e, em seguida, carregue os pesos.

RESPOSTA LONGA:

Para economizar os pesos, uso a seguinte função anexada ao caminho do arquivo do meu modelo acima dela.

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

# Save the model
model.save_weights(model_dir)

Eu primeiro construo meu modelo a partir da minha pergunta acima e o armazeno em um objeto modelo

model = build_model(arguments)

Eu adiciono minha função de perda e otimizador, então compilo meu modelo para ter certeza de que possui todos os recursos relevantes antes de carregar os 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'])

Eu encontrei minha resposta a partir desta linha aqui , mas no fundo diz para ajustar o modelo por 1 época antes de carregar os pesos.

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

Depois disso, você poderá carregar os pesos perfeitamente usando a função abaixo.

model.load_weights(model_path)