PMML讲解及使用

                                     PMML讲解及使用

1. PMML概述

PMML全称预言模型标记语言(Predictive Model Markup Language),利用XML描述和存储数据挖掘模型,是一个已经被W3C所接受的标准。使用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模型文件。

                         PMML åå«æ°æ®é¢å¤çåæ°æ®åå¤ç以åé¢æµæ¨¡åæ¬èº«

pmml支持的model有 :

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

下面我们给一个示例,使用sklearn生成一个决策树模型,用sklearn2pmml生成模型文件,用JPMML加载模型文件,并做预测。

首先是用用sklearn生成一个决策树模型,由于我们是需要保存PMML文件,所以最好把模型先放到一个Pipeline数组里面。这个数组里面除了我们的决策树模型以外,还可以有归一化,降维等预处理操作,这里作为一个示例,我们Pipeline数组里面只有决策树模型。代码如下:


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

上面这段代码做了一个非常简单的决策树分类模型,只有5个训练样本,特征有4个,输出类别有3个。实际应用时,我们需要将模型调参完毕后才将其放入PMMLPipeline进行保存。运行代码后,我们在当前目录会得到一个PMML的XML文件,可以直接打开看,内容大概如下:


 
 
  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2. <PMML xmlns="http://www.dmg.org/PMML-4_3" version="4.3">
  3. <Header>
  4. <Application name="JPMML-SkLearn" version="1.5.3"/>
  5. <Timestamp>2018-06-24T05:47:17Z </Timestamp>
  6. </Header>
  7. <MiningBuildTask>
  8. <Extension>PMMLPipeline(steps=[('classifier', DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,
  9. max_features=None, max_leaf_nodes=None,
  10. min_impurity_decrease=0.0, min_impurity_split=None,
  11. min_samples_leaf=1, min_samples_split=2,
  12. min_weight_fraction_leaf=0.0, presort=False, random_state=9,
  13. splitter='best'))]) </Extension>
  14. </MiningBuildTask>
  15. <DataDictionary>
  16. <DataField name="y" optype="categorical" dataType="integer">
  17. <Value value="0"/>
  18. <Value value="1"/>
  19. <Value value="2"/>
  20. </DataField>
  21. <DataField name="x3" optype="continuous" dataType="float"/>
  22. <DataField name="x4" optype="continuous" dataType="float"/>
  23. </DataDictionary>
  24. <TransformationDictionary>
  25. <DerivedField name="double(x3)" optype="continuous" dataType="double">
  26. <FieldRef field="x3"/>
  27. </DerivedField>
  28. <DerivedField name="double(x4)" optype="continuous" dataType="double">
  29. <FieldRef field="x4"/>
  30. </DerivedField>
  31. </TransformationDictionary>
  32. <TreeModel functionName="classification" missingValueStrategy="nullPrediction" splitCharacteristic="multiSplit">
  33. <MiningSchema>
  34. <MiningField name="y" usageType="target"/>
  35. <MiningField name="x3"/>
  36. <MiningField name="x4"/>
  37. </MiningSchema>
  38. <Output>
  39. <OutputField name="probability(0)" optype="continuous" dataType="double" feature="probability" value="0"/>
  40. <OutputField name="probability(1)" optype="continuous" dataType="double" feature="probability" value="1"/>
  41. <OutputField name="probability(2)" optype="continuous" dataType="double" feature="probability" value="2"/>
  42. </Output>
  43. <Node>
  44. <True/>
  45. <Node>
  46. <SimplePredicate field="double(x3)" operator="lessOrEqual" value="3.5"/>
  47. <Node score="1" recordCount="1.0">
  48. <SimplePredicate field="double(x3)" operator="lessOrEqual" value="2.0"/>
  49. <ScoreDistribution value="0" recordCount="0.0"/>
  50. <ScoreDistribution value="1" recordCount="1.0"/>
  51. <ScoreDistribution value="2" recordCount="0.0"/>
  52. </Node>
  53. <Node score="0" recordCount="2.0">
  54. <True/>
  55. <ScoreDistribution value="0" recordCount="2.0"/>
  56. <ScoreDistribution value="1" recordCount="0.0"/>
  57. <ScoreDistribution value="2" recordCount="0.0"/>
  58. </Node>
  59. </Node>
  60. <Node score="2" recordCount="1.0">
  61. <SimplePredicate field="double(x4)" operator="lessOrEqual" value="8.0"/>
  62. <ScoreDistribution value="0" recordCount="0.0"/>
  63. <ScoreDistribution value="1" recordCount="0.0"/>
  64. <ScoreDistribution value="2" recordCount="1.0"/>
  65. </Node>
  66. <Node score="1" recordCount="1.0">
  67. <True/>
  68. <ScoreDistribution value="0" recordCount="0.0"/>
  69. <ScoreDistribution value="1" recordCount="1.0"/>
  70. <ScoreDistribution value="2" recordCount="0.0"/>
  71. </Node>
  72. </Node>
  73. </TreeModel>
  74. </PMML>


