Seldon部署时pickle.load()报找不到MyEncoder属性的AttributeError
问题根源
模型序列化时pickle会记录MyEncoder所属的模块路径,本地运行my_prediction.py时模块导入路径匹配可以正常加载,但Seldon部署时是通过seldon-core-microservice启动服务,运行时主模块为__main__,导入的MyEncoder没有被注册到pickle加载时能识别的命名空间,因此加载失败。
可行解决方案
方案1:加载pickle前手动绑定自定义类到__main__模块
无需修改训练逻辑,仅调整my_prediction.py代码即可,是成本最低的修复方案:
import pickle import pandas as pd import dill import sys from MyPipelines.CustomPipelines import MyEncoder # 新增两行代码,手动把自定义类绑定到运行时的__main__模块 sys.modules['__main__'].MyEncoder = MyEncoder class my_prediction: def __init__(self): file_name = 'model.sav' with open(file_name, 'rb') as model_file: self.model = pickle.load(model_file) def predict(self, request): data = request.get('ndarray') columns = request.get('names') X = pd.DataFrame(data, columns = columns) predictions = self.model.predict(X) return predictions
方案2:用dill替代pickle完成序列化
如果后续还会新增多个自定义Transformer类,可以直接用dill做序列化,dill会直接序列化类的完整定义,不依赖运行时的导入路径:
- 训练阶段把
pickle.dump(xxx, file)替换为dill.dump(xxx, file)重新保存模型 - 部署阶段把
pickle.load(model_file)替换为dill.load(model_file)即可
方案3:统一训练和部署的模块导入路径
在Seldon部署的环境变量中新增PYTHONPATH配置,把你代码的根目录加到环境变量中,确保运行时MyPipelines模块的导入路径和训练模型时的路径完全一致,pickle就能自动找到对应的类定义。
内容的提问来源于stack exchange,提问作者Chaitanya Patil
相关产品推荐
相关产品推荐

