前言

应该是首发原创,网上没搜到。
总体的逻辑是:数据导入----tpot自动化机器学习挑选最适合的模型和数据预处理思路----转换为sklearn代码----通过sklearn2pmml库转换为pmml模型----通过jpmml库调用pmml模型实现在java中部署。
好像看起来很简单,但是实际处理中问题不少,且在外网上甚至搜不到相关答案,可以说完全自己摸索出来的路径,在这里给后来人借鉴宝贵经验。
注:本章中的模型为stacking三层模型,因此和一般的机器学习模型转换存在相当大的差异。

实验

sklearn2pmml,tpot库都用最新的。
jpmml库版本为1.5.15,官网现在最新为1.6,输入方式略有不同,主要体现为去掉了fieldname和fieldvalue这种调用方式,使用时需注意,怎么安装不说了看以前的文章,主要是pom.xml文件里写相关依赖,然后通过maven仓库一键拉下来。

tpot部分

from sklearn import preprocessing
from sklearn.model_selection import train_test_split
from tpot import TPOTClassifier
le = preprocessing.LabelEncoder() #标签列转换工具
x = df.iloc[:,1:17] #特征列
y = le.fit_transform(df.iloc[:,17]) #转换标签 YES-->0,NO-->1
X_train, X_test, y_train, y_test = train_test_split(x, y,train_size=0.75, test_size=0.25, random_state=1)tpot = TPOTClassifier(generations=100, population_size=100, verbosity=2,n_jobs=2,random_state=42,warm_start=True)
tpot.fit(X_train,y_train)#拟合训练集
print(tpot.score(X_test,y_test))#给测试集打分
print(tpot.score(x,y))#给整个数据集打分

tpot的用法和sklearn大同小异,这里着重讲一下TPOTClassifier的API重点。
population_size + generations × offspring_size等于总共寻找的pipeline个数(默认情况下offspring_size的默认值等于population_size),这里等于训练10100个不同的pipeline,在我的办公电脑上大概要跑一个小时,基本可以找到最优解。
verbosity是用来输出信息的,训练过程中可以看见一个进度条,如果调成0,那啥都不会输出,如果调成3,会输出中间的一切信息,一般用2就足够了。
n_jobs可以简单理解为你要用电脑cpu的几个核心进行并行计算,我这里写2是因为这办公电脑只有两个核心,如果算力足够往上加就完事了,或者写成-1,可以尽量多的占用你电脑核心的算力
random_state不用说了吧,为了固定结果,随机状态固定是必要的,特别是跑一万个pipeline。
warm_start是重点,如果你中途想暂停(指中断一下kernel的计算)看结果然后再继续跑,warm_start=True是必要的,不然又会从头开始训练,得不偿失。

模型转换

比较令人遗憾的是tpot的优化用的是cv验证,而不是用指定的测试集去验证,当然一般来说cv准确率上去了,测试集准确率不会差的。那么在经过一代代的优化之后,我们得到了最终的模型(一般会比较复杂),那么是否可以直接转化为pmml模型呢?

from sklearn2pmml import sklearn2pmml, make_pmml_pipeline
pmml_pipeline = make_pmml_pipeline(classifier.fitted_pipeline_, active_fields = iris.feature_names, target_fields = ["species"])sklearn2pmml(pmml_pipeline, "TPOTIris.pmml", with_repr = True)

这是官方给出的转换tpot模型的代码,你只需要把classifier改成tpot(你训练的tpot模型的名字),并指定好active_fields(指特征列名字)和target_fields(指标签列名字)即可(或者你也可以不搞这两个参数,默认会识别为x1—xn和y)。

很遗憾,一般来说会转换错误。

我们先来看看tpot给出的到底是什么模型:

tpot.export('tpot_digits_pipeline.py')

在当前目录下找到并打开py文件,并摘出核心内容:

exported_pipeline = make_pipeline(StackingEstimator(estimator=XGBClassifier(learning_rate=0.5, max_depth=9, min_child_weight=1, n_estimators=100, n_jobs=1, subsample=0.7500000000000001, verbosity=0)),StackingEstimator(estimator=DecisionTreeClassifier(criterion="gini", max_depth=10, min_samples_leaf=19, min_samples_split=12)),KNeighborsClassifier(n_neighbors=3, p=2, weights="distance")
)

make_pipeline是sklearn库中的方法,StackingEstimator怎么tpot.builtins 里面的方法?(夹带私货)
先不说这个,这个pmml模型竟然不支持KNeighborsClassifier里面的distance参数!ok,我们把distance改成uniform之后准确率成功下降了0.03%,并再次尝试导出,会发现还是报错。

Name(s) [probability(stack(x1, x2, .., x14, x15), 0)] do not match any fields

问题就在于这个StackingEstimator,官方说是支持,实际做的兼容性可真烂,我尝试了各种构建pipeline的方法,一开始还以为是嵌套的问题,结果就是这个tpot的类兼容太差了!

