使用joblib加载序列化的scikit-learn模型时出现KeyError

29

我有一个包含两个scikit-learn模型的对象,一个是IsolationForest,另一个是RandomForestClassifier,我想把它存储下来并在以后重新加载并用于产生预测。除了这两个模型之外,该对象还包含一些StandardScaler和几个Python列表。

使用joblib对此对象进行pickle没有问题,但是当我尝试稍后进行unpickle时,会出现以下异常:

Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "/home/(...)/python3.5/site-packages/joblib/numpy_pickle.py", line 578, in load
   obj = _unpickle(fobj, filename, mmap_mode)
 File "/home/(...)/python3.5/site-packages/joblib/numpy_pickle.py", line 508, in _unpickle
   obj = unpickler.load()
 File "/usr/lib/python3.5/pickle.py", line 1039, in load
   dispatch[key[0]](self)
KeyError: 0

这个程序既可以将对象序列化成pickle格式,也可以把pickle格式的对象反序列化回来。因此,在使用scikit-learnjoblib以及其他库的时候,它们的版本必须一致。由于错误信息不明确,我不确定从哪里开始调试。你有什么想法或提示吗?


你的电脑上安装了最新版本的scikit吗? - Flika205
你能否提供一个最小可复制的代码? - Vivek Kumar
6个回答

42

解决方案很平凡:在不知情的情况下,我使用了sklearn.externals.joblib中的joblib版本来进行数据封装,但是使用了更新的joblib版本来进行数据解析。当我在两个任务中都使用更新版本的joblib时,问题得到解决。


你好 @haroba,我遇到了同样的问题,请问你用的是哪个版本?我正在使用 joblib-0.13.0 版本。 - Jignasha Royala
平凡但有用的;) - jibiel
你救了我的一天!非常有用。我遇到了一个由numpy引起的非常相似的负载错误。将joblib更新到等效版本解决了这个问题。所以,谢谢! - petezurich

15

我遇到了这样的情况,我使用from sklearn.externals import joblib导出模型,尝试使用import joblib加载。


在版本 1.3.0 中不再有 sklearn.externals.joblib。我的问题是不同计算机之间的 joblib 版本问题太平凡了。 - undefined

8

我的经历很有趣。我正在使用 git-lfs,因此文件已被更改,而 joblib 无法打开它们。因此,我需要运行 git lfs pull 来获取实际的文件。所以,如果您正在使用兼容的 joblib 版本,请确保您的文件未被某种方式更改!


1

对我来说,使用相同版本的joblib进行转储和加载,但我是在Python 3.7.4下保存文件,并尝试在Python 3.7.6下加载,这引发了相同的KeyError错误。


0
在我的情况下,我试图加载一个XGB。我发现XGB与其他sklearn模型不兼容,所以我采取了以下措施:
from xgboost import *
import joblib

def get_model(model_path):
    if 'xgb' in model_path:
        xgb_model = XGBClassifier()
        xgb_model.load_model(model_path)
        model = xgb_model
    else: 
        model = get_obj(model_path)
    return model 

xbg = get_model('Models/xgb_v1.pkl') # an xgb

tree = model = get_model('Models/dt_v1.pkl') # a decition tree

0

我试图加载多年前的joblib文件,但是无论我使用哪种方法来绕过它们,都会出现多层级的错误。

随着joblib版本的不断更新,这些方法已经不再奏效,因此我不得不创建一个专门用于sklearn-0.23的conda环境,如下所示:

conda create -n outdated "scikit-learn<0.23"

之后,我能够以不同的方式打开并保存文件。有时这意味着使用非sklearn joblib文件重新保存数据import joblib;有时这意味着使用pickle;有时这意味着使用pandas.to_csv

解决方案是针对要保存的数据文件而制定的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接