算法建模流程详解及python代码实现
算法建模
前⾔
每个算法⼯程师都有⾃⼰建模的习惯,因此在建模流程上会有所不同。本⽂主要介绍了⼀般的建模流程,有些步骤的先后顺序可能会有所差异,具体还需结合⾃⼰的实际相结合。
建模的⼀般流程
1.明确需求,确定y: 这是建模第⼀步需要做的,y定义的合理程度很⼤程度的影响模型乃⾄策略的评估。⼀⽅⾯需要经验的⽀撑,另⼀⽅⾯需要结合业务知识来确定。例如在信贷中A卡⼀般根据vintage曲线或者滚动率来确定好⼈与坏⼈的标签。
2.寻与y相关的底层变量: 在确定y的业务基础上,寻相关变量可以是传统相关的业务变量,可以是相关的数据埋点,可以是三⽅公司的数据,可以是⽤户授权所爬取的相关数据等。(注意:每个变量的具体业务含义必须明确,下⾯流程需要评估合理性与衍⽣)
3.数据EDA: 这部分主要是对数据有⼀个⼤体的了解。主要包含变量的均值、中位数、缺失率(缺失率⾼
的是否考虑删除)、同⼀值(取值distinct较少是否删除)、异常值、分布、相关性(这⼀步也可以放在后⾯降维步骤后再进⾏⼀波降维)等。
4.变量衍⽣: 在拿到且理解了基础的变量之后,需要做变量衍⽣处理(涉及到空值时需要注意,结合业务)。可以通过四则运算、结合时间维度、PCA等模型的⽅法、结合业务知识等。
5.数据编码(确保数据可⼊模): 不同的模型对含有缺失值、字符型变量的容忍度各不相同,因此需要对数据做编码(可以看成数据清洗的⼀种)来适应不同的模型,确保模型的顺利训练。对于涉及计算距离的模型数据需要进⾏标准化/归⼀化处理;对分类变量可以进⾏one-hot(独热编码会导致维度急剧增加,可通过one-hot+PCA)、LaberEncoder、woe编码等;对于缺失值需要删除或者填充。
6.降维: 根据缺失率与同⼀值做初步剔除;单变量分析进⾏⼀波降维(包含分箱看趋势及IV等);PCA等降维模式;机器学习⽅法输出变量重要性等降维;变量相关性做降维。
7.模型调参、评估指标: 模型调参主要根据每个模型本⾝进⾏调参。主要涉及解决样本不平衡、过拟合与⽋拟合的问题。调参可以调⽤⽹格搜索、贝叶斯调参等⽅法。评估指标主要是根据不同的应⽤场景来确定具体的评估指标,例如A卡会关注模型衰减度(稳定性)、ROC、AUC、KS、swap分析等。
8.模型部署监控: 模型的监控⼀⽅⾯保证⽣产上顺利进⾏,另⼀⽅⾯是观察模型的效果。在信贷中A
卡⼀般监控:进件量、评分卡均值、评分卡分10档分组占⽐、评分PSI波动;变量均值、缺失率、PSI波动,变量分bin;后端:每周放款件及对应逾期率、auc、ks、Lift图、变量分bin、变量iv、变量TP图等
代码实现(以逻辑回归为例,重在解释流程)
导⼊相关模块
import pandas as pd
import Logistic_model as lm #⾃⼰定义的包,主要涉及EDA、等频分箱、卡⽅分箱、变量IV、⼀些树模型的变量重要性⾃动化
import os
os.chdir("E:/wyz/Desktop/模型学习/data/")
data = pd.read_excel("E:/wyz/Desktop/模型学习/data/data.xlsx")
数据清洗及降维
#eda
data_eda = lm.eda_data(data)
_csv('EDA.csv',encoding ='utf-8-sig')
#根据eda做清洗
data_drop = lm.eda_drop(data_eda,data,0.7,2,'target')
#单变量分箱(包含等频分箱和卡⽅分箱,需要⼿⼯挑选有效变量)
page = lm.single_variable(data_drop,'target',5,10,10)
#变量重要性分析(可以在单变量分箱之后,也可以拿全变量进⾏分析)
page = lm.variable_imp(data_drop,'target')
#相关性(变量较少可以直接运⾏,变量较多可以前⼏布降维后输出)
heatmap = lm.cor_chart(data_drop,'target')
woe编码(好处不需要填充缺失值不需要数据标准化)
#挑选出有效变量
data_drop_new = data_drop[['target','var1','var2','var3','var4','var5']]
#将变量进⾏woe编码
var1 =[0.82,0.849,0.928,11.795]
data_drop1 = lm.Con_data_process(data_drop_new,"var1",var1,'bin5')
var2 =[0.0788,0.108,0.176,27]
data_drop1 = lm.Con_data_process(data_drop1,"var2",var2,'bin4')
var3 =[-0.253,-0.0232,0.0291,2]
data_drop1 = lm.Con_data_process(data_drop1,"var3",var3,'bin1')
var4 =[0.0776,0.16,0.327,97]
data_drop1 = lm.Con_data_process(data_drop1,"var4",var4,'bin1')
var5 =[0.163673,0.334605,0.505539,0.678744,22]
data_drop1 = lm.Con_data_process(data_drop1,"var5",var5,'bin1')
#取出woe编码后的数据
data_model = data_drop1[['target','var1','var2','var3','var4','var5']]
检验多重共线性(在这步之后决定样本不平衡怎么处理)
from statsmodels.stats.outliers_influence import variance_inflation_factor
def vif_value(df):
vif = pd.DataFrame()
vif["VIF Factor"]=[variance_inflation_factor(df.values, i)for i in range(df.shape[1])]
vif["features"]= df.columns
return vif
vif_value(data_model.drop('target', axis=1))
模型训练(观察没通过假设性检验的变量)
from statsmodels.formula.api import ols
import statsmodels.api as sm#最⼩⼆乘
del_selection import train_test_split
data_model['intercept']=1#statsmodels需要价格截距项
y = data_model['target']
x = data_model.drop('target', axis=1)
x_train, x_test, y_train, y_test = train_test_split(x, y,random_state=0,train_size=0.7)
#训练模型
logit=sm.Logit(y_train,x_train)
model_logit=logit.fit()
#假设性检验输出
model_logit.summary()
评估指标(以AUC和KS为例)
ics import roc_auc_score
#计算ks
def cal_ks(y_true,y_pred,bins):
'''
y_true:真实标签
y_pred:预测的概率
bins:划分的组
'''
df1 = pd.DataFrame(y_true).join(pd.DataFrame(y_pred))
python新手代码及作用
factor1,bins1=pd.qcut(df1["score"],bins,retbins=True,precision=6,duplicates='drop')
bins =[]
bad_rate =[]
good_rate =[]
bad_total_num = df1.loc[df1.t7_cnt ==1].unt()
good_total_num = df1.loc[df1.t7_cnt ==0].unt()
for i in range(len(bins1[1:])):
bin_group ='bin'+str(i+1)
if i !=len(bins1[1:])-1:
bad_num = df1.loc[df1.score <= bins1[1:][i]].t7_cnt.sum()
good_num = df1.loc[df1.score <= bins1[1:][i]].unt()-df1.loc[df1.score <= bins1[1:][i]].t7_cnt.sum()
bins.append(bin_group)
bad_rate.append(bad_num/bad_total_num)
good_rate.append(good_num/good_total_num)
else:
bad_num = df1.loc[df1.score <=1].t7_cnt.sum()
good_num = df1.loc[df1.score <=1].unt()-df1.loc[df1.score <=1].t7_cnt.sum()
bins.append(bin_group)
bad_rate.append(good_num/good_total_num)
good_rate.append(good_num/good_total_num)
df2 = pd.DataFrame(bad_rate,index = bins,columns =['bad_rate']).join(pd.DataFrame(good_rate,index = bins,columns =['good_rate'])) df2["D_value"]= df2["good_rate"]- df2["bad_rate"]
ks =max(df2["D_value"])
return ks,df2
test_pre_pro = model.predict(x_test)#输出预测为1的概率(其它评估指标可能需要将概率转化为类别)
ks_test,ks_dataframe_test = lm.cal_ks(y_test,test_pre_pro,10)#计算ks
print('test_AUC: %.6f'%roc_auc_score(y_test,test_pre_pro))#AUC,预测为概率
print('ks_test: %.6f'%ks_test)
保存模型
als import joblib
# 保存模型
joblib.dump(model_logit,'Logistic.pkl')
读取模型并在样本上打分
#读取数据,⼀般都是原始数据
data_pre = pd.read_excel("E:/wyz/Desktop/论⽂/predict/pre_sample.xlsx") #将原始数据以训练集中相同⽅式woe编码
col_list =['var1','var2','var3','var4','var5']
data_pre_model= lm.woe_pre(data_pre ,5,col_list,'target')
#从本地读取模型
clf = joblib.load("Logistic.pkl")
#添加截距项并进⾏预测
data_pre_model['intercept']=1
clf.predict(data_pre_model)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论