解决方法:使用sklearn自己的StackingClassifier取代tpot的StackingEstimator

像上面的模型转换之后应该是下面这样:

from sklearn.ensemble import StackingClassifier
estimators = [('GB', GradientBoostingClassifier(learning_rate=1.0, max_depth=8, max_features=0.35000000000000003, min_samples_leaf=9, min_samples_split=6, n_estimators=100, subsample=0.6500000000000001,random_state=42)),('svr', DecisionTreeClassifier(criterion="gini", max_depth=9, min_samples_leaf=1, min_samples_split=2,random_state=42))
]
clf = StackingClassifier(estimators=estimators, final_estimator=KNeighborsClassifier(n_neighbors=3, p=2, weights="uniform")
)

再进行sklearn2pmml的pipeline构建和导出:

pipeline = PMMLPipeline([("classifier", clf)
])
pipeline.fit(X_train,y_train) #千万不要忘记训练过程
sklearn2pmml(pipeline, "xxx.pmml",debug=True,with_repr = True)

就完成了!

JPMML部分
先讲重点,因为是集成模型,stack堆叠有三层,所以特征名转换会混乱,不能用我们上次文章里面使用的map方式传参,你会发现结果完全不对!这个问题困扰了我两天,各种调试都没找到原因,最后采用数组形式传参才发现根本问题

直接上代码:

import org.dmg.pmml.FieldName;
import org.dmg.pmml.PMML;
import org.jpmml.evaluator.*;
import java.io.*;
import java.util.*;import static org.jpmml.evaluator.example.Example.newInstance;public class TestPmml {private static String modelEvaluatorFactoryClazz = ModelEvaluatorFactory.class.getName();private static String valueFactoryFactoryClazz = ValueFactoryFactory.class.getName();public static void main(String args[]) throws Exception {TestPmml obj = new TestPmml();PMML pmml;File file = new File("xxx.pmml");InputStream inputStream = new FileInputStream(file);pmml = org.jpmml.model.PMMLUtil.unmarshal(inputStream);ModelEvaluatorBuilder modelEvaluatorBuilder = new ModelEvaluatorBuilder(pmml).setOutputFilter(OutputFilters.KEEP_ALL).setModelEvaluatorFactory((ModelEvaluatorFactory)newInstance(modelEvaluatorFactoryClazz)).setValueFactoryFactory((ValueFactoryFactory)newInstance(valueFactoryFactoryClazz));Evaluator evaluator = modelEvaluatorBuilder.build();Map<FieldName, Object> arguments = new HashMap<>();List<InputField> inputFields = evaluator.getInputFields();System.out.println("Input fields: " + inputFields);double aa[]={81.48,78.38,26.63,18.53,48.47,4.6,0.58,22.37,37.38,21.12,76.93,43.02,34.28,26.84,31.08};int i = 0;for(InputField inputField : inputFields){FieldName inputName = inputField.getName();FieldValue inputValue = inputField.prepare(aa[i]);arguments.put(inputName, inputValue);i++;}evaluator.verify();Map<FieldName, ?> results = evaluator.evaluate(arguments);System.out.println("result fields: " + results);}
}

和上次文章相比会看起来臃肿很多,但其实抓住evaluator这个重点就行了,我们是用它进行预测,变化的无非是evaluator的初始化方式,在调试过程中,我试了各种新的老的evaluator的初始化方式都发现没有任何变化。

重点在于double开始的数组传入部分,先说一下inputfields,你可以像我一样把它打印出来看看模型的输入是什么,而它的顺序也就是数组输入的正确顺序,传参数时要按照inputfields里面的特征名一个个顺序传入,特别是在集成模型中,再次强调不能采用map形式。将这些参数传入arguments后,我们就可以使用evaluator对arguments进行evaluate(评估,打分),也就能得到我们要的结果,在这个示例中,结果存在results里,还有其他的方式,新的老的都在官网里写着,大家可以试试。

以上只是示例,是对单个进行打分预测,至于批量打分预测,你可以写一个读csv的类,一行行读,或者你要验证结果,可以采用官网提供的命令行调用jar预测

java -cp target/pmml-evaluator-example-executable-1.6-SNAPSHOT.jar org.jpmml.evaluator.example.TestingExample --model model.pmml --input input.csv --expected-output expected-output.csv


注意文件名,model.pmml改成你的pmml文件名,input和output的csv文件也是,如果这个打分结果和你的python预测不一致,那是jpmml库计算错误,你可以去github上提issue。如果你只是代码写出来有问题,用命令行调用jar和你的python预测是一致的,那是你的代码问题。

总结

