日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

用PMML实现机器学习模型的跨平台上线

發布時間:2024/1/17 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用PMML实现机器学习模型的跨平台上线 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在機器學習用于產品的時候,我們經常會遇到跨平臺的問題。比如我們用Python基于一系列的機器學習庫訓練了一個模型,但是有時候其他的產品和項目想把這個模型集成進去,但是這些產品很多只支持某些特定的生產環境比如Java,為了上一個機器學習模型去大動干戈修改環境配置很不劃算,此時我們就可以考慮用預測模型標記語言(Predictive Model Markup Language,以下簡稱PMML)來實現跨平臺的機器學習模型部署了。

1. PMML概述

    PMML是數據挖掘的一種通用的規范,它用統一的XML格式來描述我們生成的機器學習模型。這樣無論你的模型是sklearn,R還是Spark MLlib生成的,我們都可以將其轉化為標準的XML格式來存儲。當我們需要將這個PMML的模型用于部署的時候,可以使用目標環境的解析PMML模型的庫來加載模型,并做預測。

    可以看出,要使用PMML,需要兩步的工作,第一塊是將離線訓練得到的模型轉化為PMML模型文件,第二塊是將PMML模型文件載入在線預測環境,進行預測。這兩塊都需要相關的庫支持。

2. PMML模型的生成和加載相關類庫

    PMML模型的生成相關的庫需要看我們使用的離線訓練庫。如果我們使用的是sklearn,那么可以使用sklearn2pmml這個python庫來做模型文件的生成,這個庫安裝很簡單,使用"pip install sklearn2pmml"即可,相關的使用我們后面會有一個demo。如果使用的是Spark MLlib, 這個庫有一些模型已經自帶了保存PMML模型的方法,可惜并不全。如果是R,則需要安裝包"XML"和“PMML”。此外,JAVA庫JPMML可以用來生成R,SparkMLlib,xgBoost,Sklearn的模型對應的PMML文件。github地址是:https://github.com/jpmml/jpmml。

    加載PMML模型需要目標環境支持PMML加載的庫,如果是JAVA,則可以用JPMML來加載PMML模型文件。相關的使用我們后面會有一個demo。

3. PMML模型生成和加載示例

    下面我們給一個示例,使用sklearn生成一個決策樹模型,用sklearn2pmml生成模型文件,用JPMML加載模型文件,并做預測。

    首先是用用sklearn生成一個決策樹模型,由于我們是需要保存PMML文件,所以最好把模型先放到一個Pipeline數組里面。這個數組里面除了我們的決策樹模型以外,還可以有歸一化,降維等預處理操作,這里作為一個示例,我們Pipeline數組里面只有決策樹模型。代碼如下:

