加载含自定义对象的Keras模型时出现AttributeError问题求助
解决Keras加载自定义嵌套损失模型时的AttributeError问题
问题原因
- 你的自定义损失采用嵌套函数结构,模型保存时Keras实际记录的是内层函数
conditional_BCE2,但加载时你在custom_objects中注册的是外层的conditional_BCE函数,两者无法匹配,导致Keras错误地将外层函数当作损失张量处理,触发'function' object has no attribute 'get_shape'报错。 - 你使用的Keras 2.0.8 + TensorFlow 1.2.1属于老旧版本,对嵌套式自定义损失的序列化/反序列化支持不完善,进一步放大了这个问题。
解决方案
方案一:重构损失函数,避免嵌套结构
将嵌套式损失改为直接接收所有参数的形式,编译时通过partial绑定额外参数:
from keras import backend as K from functools import partial from keras.losses import register_loss @register_loss def conditional_BCE(y_true, y_pred, input_mask, flag): loss = flag * K.binary_crossentropy(y_true, y_pred) * input_mask return K.sum(loss) / K.sum(input_mask) # 训练时绑定额外参数 loss_func = partial(conditional_BCE, input_mask=input_mask_tensor, flag=flag_value) model.compile(optimizer='adam', loss=loss_func)
加载模型时,只需在custom_objects中注册重构后的损失函数:
from keras.models import load_model load_model('path_to_your_model.h5', custom_objects={'Self_Attention': Self_Attention, 'conditional_BCE': conditional_BCE})
方案二:匹配保存时的内层损失函数
模型保存时记录的是内层的conditional_BCE2,加载前需先生成与训练时完全一致的内层函数实例并注册:
from keras.models import load_model # 必须使用与训练时完全相同的input_mask和flag input_mask = ... # 训练时传入的input_mask张量 flag = ... # 训练时传入的flag值 custom_loss = conditional_BCE(input_mask, flag) # 加载时注册内层函数(注意键名是conditional_BCE2) load_model('path_to_your_model.h5', custom_objects={'Self_Attention': Self_Attention, 'conditional_BCE2': custom_loss})
方案三:升级依赖版本(推荐长期维护)
Keras 2.0.8和TensorFlow 1.2.1的自定义对象序列化机制存在诸多缺陷,升级到Python 2.7支持的较新版本(如Keras 2.2.5 + TensorFlow 1.14.0),可大幅改善这类兼容性问题,很多情况下无需修改代码即可正常加载模型。
验证步骤
- 若采用方案一,重新训练并保存模型,再尝试加载,确认无报错;
- 若采用方案二,确保
input_mask和flag与训练时完全一致,加载后测试推理或继续训练的效果; - 若采用方案三,升级依赖后重新加载原模型,验证功能正常。
内容的提问来源于stack exchange,提问作者kwcool
相关产品推荐
相关产品推荐

