使用joblib加载ML模型时遇模块缺失及版本兼容报错,求解决方案
第一个报错:ModuleNotFoundError: No module named 'sklearn.ensemble.forest'
报错详情
加载模型时触发的完整追踪信息:
Traceback (most recent call last): File "E:\__COURSE IIT\XYZ\ROAD\main.py", line 10, in <module> model = joblib.load('litemodel.sav') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\mitta\AppData\Local\Programs\Python\Python312\Lib\site-packages\joblib\numpy_pickle.py", line 658, in load obj = _unpickle(fobj, filename, mmap_mode) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\mitta\AppData\Local\Programs\Python\Python312\Lib\site-packages\joblib\numpy_pickle.py", line 577, in _unpickle obj = unpickler.load() ^^^^^^^^^^^^^^^^ File "C:\Users\mitta\AppData\Local\Programs\Python\Python312\Lib\pickle.py", line 1205, in load dispatch[key[0]](self) File "C:\Users\mitta\AppData\Local\Programs\Python\Python312\Lib\pickle.py", line 1521, in load_global klass = self.find_class(module, name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\mitta\AppData\Local\Programs\Python\Python312\Lib\pickle.py", line 1572, in find_class __import__(module, level=0) ModuleNotFoundError: No module named 'sklearn.ensemble.forest'
原因
Scikit-learn版本迭代后,内部模块路径发生变更:旧版本的sklearn.ensemble.forest模块,在新版本中被重命名为sklearn.ensemble._forest(前缀增加下划线)。你当前使用的是新版sklearn,但模型是用旧版sklearn保存的,因此加载时找不到旧路径的模块。
解决方法
方案1:匹配模型保存时的sklearn版本
确认当初训练并保存模型时使用的sklearn版本,在当前环境安装该版本:pip install scikit-learn==[具体版本号]例如当初用的是0.22版本,就执行
pip install scikit-learn==0.22方案2:手动修改模型文件的模块路径
若不想回退版本,可先备份litemodel.sav,再用文本编辑器打开原文件,将所有sklearn.ensemble.forest替换为sklearn.ensemble._forest,保存后尝试重新加载。注意此方法可能因文件二进制内容导致异常,需谨慎操作。
第二个报错:ValueError: You may be trying to read with python 3 a joblib pickle generated with python 2
报错详情
解决模块问题后出现的新错误:
File "E:\__COURSE IIT\BTP\ROAD-ACCIDENTS-PREDICTION-AND-CLASSIFICATION\main.py", line 10, in <module> model = joblib.load('litemodel.sav') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\mitta\AppData\Local\Programs\Python\Python312\Lib\site-packages\joblib\numpy_pickle.py", line 658, in load obj = _unpickle(fobj, filename, mmap_mode) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\mitta\AppData\Local\Programs\Python\Python312\Lib\site-packages\joblib\numpy_pickle.py", line 591, in _unpickle raise new_exc ValueError: You may be trying to read with python 3 a joblib pickle generated with python 2. This feature is not supported by joblib.
原因
Joblib不支持跨Python大版本读取模型——你的模型是用Python2环境保存的,而当前使用Python3加载,两者的pickle序列化格式不兼容,因此触发该错误。
解决方法
方案1:用Python2重新导出模型
在Python2环境中安装对应版本的joblib和sklearn,加载原模型后重新保存为Python3兼容格式:import joblib model = joblib.load('litemodel.sav') joblib.dump(model, 'litemodel_py3_compatible.sav')之后用Python3加载新生成的
litemodel_py3_compatible.sav即可。方案2:尝试用pickle兼容模式加载
用原生pickle加载模型时指定encoding='latin1'参数,再重新用joblib保存:import pickle import joblib with open('litemodel.sav', 'rb') as f: model = pickle.load(f, encoding='latin1') joblib.dump(model, 'litemodel_py3_compatible.sav')注意此方法仅适用于部分简单模型,若模型包含复杂自定义对象可能失效。
内容的提问来源于stack exchange,提问作者Krishna Sharma

