如何将训练过的朴素贝叶斯分类器保存到磁盘并使用它来预测数据?

我从scikit-learn网站上获得了以下示例程序:

from sklearn import datasets
iris = datasets.load_iris()
from sklearn.naive_bayes import GaussianNB
gnb = GaussianNB()
y_pred = gnb.fit(iris.data, iris.target).predict(iris.data)
print "Number of mislabeled points : %d" % (iris.target != y_pred).sum()

当前回答

你也可以使用joblib。Dump和joblib。Load,它在处理数值数组时比默认的python pickler更有效。

scikit-learn中包含Joblib:

>>> import joblib
>>> from sklearn.datasets import load_digits
>>> from sklearn.linear_model import SGDClassifier

>>> digits = load_digits()
>>> clf = SGDClassifier().fit(digits.data, digits.target)
>>> clf.score(digits.data, digits.target)  # evaluate training error
0.9526989426822482

>>> filename = '/tmp/digits_classifier.joblib.pkl'
>>> _ = joblib.dump(clf, filename, compress=9)

>>> clf2 = joblib.load(filename)
>>> clf2
SGDClassifier(alpha=0.0001, class_weight=None, epsilon=0.1, eta0=0.0,
       fit_intercept=True, learning_rate='optimal', loss='hinge', n_iter=5,
       n_jobs=1, penalty='l2', power_t=0.5, rho=0.85, seed=0,
       shuffle=False, verbose=0, warm_start=False)
>>> clf2.score(digits.data, digits.target)
0.9526989426822482

编辑:在Python 3.8+中,如果你使用pickle协议5(这不是默认的),现在可以使用pickle对具有大型数值数组作为属性的对象进行有效的pickle。

其他回答

在很多情况下,特别是在文本分类中,仅仅存储分类器是不够的,你还需要存储向量化器,以便将来可以对输入进行向量化。

import pickle
with open('model.pkl', 'wb') as fout:
  pickle.dump((vectorizer, clf), fout)

未来用例:

with open('model.pkl', 'rb') as fin:
  vectorizer, clf = pickle.load(fin)

X_new = vectorizer.transform(new_samples)
X_new_preds = clf.predict(X_new)

在转储vectorizer之前,可以通过以下方式删除vectorizer的stop_words_属性:

vectorizer.stop_words_ = None

提高倾倒效率。 此外,如果你的分类器参数是稀疏的(就像在大多数文本分类例子中一样),你可以将参数从密集转换为稀疏,这将在内存消耗、加载和转储方面产生巨大的差异。稀疏化模型:

clf.sparsify()

这将自动工作于SGDClassifier,但如果你知道你的模型是稀疏的(大量的零在clf.coef_),那么你可以手动转换clf。将Coef_转化为CSR scipy稀疏矩阵:

clf.coef_ = scipy.sparse.csr_matrix(clf.coef_)

这样你就能更有效地储存它。

分类器只是可以像其他对象一样进行pickle和转储的对象。继续你的例子:

import cPickle
# save the classifier
with open('my_dumped_classifier.pkl', 'wb') as fid:
    cPickle.dump(gnb, fid)    

# load it again
with open('my_dumped_classifier.pkl', 'rb') as fid:
    gnb_loaded = cPickle.load(fid)

编辑:如果您正在使用sklearn Pipeline,其中您有无法通过pickle(也不能通过joblib)序列化的自定义转换器,那么使用Neuraxle的自定义ML Pipeline保存是一个解决方案,您可以在每个步骤的基础上定义自己的自定义步骤保存器。如果在保存时定义了保存器,则对每个步骤调用保存器,否则,对于没有保存器的步骤,将默认使用joblib。

Sklearn.externals.joblib自0.21以来已弃用,并将在v0.23中被移除:

/usr/local/lib/python3.7/site-packages / sklearn /外部/ joblib / init.py: 15: FutureWarning: sklearn.externals.joblib在0.21中已弃用 在0.23被移除。请直接从 可以安装:PIP install Joblib。如果这 在加载pickle模型时引发警告,您可能需要 使用scikit-learn 0.21+重新序列化这些模型。 警告。警告(味精、类别= FutureWarning)


因此,您需要安装joblib:

pip install joblib

最后将模型写入磁盘:

import joblib
from sklearn.datasets import load_digits
from sklearn.linear_model import SGDClassifier


digits = load_digits()
clf = SGDClassifier().fit(digits.data, digits.target)

with open('myClassifier.joblib.pkl', 'wb') as f:
    joblib.dump(clf, f, compress=9)

现在为了读取转储文件,你需要运行的是:

with open('myClassifier.joblib.pkl', 'rb') as f:
    my_clf = joblib.load(f)

在sklearn中,您要寻找的是所谓的模型持久性,它在介绍和模型持久性部分中都有说明。

你已经初始化了分类器并且训练了很长时间

clf = some.classifier()
clf.fit(X, y)

在这之后,你有两个选择:

1)使用泡菜

import pickle
# now you can save it to a file
with open('filename.pkl', 'wb') as f:
    pickle.dump(clf, f)

# and later you can load it
with open('filename.pkl', 'rb') as f:
    clf = pickle.load(f)

2)使用Joblib

from sklearn.externals import joblib
# now you can save it to a file
joblib.dump(clf, 'filename.pkl') 
# and later you can load it
clf = joblib.load('filename.pkl')

再次强调,阅读上述链接是有帮助的

Sklearn估计器实现了一些方法,使您可以轻松保存估计器的相关训练属性。一些估计器自己实现__getstate__方法,但其他的估计器,如GMM,只使用基本实现,简单地保存对象的内部字典:

def __getstate__(self):
    try:
        state = super(BaseEstimator, self).__getstate__()
    except AttributeError:
        state = self.__dict__.copy()

    if type(self).__module__.startswith('sklearn.'):
        return dict(state.items(), _sklearn_version=__version__)
    else:
        return state

将模型保存到磁盘的推荐方法是使用pickle模块:

from sklearn import datasets
from sklearn.svm import SVC
iris = datasets.load_iris()
X = iris.data[:100, :2]
y = iris.target[:100]
model = SVC()
model.fit(X,y)
import pickle
with open('mymodel','wb') as f:
    pickle.dump(model,f)

但是,您应该保存额外的数据,以便将来可以重新训练您的模型,否则将遭受可怕的后果(例如被锁定在旧版本的sklearn中)。

从文档中可以看到:

以重建一个类似的模型与未来的版本 Scikit-learn,额外的元数据应该随着pickle一起保存 模型: 训练数据,例如对不可变快照的引用 用于生成模型的python源代码 scikit-learn的版本及其依赖项 训练数据的交叉验证得分

对于依赖于树的集成估计器尤其如此。pyx模块是用Cython编写的(例如IsolationForest),因为它创建了到实现的耦合,不能保证在sklearn版本之间是稳定的。在过去,它经历了向后不兼容的变化。

如果你的模型变得非常大,加载变得麻烦,你也可以使用更有效的joblib。从文档中可以看到:

在scikit的特定情况下,使用它可能更有趣 Joblib的泡菜替代品(Joblib。Dump & jobb .load),也就是 对于内部携带大型numpy数组的对象更有效 通常情况下,适合scikit-learn估计器,但只能 Pickle到磁盘而不是字符串: