信用评分系统运行原理中篇-分箱逻辑

本文深入解析信用评分系统中的自动分箱算法,通过Python代码演示如何使用斯皮尔曼等级相关系数进行分箱,并分析关键步骤,包括数据预处理、分箱逻辑及结果评估。同时介绍了rank和qcut等数据处理函数的应用。
摘要由CSDN通过智能技术生成

前言

本篇承接上篇

信用评分系统运行原理上篇

分箱逻辑比较复杂 设计到很多的算法

为了确保分析的准确性 我通过pycharm编译器Debug的方式跑这段代码

一步一步的分析代码的实现逻辑

编译器环境的准备

python代码准备

编译器配置

python依赖包安装

pip3 install numpy
pip3 install pandas
pip3 install matplotlib==3.2.0
pip3 install --target=./venv/lib/python3.7/site-packages seaborn
pip3 install ipython
pip3 install xlrd
pip3 install sklearn

代码逻辑分析

自动分箱


# 调用自定义分箱
dfx1, ivx1, cutx1, woex1 = mono_bin(train.SeriousDlqin2yrs, train.RevolvingUtilizationOfUnsecuredLines, n=10)


# 自定义自动分箱函数
def mono_bin(Y, X, n=20):
    r = 0
    # 好人个数 6936
    good = Y.sum()
    # 坏人个数 94957
    bad = Y.count() - good
    # np.abs(0)=0.9272727272727272m
    absR = np.abs(r)
    while absR < 1: # 满足循环条件 进入循环体
        # 先对训练集X排序 再分组
        dfX = X.rank(method="first")
        cutPd = pd.qcut(dfX, n)
        d1 = pd.DataFrame({"X": X, "Y": Y, "Bucket": cutPd}) # X.rank(method="first")
        d2 = d1.groupby("Bucket", as_index = True)
        d2Mean = d2.mean()
        d2MeanX = d2Mean.X
        r, p = stats.spearmanr(d2MeanX, d2.mean().Y) # 使用斯皮尔曼等级相关系数来评估两个变量之间的相关性
        n = n - 1
    d3 = pd.DataFrame(d2.X.min(), columns = ['min'])
    d3['min']=d2.min().X
    d3['max'] = d2.max().X
    d3['sum'] = d2.sum().Y
    d3['total'] = d2.count().Y
    d3['rate'] = d2.mean().Y
    d3['woe'] = np.log((d3['rate'] / (1-d3['rate'])) / (good/bad))
    d3['goodattribute'] = d3['sum'] / good
    d3['badattribute'] = (d3['total'] - d3['sum']) / bad
    iv = ((d3['goodattribute'] - d3['badattribute']) * d3['woe']).sum()
    d4 = (d3.sort_values(by = 'min'))
    print(d4)
    cut=[]
    cut.append(float('-inf'))
    for i in range(1, n+1):
        qua = X.quantile(i/(n+1))
        cut.append(round(qua,4))
    cut.append(float('inf'))
    woe = list(d4['woe'].round(3))
    return d4, iv, cut, woe
详细分析分箱逻辑
参数分析
  • train.SeriousDlqin2yrs 对应函数中的X值
61003     0
26974     0
64962     0
22271     0
21614     0
         ..
133033    0
123509    0
18246     0
28850     0
16172     0
第一列参数 表示 一行索引值 可以理解成唯一主键id
第二列参数 表示 真实值 0表示坏客户 ,1 表示好客户
  • train.RevolvingUtilizationOfUnsecuredLines 对应函数中的Y值
RevolvingUtilizationOfUnsecuredLines 信用卡和个人信用额度的总余额,除了房地产和没有分期付款债务,如汽车贷款除以信用额度
61003     0.119104
26974     0.042524
64962     0.067740
22271     0.866513
21614     1.000000
            ...   
133033    0.367954
123509    0.031879
18246     0.090163
28850     1.644518
16172     0.160312
第一列是行索引值
第二列表示总额度
函数实现逻辑分析
Y.sum() 表示好人总计
Y.count() 表示所有人
Y.count() - good 表示坏人个数


a、 循环初始条件:r = 0,n=10

b、 while循环条件:np.abs(r)<1

取绝对值

c-1、 循环过程中使用 斯皮尔曼等级相关系数 算法重新计算r值

c-2、 每次循环:n = n - 1

第一次循环: r=0

np.abs(0)==0 进入循环体