经过这几天的调试总算是对jpmml库有了比较深的了解,很多网上查不到的疑难杂症都要自己解决,可以说差点把我整抑郁了。之前也在找其他模型部署的方式,结果一轮看下来都不是特别满意,我需要一个真正傻瓜式的一键部署的懒人包,而不是被迫去学习服务器网络知识和我不熟悉的java知识。希望国内能有这样的开源框架吧。

玩转jpmml之tpot+sklearn2pmml自动化机器学习集成模型部署相关推荐

  1. GitHub之GitHub Actions的项目自动化持续集成和部署

    一.基本概念 GitHub Actions 是一个由事件驱动的自动化平台,通过设置触发条件,在某些事件发生时自动运行指定的操作.换言之,GitHub Actions 不仅允许开发人员在平台上托管代码, ...

  2. 机器学习集成模型学习——Stacking集成学习(五)

    stacking集成模型示例如下: stacking一般由2层堆叠构成 Stacking集成算法思路 上图为整体流程,思路如下: 把原始数据切分成两部分:训练集D-train与测试集D-test,训练 ...

  3. 机器学习集成模型学习——Boosting集成学习(四)

    Boosting Boosting模型是线性训练的,后面的模型会纠结于前一个模型预测错的部分,然后尝试把它修正,步骤如下: 第一个模型用一部分训练集训练,得出这部分训练集上的错误点 错误的数据会有更大 ...

  4. 机器学习集成模型学习——Bagging集成学习(三)

    Bagging bagging的集成方式是: 用1个模型(元模型) 然后将这个元模型分成多个相同模型,每个模型使用训练集的一部分进行训练,得到多个基模型 最后测试时分别跑每个模型,平均结果得出这个集成 ...

  5. 机器学习集成模型学习——投票集成Voting(二)

    Voting集成 投票机制就是多个模型分别预测,然后投票,票数最高的就是整个模型最后的效果 案例代码 from sklearn.linear_model import LogisticRegressi ...

  6. 机器学习集成模型ML ens学习——多层模型集成(一)

    集成模型就是把多个模型融合在一起使用,通过构建一层层的模型体系,最终得到不同模型的预测结果 首先安装:pip install mlens 案例 import pandas as pd from skl ...

  7. python自动化工具开发_初识TPOT:一个基于Python的自动化机器学习开发工具

    1. TPOT介绍 一般来讲,创建一个机器学习模型需要经历以下几步: 数据预处理 特征工程 模型选择 超参数调整 模型保存 本文介绍一个基于遗传算法的快速模型选择及调参的方法,TPOT:一种基于Pyt ...

  8. 自动化机器学习TPOT及其python实例

    自动化机器学习TPOT及其python实例 自动化机器学习,顾名思义就是输入为整理好的一个数据文件,告知特征和目标.利用该工具可以自动生成模型,实现分类或回归的预测任务.同时还能导出选用的代码管道,以 ...

  9. 自动化机器学习(二)自动构建机器学习流水线

    文章目录 技术介绍 核心技术栈 实现 数据 实现 类库加载与数据读取 参数 方法: 总结 技术介绍 自动化机器学习(一)超参数自动优化 自动化机器学习就是能够自动建立机器学习模型的方法,其主要包含三个 ...

最新文章

  1. Oracle别名大小写 -----解决方案
  2. mysql workbench ssh_通过MySQL Workbench进行SSH隧道
  3. DG备库磁盘空间满导致无法创建归档
  4. pytorch安装换源ubuntu_ubuntu 安装pytorch问题
  5. android Lint优化代码
  6. sqlserver循环like变量_numba从入门到精通(6)—numba与循环与并行
  7. MTK 驱动(51)---TP 驱动移植
  8. hashset去重原理_9道Java集合面试题,搞定了再去投简历吧!
  9. struts 标签导入
  10. 第七部分:小插曲,Deferred
  11. Java Object[] 向下强转的时候可能会发生异常
  12. elementui 遮罩
  13. AN515-43 COMPAL LA-H901P笔记本主板+小板点位图
  14. FreeCAD 乐高积木
  15. 【JAXP】Dom方式解析XML文件
  16. Cookie、Session的使用及区别
  17. Nature综述:一文揭秘土壤微生物的生死过程如何影响生物地球化学
  18. ※前端面试--知识总结
  19. 宝塔面板IP域名绑定
  20. c语言编程实现两个分数相加,C语言分数相加

热门文章

  1. CentOS安装Oracle数据库12C图文教程
  2. 阿里巴巴中台战略--数据库分库分表之异构索引表
  3. 中专学渣上岸内蒙古大学计算机专硕考研经验分享
  4. ipynb文件用什么打开
  5. STEVAL-MKI109V3评估板 PART2 - LPS27HHW传感器接口
  6. GoAccess 安装
  7. U-Boot完美解读(2)——启动文件start.s解析
  8. python怎么使用pip list_python怎么使用pip工具
  9. java 多线程 并发实例_Java 多线程(并发)
  10. 华为路由器AR1220E-S通过web页面不能登录