大家都知道Python和SAS是两种非常常用的数据挖掘工具。Python开源免费,第三方库丰富,普遍被互联网公司广泛使用。但是SAS需要付费,费用比较高。一般互联网公司都买不起。多用于银行等传统金融机构。但是,由于这两年Python的流行,原来用SAS的也逐渐转向了Python。拥抱开源,越来越多的爱好者创造出优秀的Python轮子,比如流行的万能模型Xgboost和LightGBM,在各种比赛的顶级方案中都有使用。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数据集。链接如下:https://scikit-learn.org/stab...接下来,我们将演示如何将Python的XGBoost模型转换为SAS代码。首先导入需要的库包和数据。#?导入库import?pandas?as?pdimport?numpy?as?npimport?os?import?refrom?sklearn?import?datasetsfrom?xgboost?import?XGBClassifierfrom?sklearn.model_selection?import?train_test_splitfrom?sklearn.metrics?import?accuracy_scoreimport?m2cgen?as?m2c#?导入数据iris?=?datasets.load_iris()X?=?iris.dataY?=?iris.target然后,我们将数据集进行划分,直接丢到XGBoost中构建基础模型。#将数据分成训练集和测试集seed=2020test_size=0.3X_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脚本。改动不多,主要是:删除了上面结果中Modulexxx、Functionyyy、DimvarZAsDouble等不能在SAS环境下使用的代码,并增加了;在语句的末尾,这些都遵循SAS语法规则。下面是转换后的Python脚本,可以自动执行上述转换操作。#1.去掉SAS中不能使用的代码code=re.sub('Dimvar.*AsDouble','',code)code=re.sub('EndIf','',code)#下面的operations修改代码以符合SAS??#2,修改起始代码=re.sub('ModuleModel\nFunctionpred(ByRefinputVector()AsDouble)AsDouble()\n','DATApred_result;\nSETdataset_name;',code)#3.修改结束代码=re.sub('EndFunction\nEndModule\n','RUN;',code)#4.在最后添加分号';'all_match_list=re.findall('[0-9]+\n',code)foridxinrange(len(all_match_list)):original_str=all_match_list[idx]new_str=all_match_list[idx][:-1]+';\n'code=代码。替换(original_str,new_str)all_match_list=re.findall(')\n',code)foridxinrange(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)#将inputVectordictionary替换为var={'inputVector(0)':'sepal_length','inputVector(1)':'sepal_width',Vector'(2input):'petal_length','inputVector(3)':'petal_width'}forkeyindictionary.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)forvar_idxinrange(len(temp_var_list)):code=re.sub(re.sub('\(','\(',re.sub('\)','\)',temp_var_list[var_idx])),iris.target_names[var_idx]+'_prob',code)一步步解释上面的脚本1、开头、结尾、输出名称的前三部分都很简单。使用正则表达式删除多余的行,然后将脚本的开头更改为DATApred_result;\nSETdataset_name;。用过SAS的同学都不会陌生。pred_result是运行SAS脚本后的输出表名,dataset_name是我们需要预测的输入表名。最后,将脚本的结尾更改为RUN;。#去除SAS中不能使用的代码code=re.sub('Dimvar.*AsDouble','',code)code=re.sub('EndIf','',code)#下面的操作将修改成符合SAS??的代码#修改初始代码=re.sub('ModuleModel\nFunctionpred(ByRefinputVector()AsDouble)AsDouble()\n','DATApred_result;\nSETdataset_name;',code)#修改结束代码=re.sub('EndFunction\nEndModule\n','RUN;',code)2.在语句末尾添加分号遵循SAS中的语法规则,并添加;.还是用正则表达式,然后for循环在每行末尾添加字符;#在末尾加分号';'all_match_list=re.findall('[0-9]+\n',code)foridxinrange(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)foridxinrange(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和变量名映射到输入数据集,一次永久更改所有InputVectors。#将inputVectordictionary替换为var={'inputVector(0)':'sepal_length','inputVector(1)':'sepal_width','inputVector(2)':'petal_length',talwpeput3ididor'('}forkeyindictionary.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)forvar_idxinrange(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脚本做进一步的调整。以上就是本次分享的全部内容。觉得文章还不错的话,请关注公众号:Python编程学习圈,每日干货分享,发送“J”还能收到海量学习资料,涵盖Python电子书和教程,数据库编程、Django、爬虫、云计算等。或者去编程学习网了解更多编程技术知识。
