risk-jianmo整体流程梳理

2024-01-23 09:04
文章标签 流程 整体 梳理 risk jianmo

本文主要是介绍risk-jianmo整体流程梳理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 加载数据与探索

1. 数据探索

from sklearn.metrics import roc_auc_score, roc_curve, auc  
from sklearn.model_selection import train_test_split  
from sklearn.linear_model import LogisticRegression   
import numpy as np
import xgboost as xgb  
import toad, math df = pd.read_csv("scorecard.txt")  
# 探索性数据分析
toad.detector.detect(df) 

2. 样本切分

ex_lis = ['uid', 'samp_type', 'label']  # 指定不参与训练列名  
ft_lis = list(df.columns)  # 参与训练列名  
for i in ex_lis:      ft_lis.remove(i) 
# 开发样本、验证样本与时间外样本(验证样本)  
dev = df[(df['samp_type']=='dev')]
val = df[(df['samp_type']=='val')]  
off = df[(df['samp_type']=='off')] 

2. 特征筛选

      可以使用缺失率、IV、相关系数进行特征筛选。但是考虑到后续建模过程要对变量进行分箱处理,该操作会使变量的IV变小,变量间的相关性变大,因此此处可以对IV和相关系数的阈值限制适当放松,或不做限制。

dev_slct1, drop_lst= toad.selection.select(dev, dev['label'], empty=0.7, iv=0.03, corr=0.7, return_drop=True, exclude=ex_lis) 
print("keep:", dev_slct1.shape[1],  "drop empty:", len(drop_lst['empty']), "drop iv:", len(drop_lst['iv']),  "drop corr:", len(drop_lst['corr']))
# keep: 12; drop empty: 0; drop iv: 1; drop corr: 0

3. 卡方分箱

combiner = toad.transform.Combiner()  # 得到切分节点  
combiner.fit(dev_slct1, dev_slct1['label'], method='chi', min_samples=0.05, exclude=ex_lis)   
bins = combiner.export()  # 导出分箱的节点 
print(bins)
{'td_score': [0.7989831262724624],'jxl_score': [0.4197048501965005],'mj_score': [0.3615303943747963],'zzc_score': [0.4469861520889339],'zcx_score': [0.7007847486465795],'person_info': [-0.2610139784946237, -0.1286774193548387, -0.05371756272401434, 0.013863440860215051, 0.06266021505376344, 0.07885304659498207],'finance_info': [0.047619047619047616],'credit_info': [0.02, 0.04, 0.11],'act_info': [0.1153846153846154, 0.14102564102564102, 0.16666666666666666, 0.20512820512820512, 0.2692307692307692, 0.35897435897435903, 0.3974358974358974, 0.5256410256410257]
}

4. Bivar图&分箱调整

      画图观察每个变量(以单变量act_info为例)在开发样本和时间外样本上的Bivar图。

dev_slct2 = combiner.transform(dev_slct1)  # 根据节点实施分箱
val2 = combiner.transform(val[dev_slct1.columns])
off2 = combiner.transform(off[dev_slct1.columns])
# 分箱后通过画图观察  
from toad.plot import bin_plot, badrate_plot  
bin_plot(dev_slct2, x='act_info', target='label')  
bin_plot(val2, x='act_info', target='label')  
bin_plot(off2, x='act_info', target='label') 

      由于前3箱的变化趋势与整体不符(整体为递减趋势),因此需将其合并(第4~6箱合并,最后3箱进行合并),从而得到严格递减的变化趋势。

print(bins['act_info'])
# [0.115,0.141,...,0.525]
adj_bin = {'act_info': [0.166,0.3589,]}  
combiner.set_rules(adj_bin)
dev_slct3 = combiner.transform(dev_slct1)
val3 = combiner.transform(val[dev_slct1.columns])
off3 = combiner.transform(off[dev_slct1.columns])
# 画出Bivar图
bin_plot(dev_slct3, x='act_info', target='label')  
bin_plot(val3, x='act_info', target='label')  
bin_plot(off3, x='act_info', target='label') 

5. 绘制负样本占比关联图

data = pd.concat([dev_slct3,val3,off3], join='inner')   
badrate_plot(data, x='samp_type', target='label', by='act_info')  

      图中的线没有交叉,不需要对该特征的分组进行合并,即使有少量交叉也不会对结果造成明显的影响,只有当错位比较严重的情况下才进行调整。

6. WOE编码,并验证IV

计算训练样本与测试样本的PSI

t = toad.transform.WOETransformer()  
dev_slct3_woe = t.fit_transform(dev_slct3, dev_slct3['label'], exclude=ex_lis) 
val_woe = t.transform(val3[dev_slct3.columns])  
off_woe = t.transform(off3[dev_slct3.columns])  
data = pd.concat([dev_slct3_woe, val_woe, off_woe])psi_df = toad.metrics.PSI(dev_slct3_woe, val_woe).sort_values(0)  
psi_df = psi_df.reset_index()  
psi_df = psi_df.rename(columns = {'index': 'feature', 0: 'psi'}) 
print(psi_df)

      删除PSI大于0.1的特征(通常单个特征的PSI值建议在0.1以下),根据具体情况可以适当调整。

