提问:加载包含多个自定义loss的预训练模型报错

错误说明:

在使用tensorflow.keras加载包含多个自定义loss预训练神经网络时,Visual Studio Code蹿红:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "D:\ProgramFiles\Anaconda3\envs\MatlabEngine\lib\site-packages\keras\utils\traceback_utils.py", line 70, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "D:\ProgramFiles\Anaconda3\envs\MatlabEngine\lib\site-packages\keras\dtensor\utils.py", line 144, in _wrap_function
    init_method(instance, *args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'reduction'

 加载模型代码为:

M = tf.keras.models.load_model('D:/MODEL/my_model.h5', {'user_loss1': user_loss1, 'user_loss2': user_loss2})

自定义损失函数如下:

# Define the loss functions
def user_loss1(y_true, y_pred):
      loss = tf.keras.backend.mean(tf.keras.backend.std(y_true - y_pred)) / tf.keras.backend.std(tf.keras.backend.square(y_true))
      return loss
def user_loss2(y_true, y_pred):
      loss = tf.keras.backend.std(y_true - y_pred)
      return loss

环境配置如下:

# 输入:

Python --version

conda list tensorflow


# 输出:

Python 3.9.16

# packages in environment at D:\ProgramFiles\Anaconda3\envs\MatlabEngine:#

# Name Version Build Channel

tensorflow 2.11.1 pypi_0 pypi

tensorflow-estimator 2.11.0 pypi_0 pypi

tensorflow-intel 2.11.1 pypi_0 pypi

tensorflow-io-gcs-filesystem 0.31.0 pypi_0 pypi

测试描述:

单一只使用user_loss1或者user_loss2时,该报错消失,而给出如下报错

M = tf.keras.models.load_model('D:/MODEL/my_model.h5', {'user_loss1': user_loss1})

# 输出
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "D:\ProgramFiles\Anaconda3\envs\MatlabEngine\lib\site-packages\keras\utils\traceback_utils.py", line 70, in error_handler
    raise e.with_traceback(filtered_tb) from None
  File "D:\ProgramFiles\Anaconda3\envs\MatlabEngine\lib\site-packages\keras\saving\legacy\serialization.py", line 557, in deserialize_keras_object
    raise ValueError(
ValueError: Unknown loss function: 'user_loss2'. Please ensure you are using a `keras.utils.custom_object_scope` and that this object is included in the scope. See https://www.tensorflow.org/guide/keras/save_and_serialize#registering_the_custom_object for details.

 有遇到过类似错误的小伙伴不?后面是如何解决的呀?

该报错可能是由于在加载模型时没有正确注册自定义损失函数导致的。另一个可能的原因是,使用的 TensorFlow 版本不支持 reduction 参数,但在自定义损失函数中使用了该参数。
在 TensorFlow 2.0 以后的版本中,reduction 参数被添加到了许多损失函数中,用于指定损失函数在计算损失值时如何将不同样本的损失值进行聚合,例如取平均值、求和等。如果您的 TensorFlow 版本过旧,可能不支持该参数。
解决方法是,在自定义损失函数中移除 reduction 参数,或者升级 TensorFlow 版本至 2.0 或以上版本。

以下内容部分参考ChatGPT模型:


问题原因:

该错误是因为在模型加载时使用了自定义损失函数,并且该自定义损失函数中使用了未知的参数'reduction'。这是因为TensorFlow 2.0之后,自定义损失函数中的'reduction'参数已经被废弃,不再使用。

解决思路:

  1. 将自定义损失函数中的'reduction'参数移除,即去掉所有的'reduction'参数。
  2. 在加载模型时,使用tf.keras.utils.custom_object_scope()将自定义损失函数加入作用域中,避免在加载模型时出现未知损失函数的错误。

解决方法:

修改自定义损失函数,移除'reduction'参数,即:

def user_loss1(y_true, y_pred):
    loss = tf.keras.backend.mean(tf.keras.backend.std(y_true - y_pred)) / tf.keras.backend.std(tf.keras.backend.square(y_true))
    return loss

def user_loss2(y_true, y_pred):
    loss = tf.keras.backend.std(y_true - y_pred)
    return loss

在加载模型时,使用tf.keras.utils.custom_object_scope()将自定义损失函数加入作用域中,即:

with tf.keras.utils.custom_object_scope({'user_loss1': user_loss1, 'user_loss2': user_loss2}):
    M = tf.keras.models.load_model('D:/MODEL/my_model.h5')

这样就可以成功加载包含多个自定义损失函数的预训练模型了。

注:在加载模型时,不需要再指定自定义损失函数,因为已经将其加入作用域中,可以直接加载模型。


如果我的建议对您有帮助、请点击采纳、祝您生活愉快