跨平台机器学习模型交互–PMML简述
问题导读
1.跨语言,跨平台之间的机器学习模型如何共享交互?
2.机器学习模型如何上线?
PMML简介
模型预测标记语言(Predictive Model Markup Language)是由Dr. Robert Lee Grossman 提出的一种基于XML的存储模型的格式标准。
这里的模型是指那些由数据挖掘和机器学习算法生成的预测模型。PMML为不同的数据分析软件或者编程语言,提供了一种轻松共享预测分析模型的方式。它支持常见的模型,比如逻辑回归和前馈神经网络等。
常见的就是,公司的数据分析人员使用的是R,线上的生产的环境是Java,分析人员在R中将模型训练好之后,就可以将模型导出为PMML,然后在Java中导入,实现模型在R与Java之间的共享与快速上线。
PMML的第一个版本 Version 0.7 是在1997年7月发布的。 第二个版本 Version 0.9 在1998年7月发布的。随后的版本由Data Mining Group 组织维护开发。
因为PMML是一个基于XML的格式标准,所有定义都是和XML schema保持一致的。PMML本身也是一个成熟的标准,已经有超过30个组织声明他们的产品支持PMML。
机器学习模型上线过程与PMML的作用
一个机器学习的上线过程,主要包括:分析、特征工程、模型训练、调优、上线。
其中,PMML的便捷性,主要体现在模型上线的过程中。
模型上线是将训练好的模型有效地应用于生产环境的过程。一般而言,生产环境和数据分析人员所使用的环境差距巨大。以我们目前的实践为例,线上DMP是基于Hadoop的,计算框架用的Spark + MR。线下人员建模主要使用的是R、python 中的sklearn库 以及 部分使用keras。(这里需要吐槽下Spark MLlib 库中的优化算法,效率和精度都差sklearn太多了。)
如果没有PMML,因为不同的系统采用不同的方式呈现其计算,模型上线时就必须经历一个漫长的、容易出现错误和误呈现的翻译过程。
此外,还需要对模型结构了解非常深入的工程人员。
比如,将R中的LR迁移至Java中,就需要工程人员根据训练好模型的参数,裸写一个java类。
以最简单的LR为例,就是一个数据表示权重向量,权重向量和参数向量相乘之后求一次激活函数。
但复杂一点的模型,就要求对模型结构了解非常深入的工程人员,严格按照模型的计算逻辑,来编写该类。
有了PMML,就可以从应用程序A到B再到C轻松共享模型,并且在训练完成之后,迅速将模型上线(只需替换模型文件即可)。现在的实践就是,线下分析人员,使用R等训练好一版的模型之后,导出为PMML,在线上只需替换该PMML文件即可。
PMML 基础知识
注:以下内容基于PMML 4.3版本
PMML 包含数据预处理和数据后处理(即模型预测结果的处理)和预测模型本身,见下图:
PMML文件的结构遵从了用于构建预测模型的常用步骤。
文头件:包含了PMML文档的基本信息,例如模型的版权信息,模型的描述,以及生成该文件所用软件的信息(比如软件的名字和版本)。头文件中也会包含该PMML文件的生成时间。
数据字典:包含了模型可能用到的所有字段名。并定义了字段的类型,可以是连续型(continuous)、类别型(categorical)、定序型(ordinal)。和字段值的类型,如String、Double。
数据挖掘模式:数据挖掘模式,可以看做是模型的一个看门人。所有进入模型的数据,必须经过数据挖掘模式。每个模型都包含且只包含一个数据挖掘模式,用于列出该模型使用的数据。数据挖掘模式包含针对特定模型不同的信息,相对的,数据字典中定义则是稳定的,不会随模型变化而变化。数据挖掘模式的主要目的是列出使用模型需要的数据。
数据挖掘模式也定义了每个字段的使用用途(激活、追加、目标)以及针对空值、非法数据的策略。
数据转化:数据转化操作可以用于对进入模型之前的数据进行预处理。类比python sklearn中的DataFrameMapper,以及Spark中特征预处理相关算子。
PMML定义了如下简单的数据转化操作:标准化、离散化、值映射、自定义函数、聚合
模型:包含了模型的定义和结构信息。
输出:定义了模型输出。对于一个分类任务来说,输出可以包括预测类及与所有可能类相关的概率。
目标:定义了应用于模型输出的后处理步骤。对于一个回归任务来说,此步骤支持将输出转变为人们很容易就可以理解的分数(预测结果)。
模型解释:定义了将测试数据传递至模型时获得的性能度量标准(与训练数据相对)。这些度量标准包括字段相关性、混淆矩阵、增益图及接收者操作特征(ROC)曲线图。
模型验证:定义了一个包含输入数据记录和预期模型输出的示例集。这是非常重要的一个步骤,因为在应用程序之间移动模型时,该模型需要通过匹配测试。这样就可以确保,在呈现相同的输入时,新系统可以生成与旧系统同样的输出。如果实际情况是这样的话,一个模型将被认为经过了验证,且随时可用于实践。
实例解析
在这里,我们使用R语言生成一个LR模型。
其中使用了r2pmml工具,使用参见
使用的数据集是经典的iris。可以说是机器学习中入门的helloworld了,感兴趣的可以查看。
R的代码如下
# 二分类实例
# 去掉setosa类
index <
-
which(iris$Species
=
=
'setosa'
)
iris <
-
iris[
-
index,]
training <
-
iris
#抽样方法
ind<
-
sample(
2
,nrow(training),replace
=
TRUE,prob
=
c(
0.7
,
0.3
))
#对数据分成两部分,70%训练数据,30%检测数据nrow(training)行数
traindata<
-
training [ind
=
=
1
,]
#训练集
testdata<
-
training [ind
=
=
2
,]
#二项分布族binomial--正态、指数、gamma、逆高斯、Poisson、二项
fit <
-
glm(Species ~.,family
=
binomial(link
=
'logit'
),data
=
traindata)
predict <
-
predict(fit,
type
=
'response'
,newdata
=
testdata)
real <
-
testdata$Species
res <
-
data.frame(real,predict
=
ifelse(predict>
0.5
,
'virginca'
,
'versicorlor'
))
table(real,predict
=
ifelse(predict>
0.5
,
'virginca'
,
'versicorlor'
))
# 存成pmml
library(
"r2pmml"
)
r2pmml(fit,
"iris.pmml"
)
生成的PMML文档,有三个子元素
文件头
<
Header
>
<
Application
name
=
"JPMML-R"
version
=
"1.2.20"
/>
<
Timestamp
>2018-06-26T12:10:20Z</
Timestamp
>
</
Header
>
表名该PMML文件是用1.2.20版本的JPMML-R生成的。
生成时间为2018-06-26T12:10:20Z
数据字典
<
DataDictionary
>
<
DataField
name
=
"Species"
optype
=
"categorical"
dataType
=
"string"
>
<
Value
value
=
"versicolor"
/>
<
Value
value
=
"virginica"
/>
</
DataField
>
<
DataField
name
=
"Sepal.Length"
optype
=
"continuous"
dataType
=
"double"
/>
<
DataField
name
=
"Sepal.Width"
optype
=
"continuous"
dataType
=
"double"
/>
<
DataField
name
=
"Petal.Length"
optype
=
"continuous"
dataType
=
"double"
/>
<
DataField
name
=
"Petal.Width"
optype
=
"continuous"
dataType
=
"double"
/>
</
DataDictionary
>
该模型共涉及5个字段,其中Species字段为类别类型,共有两个可能值。 数据集应该是在三个,为了实现,在代码中删除了一个。
其余四个字段分别为连续型,值都是double型的。
模型部分
具体定义
</
GeneralRegressionModel
>
模型是一个 普通的线性二分类模型。激活函数式logit。具体内容定义在其子元素中。
数据挖掘模式
<
MiningSchema
>
<
MiningField
name
=
"Species"
usageType
=
"target"
/>
<
MiningField
name
=
"Sepal.Length"
/>
<
MiningField
name
=
"Sepal.Width"
/>
<
MiningField
name
=
"Petal.Length"
/>
<
MiningField
name
=
"Petal.Width"
/>
</
MiningSchema
>
定义了该模型使用到的字段。数据字典中的5个字段都使用了,其中Species是作为结果的。其余都是模型输入
这里是将数据字典中的所有字段都用上了,实际操作过程中,存在数据字典中的部分字段,对最后的结果无影响,在数据挖掘模式中,便不会包括这部分字段。
输出
<
Output
>
<
OutputField
name
=
"probability(versicolor)"
optype
=
"continuous"
dataType
=
"double"
feature
=
"probability"
value
=
"versicolor"
/>
<
OutputField
name
=
"probability(virginica)"
optype
=
"continuous"
dataType
=
"double"
feature
=
"probability"
value
=
"virginica"
/>
</
Output
>
定义了模型预测结果的输出格式,包括判断为某一分类的概率,是一个连续型,值为double型。
参数部分
<
ParamMatrix
>
<
PCell
targetCategory
=
"virginica"
parameterName
=
"p0"
beta
=
"-732.0440201835713"
/>
<
PCell
targetCategory
=
"virginica"
parameterName
=
"p1"
beta
=
"-23.885379989132485"
/>
<
PCell
targetCategory
=
"virginica"
parameterName
=
"p2"
beta
=
"-205.83327893055016"
/>
<
PCell
targetCategory
=
"virginica"
parameterName
=
"p3"
beta
=
"129.4711031033915"
/>
<
PCell
targetCategory
=
"virginica"
parameterName
=
"p4"
beta
=
"494.71600981992856"
/>
</
ParamMatrix
>
Java中使用
在Java中使用pmml,主要是用到一个开源的包[jpmml]()
先load 模型
PMML pmml;
try
(InputStream is = ...){
pmml = org.jpmml.model.PMMLUtil.unmarshal(is);
}
[Java]
Map<FieldName, FieldValue> arguments =
new
LinkedHashMap<>();
List<InputField> inputFields = evaluator.getInputFields();
for
(InputField inputField : inputFields){
FieldName inputFieldName = inputField.getName();
// The raw (ie. user-supplied) value could be any Java primitive value
Object rawValue = ...;
// The raw value is passed through: 1) outlier treatment, 2) missing value treatment, 3) invalid value treatment and 4) type conversion
FieldValue inputFieldValue = inputField.prepare(rawValue);
arguments.put(inputFieldName, inputFieldValue);
}
[Java]
Map<FieldName, ?> results = evaluator.evaluate(arguments);
PMML主要用于跨平台,跨语言之间的模型共享和交互,对于模型快速上线,具有非常重大的意义。
Reference
时间:2018-08-31 13:26 来源: 转发量:次
声明:本站部分作品是由网友自主投稿和发布、编辑整理上传,对此类作品本站仅提供交流平台,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,不为其版权负责。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。
相关文章:
相关推荐:
网友评论: