1. 程式人生 > >跨平臺機器學習實踐小結(一)

跨平臺機器學習實踐小結(一)

一、問題來源:

如何在node web服務下呼叫sklearn的模型結果來進行實時模型預測?

二、問題分析:

1、sklearn的模型結果有幾種儲存方式:

(1)pickle.dumps ,結果通過變數儲存在記憶體中

附上pickle文件:https://docs.python.org/2/library/pickle.html

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

(2)joblib.dump,持久化到二進位制檔案pkl中,可複用性更強

>>> from sklearn.externals import joblib
>>> joblib.dump(clf, 'filename.pkl')

預測時,在另一個python程序中可以執行:

>>> clf2 = joblib.load('filename.pkl')

(3)pmml檔案,PMML一種使用xml描述模型的語言標準

最有用的參考文件是:http://dmg.org/pmml/v4-1/GeneralStructure.html

 ,對PMML檔案的結構及標籤含義都有較清楚的說明。

先說明一下生成方式,以sklearn的gbdtregression為例:


from sklearn2pmml import sklearn2pmml

from sklearn2pmml.pipeline import PMMLPipeline

from sklearn.ensemble import GradientBoostingRegressor

from sklearn2pmml import sklearn2pmml

import numpy as np

import matplotlib.pyplot as plt



from sklearn import ensemble

from sklearn import datasets

from sklearn.utils import shuffle

# Load data

boston = datasets.load_boston()

X, y = shuffle(boston.data, boston.target, random_state=13)

X = X.astype(np.float32)

offset = int(X.shape[0] * 0.9)

X_train, y_train = X[:offset], y[:offset]

X_test, y_test = X[offset:], y[offset:]

params = {'n_estimators': 500, 'max_depth': 4, 'min_samples_split': 2,

'learning_rate': 0.01, 'loss': 'ls'}

pipeline = PMMLPipeline([

    ("classifier", GradientBoostingRegressor(**params))

])
pipeline.fit(X_train, y_train)

sklearn2pmml(pipeline, "GradientBoostingRegressor.pmml", with_repr = True)

scikit-learn原始碼中有許多example和資料集,可參考。

總的來說,想要跨平臺呼叫模型,實時的進行預測,那隻能採用持久化之後的結果了。不然跑一邊模型拿到記憶體結果再預測,使用者不知道得等多久。

2、如何在web中應用pkl,pmml

(1)首先考慮pkl

.pkl是python物件經過序列化和持久化之後的檔案。首先來看序列化:

pickle模組可以實現將Python物件序列化成byte stream位元組流以及反序列化過程。

注意:一般“serialization”, “marshalling,” or “flattening”也表示pickle,序列化過程。

但是pickle是沒有對載入序列化後的資料時做防護措施的,就是說如果有惡意程式碼插入其中的話,pickle模組不能識別,所以一般要在這個階段把好關,只加載可信資料。

python還有一個marshal模組也是做序列化,但是它有幾個缺點:不能識別已經序列化過的物件,所以在序列化遞迴程式碼時程式可能會崩。

shelve可以將pickle\unpickle物件持久化存成dbm檔案

根據官方文件

The data format used by pickle is Python-specific. This has the advantage that there are no restrictions imposed by external standards such as XDR (which can’t represent pointer sharing); however it means that non-Python programs may not be able to reconstruct pickled Python objects.

By default, the pickle data format uses a printable ASCII representation. This is slightly more voluminous than a binary representation. The big advantage of using printable ASCII (and of some other characteristics of pickle’s representation) is that for debugging or recovery purposes it is possible for a human to read the pickled file with a standard text editor.

There are currently 3 different protocols which can be used for pickling.

  • Protocol version 0 is the original ASCII protocol and is backwards compatible with earlier versions of Python.
  • Protocol version 1 is the old binary format which is also compatible with earlier versions of Python.
  • Protocol version 2 was introduced in Python 2.3. It provides much more efficient pickling of new-style classes.

pkl檔案是Pyhon的Pickle模組獨有的,因此別的語言無法解析檔案內容。

因此想要跨平臺使用是不可能的了。

(2)轉換成PMML

Java提供了一個PMML API 即JPMML。https://github.com/jpmml

JPMML封裝了處理pmml檔案的類庫,可以方便使用,並且支援Spark\R\sklearn\xgboost

如對sklearn的支援是與Python 側 的 sklearn2pmml配合使用的。

測試的時候不使用pmml-evalutor的example,而通過自己修改pom.xml去簡單的執行例項會更加方便。

可以下載maven庫檢視JPMML原始碼。http://mvnrepository.com/artifact/org.jpmml/pmml-evaluator/1.4.3

三、待解決問題

sklearn2pmml樣例庫中的boston房價資料使用GBDTRegression一共生成了500顆深度為4的樹,檢視同一個訓練模型生成的pmml檔案中Segmentation的Tree 1,與Python圖形庫生成的dot檔案描述的不一致,pmml中描述的節點少了許多,但是兩者預測值確實基本一致的,只是預設數值精度上的區別。

四、方案制定

待續