这个是对训练集X进行顺序排名 重复的值 谁出现在前面  就先排谁

X.rank(method="first")

这里简单介绍下 rank排名函数和qcut\cut函数

理解了这些函数的作用就可以更好的理解分箱算法对于数据处理的过程

  • rank函数

举一个简单的例子

有一个数据源 字段:班级、姓名、成绩
目的:找出每个班级中排名第二的学生信息

需要做的步骤:

1、根据班级分组
2、每个组计算排名
3、筛选出排名为第二的学生

此时对于相同成绩的同学如何排名

a 顺序排名 先到先得

李四和王五的成绩都为30,但是李四出现在王五的前面,所以李四的排名靠前

当method取值为min,max,average时,都是要参考“顺序排名”的)


b 密集排名:成绩相同 排名相同

相同成绩的同学排名相同,其他依次加1即可

1,2,2,3,4


c 跳跃排名:成绩相同 排名相同

1,2,2,4,5

成绩相同的同学,取在顺序排名中最小的那个排名作为该值的排名,李四和王五同学排名分别为2和3,那么当method为min时,取2和3的最小的那个作为第2名作为成绩30的排名

rank函数取值范围

‘average’,’first’,’min’, ‘max’,’dense’

min和max是跳跃排名的一种

关于average,成绩相同时,取顺序排名中所有名次之和除以该成绩的个数,即为该成绩的名次;比如上述排名中,30排名为2,3,那么 30的排名 = (2+3)/2=2.5,成绩为50的同学只有1个,且排名为1,那50的排名就位1/1=1。

​关于max,和min一样也是跳跃排名的一种,成绩相同时取顺序排名中排名最大的作为该成绩的名次,在顺序排名中,30最大的排名为3,那么当参数为max时,30的排名=3,此时,李四和王五的排名都为第3名了。
  • qcut函数

跟cut()按照变量的值对变量进行分割不同, qcut()是按变量的数量来对变量进行分割,并且尽量保证每个分组里变量的个数相同

例子:把数据由小到大分成四组,并且让每组数据的数量相同

# 把变量由小到大分成四组,并且让每组变量的数量相同
d_qcut = d.copy()
d_qcut['qcut_group'] = pd.qcut(d_qcut['number'], 4)
d_qcut

# 查看每个分组里变量的个数
d_qcut['qcut_group'].value_counts()

使用qcut()对数据进行分割之后,每个分组里的数据个数都大致相同,但是跟cut()不同的是,每个分组里值的范围并不相同

  • cut() 函数

按照指定的边界值对变量进行分割

# 使用bins参数, 指定每个分组的边界
d_cut_bins = d.copy()
d_cut_bins['cut_group'] = pd.cut(d_cut_bins['number'], 
                                bins=[0, 10, 50, 100])
d_cut_bins

继续信用评分系统 分箱代码分析

dfX = X.rank(method="first")
cutPd = pd.qcut(dfX, n)

n=10

对dfX 分10组 每组的数量大小一致

d1 = pd.DataFrame({"X": X, "Y": Y, "Bucket": cutPd}) 
d2 = d1.groupby("Bucket", as_index = True)
d2Mean = d2.mean()
d2MeanX = d2Mean.X

使用斯皮尔曼等级相关系数来评估两个变量之间的相关性

r, p = stats.spearmanr(d2MeanX, d2Mean.Y)
这个具体什么原理感兴趣的朋友 可以自己查阅一下资料
每个指标具体计算过程

min 最小值 d2.min().X
max 最大值 d2.max().X
total 总人数 d2.count().Y
sum 好人数 d2.sum().Y
rate 均值 d2.mean().Y
woe=np.log((d3['rate'] / (1-d3['rate'])) / (good/bad))

 (好人均值/坏人均值)/(好人人数/坏人人数) 取对数 即WOE
 
 goodattribute=d3['sum'] / good 每组好人数量/总的好人数
 
 badattribute=(d3['total'] - d3['sum']) / bad 每组坏人人数/坏人总人数
 
 iv = ((d3['goodattribute'] - d3['badattribute']) * d3['woe']).sum()
 
 d4 = (d3.sort_values(by = 'min'))
 通过min列排序
 

该分箱函数最终得到的结果

ivx1:  1.0027047570109968
cutx1:  [-inf, 0.0313, 0.1583, 0.5605, inf]
woex1:  [-1.37, -1.212, -0.288, 1.106]
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值