升级scikit-learn后加载v0.19.1训练的Pickle模型失败,如何解决?
解决scikit-learn跨版本Pickle模型加载的DeprecationDict问题
这个问题我之前也碰到过,确实不用重新训练所有模型就能解决——核心原因是DeprecationDict是scikit-learn v0.19.1里的内部辅助类,在v0.23.1版本中被移除或重构了,pickle加载时找不到这个类就会抛出AttributeError。下面给你几个可行的解决方案:
方案1:手动补全缺失的DeprecationDict类
在加载模型前,先在当前环境的sklearn.utils.deprecation模块中定义这个类,让pickle能找到对应的结构。这是最直接的即时解决方案:
import sklearn.utils.deprecation import warnings # 还原scikit-learn v0.19.1中DeprecationDict的核心实现 class DeprecationDict(dict): def __init__(self, *args, **kwargs): self._deprecations = kwargs.pop('_deprecations', {}) super().__init__(*args, **kwargs) def __getitem__(self, key): if key in self._deprecations: warnings.warn(self._deprecations[key], DeprecationWarning, stacklevel=2) return super().__getitem__(key) # 将这个类注入到对应的模块中 sklearn.utils.deprecation.DeprecationDict = DeprecationDict # 现在正常加载你的模型 import pickle with open("your_model_file.pkl", "rb") as pkl_file: page_selector = pickle.load(pkl_file)
这个实现还原了旧版本中DeprecationDict的核心功能——一个带有废弃警告提示的字典子类,补上之后pickle就能顺利解析模型文件了。
方案2:临时降级后转存模型(适合批量处理)
如果你的模型数量较多,或者不想修改加载脚本,可以先临时降级到v0.19.1加载模型,再用新版本兼容的方式重新保存:
- 临时降级scikit-learn:
pip install scikit-learn==0.19.1
- 加载旧模型并转存为joblib格式(sklearn官方推荐用joblib存储模型,兼容性和效率都比pickle好):
import pickle from sklearn.externals import joblib # 加载旧pickle模型 with open("old_model.pkl", "rb") as f: model = pickle.load(f) # 用joblib重新保存 joblib.dump(model, "new_model.joblib")
- 升级回v0.23.1:
pip install scikit-learn==0.23.1
- 加载新保存的模型:
from sklearn.externals import joblib page_selector = joblib.load("new_model.joblib")
注意事项
- 方案1的代码需要放在
pickle.load()执行之前,确保类已经被注入到模块中 - 如果后续还有其他旧版本内部类缺失的报错,可以用类似的思路补全对应的类实现
- 后续建议统一用joblib存储sklearn模型,避免跨版本的pickle兼容性问题
内容的提问来源于stack exchange,提问作者Robycool
相关产品推荐
相关产品推荐

