通常xgb或lgb模型通过pmml上线都比较简单,但是逻辑回归模型因为涉及到woe的转换,就要通过自定义转换函数的方式来实现。

1、常规转换-模型训练好之后立即转换

import joblib
from sklearn2pmml import PMMLPipeline,sklearn2pmml# 保存模型 python可读入
def dump(clf, fp='clf'):joblib.dump(feature_names_2, 'feature_' + fp +'.pkl')joblib.dump(clf, fp + '.pkl')pipeline = PMMLPipeline([("classifier", clf)])pipeline.fit(data_train[feature_names_2], data_train['target'])sklearn2pmml(pipeline, fp + '.pmml', with_repr=True)

以上clf是训练好的模型,data_train是训练数据集,feature_names_2是入模特征,这样在模型训练好之后就可以立即将模型转换成pkl和pmml的形式。

2、只有模型和特征的pkl文件,没有训练集
先将模型和特征的pkl进行load,然后在运行以下代码就可以保存为pmml

def pmml_save(model, feat_list, save_file_path):from sklearn2pmml import sklearn2pmml, PMMLPipelinefrom sklearn_pandas import DataFrameMapperif not save_file_path.endswith('.pmml'):raise Exception('参数save_file_path后缀必须为pmml, 请检查!')mapper = DataFrameMapper([([i], None) for i in feat_list])pipeline = PMMLPipeline([('mapper', mapper), ("classifier", model)])sklearn2pmml(pipeline, pmml=save_file_path)print('模型文件已保存至{}'.format(save_file_path))pmml_save(model, feature_names_2, 'xgb_0708.pmml')

注意:pkl转pmml失败,以及pmml上线问题,基本上都是sklearn2pmml的版本问题,pmml4.3比pmml4.4更稳定,部署不易出错,建议使用pmml4.3。对应所需包
的版本如下:sklearn:0.22.0,sklearn2pmml:0.56.0,lightgbm:3.2.1,xgboost:1.0.2

3、数据预处理的pmml转换

from sklearn2pmml import sklearn2pmml, PMMLPipeline
from sklearn_pandas import DataFrameMapper
from sklearn2pmml.preprocessing import ExpressionTransformer    mapper = DataFrameMapper([
(['age'], ExpressionTransformer("-0.1111 if X[0] <= 25 else (0.3333 if X[0]<=30 else 1.4598)")),
(['tx_riskscore'], ExpressionTransformer("-0.42264 if X[0] <= 40  else (0.2344 if X[0]<=70 else 1.44323)")),
(['rh_fraud_score'], ExpressionTransformer("-0.8888 if X[0] <= 50 else (0.8822 if X[0]<=60 else 1.12123)")),
]) pipeline = PMMLPipeline([('mapper', mapper),("classifier", sklearn.linear_model.LogisticRegression())])
pipeline.fit(data2[data2.columns.difference(['cpd30'])], data2['cpd30'])
sklearn2pmml(pipeline, 'test.pmml', with_repr=True)

使用ExpressionTransformer函数,来定义ifelse语句,然后再对转换后的woe变量训练模型,下面是转换后的pmml,欢迎测试。


4、模型上线缺失值问题
如果lgb模型训练时在本地没有做缺失值处理,用sklearn2pmml生成的pmml文件上线后是没有问题的。但是如果pmml要对缺失的变量做二次衍生,就会由于java未传参导致报错。

解决方法:用pandas.isnull(X[0]) 表示是否缺失!!!!最主要的是使用ExpressionTransformer if语句的时候,先要进行是否missing判断。

#逻辑回归woe转换
(["App_SMALLLOAN_Installed_24M"], ExpressionTransformer("0.21722199999999997 if pandas.isnull(X[0]) else(0.770462 if X[0]<=0.5 else(0.067147 if X[0]<=2.5 else(-0.8716940000000001 if X[0]<=6.5 else(-1.8263049999999998 if X[0]<=13.0 else(-2.789888 if X[0]<=24.5 else -3.313811 )))))"),{"alias":"W_App_SMALLLOAN_Installed_24M"}),#生成中间变量,分母为0的处理
(['cts_msg_002','cts_msg_018'],[ExpressionTransformer('X[0]/X[1] if pandas.isnull(X[1]) else(0 if X[1]==0 else X[0]/X[1])')],{'alias':'cts_msg_ys_003'}),

