1. 程式人生 > >模型上線和pmml簡介

模型上線和pmml簡介

目前存在的幾種模型上線的方式

1、R+pmml+spark+airflow排程 
其他團隊用R語言訓練模型並轉為pmml檔案,然後我們使用spark將這個pmml檔案封裝為jar,使用airflow提交到yarn。  val is: InputStream = fs.open(path)
val pmml: PMML = PMMLUtil.unmarshal(is)
modelEvaluator = ModelEvaluatorFactory.newInstance.newModelEvaluator(pmml)

2、python+sklearn+airflow排程 
其他團隊使用python訓練好sklearn模型,並joblib.dumps()儲存,然後我們在python檔案中joblib.load()載入改檔案,使用airflow離線排程。

3、xgboost+spark+xgb4j 
我們使用的是分散式的spark版的xgboost,訓練好的模型直接儲存為二進位制檔案model.booster.saveModel(hdfsOutStream),然後xgboost4j載入該檔案XGBoost.loadModel(is)實現線上實時預測。

4、tensorflow+tensorflow的java庫 
ft模型先轉為protobuf協議的模型, 
frozen_graph = freeze_session(get_session(), output_names=["output"])
tf.train.write_graph(frozen_graph, "./", "model.pb", as_text=False)


然後使用tf的java庫載入改pb模型,線上預測  try (Graph graph = new Graph()) {
graph.importGraphDef(Files.readAllBytes(Paths.get("xxx/model.pb"))); try (Session sess = new Session(graph)) { float[][] input = xxx; try (Tensor x = Tensor.create(input); Tensor y = sess.runner().feed("input", x).fetch("output").run().get(0)) { float[][] result = new float[1][y.shape[1]]; y.copyTo(result); System.out.println(Arrays.toString(y.shape())); System.out.println(Arrays.toString(result[0])); } } } ...

5、keras+Flask 
python環境先將keras模型儲存為hdf5檔案model.save(model.h5),然後在輕量級的web框架flask中載入實現線上預測。

總結分類為

1、離線預測+不跨語言 
這種最簡單,就是用什麼語言訓練的就用什麼語言預測,而且不用考慮多併發和響應時間等問題,例如方式2。

2、離線預測+跨語言 
用一種語言訓練,另一種語言預測,但是不用考慮多併發和響應時間等問題,例如方式1。

3、線上預測+不跨語言 
用同一種語言訓練和預測,同時要考慮多併發和響應時間等問題,例如方式3、4、5。像scala和java這種都是跑在jvm上的,以及tf自己實現了java庫的,我們這裡認為是同一種語言,

4、線上預測+跨語言 
用不同的語言訓練和預測,同時要考慮多併發和響應時間等問題,我們目前還沒有這種。但是型別2和3變一下就是線上+跨語言。

不跨平臺的,即當訓練和預測使用同一種開發語言的時候,PMML 就沒有必要使用了,因為任何中間格式都會犧牲掉獨有的優化。 而其他跨平臺的模型要轉為java能使用的類(因為我們的業務大部分是java實現的),這個工具就是jpmml-evaluator。

jpmml-evaluator

Java Evaluator API for Predictive Model Markup Language (PMML). 
它可以載入以下模型:

什麼是PMML

PMML:Predictive Model Markup Language預測模型標記語言。 
data mining group推出的,有十多年的歷史了。是一種可以呈現預測分析模型的事實標準語言。標準東西的好處就是,各種開發語言都可以使用相應的包,把模型檔案轉成這種中間格式,而另外一種開發語言,可以使用相應的包匯入該檔案做線上預測。

PMML 是基於 XML 的,看個例子 

一般的結構是

pmml支援的model有 

怎麼操作?

1、生成pmml檔案 
sklearn: 
pipeline = PMMLPipeline([
('mapper', mapper), ("classifier", linear_model.LinearRegression()) ]) pipeline.fit(heart_data[heart_data.columns.difference(["chd"])], heart_data["chd"])
sklearn2pmml(pipeline, "lrHeart.xml", with_repr = True)

R: 類似 使用r2pmml 
Spark MLlib: 這個庫有一些模型已經自帶了儲存PMML模型的方法,可惜不全

2、jpmml載入pmml檔案 
先新增maven依賴,

<dependency> <groupId>org.jpmml</groupId> <artifactId>pmml-evaluator</artifactId> <version>1.4.2</version> </dependency>
<dependency>
<groupId>org.jpmml</groupId> <artifactId>pmml-evaluator-extension</artifactId> <version>1.4.2</version> </dependency>

然後載入pmml模型和呼叫

PMML pmml; try(InputStream is = ...){
pmml = org.jpmml.model.PMMLUtil.unmarshal(is); }

pmml缺點

1、PMML為了滿足跨平臺,犧牲了很多平臺獨有的優化。所以很多時候我們用演算法庫自己的api儲存得到的模型檔案要比轉為PMML的模型檔案小很多。同時PMML模型檔案載入也要比演算法自己獨有的格式檔案慢很多。 
2、用PMML模型檔案預測的結果跟演算法自身預測的結果會有一點點偏差,儘管不大。 
3、對於複雜的模型如xgboost、tensorflow等,生成的PMML模型檔案會很大,載入和預測會慢很多。

參考

https://github.com/jpmml/jpmml-evaluator 
http://dmg.org/pmml/v4-3/GeneralStructure.html 
https://zhuanlan.zhihu.com/p/23382412 
https://www.jianshu.com/p/0016a34c82c8 
https://blog.csdn.net/fansy1990/article/details/53293024