import numpy as np import matplotlib.pyplot as plt %matplotlib inline import pandas as pd from sklearn import tree from sklearn2pmml.pipeline import PMMLPipeline from sklearn2pmml import sklearn2pmmlimport os os.environ["PATH"] += os.pathsep + 'C:/Program Files/Java/jdk1.8.0_171/bin'X=[[1,2,3,1],[2,4,1,5],[7,8,3,6],[4,8,4,7],[2,5,6,9]] y=[0,1,0,2,1] pipeline = PMMLPipeline([("classifier", tree.DecisionTreeClassifier(random_state=9))]); pipeline.fit(X,y)sklearn2pmml(pipeline, ".\demo.pmml", with_repr = True)

    上面這段代碼做了一個非常簡單的決策樹分類模型,只有5個訓練樣本,特征有4個,輸出類別有3個。實際應用時,我們需要將模型調參完畢后才將其放入PMMLPipeline進行保存。運行代碼后,我們在當前目錄會得到一個PMML的XML文件,可以直接打開看,內容大概如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <PMML xmlns="http://www.dmg.org/PMML-4_3" version="4.3"><Header><Application name="JPMML-SkLearn" version="1.5.3"/><Timestamp>2018-06-24T05:47:17Z</Timestamp></Header><MiningBuildTask><Extension>PMMLPipeline(steps=[('classifier', DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,max_features=None, max_leaf_nodes=None,min_impurity_decrease=0.0, min_impurity_split=None,min_samples_leaf=1, min_samples_split=2,min_weight_fraction_leaf=0.0, presort=False, random_state=9,splitter='best'))])</Extension></MiningBuildTask><DataDictionary><DataField name="y" optype="categorical" dataType="integer"><Value value="0"/><Value value="1"/><Value value="2"/></DataField><DataField name="x3" optype="continuous" dataType="float"/><DataField name="x4" optype="continuous" dataType="float"/></DataDictionary><TransformationDictionary><DerivedField name="double(x3)" optype="continuous" dataType="double"><FieldRef field="x3"/></DerivedField><DerivedField name="double(x4)" optype="continuous" dataType="double"><FieldRef field="x4"/></DerivedField></TransformationDictionary><TreeModel functionName="classification" missingValueStrategy="nullPrediction" splitCharacteristic="multiSplit"><MiningSchema><MiningField name="y" usageType="target"/><MiningField name="x3"/><MiningField name="x4"/></MiningSchema><Output><OutputField name="probability(0)" optype="continuous" dataType="double" feature="probability" value="0"/><OutputField name="probability(1)" optype="continuous" dataType="double" feature="probability" value="1"/><OutputField name="probability(2)" optype="continuous" dataType="double" feature="probability" value="2"/></Output><Node><True/><Node><SimplePredicate field="double(x3)" operator="lessOrEqual" value="3.5"/><Node score="1" recordCount="1.0"><SimplePredicate field="double(x3)" operator="lessOrEqual" value="2.0"/><ScoreDistribution value="0" recordCount="0.0"/><ScoreDistribution value="1" recordCount="1.0"/><ScoreDistribution value="2" recordCount="0.0"/></Node><Node score="0" recordCount="2.0"><True/><ScoreDistribution value="0" recordCount="2.0"/><ScoreDistribution value="1" recordCount="0.0"/><ScoreDistribution value="2" recordCount="0.0"/></Node></Node><Node score="2" recordCount="1.0"><SimplePredicate field="double(x4)" operator="lessOrEqual" value="8.0"/><ScoreDistribution value="0" recordCount="0.0"/><ScoreDistribution value="1" recordCount="0.0"/><ScoreDistribution value="2" recordCount="1.0"/></Node><Node score="1" recordCount="1.0"><True/><ScoreDistribution value="0" recordCount="0.0"/><ScoreDistribution value="1" recordCount="1.0"/><ScoreDistribution value="2" recordCount="0.0"/></Node></Node></TreeModel> </PMML>

    可以看到里面就是決策樹模型的樹結構節點的各個參數,以及輸入值。我們的輸入被定義為x1-x4,輸出定義為y。

    有了PMML模型文件,我們就可以寫JAVA代碼來讀取加載這個模型并做預測了。

    我們創建一個Maven或者gradle工程,加入JPMML的依賴,這里給出maven在pom.xml的依賴,gradle的結構是類似的。

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

    接著就是讀取模型文件并預測的代碼了,具體代碼如下:

