太骚了!Python模型完美切换SAS,还能这么玩。。
作者:东哥起飞
来源:Python数据科学
大家都知道,Python
和 SAS
是两个很常用的数据挖掘工具。Python 开源、免费、有丰富的三方库,一般在互联网公司广泛使用。而SAS需付费,且费用较高,一般互联网公司无法承担,更多的是在银行等传统金融机构中使用,不过这两年由于Python太火,原本使用SAS的也开始逐渐转向Python了。
拥抱开源,越来越多的爱好者造出优秀的Python轮子,比如当下比较流行的万金油模型Xgboost
、LightGBM
,在各种竞赛的top级方案中均有被使用。而SAS的脚步就比较慢了,对于一些比较新的东西都无法直接提供,所以对于那些使用SAS的朋友,就很难受了。
一直以来很多粉丝问过东哥这个问题:有没有一种可以将Python模型转成SAS的工具?
因为我本身是两个技能都具备的,实际工作中一般都是配合使用,也很少想过进行转换。但是,最近东哥逛技术论坛刚好发现了一个骚操作,借助Python的三方库m2cgen和Python脚本即可完成Python模型到SAS的转换。
m2cgen是什么?
m2cgen
是一个Python的第三方库,主要功能就是将Python训练过的模型转换为其它语言,比如 R
和 VBA
。遗憾的是,目前m2cgen
尚不支持SAS
,但这并不影响我们最终转换为SAS
。
我们仍然使用m2cgen
,需要借助它间接转换成SAS。具体的方案就是先将Python模型转换为VBA代码
,然后再将VBA代码更改为 SAS脚本
,曲线救国。
如何使用m2cgen?
我直接用一个例子说明下如何操作。
数据我们使用sklearn自带的iris dataset
,链接如下:
https://scikit-learn.org/stable/auto_examples/datasets/plot_iris_dataset.html
下面,演示一下如何将Python的XGBoost模型转成SAS代码。
首先导入所需的库包和数据。
# 导入库
import pandas as pd
import numpy as np
import os
import re
from sklearn import datasets
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import m2cgen as m2c
# 导入数据
iris = datasets.load_iris()
X = iris.data
Y = iris.target
然后,我们划分数据集,直接扔进XGBoost
里面,建立base模型。
# 划分数据为训练集和测试集
seed = 2020
test_size = 0.3
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=test_size, random_state=seed)
# 训练数据
model = XGBClassifier()
model.fit(X_train, y_train)
然后,再将XGBoost模型转换为VBA。使用m2cgen
的export_to_visual_basic
方法就可以直接转成VBA了。转换成其他语言脚本也是同理,非常简单。
code = m2c.export_to_visual_basic(model, function_name = 'pred')
核心的骚操作来了!
m2cgen不支持SAS,但我们可以把VBA代码稍加改动,就能变成符合SAS标准的代码了。而这个改动也无需手动一个个改,写一段Python脚本即可实现VBA脚本转换为SAS脚本。
改动的地方不多,主要包括:删除在SAS环境中不能使用的代码,像上面结果中的Module xxx
,Function yyy
,Dim var Z As Double
,还有在语句结尾加上;
,这些为的就是遵循SAS的语法规则。
下面就是转换的Python脚本,可以自动执行上面所说的转换操作。
# 1、移除SAS中不能使用的代码
code = re.sub('Dim var.* As Double', '', code)
code = re.sub('End If', '', code)
# 下面操作将修改成符合SAS的代码
# 2、修改起始
code = re.sub('Module Model\nFunction pred\(ByRef inputVector\(\) As Double\) As Double\(\)\n', 'DATA pred_result;\nSET dataset_name;', code)
# 3、修改结尾
code = re.sub('End Function\nEnd Module\n', 'RUN;', code)
# 4、在结尾加上分号';'
all_match_list = re.findall('[0-9]+\n', code)
for idx in range(len(all_match_list)):original_str = all_match_list[idx]new_str = all_match_list[idx][:-1]+';\n'code = code.replace(original_str, new_str)
all_match_list = re.findall('\)\n', code)
for idx in range(len(all_match_list)):original_str = all_match_list[idx]new_str = all_match_list[idx][:-1]+';\n'code = code.replace(original_str, new_str)
# 用var来替代inputVector
dictionary = {'inputVector(0)':'sepal_length','inputVector(1)':'sepal_width','inputVector(2)':'petal_length','inputVector(3)':'petal_width'}
for key in dictionary.keys():code = code.replace(key, dictionary[key])
# 修改预测标签
code = re.sub('Math.Exp', 'Exp', code)
code = re.sub('pred = .*\n', '', code)
temp_var_list = re.findall(r"var[0-9]+\(\d\)", code)
for var_idx in range(len(temp_var_list)):code = re.sub(re.sub('\\(', '\\(', re.sub('\\)', '\\)', temp_var_list[var_idx])), iris.target_names[var_idx]+'_prob', code)
对以上脚本分步解释说明一下。
1、开头、结尾、输出名称
前三个部分非常简单。使用正则表达式删除多余的行,然后将脚本的开头更改为DATA pred_result; \ nSETdataset_name;
。
使用过SAS的同学就很熟悉了,pred_result
是运行SAS脚本后的输出表名称,dataset_name
是我们需要预测的输入表名称。
最后再将脚本的结尾更改为RUN;
。
# 移除SAS中不能使用的代码
code = re.sub('Dim var.* As Double', '', code)
code = re.sub('End If', '', code)
# 下面操作将修改成符合SAS的代码
# 修改起始
code = re.sub('Module Model\nFunction pred\(ByRef inputVector\(\) As Double\) As Double\(\)\n', 'DATA pred_result;\nSET dataset_name;', code)
# 修改结尾
code = re.sub('End Function\nEnd Module\n', 'RUN;', code)
2、语句末尾添加分号
为遵循SAS中的语法规则,还需将每个语句的结尾加上;
。仍用正则表达式,然后for循环在每一行最后添加字符;
即可。
# 在结尾加上分号';'
all_match_list = re.findall('[0-9]+\n', code)
for idx in range(len(all_match_list)):original_str = all_match_list[idx]new_str = all_match_list[idx][:-1]+';\n'code = code.replace(original_str, new_str)
all_match_list = re.findall('\)\n', code)
for idx in range(len(all_match_list)):original_str = all_match_list[idx]new_str = all_match_list[idx][:-1]+';\n'code = code.replace(original_str, new_str)
3、映射变量名称
使用字典将InputVector
与变量名称映射到输入数据集中,一次性更改所有InputVector
。
# 用var来替代inputVector
dictionary = {'inputVector(0)':'sepal_length','inputVector(1)':'sepal_width','inputVector(2)':'petal_length','inputVector(3)':'petal_width'}
for key in dictionary.keys():code = code.replace(key, dictionary[key])
4、映射变量名称
最后一步就是更改预测标签。
# 修改预测标签
code = re.sub('Math.Exp', 'Exp', code)
code = re.sub('pred = .*\n', '', code)
temp_var_list = re.findall(r"var[0-9]+\(\d\)", code)
for var_idx in range(len(temp_var_list)):code = re.sub(re.sub('\\(', '\\(', re.sub('\\)', '\\)', temp_var_list[var_idx])), iris.target_names[var_idx]+'_prob', code)
然后保存sas模型文件。
#保存输出
vb = open('vb1.sas', 'w')
vb.write(code)
vb.close()
最后,为了验证sas脚本是否正确,我们将sas模型的预测结果和Python的结果进行一下对比。
# python 预测
python_pred = pd.DataFrame(model.predict_proba(X_test))
python_pred.columns = ['setosa_prob','versicolor_prob','virginica_prob']
python_pred
# sas 预测
sas_pred = pd.read_csv('pred_result.csv')
sas_pred = sas_pred.iloc[:,-3:]
sas_pred
(abs(python_pred - sas_pred) > 0.00001).sum()
可以看到,两个预测的结果基本上一样,基本没问题,我们就可以在sas中跑xgboost模型了。
总结
上面只是个最简单的示例,没有对特征处理。对于复杂的建模过程,比如很多特征工程,那就要对Python脚本进一步调整了。
觉得这个方法比较新颖,拿来分享一下,大家也可举一反三。如果铁子们有更多好玩的方法,欢迎文章下面留言。
参考:https://towardsdatascience.com/converting-machine-learning-models-to-sas-using-m2cgen-python-190d846090dc
推荐阅读
误执行了rm -fr /*之后,除了跑路还能怎么办?!
程序员必备58个网站汇总
大幅提高生产力:你需要了解的十大Jupyter Lab插件
太骚了!Python模型完美切换SAS,还能这么玩。。相关推荐
- python版本切换_Ubuntu18.04下python版本完美切换的解决方法
ubuntu18.04版本,python版本python2.7,python3.5,python3.6 因为安装一些库会安装到python3.6上,而默认使用的是python2.7,使用python3 ...
- ubuntu查看python版本-Ubuntu18.04下python版本完美切换的解决方法
ubuntu18.04版本,python版本python2.7,python3.5,python3.6 因为安装一些库会安装到python3.6上,而默认使用的是python2.7,使用python3 ...
- pyenv 让 python 版本完美切换
前言 我觉得如果使用 python 开发的话,还是在 unix/linux 的环境下吧,shell 工具的效率比 windows 高得多,尽管 windows 下也有 cmder 这种神器,而且现在 ...
- python植物大战僵尸辅助器手机版_GitHub又放大招,Python版本的植物大战僵尸还能作弊玩!...
<植物大战僵尸>游戏它是一款极富策略性的小游戏,集成了即时战略.塔防御战和卡片收集等要素,玩家控制植物抵御僵尸的进攻,保护这片植物园.记得小编刚工作的时候抱着IPAD经常玩到深夜. 最近在 ...
- Python控制键盘鼠标,原来还能这样玩?
这个库让你可以控制和监控输入设备. 对于每一种输入设备,它包含一个子包来控制和监控该种输入设备: pynput.mouse:包含控制和监控鼠标或者触摸板的类. pynput.keyboard:包含控制 ...
- python 寻找完美数_寻找完美的鼠标
python 寻找完美数 I have a small problem. I'm always looking for great computer mice. I've tried a number ...
- 独家 | 从全方位为你比较3种数据科学工具的比较:Python、R和SAS(附链接)
翻译:张玲 校对:吴金笛 本文约3000字,建议阅读5分钟. 关于三种数据科学工具Python.R和SAS,本文从8个角度进行比较分析并在文末提供记分卡,以便你随时调整权重,快速做出选择. 简介 我们 ...
- Python、R和SAS的比较
从全方位为你比较3种数据科学工具的比较:Python.R和SAS(附链接): 简介 我们喜欢比较!从比较三星.苹果.HTC的智能手机,iOS.Android.Windows的移动操作系统到比较即将选举 ...
- sas和python哪个好学_从全方位为你比较3种数据科学工具的比较:Python、R和SAS(附链接)...
原标题:从全方位为你比较3种数据科学工具的比较:Python.R和SAS(附链接) 本文约3000字,建议阅读5分钟. 关于三种数据科学工具Python.R和SAS,本文从8个角度进行比较分析并在文末 ...
最新文章
- c语言复习笔记(2)--标准库中的I/O
- ASP.NET MVC:@helper 不能调试
- QT的QGraphicsItem类的使用
- DenseNet详述
- Istio 中的 Sidecar 注入及透明流量劫持过程详解
- 41款常用APP被爆过度索取权限、数据共享给第三方
- linux exfat分区格式化,技术|如何在 Linux 上将 USB 盘格式化为 exFAT
- Collection和Collections有什么区别?
- 阶乘c 语言代码,求10000的阶乘(c语言代码实现)
- QT每日一练day21:鼠标事件
- java core 之 IO流
- linux内核热插拔,Linux热插拔机制的介绍和应用
- Linux操作系统———李纳斯
- 文件上传案例(java)
- 【FPGA】五、蜂鸣器播放音乐
- 实现运动目标检测(opencv3)(一)
- 连接不上oracle数据库
- Redis集群搭建(转自一菲聪天的“Windows下搭建Redis集群”)
- 暗影精灵 官方恢复出厂系统镜像HP Cloud Recovery Tool
- cascades文档翻译——HomeScreen
热门文章
- php 判断http还是https,以及获得当前url的方法
- 探究php底层运行机制
- nginx中SSI问题的研究
- promise使用promise进行封装授权登录接口
- PHP的array_column
- Vue的阻止冒泡与阻止默认
- springmvc执行流程(简述易懂)
- vfp如何比较两张表的关键字重复_Access开发中建表的基本原理和规范(上)
- linux主从服务器不能同步,Linux下redis的持久化、主从同步与哨兵详解
- 基于matlab的单相pwm逆变电路的仿真研究,基于MATLAB的单相PWM逆变电路的仿真研究...