3.4 模型持久性

在训练一个scikit-learn模型后,最好有一种方法可以将模型持久化以备重复使用,而不需要重新训练模型。随后将会提供例子以解释如何使用pickle来始模型更加持久。当使用pickle序列化时,需要回顾一些安全性和可维护性问题。

pickle的另一个选择是以另一种形式输出模型,通过使用模型输出工具,详见 Related Projects。 与pickle不同的是,一旦输出就不能恢复完整的Scikit-learn估计器对像,但是你可以使用模型进行预测,通常使用支持开放模型交换格式的工具,例如 ONNX或者 PMML

3.4.1 持久性例子

通过使用Python内置的持久性模型,可以将模型保存在scikit-learn中,即pickle

>>> from sklearn import svm
>>> from sklearn import datasets
>>> clf = svm.SVC()
>>> X, y= datasets.load_iris(return_X_y=True)
>>> clf.fit(X, y)
SVC()

>>> import pickle
>>> s = pickle.dumps(clf)
>>> clf2 = pickle.loads(s)
>>> clf2.predict(X[0:1])
array([0])
>>> y[0]
0 

在scikit-learn的具体例子中,最好使用joblib替换pickle(joblib.dump & joblib.load),它在处理内部携带大型numpy数组的对象时更有效,这通常适用于用scikit-learn估计器拟合大型numpy数组,但是只能pickle到硬盘而不是字符串:

>>> from joblib import dump, load
>>> dump(clf, 'filename.joblib')  

然后,你可以装回pickle好的模型(可能在另一个Python过程):

>>> clf = load('filename.joblib')  

**注意:**转存和加载各类函数也可以接受类文件对象而不是文件名。关于Joblib的数据持久性的更多信息参见here

3.4.2 安全性和可维护性限制

pickle(和通过扩展的joblib),有一些关于可维护性和安全性的例子。因为,

  • 不要使用未pickle的不信任数据,因为它可能导致在运行过程中执行恶意文件。
  • 当模型保存在scikit-learn的某个版本中,然后加载在另一个版本中, 这是完全不支持且不建议的。始终应该牢记的是在这样的数据上执行操作可能会得到不同且意想不到的结果。

为了在未来版本的scikit-learn中重新构建一个相似的模型,额外的元数据应该被保存在pickle模型中:

  • 训练数据,例如参考不可改变的快照
  • python源代码被用来生成模型
  • scikit-learn的版本和它的依赖性
  • 在训练集中交叉验证的得分

这样可以检查交叉验证的得分是否与以前的在同样的范围内。

由于模型的内部表示在两个不同的结构体系中可能表示不同,在一个结构体系上转存模型,并在另一个结构体系上加载是不被允许的。

如果想了解更多的相关问题及其它可能的序列方法,可以参考 talk by Alex Gaynor