Joblib加载sklearn模型报错scipy.sparse._csr模块缺失如何解决
环境信息
- Python版本:3.7(必须使用该版本)
- 操作系统:Linux
- 云平台:Azure
- 使用资源:基于Python的Azure Function
- 实现目标:加载由scikit-learn 1.0.2版本训练生成的模型,当前环境已安装依赖版本如下:
numpy: 1.17.3
joblib: 1.1.0
scipy: 1.7.3
问题描述
使用joblib加载本地Python 3.9环境下训练生成的scikit-learn模型时,抛出如下报错:
Traceback (most recent call last): File "/home/site/wwwroot/sortierung/__init__.py", line 51, in main prediction_file_path) File "/home/site/wwwroot/shared_code/custom_functions_prediction.py", line 255, in predict result.update(classify_mail(m,s,X, stop_words, model_folder_path)) File "/home/site/wwwroot/shared_code/custom_functions_prediction.py", line 105, in classify_mail model = load(modelFilePath) File "/home/site/wwwroot/.python_packages/lib/site-packages/joblib/numpy_pickle.py", line 587, in load obj = _unpickle(fobj, filename, mmap_mode) File "/home/site/wwwroot/.python_packages/lib/site-packages/joblib/numpy_pickle.py", line 506, in _unpickle obj = unpickler.load() File "/usr/local/lib/python3.7/pickle.py", line 1088, in load dispatch[key[0]](self) File "/usr/local/lib/python3.7/pickle.py", line 1385, in load_stack_global self.append(self.find_class(module, name)) File "/usr/local/lib/python3.7/pickle.py", line 1426, in find_class __import__(module, level=0) ModuleNotFoundError: No module named 'scipy.sparse._csr'
检查当前环境scipy安装目录,确认不存在scipy.sparse._csr模块。
问题根因
报错由版本不兼容直接导致:
- scipy从1.8.0版本开始调整了稀疏矩阵模块的内部结构,将原本公开路径下的csr/csc/coo等稀疏矩阵实现,移动到了带下划线前缀的私有路径下(即报错中的
scipy.sparse._csr)。 - 本地训练模型使用的Python 3.9环境中,安装的scipy版本≥1.8.0,模型序列化时记录的是新版私有模块路径;而线上Azure Function环境的scipy版本为1.7.3,仍使用旧版公开路径,反序列化时找不到对应模块就会抛出错误。
- 跨Python大版本(3.9→3.7)做pickle序列化/反序列化本身也存在兼容性风险,属于模型部署时的不规范操作。
解决方案
由于运行环境强制要求Python 3.7,无法升级运行时版本,可按优先级选择以下方案修复:
方案1(推荐,长期稳定)
搭建与线上完全一致的依赖环境:Python 3.7 + numpy 1.17.3 + joblib 1.1.0 + scipy 1.7.3 + scikit-learn 1.0.2,在该环境中重新训练并保存模型,再将新生成的模型文件部署到线上。
该方案完全规避跨版本pickle反序列化的所有兼容性问题,是工业界部署scikit-learn模型的标准做法,不会出现隐式的版本适配bug。
方案2(快速修复,无需重训)
如果暂时无法重新训练模型,可以在加载模型的代码最前端,手动为旧版本scipy添加模块别名映射,让反序列化流程可以找到对应对象,代码示例如下:
import scipy.sparse # 补全新版scipy的稀疏模块路径映射 scipy.sparse._csr = scipy.sparse.csr scipy.sparse._csc = scipy.sparse.csc scipy.sparse._coo = scipy.sparse.coo # 后续再执行原有模型加载逻辑 from joblib import load model = load(modelFilePath)
该方案属于补丁式修复,如果模型中还包含其他跨版本变动的对象,可能会抛出同类模块缺失错误,需要按需补全映射,仅适合临时紧急修复使用,不建议作为长期方案。
方案3(对齐本地依赖版本)
如果不想搭建线上匹配环境重训,也可以将本地训练环境的scipy降级到1.7.3版本,与线上版本对齐后重新保存模型再部署。注意降级scipy后需要验证scikit-learn 1.0.2功能正常,模型预测结果符合预期。
内容的提问来源于stack exchange,提问作者sergioMoreno
相关产品推荐
相关产品推荐

