当前位置: 首页 > article >正文

机器学习与金融风控项目篇-day04-卡方分箱案例与模型的可解释性

案例-卡方分箱

数据集使用germancredit
  1. Toad 是专为工业界模型开发设计的Python工具包,特别针对评分卡的开发

  2. Toad 的功能覆盖了建模全流程,从EDA、特征工程、特征筛选到模型验证和评分卡转化

  3. Toad 的主要功能极大简化了建模中最重要最费时的流程,即特征筛选和分箱。

第一次使用toad,需要安装:

pip install toad==0.1.0 -i https://pypi.tuna.tsinghua.edu.cn/simple/

案例代码实现:

import pandas as pd
import numpy as np
import toad
​
data = pd.read_csv('../data/germancredit.csv')
data.replace({'good':0,'bad':1},inplace=True)
​
print(data.shape) # 1000 data and 20 features 
data.head()

显示结果

(1000, 21)

status.of.existing.checking.accountduration.in.monthcredit.historypurposecredit.amountsavings.account.and.bondspresent.employment.sinceinstallment.rate.in.percentage.of.disposable.incomepersonal.status.and.sexother.debtors.or.guarantors...propertyage.in.yearsother.installment.planshousingnumber.of.existing.credits.at.this.bankjobnumber.of.people.being.liable.to.provide.maintenance.fortelephoneforeign.workercreditability
0... < 0 DM6critical account/ other credits existing (not ...radio/television1169unknown/ no savings account... >= 7 years4male : singlenone...real estate67noneown2skilled employee / official1yes, registered under the customers nameyes0
10 <= ... < 200 DM48existing credits paid back duly till nowradio/television5951... < 100 DM1 <= ... < 4 years2female : divorced/separated/marriednone...real estate22noneown1skilled employee / official1noneyes1
2no checking account12critical account/ other credits existing (not ...education2096... < 100 DM4 <= ... < 7 years2male : singlenone...real estate49noneown1unskilled - resident2noneyes0
3... < 0 DM42existing credits paid back duly till nowfurniture/equipment7882... < 100 DM4 <= ... < 7 years2male : singleguarantor...building society savings agreement/ life insur...45nonefor free1skilled employee / official2noneyes0
4... < 0 DM24delay in paying off in the pastcar (new)4870... < 100 DM1 <= ... < 4 years3male : singlenone...unknown / no property53nonefor free2skilled employee / official2noneyes1
数据字段说明
  1. Status of existing checking account(现有支票帐户的存款状态)

  2. Duration in month(持续月数)

  3. Credit history(信用历史记录)

  4. Purpose(申请目的)

  5. Credit amount(信用保证金额)

  6. Savings account/bonds(储蓄账户/债券金额)

  7. Present employment since(当前就业年限)

  8. Installment rate in percentage of disposable income(可支配收入占比)

  9. Personal status and gender(个人婚姻状态及性别)

  10. Other debtors / guarantors(其他债务人或担保人)

  11. Present residence since(当前居民年限)

  12. Property(财产)

  13. Age in years(年龄)

  14. Other installment plans (其他分期付款计划)

  15. Housing(房屋状况)

  16. Number of existing credits at this bank(在该银行已有的信用卡数)

  17. Job(工作性质)

  18. Number of people being liable to provide maintenance for(可提供维护人数)

  19. Telephone(是否留存电话)

  20. foreign worker(是否外国工人)

  21. creditability数据标签

数据预处理
import pandas as pd
import numpy as np
import toad
from toad.plot import bin_plot
import os
os.chdir(r'D:\CodeProject\05JRFK_Project\my_project\day04-分箱和编码')
os.getcwd()
​
data = pd.read_csv('../data/germancredit.csv')
​
# 替换标签列, 0 for good, 1 for bad
data.replace({'good':0,'bad':1},inplace=True)
​
print(data.shape) # 1000 data and 20 features 
data.head()
分箱入门
# 初始化一个combiner类
combiner = toad.transform.Combiner()
​
# 训练数据并指定分箱方法,其它参数可选  # min_samples: 每箱至少包含样本量,可以是数字或者占比
combiner.fit(data,y='creditability',method='chi',min_samples = 0.05)
​
# 以字典形式保存分箱结果
bins = combiner.export()
# 分箱调整方式:
# 1. n_bins : 指定箱数
# 2. update/set_rules API
bins        # 字典类型(所有列)
​
#查看分箱结果
print('duration.in.month:', bins['duration.in.month'])
# duration.in.month: [9, 12, 13, 16, 36, 45]
调整分箱绘图

bin_plot, 用来查看分箱结果是否可行, 箱数是否设置合理

评判方式: 看bin_plot图是否单调, 只有单调才具有可解释性

from toad.plot import bin_plot
c2 = toad.transform.Combiner()
c2.fit(data[['duration.in.month', 'creditability']], y='creditability', method='chi', n_bins=5)# 调整指定箱数调整分箱结果
transformed = c2.transform(data[['duration.in.month', 'creditability']], labels=True)
bin_plot(transformed, x='duration.in.month', target='creditability')
# bin_plot, 用来查看分箱结果是否可行, 箱数是否设置合理
# 评判方式: 看bin_plot图是否单调, 只有单调才具有可解释性
其他分箱方式

分箱方式介绍

chi:卡方分箱

dt:决策树分箱

quantile:等频分箱

step:等距分箱

kmeans:KMeans分箱

for method in ['chi', 'dt', 'quantile', 'step', 'kmeans']:
    c2 = toad.transform.Combiner()
    c2.fit(data[['duration.in.month', 'creditability']],
           y='creditability', method=method, n_bins=5)
    bin_plot(c2.transform(data[['duration.in.month', 'creditability']], labels=True),
             x='duration.in.month', target='creditability')

编码

编码方式:one-hot: 热编码, label: 标签编码WOE: Weight of Evidence: 风控下常用, 计算方式引入了正负样本比例

WOE Encoding

WOE(Weight of Evidence) 反映单特征在好坏用户区分度的度量,WOE编码是一种用于二分类问题的编码方法,通过计算每个类别的证据权重来表示其与目标变量之间的关系。

优势:WOE越大,bad rate越高,也就是说,通过WOE变换,特征值不仅仅代表一个分类,还代表了这个分类的权重。WOE可以把相对于bad rate显现非线性的特征转换为线性的,且对波动不敏感。遇到异常数据亦能平稳表现。

应用场景:该方法通常用于分类建模中的特征工程,特别是在信用风险评估、营销模型和欺诈检测等领域。该方法的目标是将分类变量转换为数值变量,以便在统计建模中使用。

计算公式:

好用户比例/坏用户比例

婚姻状态GoodBadG-Bln(G/B)WOE
未婚30%20%10%0.4050.405
已婚40%10%30%1.3861.386
离异10%40%-30%-1.386-1.386
丧偶20%30%-10%-0.405-0.405
总计100%100%
toad计算woe
数据准备
from sklearn.model_selection import train_test_split
​
x_train, x_test, y_train, y_test= train_test_split(data.drop('creditability', axis=1), data['creditability'], test_size=0.25, random_state=450)
#%%
# 拼接训练集和测试集
data_train = pd.concat([x_train, y_train], axis=1)
data_test = pd.concat([x_test, y_test], axis=1)
data_train['type'] = 'train'
data_test['type'] = 'test'
#%%
data_train
分箱(调整前)
c2 = toad.transform.Combiner()
adj_bins = {'duration.in.month': [9, 12, 18, 33]}
c2.set_rules(adj_bins)
#%%
data_ = pd.concat([data_train, data_test])
temp_data = c2.transform(data_[['duration.in.month', 'creditability', 'type']], labels=True)
#%%
from toad.plot import badrate_plot
from toad.plot import proportion_plot
​
badrate_plot(temp_data, by='duration.in.month', target='creditability', x='type')
proportion_plot(temp_data['duration.in.month'])
分箱(调整后)
# 假定将第一箱、第二箱合并
adj_bin = {'duration.in.month': [9,18,33]}
c2.set_rules(adj_bin)
​
temp_data = c2.transform(data_[['duration.in.month','creditability','type']])
badrate_plot(temp_data, target = 'creditability', x = 'type', by = 'duration.in.month')
proportion_plot(temp_data['duration.in.month'])
计算WOE
binned_data = c2.transform(data_train)
​
transfer = toad.transform.WOETransformer()
data_woe_result = transfer.fit_transform(binned_data, binned_data['creditability'], exclude=['creditability', 'type'])
data_woe_result.head()
显示结果
status.of.existing.checking.accountduration.in.monthcredit.historypurposecredit.amountsavings.account.and.bondspresent.employment.sinceinstallment.rate.in.percentage.of.disposable.incomepersonal.status.and.sexother.debtors.or.guarantors...age.in.yearsother.installment.planshousingnumber.of.existing.credits.at.this.bankjobnumber.of.people.being.liable.to.provide.maintenance.fortelephoneforeign.workercreditabilitytype
5690.7863130.7866220.069322-0.3841250.3331520.2448020.002898-0.0563410.3550580.0...0.085604-0.157497-0.1744410.0394850.0026480.0128220.0017220.0437421train
5740.363027-0.2797290.069322-0.384125-0.1594080.244802-0.1733260.154169-0.2123560.0...0.085604-0.157497-0.174441-0.071350-0.2984670.012822-0.0011300.0437420train
9930.7863130.7866220.0693220.1414840.3331520.2448020.5345270.154169-0.2123560.0...0.085604-0.157497-0.1744410.0394850.3113830.0128220.0017220.0437420train
3550.3630270.0998120.0693220.272947-0.1594080.2448020.3993130.154169-0.2123560.0...0.5469490.605057-0.1744410.039485-0.2984670.012822-0.0011300.0437421train
508-1.0729600.0998120.069322-0.384125-0.1594080.2448020.0028980.154169-0.3024470.0...0.085604-0.157497-0.1744410.0394850.0026480.012822-0.0011300.0437420train

  1. WOE理解:当前组中好用户和坏用户的比值与所有样本中这个比值的差异。差异通过对这两个比值取对数来表示

    WOE越大,差异越大,这个分组里的好用户的可能性就越大

    WOE越小,差异越小,这个分组里的好用户的可能性也就越小。

  2. 分箱结果对WOE结果有直接影响,分箱不同,WOE映射值也会有很大的不同

    箱的总数在5~10箱(可以适当调整,通常不超过10箱)

    并且将每一箱之间的负样本占比差值尽可能大作为箱合并的基本原则

    每一箱的样本量不能小于整体样本的5%,原则是每一箱的频数需要具有统计意义

  3. 三种encoding的利弊

优势劣势
Onehot Encoding简单易处理、稳定、无需归一化、不依赖历史数据数据过于稀疏
Label Encoding区分效果好,维度小需统计历史数据、不稳定、需要归一化
WOE Encoding区分效果好,维度小,不需要归一化需统计历史数据、不稳定

案例总结

  1. 分箱:

    创建对象

    c = toad.transform.Combiner()

    分箱, n_bins指定分箱的数量

    c.transform(n_bins=xxx)

    调整分箱

    c.set_rules()/ c.update()

  2. 编码

    创建对象

    transfer = toad.transform.WOETransformer()

    WOE编码

    transfer.fit_transform()

可解释性

信贷业务的特征要求

  1. 逻辑简单

  2. 有强业务解释性

  3. 容易构造

  4. 容易排查错误

模型的可解释性没有准确的定义,凡是可以协助人理解模型决策过程和结果的方法,都可称之为模型的可解释性。

我们常说一个模型是“黑盒”模型,就是指该模型可解释性差。模型的构建者和使用者无法准确梳理模型的决策依据。

如果某个模型可解释性好,则是说我们能通过某些方法理解模型结果产生的逻辑。

一般来说,算法越复杂,一般精度越好,可解释性越差。

按照可解释性的强弱关系,将算法分类如下:

  • 第一梯度:线性回归、逻辑回归

  • 第二梯度:集成学习(结果是多个树共同决定的)

  • 第三梯度:支持向量机(把数据往高维空间映射,数据会失真)

  • 第四梯队: 深度学习

结论: 在本项目中, 可以选择的算法有: 逻辑回归(输出违约的概率), 集成学习


http://www.kler.cn/news/368893.html

相关文章:

  • SSM-Springboot笔记(2)- SpringBoot常用开发技能
  • Docker中如何控制服务启动顺序实现探讨
  • LeetCode 107.二叉树的层次遍历 II
  • Kafka如何控制消费的位置?
  • 使用注解@ExcelIgnoreUnannotated实现了在导出 Excel 时忽略没有被标注的字段
  • centos7 使用yum卸载redis3.2版本并安装redis5版本
  • 使用SQL在PostGIS中创建各种空间数据
  • 极狐GitLab 17.5 发布 20+ 与 DevSecOps 相关的功能【二】
  • ArcGIS计算多个面要素范围内栅格数据各数值的面积
  • NLP自然语言处理中的Attention机制原理揭秘
  • 创新业态下金融头部机构在 FICC 平台建设上的思考与实践
  • Python实现贝叶斯优化器(Bayes_opt)优化简单循环神经网络回归模型(SimpleRNN回归算法)项目实战
  • 秦时明月2搭建笔记
  • Isaac Sim Docker 部署并使用过程记录
  • 《战场车辆及部件损毁识别与评估的神经网络迁移训练》
  • Clickhouse笔记(二) 集群搭建
  • 【Golang】Go语言中如何进行包管理
  • 新品发布:Manus Metagloves Pro虚拟现实手套
  • 蓝桥杯 单片机 DS1302和DS18B20
  • 大数据Azkaban(二):Azkaban简单介绍
  • 【随便聊聊】MySQL数据类型详解:从基础到高级应用
  • 新华三H3CNE网络工程师认证—OSPF路由协议
  • NLP实践项目1——判断推文的负面情绪
  • C++的 / 运算符
  • 如何构建一个支持GPU的Llamafile容器
  • 【知识科普】正则表达式深入解读