TensorFlow 2.2.0加载FaceNet模型报错:bad marshal data
这个错误很常见,根源在于你下载的FaceNet Keras模型里包含了Lambda层,这些层使用了匿名lambda函数做预处理操作。旧版本Keras保存模型时会把lambda函数的字节码序列化,而TensorFlow 2.x(包括你的2.2.0版本)在反序列化这些字节码时,会因为版本/环境差异出现兼容性问题,从而抛出bad marshal data错误。
下面是几种可行的解决方案:
方法1:使用自定义对象加载模型
你需要先定义模型中Lambda层对应的具体函数,然后在加载模型时通过custom_objects参数传入,让TensorFlow正确识别这些自定义操作。FaceNet模型里通常用到的是归一化预处理函数,示例代码如下:
from tensorflow.keras.models import load_model import tensorflow as tf # 定义FaceNet预处理函数(对应模型中Lambda层的操作) def preprocess_input(x): # 对应原始模型中把RGB转为灰度并归一化到[-1,1]的操作 x = tf.keras.backend.mean(x, axis=-1, keepdims=True) return (x - 127.5) / 127.5 # 加载模型时传入自定义对象 custom_objects = {'preprocess_input': preprocess_input} model = load_model('facenet_keras.h5', custom_objects=custom_objects)
如果这个函数不匹配,你可以通过h5py查看模型配置,找出Lambda层对应的具体操作:
import h5py with h5py.File('facenet_keras.h5', 'r') as f: model_config = f.attrs.get('model_config') print(model_config.decode('utf-8'))
从输出的模型配置里找到Lambda层的function字段,对应写出函数即可。
方法2:转换为SavedModel格式(推荐)
如果有条件,先在能加载该模型的环境(比如TensorFlow 1.x或旧版Keras)中加载模型,然后保存为TensorFlow的SavedModel格式,这样可以彻底避免lambda函数的序列化问题:
# 在兼容环境中执行 from tensorflow.keras.models import load_model model = load_model('facenet_keras.h5') model.save('facenet_savedmodel', save_format='tf')
之后在你的TensorFlow 2.2.0环境中直接加载SavedModel:
from tensorflow.keras.models import load_model model = load_model('facenet_savedmodel')
方法3:临时降级TensorFlow版本
如果上面的方法暂时无法实现,你可以尝试降级到TensorFlow 1.x系列(比如1.15.x),因为FaceNet的原始Keras模型是基于TF1.x开发的,兼容性更好。不过这只是临时方案,长期来看还是推荐使用前两种方法适配TF2.x。
最后建议确认一下你的模型文件没有损坏,必要时可以重新下载验证文件完整性。
内容的提问来源于stack exchange,提问作者mj125