psi_013 = list(psi_df[psi_df.psi<0.1].feature) 
psi_013.extend(ex_lis)  # 避免不参与计算的几个特征被删掉,把uid,samp_type,label添加回来并去重
psi_013 = list(set(psi_013)) 
data = data[psi_013]    
dev_woe_psi, val_woe_psi, off_woe_psi = dev_slct3_woe[psi_013], val_woe[psi_013], off_woe[psi_013] 
print(data.shape)
# (95806, 11)

      卡方分箱后部分变量的IV降低,且整体相关程度增大,需要再次筛选特征。

dev_woe_psi2, drop_lst = toad.selection.select(dev_woe_psi,dev_woe_psi['label'], empty=0.6, iv=0.001, corr=0.5, return_drop=True, exclude=ex_lis)  
print("keep:", dev_woe_psi2.shape[1],  "drop empty:", len(drop_lst['empty']),  "drop iv:", len(drop_lst['iv']),  "drop corr:", len(drop_lst['corr'])) 

7. 特征筛选

       使用逐步回归进行特征筛选,使用线性回归模型,并选择KS作为评价指标

1. estimator: 用于拟合的模型,支持'ols', 'lr', 'lasso', 'ridge';

2. direction: 逐步回归的方向,支持'forward', 'backward', 'both' (推荐);

(1)Forward selection

        将自变量逐个引入模型,引入一个自变量后查看该模型是否发生显著性变化,如果发生了显著性变化,那么则将该变量引入模型中,否则忽略该变量,直至遍历所有变量;即将变量按照贡献度从大到小排列,依次加入。

(2)Backward elimination:

        与Forward selection选择相反,将所有变量放入模型, 尝试将某一变量进行剔除,查看剔除后对整个模型是否有显著性变化,如没有显著性变化则剔除,有则保留,直到留下所有对模型有显著性变化的因素;也就是将自变量按贡献度从小到大,依次剔除。

(3)both:将前向选择与后向消除同时进行

        模型中每加入一个自变量,可能使某个已放入模型的变量显著性减小,显著性小于阈值时,可将该变量从模型中剔除;即每增加一个新的显著变量的同时,检验模型中所有变量的显著性,剔除不显著变量,从而得到最优变量组合。

3. criterion: 评判标准,支持'aic'、'bic'、'ks'、 'auc';

4. max_iter: 最大循环次数;

5. return_drop: 是否返回被剔除的列名;

6. exclude: 不需要被训练的列名,比如ID列和时间列。

dev_woe_psi_stp = toad.selection.stepwise(dev_woe_psi2, dev_woe_psi2['label'], exclude=ex_lis, direction='both', criterion='ks', estimator='ols', intercept=False)  
val_woe_psi_stp = val_woe_psi[dev_woe_psi_stp.columns]  
off_woe_psi_stp = off_woe_psi[dev_woe_psi_stp.columns]  
data = pd.concat([dev_woe_psi_stp, val_woe_psi_stp, off_woe_psi_stp]) 
print(data.shape)
print(dev_woe_psi_stp.columns)  # 查看剩下的特征列

8. 模型训练

1. 模型训练及评估画图

def xgb_model(x, y, valx, valy, offx, offy, C):  # model = LogisticRegression(C=C, class_weight='balanced')  model = xgb.XGBClassifier(learning_rate=0.05, n_estimators=400,  max_depth=2, class_weight='balanced', min_child_weight=1,  subsample=1, nthread=-1, scale_pos_weight=1,  random_state=1, n_jobs=-1, reg_lambda=300)      model.fit(x,y)  y_pred = model.predict_proba(valx)[:,1]  fpr_val, tpr_val, _ = roc_curve(valy, y_pred)  val_ks = abs(fpr_val - tpr_val).max()  print('val_ks: ', val_ks)  from matplotlib import pyplot as plt  plt.plot(fpr_val, tpr_val, label='val')  plt.plot([0,1], [0,1], 'k--')  plt.xlabel('False positive rate')  plt.ylabel('True positive rate')  plt.title('ROC Curve')  plt.legend(loc='best')  plt.show() 

    2. 定义函数调用模型训练的方法

