
在使用TensorFlow保存并跨环境加载自定义Keras模型时,若自定义Model子类重写了__init__但未兼容父类参数(如name),调用load_model()会因配置反序列化失败而报错“unexpected keyword argument 'name'”。
在使用tensorflow保存并跨环境加载自定义keras模型时,若自定义`model`子类重写了`__init__`但未兼容父类参数(如`name`),调用`load_model()`会因配置反序列化失败而报错“unexpected keyword argument 'name'”。
当您通过model.save('xxx.h5')保存一个继承自tf.keras.Model的自定义类(如Agent)后,TensorFlow在序列化时不仅保存权重,还会调用get_config()获取模型结构信息,并在加载时尝试用该配置重新实例化类对象。此时,Keras默认会将get_config()返回的所有键值对(包括从super().get_config()继承的name、trainable等)作为关键字参数传入__init__。
然而,您的Agent.__init__仅接受两个显式参数:number_of_outputs和number_of_hidden_units,未声明对name等父类参数的支持。尽管super(Agent, self).__init__()内部需要这些参数,但因签名不匹配,Python在反序列化时抛出TypeError。
✅ 正确做法是扩展__init__签名,显式接收并透传所有父类所需参数。推荐使用**kwargs方式,既保持向后兼容,又避免遗漏:
class Agent(Model):
def __init__(self, number_of_outputs: int, number_of_hidden_units: int, **kwargs):
# 关键修改:接收并透传 kwargs 给父类 __init__
super(Agent, self).__init__(**kwargs)
self.number_of_outputs = number_of_outputs
self.number_of_hidden_units = number_of_hidden_units
# ... 其余层定义保持不变(first_block, second_block 等)
def call(self, data):
# ... 保持不变
pass
def get_config(self):
base_config = super().get_config() # 此调用已自动包含 name, trainable 等
config = {
"number_of_outputs": self.number_of_outputs,
"number_of_hidden_units": self.number_of_hidden_units
}
return {**base_config, **config}
⚠️ 注意事项:
-
get_config()中无需手动添加"name"字段——super().get_config()已处理; - 若后续需支持
from_config()自定义反序列化逻辑(如依赖外部状态),应同时重写该方法,但本例中默认行为已足够; - 使用HDF5格式(
.h5)保存时,确保训练与加载环境的TensorFlow版本尽量一致(≥2.9建议优先使用SavedModel格式); - 加载代码可保持不变:
load_model(path, custom_objects={'Agent': Agent})。
? 总结:自定义Keras模型的可序列化性依赖于__init__与get_config()的严格契约。只要__init__能接收get_config()返回的所有键,模型即可无损保存与重建。添加**kwargs是最简洁、鲁棒的解决方案。