import org.dmg.pmml.FieldName; import org.dmg.pmml.PMML; import org.jpmml.evaluator.*; import org.xml.sax.SAXException;import javax.xml.bind.JAXBException; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map;/*** Created by 劉建平Pinard on 2018/6/24.*/ public class PMMLDemo {private Evaluator loadPmml(){PMML pmml = new PMML();InputStream inputStream = null;try {inputStream = new FileInputStream("D:/demo.pmml");} catch (IOException e) {e.printStackTrace();}if(inputStream == null){return null;}InputStream is = inputStream;try {pmml = org.jpmml.model.PMMLUtil.unmarshal(is);} catch (SAXException e1) {e1.printStackTrace();} catch (JAXBException e1) {e1.printStackTrace();}finally {//關閉輸入流try {is.close();} catch (IOException e) {e.printStackTrace();}}ModelEvaluatorFactory modelEvaluatorFactory = ModelEvaluatorFactory.newInstance();Evaluator evaluator = modelEvaluatorFactory.newModelEvaluator(pmml);pmml = null;return evaluator;}private int predict(Evaluator evaluator,int a, int b, int c, int d) {Map<String, Integer> data = new HashMap<String, Integer>();data.put("x1", a);data.put("x2", b);data.put("x3", c);data.put("x4", d);List<InputField> inputFields = evaluator.getInputFields();//過模型的原始特征,從畫像中獲取數據,作為模型輸入Map<FieldName, FieldValue> arguments = new LinkedHashMap<FieldName, FieldValue>();for (InputField inputField : inputFields) {FieldName inputFieldName = inputField.getName();Object rawValue = data.get(inputFieldName.getValue());FieldValue inputFieldValue = inputField.prepare(rawValue);arguments.put(inputFieldName, inputFieldValue);}Map<FieldName, ?> results = evaluator.evaluate(arguments);List<TargetField> targetFields = evaluator.getTargetFields();TargetField targetField = targetFields.get(0);FieldName targetFieldName = targetField.getName();Object targetFieldValue = results.get(targetFieldName);System.out.println("target: " + targetFieldName.getValue() + " value: " + targetFieldValue);int primitiveValue = -1;if (targetFieldValue instanceof Computable) {Computable computable = (Computable) targetFieldValue;primitiveValue = (Integer)computable.getResult();}System.out.println(a + " " + b + " " + c + " " + d + ":" + primitiveValue);return primitiveValue;}public static void main(String args[]){PMMLDemo demo = new PMMLDemo();Evaluator model = demo.loadPmml();demo.predict(model,1,8,99,1);demo.predict(model,111,89,9,11);} }

    代碼里有兩個函數,第一個loadPmml是加載模型的,第二個predict是讀取預測樣本并返回預測值的。我的代碼運行結果如下:

target: y value: {result=2, probability_entries=[0=0.0, 1=0.0, 2=1.0], entityId=5, confidence_entries=[]} 1 8 99 1:2 target: y value: {result=1, probability_entries=[0=0.0, 1=1.0, 2=0.0], entityId=6, confidence_entries=[]} 111 89 9 11:1

    也就是樣本(1,8,99,1)被預測為類別2,而(111,89,9,11)被預測為類別1。

    以上就是PMML生成和加載的一個示例,使用起來其實門檻并不高,也很簡單。

4. PMML總結與思考

    PMML的確是跨平臺的利器,但是是不是就沒有缺點呢?肯定是有的!

    第一個就是PMML為了滿足跨平臺,犧牲了很多平臺獨有的優化,所以很多時候我們用算法庫自己的保存模型的API得到的模型文件,要比生成的PMML模型文件小很多。同時PMML文件加載速度也比算法庫自己獨有格式的模型文件加載慢很多。

    第二個就是PMML加載得到的模型和算法庫自己獨有的模型相比,預測會有一點點的偏差,當然這個偏差并不大。比如某一個樣本,用sklearn的決策樹模型預測為類別1,但是如果我們把這個決策樹落盤為一個PMML文件,并用JAVA加載后,繼續預測剛才這個樣本,有較小的概率出現預測的結果不為類別1.

    第三個就是對于超大模型,比如大規模的集成學習模型,比如xgboost, 隨機森林,或者tensorflow,生成的PMML文件很容易得到幾個G,甚至上T,這時使用PMML文件加載預測速度會非常慢,此時推薦為模型建立一個專有的環境,就沒有必要去考慮跨平臺了。

    此外,對于TensorFlow,不推薦使用PMML的方式來跨平臺。可能的方法一是TensorFlow serving,自己搭建預測服務,但是會稍有些復雜。另一個方法就是將模型保存為TensorFlow的模型文件,并用TensorFlow獨有的JAVA庫加載來做預測。

    我們在下一篇會討論用python+tensorflow訓練保存模型,并用tensorflow的JAVA庫加載做預測的方法和實例。

總結

以上是生活随笔為你收集整理的用PMML实现机器学习模型的跨平台上线的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。