def bi_train(data, dep='label', exclude=None):  from sklearn.preprocessing import StandardScaler  std_scaler = StandardScaler()  lis = list(data.columns)  # 变量名  for i in exclude:  lis.remove(i)  data[lis] = std_scaler.fit_transform(data[lis])  devv = data[(data['samp_type']=='dev')] vall = data[(data['samp_type']=='val')] offf = data[(data['samp_type']=='off')]x, y = devv[lis], devv[dep]valx, valy = vall[lis], vall[dep]offx, offy = offf[lis], offf[dep]# XGBoost正向xgb_model(x, y, valx, valy, offx, offy) # XGBoost反向xgb_model(offx, offy, valx, valy, x, y)  

      正向调用通过对开发样本的学习得到模型,并在时间外样本上检验效果;逆向调用使用时间外样本作为训练集,检验当前模型的效果上限;如逆向模型训练集KS值明显小于正向模型训练集KS值,说明当前时间外样本分布与开发样本差异较大,需要重新划分样本集。(样本量较小时经常发生)

9. 模型评估

from toad.metrics import KS, F1, AUC 
prob_val = lr.predict_proba(valx)[:,1]  
print('跨时间')  
print('F1:', F1(prob_val,valy))  
print('KS:', KS(prob_val,valy))  
print('AUC:', AUC(prob_val,valy)) 
print('模型PSI: ', toad.metrics.PSI(prob_val, prob_val))  
print('特征PSI: ', toad.metrics.PSI(x, offx).sort_values(0))  

    生成模型时间外样本的KS报告 

toad.metrics.KS_bucket(prob_off, offy, bucket=15, method='quantile') 

    10. 生成评分卡

    将数据集合并后,利用ScoreCard函数重新训练并生成评分卡。

1. 参数 C 为'正则化强度';

2. transer: 传入先前训练的 toad.WOETransformer 对象;

3. base_odds=20,base_score=750 实际意义为当比率为1/20,输出基准评分750,当比率为基准比率2倍时,基准分下降60分。

from toad.scorecard import ScoreCard  
card = ScoreCard(combiner=combiner, transer=t, C=0.1, class_weight='balanced',  base_score=600, base_odds=35, pdo=60, rate=2)  
card.fit(x,y)  
print(card.export(to_frame=True) )

 
 

         

这篇关于risk-jianmo整体流程梳理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/635901

相关文章

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

springboot启动流程过程

《springboot启动流程过程》SpringBoot简化了Spring框架的使用,通过创建`SpringApplication`对象,判断应用类型并设置初始化器和监听器,在`run`方法中,读取配... 目录springboot启动流程springboot程序启动入口1.创建SpringApplicat

通过prometheus监控Tomcat运行状态的操作流程

《通过prometheus监控Tomcat运行状态的操作流程》文章介绍了如何安装和配置Tomcat,并使用Prometheus和TomcatExporter来监控Tomcat的运行状态,文章详细讲解了... 目录Tomcat安装配置以及prometheus监控Tomcat一. 安装并配置tomcat1、安装

MySQL的cpu使用率100%的问题排查流程

《MySQL的cpu使用率100%的问题排查流程》线上mysql服务器经常性出现cpu使用率100%的告警,因此本文整理一下排查该问题的常规流程,文中通过代码示例讲解的非常详细,对大家的学习或工作有一... 目录1. 确认CPU占用来源2. 实时分析mysql活动3. 分析慢查询与执行计划4. 检查索引与表

Git提交代码详细流程及问题总结

《Git提交代码详细流程及问题总结》:本文主要介绍Git的三大分区,分别是工作区、暂存区和版本库,并详细描述了提交、推送、拉取代码和合并分支的流程,文中通过代码介绍的非常详解,需要的朋友可以参考下... 目录1.git 三大分区2.Git提交、推送、拉取代码、合并分支详细流程3.问题总结4.git push

C#提取PDF表单数据的实现流程

《C#提取PDF表单数据的实现流程》PDF表单是一种常见的数据收集工具,广泛应用于调查问卷、业务合同等场景,凭借出色的跨平台兼容性和标准化特点,PDF表单在各行各业中得到了广泛应用,本文将探讨如何使用... 目录引言使用工具C# 提取多个PDF表单域的数据C# 提取特定PDF表单域的数据引言PDF表单是一

PyCharm接入DeepSeek实现AI编程的操作流程

《PyCharm接入DeepSeek实现AI编程的操作流程》DeepSeek是一家专注于人工智能技术研发的公司,致力于开发高性能、低成本的AI模型,接下来,我们把DeepSeek接入到PyCharm中... 目录引言效果演示创建API key在PyCharm中下载Continue插件配置Continue引言

使用MongoDB进行数据存储的操作流程

《使用MongoDB进行数据存储的操作流程》在现代应用开发中,数据存储是一个至关重要的部分,随着数据量的增大和复杂性的增加,传统的关系型数据库有时难以应对高并发和大数据量的处理需求,MongoDB作为... 目录什么是MongoDB?MongoDB的优势使用MongoDB进行数据存储1. 安装MongoDB

Python实现NLP的完整流程介绍

《Python实现NLP的完整流程介绍》这篇文章主要为大家详细介绍了Python实现NLP的完整流程,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 编程安装和导入必要的库2. 文本数据准备3. 文本预处理3.1 小写化3.2 分词(Tokenizatio