前言:
现在大家对“pythonwoe”大体比较着重,各位老铁们都想要知道一些“pythonwoe”的相关资讯。那么小编同时在网摘上搜集了一些有关“pythonwoe””的相关内容,希望大家能喜欢,大家快快来了解一下吧!分箱逻辑
前言
本篇承接上篇
信用评分系统运行原理上篇
分箱逻辑比较复杂 设计到很多的算法
为了确保分析的准确性 我通过pycharm编译器Debug的方式跑这段代码
一步一步的分析代码的实现逻辑
编译器环境的准备python代码准备编译器配置python依赖包安装
pip3 install numpypip3 install pandaspip3 install matplotlib==3.2.0pip3 install --target=./venv/lib/python3.7/site-packages seabornpip3 install ipythonpip3 install xlrdpip3 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 026974 064962 022271 021614 0 ..133033 0123509 018246 028850 016172 0
第一列参数 表示 一行索引值 可以理解成唯一主键id第二列参数 表示 真实值 0表示坏客户 ,1 表示好客户train.RevolvingUtilizationOfUnsecuredLines 对应函数中的Y值
RevolvingUtilizationOfUnsecuredLines 信用卡和个人信用额度的总余额,除了房地产和没有分期付款债务,如汽车贷款除以信用额度
61003 0.11910426974 0.04252464962 0.06774022271 0.86651321614 1.000000 ... 133033 0.367954123509 0.03187918246 0.09016328850 1.64451816172 0.160312
第一列是行索引值第二列表示总额度函数实现逻辑分析
Y.sum() 表示好人总计Y.count() 表示所有人Y.count() - good 表示坏人个数a、 循环初始条件:r = 0,n=10b、 while循环条件:np.abs(r)<1取绝对值c-1、 循环过程中使用 斯皮尔曼等级相关系数 算法重新计算r值c-2、 每次循环:n = n - 1第一次循环: r=0np.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().Xmax 最大值 d2.max().Xtotal 总人数 d2.count().Ysum 好人数 d2.sum().Yrate 均值 d2.mean().Ywoe=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.0027047570109968cutx1: [-inf, 0.0313, 0.1583, 0.5605, inf]woex1: [-1.37, -1.212, -0.288, 1.106]
标签: #pythonwoe