Keras 2.1.5(TF后端)使用Lambda层加载模型时preprocess_input报错
解决Keras加载含preprocess_input的Lambda层模型报错问题
这个问题我之前也碰到过!核心原因是Keras在保存模型时无法序列化Lambda层里引用的外部函数(比如你用的preprocess_input),当调用load_model时,系统找不到这个函数的定义,自然就抛出相关报错了。给你几个可行的解决办法:
方法一:加载时指定custom_objects
最简单的处理方式是在加载模型时,把preprocess_input明确告知Keras。代码如下:
from keras.applications.resnet50 import preprocess_input from keras.models import load_model # 替换成你的模型文件路径 model = load_model('your_model.h5', custom_objects={'preprocess_input': preprocess_input})
这样Keras就能正确识别Lambda层里调用的函数了。
方法二:把预处理步骤移到模型外部
如果不想在加载时额外配置,可以直接去掉模型里的Lambda预处理层,把preprocess_input的调用放在数据输入模型之前:
# 重构模型:移除Lambda层 base_model = keras.applications.resnet50.ResNet50(include_top=False, input_shape=(224, 224, 3)) model = Sequential() model.add(base_model) model.add(GlobalAveragePooling2D()) model.add(Dense(len(classes), activation="softmax")) # 训练前先预处理数据 x_train = preprocess_input(x_train) model.fit(x_train, y_train, epochs=10, batch_size=32) # 预测时同样先处理输入 x_test = preprocess_input(x_test) predictions = model.predict(x_test)
这种方式更清晰,也避免了序列化问题,推荐在新项目里使用。
方法三:自定义可序列化的预处理层
如果必须把预处理放在模型内部,可以自定义一个继承自Layer的预处理层,这样Keras能正常序列化它:
from keras.layers import Layer from keras.applications.resnet50 import preprocess_input class ResNetPreprocessLayer(Layer): def __init__(self, **kwargs): super(ResNetPreprocessLayer, self).__init__(**kwargs) def call(self, inputs): # 直接调用preprocess_input处理输入 return preprocess_input(inputs) def get_config(self): # 必须实现这个方法才能正常序列化 config = super(ResNetPreprocessLayer, self).get_config() return config # 用自定义层构建模型 model = Sequential() model.add(ResNetPreprocessLayer(name='Input_Image', input_shape=(224, 224, 3))) model.add(base_model) model.add(GlobalAveragePooling2D()) model.add(Dense(len(classes), activation="softmax"))
加载模型时,需要把自定义层加入custom_objects:
model = load_model('your_model.h5', custom_objects={'ResNetPreprocessLayer': ResNetPreprocessLayer})
内容的提问来源于stack exchange,提问作者Kai
相关产品推荐
相关产品推荐

