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