作者:东哥起飞

来源:Python数据科学

大家都知道,PythonSAS 是两个很常用的数据挖掘工具。Python 开源、免费、有丰富的三方库,一般在互联网公司广泛使用。而SAS需付费,且费用较高,一般互联网公司无法承担,更多的是在银行等传统金融机构中使用,不过这两年由于Python太火,原本使用SAS的也开始逐渐转向Python了。

拥抱开源,越来越多的爱好者造出优秀的Python轮子,比如当下比较流行的万金油模型XgboostLightGBM,在各种竞赛的top级方案中均有被使用。而SAS的脚步就比较慢了,对于一些比较新的东西都无法直接提供,所以对于那些使用SAS的朋友,就很难受了。

一直以来很多粉丝问过东哥这个问题:有没有一种可以将Python模型转成SAS的工具?

因为我本身是两个技能都具备的,实际工作中一般都是配合使用,也很少想过进行转换。但是,最近东哥逛技术论坛刚好发现了一个骚操作,借助Python的三方库m2cgen和Python脚本即可完成Python模型到SAS的转换。

m2cgen是什么?

m2cgen是一个Python的第三方库,主要功能就是将Python训练过的模型转换为其它语言,比如 RVBA。遗憾的是,目前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。使用m2cgenexport_to_visual_basic方法就可以直接转成VBA了。转换成其他语言脚本也是同理,非常简单。

code = m2c.export_to_visual_basic(model, function_name = 'pred')

核心的骚操作来了!

m2cgen不支持SAS,但我们可以把VBA代码稍加改动,就能变成符合SAS标准的代码了。而这个改动也无需手动一个个改,写一段Python脚本即可实现VBA脚本转换为SAS脚本。

改动的地方不多,主要包括:删除在SAS环境中不能使用的代码,像上面结果中的Module xxxFunction yyyDim 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,还能这么玩。。相关推荐

  1. python版本切换_Ubuntu18.04下python版本完美切换的解决方法

    ubuntu18.04版本,python版本python2.7,python3.5,python3.6 因为安装一些库会安装到python3.6上,而默认使用的是python2.7,使用python3 ...

  2. ubuntu查看python版本-Ubuntu18.04下python版本完美切换的解决方法

    ubuntu18.04版本,python版本python2.7,python3.5,python3.6 因为安装一些库会安装到python3.6上,而默认使用的是python2.7,使用python3 ...

  3. pyenv 让 python 版本完美切换

    前言 我觉得如果使用 python 开发的话,还是在 unix/linux 的环境下吧,shell 工具的效率比 windows 高得多,尽管 windows 下也有 cmder 这种神器,而且现在 ...

  4. python植物大战僵尸辅助器手机版_GitHub又放大招,Python版本的植物大战僵尸还能作弊玩!...

    <植物大战僵尸>游戏它是一款极富策略性的小游戏,集成了即时战略.塔防御战和卡片收集等要素,玩家控制植物抵御僵尸的进攻,保护这片植物园.记得小编刚工作的时候抱着IPAD经常玩到深夜. 最近在 ...

  5. Python控制键盘鼠标,原来还能这样玩?

    这个库让你可以控制和监控输入设备. 对于每一种输入设备,它包含一个子包来控制和监控该种输入设备: pynput.mouse:包含控制和监控鼠标或者触摸板的类. pynput.keyboard:包含控制 ...

  6. python 寻找完美数_寻找完美的鼠标

    python 寻找完美数 I have a small problem. I'm always looking for great computer mice. I've tried a number ...

  7. 独家 | 从全方位为你比较3种数据科学工具的比较:Python、R和SAS(附链接)

    翻译:张玲 校对:吴金笛 本文约3000字,建议阅读5分钟. 关于三种数据科学工具Python.R和SAS,本文从8个角度进行比较分析并在文末提供记分卡,以便你随时调整权重,快速做出选择. 简介 我们 ...

  8. Python、R和SAS的比较

    从全方位为你比较3种数据科学工具的比较:Python.R和SAS(附链接): 简介 我们喜欢比较!从比较三星.苹果.HTC的智能手机,iOS.Android.Windows的移动操作系统到比较即将选举 ...

  9. sas和python哪个好学_从全方位为你比较3种数据科学工具的比较:Python、R和SAS(附链接)...

    原标题:从全方位为你比较3种数据科学工具的比较:Python.R和SAS(附链接) 本文约3000字,建议阅读5分钟. 关于三种数据科学工具Python.R和SAS,本文从8个角度进行比较分析并在文末 ...

最新文章

  1. c语言复习笔记(2)--标准库中的I/O
  2. ASP.NET MVC:@helper 不能调试
  3. QT的QGraphicsItem类的使用
  4. DenseNet详述
  5. Istio 中的 Sidecar 注入及透明流量劫持过程详解
  6. 41款常用APP被爆过度索取权限、数据共享给第三方
  7. linux exfat分区格式化,技术|如何在 Linux 上将 USB 盘格式化为 exFAT
  8. Collection和Collections有什么区别?
  9. 阶乘c 语言代码,求10000的阶乘(c语言代码实现)
  10. QT每日一练day21:鼠标事件
  11. java core 之 IO流
  12. linux内核热插拔,Linux热插拔机制的介绍和应用
  13. Linux操作系统———李纳斯
  14. 文件上传案例(java)
  15. 【FPGA】五、蜂鸣器播放音乐
  16. 实现运动目标检测(opencv3)(一)
  17. 连接不上oracle数据库
  18. Redis集群搭建(转自一菲聪天的“Windows下搭建Redis集群”)
  19. 暗影精灵 官方恢复出厂系统镜像HP Cloud Recovery Tool
  20. cascades文档翻译——HomeScreen

热门文章

  1. php 判断http还是https,以及获得当前url的方法
  2. 探究php底层运行机制
  3. nginx中SSI问题的研究
  4. promise使用promise进行封装授权登录接口
  5. PHP的array_column
  6. Vue的阻止冒泡与阻止默认
  7. springmvc执行流程(简述易懂)
  8. vfp如何比较两张表的关键字重复_Access开发中建表的基本原理和规范(上)
  9. linux主从服务器不能同步,Linux下redis的持久化、主从同步与哨兵详解
  10. 基于matlab的单相pwm逆变电路的仿真研究,基于MATLAB的单相PWM逆变电路的仿真研究...