跨平台机器学习模型交互–PMML简述

来自 http://www.aboutyun.com/forum.php?mod=viewthread&tid=24805

问题导读
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工具,使用参见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文档,有三个子元素

文件头

[XML]
<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

数据字典

[XML]
<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型的。

模型部分

[XML]
<GeneralRegressionModel modelType="generalizedLinear" functionName="classification" linkFunction="logit" distribution="binomial">
具体定义
</GeneralRegressionModel>

模型是一个 普通的线性二分类模型。激活函数式logit。具体内容定义在其子元素中。

数据挖掘模式

[XML]
<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是作为结果的。其余都是模型输入
这里是将数据字典中的所有字段都用上了,实际操作过程中,存在数据字典中的部分字段,对最后的结果无影响,在数据挖掘模式中,便不会包括这部分字段。

输出

[XML]
<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型。

参数部分

[XML]
<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>
这个便是训练好的LR模型的权重参数向量。

Java中使用
在Java中使用pmml,主要是用到一个开源的包[jpmml](https://github.com/jpmml/jpmml-evaluator)
先load 模型

[Java]
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

分享到:更多 ()

3

评论前必须登录!

  1. #3

    python的可以参考:
    在Windows下将python中scikit learn的模型转化为PMML文件
    https://blog.csdn.net/yz930618/article/details/76913076

    需要安装sklearn2pmml

    xsmile4个月前 (08-30)
  2. #2

    tensorflow机器学习模型的跨平台上线
    http://www.cnblogs.com/pinard/p/9251296.html
    tensorflow模型的跨平台上线的备选方案一般有三种:即PMML方式,tensorflow serving方式,以及跨语言API方式。

    xsmile4个月前 (08-30)
  3. #1

    Spark加载PMML进行预测
    https://blog.csdn.net/fansy1990/article/details/53293024/

    xsmile4个月前 (08-30)