还有一个状况,就是假设建模的时候没有做缺失值处理,上线的时候因为某些原因必须要填充缺失值,怎么办呢??
在尝试了FunctionTransformer(ufunc),以及自定义 Transformer等操作方式之后,采用如下的方式:

可以先将缺失值填充为-9999,然后对特征进行下面的操作:特征值为-9999的进行np.log1(x),这样可以在pmml文件里将其转换为nan。

(['CPL_INDM_EDU_LEVEL'], [ExpressionTransformer("numpy.log1p(X[0]) if X[0]==-9999 else X[0]")]),

参考解决思路、 pmml官方文档

完整的例子:生成中间变量的pmml转换

from sklearn.dummy import DummyRegressor
from sklearn2pmml import PMMLPipeline, sklearn2pmml
from sklearn2pmml.preprocessing import ExpressionTransformer
from sklearn_pandas import DataFrameMapper
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression,LogisticRegression
import lightgbm as lgbdf = pd.DataFrame(np.random.randint(0,100,size=(10000, 6)), columns=list('ABCDEF'))
df['target'] = df['F'].apply(lambda x:1 if x>50 else 0)#变量衍生
df['sub1'] = df.apply(lambda x:x['A']-x['B'], axis=1)
df['mean1'] = df.apply(lambda x:(x['A']+x['B']+x['C'])/3, axis=1)
df['sum2'] = df.apply(lambda x:x['C']+x['D'], axis=1)features= ['sub1','mean1','sum2','A','E']
model = lgb.LGBMClassifier(n_estimators=100, max_depth=3, random_state=100).fit(df[features], df['target'])

转pmml

# from sklearn2pmml.decoration import Alias# mapper = DataFrameMapper([
#     (['A','B'], Alias(ExpressionTransformer("X[0] + X[1]"), name = "sum1")),
#     (['C','D'], Alias(ExpressionTransformer("X[0] + X[1] "), name = "sum2")),
#     (['A'], None),
#     (['E'], None),
# ])mapper = DataFrameMapper([(['A','B'], [ExpressionTransformer("X[0] - X[1]")],{"alias":"sub1"}),(['A','B', 'C'], [ExpressionTransformer("(X[0] + X[1] + X[2]) / 3")],{"alias":"mean1"}),(['C','D'], [ExpressionTransformer("X[0] + X[1]")],{"alias":"sum2"}),(['A'], None),(['E'], None),
])pipeline = PMMLPipeline([("mapper", mapper),("classifier", model)
])
pipeline.fit(df, df['target'])
sklearn2pmml(pipeline, "pipeline_01.pmml", with_repr = True)

模型预测结果和pmml生成模型预测结果对比,结果一致:

def load_pmml_model(save_file_path):from pypmml import Modelif not os.path.exists(save_file_path):raise Exception('参数save_file_path指向的文件路径不存在, 请检查!')model = Model.fromFile(save_file_path)return modelmodel1 = load_pmml_model("pipeline_01.pmml")
df['pred'] = model.predict_proba(df[features])[:, 1]
df['pred1'] = model1.predict(df)['probability(1)']

注意,
1、DataFrameMapper中变量的顺序一定要与训练好的模型model中变量features顺序一致
2、这里在验证分数是否一致时,一定要对数据df的索引重置

df.reset_index(drop=True, inplace=True)

不然pmml打分错误,目前还未找到原因。。。

