自定义L1Dist层导致Siamese模型加载失败问题求助
解决自定义L1Dist层Siamese模型加载报错问题
问题概述
基于TensorFlow/Keras实现包含自定义L1Dist层的Siamese网络,训练完成后将模型保存为siamese_model.h5文件,使用tf.keras.models.load_model加载时触发如下错误:
ValueError: Unexpected object from deserialization, expected a layer or operation, got a <class '__main__.L1Dist'>
报错原因
- 自定义
L1Dist层的__init__方法未将关键字参数传递给父类Layer的构造函数,导致层的元信息缺失 - 自定义层缺少
get_config方法,无法在序列化时保存层的配置,反序列化时无法正确重建层对象 - 加载模型时,
custom_objects参数中存在类名拼写错误(原代码中误写为Siamese_layer,实际应为L1Dist)
代码修改方案
1. 修正自定义L1Dist层
确保__init__传递kwargs给父类,并添加get_config方法:
from tensorflow.keras.layers import Layer class L1Dist(Layer): # 修正__init__方法,传递kwargs给父类 def __init__(self, **kwargs): super(L1Dist, self).__init__(**kwargs) def call(self, input_embedding, validation_embedding): return tf.math.abs(input_embedding - validation_embedding) # 添加get_config方法,支持序列化 def get_config(self): # 调用父类的get_config,保留默认配置 config = super(L1Dist, self).get_config() return config
2. 修正模型加载代码
确保custom_objects中的类名正确,同时无需额外指定binary_crossentropy(Keras默认可识别):
# 修正加载时的custom_objects参数 new_model = tf.keras.models.load_model('siamese_model.h5', custom_objects={'L1Dist': L1Dist})
完整修正后的核心代码片段
# 嵌入层定义(假设make_embedding已正确实现) embedding = make_embedding() # 修正后的自定义L1Dist层 class L1Dist(Layer): def __init__(self, **kwargs): super(L1Dist, self).__init__(**kwargs) def call(self, input_embedding, validation_embedding): return tf.math.abs(input_embedding - validation_embedding) def get_config(self): config = super(L1Dist, self).get_config() return config # Siamese模型构建函数 def make_siamese_model(): input_image = Input(name='input_img', shape=(100,100,3)) validation_image = Input(name='validation_img', shape=(100,100,3)) siamese_layer = L1Dist(name='distance') # 直接在实例化时指定name,无需手动修改_name属性 distances = siamese_layer(embedding(input_image), embedding(validation_image)) classifier = Dense(1, activation='sigmoid')(distances) return Model(inputs=[input_image, validation_image], outputs=classifier, name='SiameseNetwork') # 训练流程(原训练代码可保留,无需修改) siamese_model = make_siamese_model() binary_cross_loss = tf.losses.BinaryCrossentropy() opt = tf.keras.optimizers.Adam(1e-4) # ...(省略训练步骤代码) # 保存模型 siamese_model.save('siamese_model.h5') # 修正后的模型加载代码 new_model = tf.keras.models.load_model('siamese_model.h5', custom_objects={'L1Dist': L1Dist})
验证方法
- 使用修正后的代码重新训练模型并保存
- 执行加载代码,确认不再报错
- 可通过
new_model.summary()查看模型结构,验证加载是否成功
内容的提问来源于stack exchange,提问作者Prateek
相关产品推荐
相关产品推荐

