Python模型上线pmml以及自定义函数转换
通常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以及自定义函数转换相关推荐
- Python使用numpy包编写自定义函数计算平均绝对误差(MAE、Mean Absolute Error)、评估回归模型和时间序列模型、解读MAE
Python使用numpy包编写自定义函数计算平均绝对误差(MAE.Mean Absolute Error).评估回归模型和时间序列模型.解读MAE 目录
- Python使用numpy包编写自定义函数计算均方误差(MSE、mean squared error)、评估回归模型和时间序列模型、解读MSE评估指标
Python使用numpy包编写自定义函数计算均方误差(MSE.mean squared error).评估回归模型和时间序列模型.解读MSE评估指标 目录
- python使用numpy包编写自定义函数计算SMAPE(对称平均绝对百分比误差)指标Symmetric mean absolute percentage error、SMAPE指标解读、指标使用的注
python使用numpy包编写自定义函数计算SMAPE(对称平均绝对百分比误差)指标Symmetric mean absolute percentage error (SMAPE).SMAPE指标解 ...
- python使用numpy包编写自定义函数计算MAPE(平均绝对百分比误差)指标mean absolute percentage error (MAPE)、MAPE指标解读、MAPE指标使用的注意事项
python使用numpy包编写自定义函数计算MAPE(平均绝对百分比误差)指标mean absolute percentage error (MAPE).MAPE指标解读.MAPE指标使用的注意事项 ...
- python模型转PMML
关于python模型的部署,目前有以下几种方式 flask等python为服务框架,无需跨语言 xgb4j,lgb4j等Java包,需跨语言,但只支持xgb/lgb PMML,跨语言,支持所有skle ...
- python知识点(六)自定义函数
一.函数(function) 定义:一段可以完成某个功能的代码. 使用函数:通过函数名即可调用函数,可以让计算机完成某个功能 举例:输入两个数,输出两个数中最大的数 a=int(input()) b= ...
- 【Python核心】不可或缺的自定义函数
一个规范的值得借鉴的Python程序,除非代码量很少(比如 10 行.20 行以下),基本都应该由多个函数组成,这样的代码才更加模块化.规范化 函数是Python程序中不可或缺的一部分 事实上,在前面 ...
- simulink仿真实例_又见Simulink库模型之(9):自定义函数
Simulink中提供了各种各样的模块,使得研究人员通过搭积木的方式,可以实现大部分功能需求.但总会有一些场景,是必须要研究人员自行编写代码,来满足自己的个性化需求. Simulink正是通过Matl ...
- 2、Py进制转换:荣耀机试题,任意2-64进制转10进制(自定义函数转换)
本文不直接解题,只解决其中核心部分:任意2-64进制数转10进制数 一.题目 原题: 小明最近在学bash语言,发现Bash算术运算相比于C/pvthon等其他语言有一个特性,是其中常量表示规则: 1 ...
最新文章
- 关于山东大学(威海)全向组海韵三队提交的 RT-Thread 技术报告中的若干疑点
- Android开发---Activity的生命周期
- Spring 2.5架构图
- mysql全文索引中文问题的解决(转)
- R-大数据分析挖掘(5-R基础回顾)
- 一文读懂类加载机制 --- ClassLoader
- vbs读取服务器上的txt文件,VBS读写txt文件常用方法
- word break II 对字符串根据已知字典 分解出所有可能组合
- JS中setAttribute的兼容性问题(摘自leejersey)
- python建立sqlite数据库_5分钟快速入门,用Python做SQLite数据库开发,附代码适合初学...
- python封装c++接口_用C++封装MySQL的API的教程
- Java操作mongoDB2.6的常见API使用方法
- 安卓数据读写全解:SharedPreferences公共数据的读写,SQLiteDatabase数据库,mysql数据库
- C#高级编程笔记(二)
- ios8来了,屏幕更大,准备好使用 iOS Auto Layout了吗?
- sql cast函数_数据分析面试必备——SQL你掌握的怎么样?
- MySQL数据库的卸载
- 2019年上半年工作总结
- 流媒体技术基础-流媒体文件格式
- 香港虚拟主机与国内虚拟主机区别