1、sklearn生成pmml文件 :


 
 
  1. pipeline = PMMLPipeline([
  2. ( 'mapper', mapper),
  3. ( "classifier", linear_model.LinearRegression())
  4. ])
  5. pipeline.fit(heart_data[heart_data.columns.difference([ "chd"])], heart_data[ "chd"])
  6. sklearn2pmml(pipeline, "lrHeart.xml", with_repr = True)

2、jpmml加载pmml文件 
先添加maven依赖,


 
 
  1. <dependency>
  2. <groupId>org.jpmml </groupId>
  3. <artifactId>pmml-evaluator </artifactId>
  4. <version>1.4.2 </version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.jpmml </groupId>
  8. <artifactId>pmml-evaluator-extension </artifactId>
  9. <version>1.4.2 </version>
  10. </dependency>

 然后加载pmml模型和调用


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

4. PMML 深度解析

您已了解了何为 PMML 及其重要性,现在让我们来深入探究这种语言本身。如上所述,PMML 的结构反映了常用于创建预测解决方案的八大步骤,从在 “数据词典” 步骤中定义原始输入数据字段到在 “模型验证” 步骤中验证模型是否得到正确部署。

清单 1 展示了一个含有三个字段的解决方案中 PMML 元素 DataDictionary 的定义,这三个字段是:数值型输入字段 Value、分类输入字段 Element 和数值型输出字段 Risk

清单 1. DataDictionary 元素

1

		<p>2</p>

		<p>3</p>

		<p>4</p>

		<p>5</p>

		<p>6</p>

		<p>7</p>

		<p>8</p>

		<p>9</p>

		<p>10</p>

		<p>11</p>

		<p>12</p>
		</td>
		<td>
		<p><code>&lt;</code><code>DataDictionary</code> <code>numberOfFields</code><code>=</code><code>"3"</code><code>&gt;</code></p>

		<p><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&lt;</code><code>DataField</code> <code>dataType</code><code>=</code><code>"double"</code> <code>name</code><code>=</code><code>"Value"</code> <code>optype</code><code>=</code><code>"continuous"</code><code>&gt;</code></p>

		<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&lt;</code><code>Interval</code> <code>closure</code><code>=</code><code>"openClosed"</code> <code>rightMargin</code><code>=</code><code>"60"</code> <code>/&gt;</code></p>

		<p><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&lt;/</code><code>DataField</code><code>&gt;</code></p>

		<p><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&lt;</code><code>DataField</code> <code>dataType</code><code>=</code><code>"string"</code> <code>name</code><code>=</code><code>"Element"</code> <code>optype</code><code>=</code><code>"categorical"</code><code>&gt;</code></p>

		<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&lt;</code><code>Value</code> <code>property</code><code>=</code><code>"valid"</code> <code>value</code><code>=</code><code>"Magnesium"</code> <code>/&gt;</code></p>

		<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&lt;</code><code>Value</code> <code>property</code><code>=</code><code>"valid"</code> <code>value</code><code>=</code><code>"Sodium"</code> <code>/&gt;</code></p>

		<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&lt;</code><code>Value</code> <code>property</code><code>=</code><code>"valid"</code> <code>value</code><code>=</code><code>"Calcium"</code> <code>/&gt;</code></p>

		<p><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&lt;</code><code>Value</code> <code>property</code><code>=</code><code>"valid"</code> <code>value</code><code>=</code><code>"Radium"</code> <code>/&gt;</code></p>

		<p><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&lt;/</code><code>DataField</code><code>&gt;</code></p>

		<p><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&lt;</code><code>DataField</code> <code>dataType</code><code>=</code><code>"double"</code> <code>name</code><code>=</code><code>"Risk"</code> <code>optype</code><code>=</code><code>"continuous"</code> <code>/&gt;</code></p>

		<p><code>&lt;/</code><code>DataDictionary</code><code>&gt;</code></p>
		</td>
	</tr></tbody></table></div><p>请注意,对于字段&nbsp;<code>Value</code>,范围从负无穷大到 60 的值是有效值。高于 60 的值被定义为无效值。(尽管在此没有显示,您可以使用 PMML 元素&nbsp;<code>MiningSchema</code>&nbsp;为无效值和遗漏值定义合适的处理方法。)考虑到字段&nbsp;<code>Element</code>&nbsp;是分类的,有效值被明确地列出。如果该特定字段的数据提要包含元素&nbsp;<code>Iron</code>,将该元素作为无效值处理。</p>

