基于VGG16迁移学习实现猫狗分类时遇‘Could not deserialize class 'Functional'’错误求助
Hey there! 看你贴的代码是在用VGG16做迁移学习实现猫狗分类,现在碰到了「Could not deserialize class 'Functional'」这个错误对吧?我来帮你梳理下可能的问题点和对应的解决思路:
大概率的问题根源:模型序列化/反序列化不兼容
这个错误基本都和模型的保存、加载环节有关,要么是自定义逻辑没做好序列化支持,要么是版本不匹配,咱们一步步来排查:
1. 自定义预处理函数未做序列化处理
你写的manual_preprocess_input是个普通函数,但Keras的Functional模型在保存时,会把整个模型的结构(包括所有层和操作)序列化下来。普通函数没法被Keras正确识别和序列化,等你后续加载模型时就会报错。
修复方案:把预处理逻辑包装成可序列化的层,有两种方式可选:
用
Lambda层快速包装(适合简单逻辑):# 把自定义函数包装成Lambda层 manual_preprocess_layer = tf.keras.layers.Lambda(manual_preprocess_input) # 模型里替换原来的直接调用 inputs = tf.keras.Input(shape=(224, 224, 3)) x = data_augmentation(inputs) x = manual_preprocess_layer(x) # 这里改用包装后的层 x = base_model(x, training=False) # ... 后续代码不变自定义
Layer类(更规范,适合复杂逻辑):class ManualPreprocessLayer(tf.keras.layers.Layer): def __init__(self, **kwargs): super().__init__(**kwargs) # 把均值定义成可序列化的变量 self.mean = tf.constant([103.939, 116.779, 123.68], dtype=tf.float32) def call(self, inputs): data_format = tf.keras.backend.image_data_format() if data_format == 'channels_first': inputs = tf.transpose(inputs, perm=[0, 2, 3, 1]) x = inputs - self.mean x = x / 127.5 return x def get_config(self): # 必须实现这个方法,让Keras能正确序列化层的参数 config = super().get_config() return config然后在模型中使用这个自定义层:
x = ManualPreprocessLayer()(x)
2. TensorFlow/Keras版本不匹配
如果是保存模型后加载时报错,很大概率是保存和加载时的TF/Keras版本不一致。比如你用TF 2.10保存模型,却用TF 2.8加载,Functional模型的序列化格式可能有差异,导致无法识别。
修复方案:
- 尽量保证保存和加载模型时使用完全相同版本的TensorFlow;
- 如果必须跨版本,可以只保存模型权重(
model.save_weights('model_weights.h5')),然后重新手动构建模型结构,再用model.load_weights('model_weights.h5')加载权重,绕开模型结构序列化的问题。
3. VGG16基础模型加载是否规范
检查下你加载VGG16的代码,确保是按照迁移学习的正确方式加载的:
base_model = tf.keras.applications.VGG16( include_top=False, # 一定要去掉顶层的分类层 input_shape=(224, 224, 3), weights='imagenet' # 加载预训练权重 ) base_model.trainable = False # 冻结基础模型,只训练后面的自定义层
如果没加include_top=False,会把VGG16的顶层分类层也加载进来,可能导致模型结构冲突,间接引发序列化问题。
4. 模型保存格式的尝试
如果用默认的SavedModel格式保存有问题,可以试试切换成HDF5格式,或者反过来:
# 保存为HDF5格式 model.save('cat_dog_model.h5') # 加载(如果用了自定义层,要在custom_objects里指定) model = tf.keras.models.load_model('cat_dog_model.h5', custom_objects={'ManualPreprocessLayer': ManualPreprocessLayer})
额外小建议
如果还没解决,可以先跳过模型保存/加载,直接运行训练流程,看看模型能不能正常训练和预测。如果训练没问题,那问题肯定出在保存/加载环节;如果训练时就报错,那得再检查模型结构的拼接是否有问题。另外,把错误的完整堆栈信息贴出来,能更精准地定位问题哦!
备注:内容来源于stack exchange,提问作者Oualid Laib

