You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TensorFlow含自定义损失函数的LSTM模型保存加载报错求助

解决TensorFlow自定义复合损失函数加载报错问题

问题根源

你遇到的ValueError: Unknown loss function: 'nested_loss'错误,是因为调用composite_loss(alpha)时返回的是内部嵌套的nested_loss函数,模型保存时会将损失函数标识为nested_loss,但你仅注册了外层的composite_loss,导致加载时无法找到对应的损失函数。

可靠解决方案:使用Keras Loss类实现

用类继承tf.keras.losses.Loss来定义损失函数,是Keras官方推荐的自定义损失序列化方式,能避免嵌套函数带来的序列化问题。

1. 重写自定义损失类

import tensorflow as tf
from tensorflow.keras.losses import Loss

# 自定义绝对值求和损失
class CustomLoss(Loss):
    def call(self, y_true, y_pred):
        return tf.reduce_sum(tf.abs(y_true - y_pred))

# 复合损失类:结合MSE和自定义损失
class CompositeLoss(Loss):
    def __init__(self, alpha=0.5, name="composite_loss"):
        super().__init__(name=name)
        self.alpha = alpha
        self.mse_loss = tf.keras.losses.MeanSquaredError()
        self.custom_loss = CustomLoss()

    def call(self, y_true, y_pred):
        mse_val = self.mse_loss(y_true, y_pred)
        custom_val = self.custom_loss(y_true, y_pred)
        return self.alpha * mse_val + custom_val

2. 模型编译、保存

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dropout, Dense
from tensorflow.keras.optimizers import Adam
from tensorflow.keras import utils

# 构建LSTM模型
model = Sequential()
model.add(LSTM(128, return_sequences=True, input_shape=(X_train.shape[1], 1)))
model.add(Dropout(0.3))
model.add(LSTM(64, return_sequences=True))
model.add(Dropout(0.3))
model.add(LSTM(32, return_sequences=True))
model.add(Dropout(0.3))
model.add(LSTM(16, return_sequences=False))
model.add(Dense(1))

# 编译模型:传入复合损失实例
alpha = 0.5
optimizer = Adam(learning_rate=0.001)  # 新版本TensorFlow用learning_rate替代lr
model.compile(loss=CompositeLoss(alpha), optimizer=optimizer)

# 注册自定义损失类,确保保存时能被序列化
utils.get_custom_objects()['CompositeLoss'] = CompositeLoss
utils.get_custom_objects()['CustomLoss'] = CustomLoss

# 保存模型
model.save('SYM-Revised-CAS-30')

3. 模型加载

from tensorflow.keras.models import load_model

# 加载时注册对应的自定义损失类
model = load_model('SYM-Revised-CAS-30', 
                   custom_objects={'CompositeLoss': CompositeLoss, 'CustomLoss': CustomLoss})

备选方案:函数式损失的临时修复(不推荐长期使用)

如果不想修改为类实现,可以提前生成损失函数实例并注册具体的函数对象:

# 先生成具体的损失函数实例
alpha = 0.5
my_composite_loss = composite_loss(alpha)

# 注册这个实例(用固定名称)
utils.get_custom_objects()['my_composite_loss'] = my_composite_loss

# 编译时使用该实例
model.compile(loss=my_composite_loss, optimizer=optimizer)

# 保存模型
model.save('SYM-Revised-CAS-30')

# 加载时必须注册同一个名称对应的实例
model = load_model('SYM-Revised-CAS-30', custom_objects={'my_composite_loss': my_composite_loss})

注意:这种方法依赖于保存和加载时使用同一个函数实例,重启代码后需要重新生成实例并注册,稳定性不如类实现。

内容的提问来源于stack exchange,提问作者Windstorm1981

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 08:56:08