keras.models.load_model() 给出 ValueError

keras.models.load_model() gives ValueError

我已将训练好的模型和权重保存如下。

model, history, score = fit_model(model, train_batches, val_batches, callbacks=[callback])
model.save('./model')
model.save_weights('./weights')

然后我尝试通过以下方式获取保存的模型

if __name__ == '__main__':
  model = keras.models.load_model('./model', compile= False,custom_objects={"F1Score": tfa.metrics.F1Score})
  test_batches, nb_samples = test_gen(dataset_test_path, 32, img_width, img_height)
  predict, loss, acc = predict_model(model,test_batches, nb_samples)
  print(predict)
  print(acc)
  print(loss)

但是它给我一个错误。我应该怎么做才能克服这个问题?

Traceback (most recent call last):
  File "test_pro.py", line 34, in <module>
    model = keras.models.load_model('./model',compile= False,custom_objects={"F1Score": tfa.metrics.F1Score})
  File "/home/dcs2016csc007/.local/lib/python3.8/site-packages/tensorflow/python/keras/saving/save.py", line 212, in load_model
    return saved_model_load.load(filepath, compile, options)
  File "/home/dcs2016csc007/.local/lib/python3.8/site-packages/tensorflow/python/keras/saving/saved_model/load.py", line 138, in load
    keras_loader.load_layers()
  File "/home/dcs2016csc007/.local/lib/python3.8/site-packages/tensorflow/python/keras/saving/saved_model/load.py", line 379, in load_layers
    self.loaded_nodes[node_metadata.node_id] = self._load_layer(
  File "/home/dcs2016csc007/.local/lib/python3.8/site-packages/tensorflow/python/keras/saving/saved_model/load.py", line 407, in _load_layer
    obj, setter = revive_custom_object(identifier, metadata)
  File "/home/dcs2016csc007/.local/lib/python3.8/site-packages/tensorflow/python/keras/saving/saved_model/load.py", line 921, in revive_custom_object
    raise ValueError('Unable to restore custom object of type {} currently. '
ValueError: Unable to restore custom object of type _tf_keras_metric currently. Please make sure that the layer implements `get_config`and `from_config` when saving. In addition, please use the `custom_objects` arg when calling `load_model()`.

查看Keras的源码,报错when trying to load a model with a custom object:

def revive_custom_object(identifier, metadata):
  """Revives object from SavedModel."""
  if ops.executing_eagerly_outside_functions():
    model_class = training_lib.Model
  else:
    model_class = training_lib_v1.Model

  revived_classes = {
      constants.INPUT_LAYER_IDENTIFIER: (
          RevivedInputLayer, input_layer.InputLayer),
      constants.LAYER_IDENTIFIER: (RevivedLayer, base_layer.Layer),
      constants.MODEL_IDENTIFIER: (RevivedNetwork, model_class),
      constants.NETWORK_IDENTIFIER: (RevivedNetwork, functional_lib.Functional),
      constants.SEQUENTIAL_IDENTIFIER: (RevivedNetwork, models_lib.Sequential),
  }
  parent_classes = revived_classes.get(identifier, None)

  if parent_classes is not None:
    parent_classes = revived_classes[identifier]
    revived_cls = type(
        compat.as_str(metadata['class_name']), parent_classes, {})
    return revived_cls._init_from_metadata(metadata)  # pylint: disable=protected-access
  else:
    raise ValueError('Unable to restore custom object of type {} currently. '
                     'Please make sure that the layer implements `get_config`'
                     'and `from_config` when saving. In addition, please use '
                     'the `custom_objects` arg when calling `load_model()`.'
                     .format(identifier))

该方法仅适用于 revived_classes 中定义的类型的自定义对象。如您所见,它目前仅适用于输入层、图层、模型、网络和顺序自定义对象。

在您的代码中,您在 custom_objects 参数中传递了一个 tfa.metrics.F1Score class,其类型为 METRIC_IDENTIFIER,因此不受支持(可能是因为它不支持'实现 get_configfrom_config 函数,如错误输出所示:

keras.models.load_model('./model', compile=False, custom_objects={"F1Score": tfa.metrics.F1Score})

自从我上次使用 Keras 以来已经有一段时间了,但也许您可以尝试遵循 中提出的建议,并将对 tfa.metrics.F1Score 的调用包装在一个方法中。像这样(根据您的需要进行调整):

def f1(y_true, y_pred):
    metric = tfa.metrics.F1Score(num_classes=3, threshold=0.5)
    metric.update_state(y_true, y_pred)
    return metric.result()

keras.models.load_model('./model', compile=False, custom_objects={'f1': f1})