FastAPI部署Sklearn Pipeline时,joblib加载自定义MultiColumnLabelEncoder类报错
嘿,我来帮你解决这个问题!这个报错的核心原因很明确:当你用joblib保存包含自定义类的Pipeline时,加载模型的Python环境找不到这个自定义类的定义了。错误提示里说在__main__模块找不到MultiColumnLabelEncoder,说明加载时这个类没有被正确导入到当前运行的命名空间中。
我给你梳理几个关键的解决步骤:
1. 确认自定义类的模块路径一致性
你已经把MultiColumnLabelEncoder放在了utils模块里,这很好,但要确保保存模型时和加载模型时,这个类的导入路径完全一致:
- 保存模型的脚本里,你应该是这样导入的:
from utils import MultiColumnLabelEncoder - FastAPI的加载脚本里,也要用完全相同的导入语句,不能有相对路径或模块名的差异。
如果之前你是在临时脚本里直接定义类然后保存的模型,那joblib会把类和__main__模块绑定,这时候加载就会找不到。这种情况必须重新保存模型:先把类移到utils模块,导入后重新训练并保存Pipeline。
2. 确保FastAPI脚本能正确找到utils模块
检查你的项目结构,比如:
your_project/ ├── main.py # FastAPI启动脚本 ├── utils.py # 包含MultiColumnLabelEncoder └── models/ └── ml/ └── ckd_model.joblib
如果utils.py和main.py在同一目录,那from utils import MultiColumnLabelEncoder是没问题的。如果不在同一目录,需要把utils所在的目录加入Python的搜索路径,比如在main.py开头加上:
import sys from pathlib import Path sys.path.append(str(Path(__file__).parent))
3. 验证类的模块归属
在加载模型前,可以加一行调试代码,确认类的模块是否正确:
from utils import MultiColumnLabelEncoder print(MultiColumnLabelEncoder.__module__) # 应该输出 'utils',而不是 '__main__'
如果输出是__main__,说明你可能在main.py里又重新定义了这个类,或者导入路径有问题,得修正导入方式。
4. 加载模型前确保类已被导入
有时候即使导入了,joblib的加载机制可能还是没识别到,你可以在load_model函数里先明确导入类,再加载模型:
@app.on_event('startup') def load_model(): from utils import MultiColumnLabelEncoder # 在这里再次导入确保类被加载 clf.model = load('models/ml/ckd_model.joblib')
按照这些步骤排查,应该就能解决这个加载报错的问题了。
备注:内容来源于stack exchange,提问作者Mohamed Amine boukriba