Python模型上线pmml以及自定义函数转换相关推荐

  1. Python使用numpy包编写自定义函数计算平均绝对误差(MAE、Mean Absolute Error)、评估回归模型和时间序列模型、解读MAE

    Python使用numpy包编写自定义函数计算平均绝对误差(MAE.Mean Absolute Error).评估回归模型和时间序列模型.解读MAE 目录

  2. Python使用numpy包编写自定义函数计算均方误差(MSE、mean squared error)、评估回归模型和时间序列模型、解读MSE评估指标

    Python使用numpy包编写自定义函数计算均方误差(MSE.mean squared error).评估回归模型和时间序列模型.解读MSE评估指标 目录

  3. python使用numpy包编写自定义函数计算SMAPE(对称平均绝对百分比误差)指标Symmetric mean absolute percentage error、SMAPE指标解读、指标使用的注

    python使用numpy包编写自定义函数计算SMAPE(对称平均绝对百分比误差)指标Symmetric mean absolute percentage error (SMAPE).SMAPE指标解 ...

  4. python使用numpy包编写自定义函数计算MAPE(平均绝对百分比误差)指标mean absolute percentage error (MAPE)、MAPE指标解读、MAPE指标使用的注意事项

    python使用numpy包编写自定义函数计算MAPE(平均绝对百分比误差)指标mean absolute percentage error (MAPE).MAPE指标解读.MAPE指标使用的注意事项 ...

  5. python模型转PMML

    关于python模型的部署,目前有以下几种方式 flask等python为服务框架,无需跨语言 xgb4j,lgb4j等Java包,需跨语言,但只支持xgb/lgb PMML,跨语言,支持所有skle ...

  6. python知识点(六)自定义函数

    一.函数(function) 定义:一段可以完成某个功能的代码. 使用函数:通过函数名即可调用函数,可以让计算机完成某个功能 举例:输入两个数,输出两个数中最大的数 a=int(input()) b= ...

  7. 【Python核心】不可或缺的自定义函数

    一个规范的值得借鉴的Python程序,除非代码量很少(比如 10 行.20 行以下),基本都应该由多个函数组成,这样的代码才更加模块化.规范化 函数是Python程序中不可或缺的一部分 事实上,在前面 ...

  8. simulink仿真实例_又见Simulink库模型之(9):自定义函数

    Simulink中提供了各种各样的模块,使得研究人员通过搭积木的方式,可以实现大部分功能需求.但总会有一些场景,是必须要研究人员自行编写代码,来满足自己的个性化需求. Simulink正是通过Matl ...

  9. 2、Py进制转换:荣耀机试题,任意2-64进制转10进制(自定义函数转换)

    本文不直接解题,只解决其中核心部分:任意2-64进制数转10进制数 一.题目 原题: 小明最近在学bash语言,发现Bash算术运算相比于C/pvthon等其他语言有一个特性,是其中常量表示规则: 1 ...

最新文章

  1. 关于山东大学(威海)全向组海韵三队提交的 RT-Thread 技术报告中的若干疑点
  2. Android开发---Activity的生命周期
  3. Spring 2.5架构图
  4. mysql全文索引中文问题的解决(转)
  5. R-大数据分析挖掘(5-R基础回顾)
  6. 一文读懂类加载机制 --- ClassLoader
  7. vbs读取服务器上的txt文件,VBS读写txt文件常用方法
  8. word break II 对字符串根据已知字典 分解出所有可能组合
  9. JS中setAttribute的兼容性问题(摘自leejersey)
  10. python建立sqlite数据库_5分钟快速入门,用Python做SQLite数据库开发,附代码适合初学...
  11. python封装c++接口_用C++封装MySQL的API的教程
  12. Java操作mongoDB2.6的常见API使用方法
  13. 安卓数据读写全解:SharedPreferences公共数据的读写,SQLiteDatabase数据库,mysql数据库
  14. C#高级编程笔记(二)
  15. ios8来了,屏幕更大,准备好使用 iOS Auto Layout了吗?
  16. sql cast函数_数据分析面试必备——SQL你掌握的怎么样?
  17. MySQL数据库的卸载
  18. 2019年上半年工作总结
  19. 流媒体技术基础-流媒体文件格式
  20. 香港虚拟主机与国内虚拟主机区别

热门文章

  1. 从0到1学SpringCloud——08 通过fegin实现微服务之间请求调用
  2. SVG动画树藤生成文字美化js特效
  3. 一 重装ubuntu后设置
  4. Linux移动文件提示权限被拒绝
  5. 短视频如何赚钱 短视频自媒体实操经验分享+真实
  6. 计算机的组成部件及其厂商
  7. 渗透测试面试题--日更(1-9day)
  8. C++ 测试驱动开发 TDD(一)
  9. 基于android系统的音乐播放器,基于Android系统的音乐播放器软件设计与实现.doc
  10. 蓝牙耳机那个牌子好,蓝牙运动耳机排行榜