图 2 展示了神经网络模型的图形表示,其中输入层包含 3 个神经元,隐藏层包含 2 个神经元,输出层包含 1 个神经元。如您所期望的,PMML 可以完全呈现这样一个结构。

图 2. 一个简单的神经网络模型,其中在对预测进行计算之前,数据经过一系列层

一个简单的神经网络模型,其中在对预测进行计算之前,数据经过一系列层

清单 2 展示了隐藏层及其神经元以及输入层(0、1 和 2)和隐藏层(3 和 4)中神经元的连接权重的定义。

清单 2. 在 PMML 中定义神经层及其神经元

PMML 不是一件艰难的事。其复杂程度反映了其呈现的建模技术的复杂程度。事实上,它揭开了许多人感到神秘的预测分析的秘密和黑匣子。利用 PMML,任何预测解决方案都可以采用同样的顺序用同一种语言元素呈现。

在公司中,PMML 不仅可以作为应用程序之间也可以作为部门、服务提供商及外部供应商之间的混合语。在这种情况下,PMML 就成为定义预测解决方案交流的单一、清晰流程的一个标准。

5. 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库加载来做预测。

【转载】:https://www.cnblogs.com/pinard/p/9220199.html

                  https://www.jianshu.com/p/0eb9b2c904a9

                  https://www.ibm.com/developerworks/cn/opensource/ind-PMML1/

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要解决XGBoost使用PMML预测时的偏差问题,我们可以采取以下步骤: 1. 检查数据:首先,我们需要仔细检查使用的数据集,确保数据的准确性和完整性。如果数据集中存在异常值或缺失值,可以尝试使用合适的数据清洗和处理方法,如插值或删除异常值。 2. 特征工程:通过特征工程来提取和选择有意义的特征,可以帮助提高模型的预测准确性。可以使用常用的特征选择方法,如方差过滤、相关系数过滤或递归特征消除等。 3. 调整参数:XGBoost模型中有一些参数可以调整以优化模型的性能。可以通过网格搜索或随机搜索等方法来寻找最佳的参数组合,以减小预测偏差。一些需要调整的参数包括学习率、树的数量、树的深度等。 4. 交叉验证:为了进一步减小预测偏差,可以使用交叉验证方法来评估模型的性能并选择最佳的模型。交叉验证可以帮助我们更准确地估计模型的泛化能力,减少过拟合的可能性。 5. 集成学习:将多个XGBoost模型进行集成学习也可以有效减小预测偏差。可以使用Bagging、Boosting等方法,通过多个模型的组合来提高整体预测准确性。 6. 模型融合:可以考虑将XGBoost与其他机器学习算法进行模型融合,以进一步降低预测偏差。通过使用不同算法的优势,可以提高预测结果的稳定性和准确性。 通过以上步骤,我们可以针对XGBoost使用PMML预测时的偏差问题进行一系列的处理和优化,以获取更准确的预测结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值