本站原创文章,转载请说明来自《老饼讲解-机器学习》www.bbbdata.com
在实现评分卡时,需要先对变量进行分箱,在实践项目中一般以手动分箱为主
本文讲解如何对变量进行手动分箱,并展示一步一步的分析与调整过程,以及具体代码实现
通过本文,可以了解在实现评分卡时,是如何对变量进行手动分箱的,以及如何用代码来实现
本节通过对rev变量的分箱,来展示评分卡中变量分箱的具体操作过程
评分卡变量分箱-数据初步探索
在实际项目中,评分卡一般以手动分箱为主,这是为了使得分箱更具可解释性
下面以bbbrisk的小贷数据中的rev变量为例,展示具体是如何手动分箱的
rev变量是一个数值变量,它的意义为:信贷余额占比,即待还余额/总信贷余额
数据探索
在正式分箱中,一般先对数据进行粗略分箱,试探变量的badRate趋势 、了解数据的分布
由于rev是数值变量,不妨先用等距分箱,将它分为10个分箱,结果如下:
可以看到,样本大部分都集中在了第1个分组,即<=1830,而>1830的样本相对较少
因此,我们尝试将<=1830进一步等距分为10个箱,而>1830独立作为一个分箱
但实际上会发现数据还是大部分集中在其中一个分箱中,所以需要按以上思路继续调整
最终为调整的结果如下:
它的分箱结果如下:
![]()
通过以上分箱,我们可以大概地了解rev变量的分布情况,以及badrate的趋势
通过初步观察可以发现随着rev提升,badrate在大趋势上也增大,因此,rev变量是有效的
评分卡变量分箱-正式分箱
由于从初探结果中可知,rev变量是有效的,因此我们对对rev变量进行更细致的分箱
分箱的过程是逐步进行的,使得分箱结果逐步更加合理,具体如下
正式分箱
通过观察初探结果表,我们将badrate较近似的一段划为一组,作为初步分箱
初步分箱结果如下:
![]()
可以看到,badrate并不是单调的,这主要是第0组(x<=0)与第6组(x>2)较为特殊
因此,第0组与第2组badrate相似,我们将它合并,同理,将第6组与与第4组合并
这里的合并是需要有业务解释支撑的,详见下文的解释
最终分箱结果如下:
![]()
从结果可以看到,变量的badrate单调且有区分度,即组与组之间的badrate差异较明显
而IV值为1.088,它远大于0.3,说明该变量对y极有区分度,因此该变量是一个"较强的变量"
业务解释
在进行分箱后,还需要进一步从业务逻辑来判断它分箱是否合理
从分箱结果可以看到,有微小rev的人群最好,而随着rev越大,badrate也在增大
从业务来上看,就是待还余额占比越大,越容易逾期,因此,分箱是符合业务逻辑的
比较需要注意的是,rev=0与rev>2是两种特殊情况,对它们的业务解释如下:
1. rev=0时,会比微小rev逾期概率较大一些
因为rev为0可能是因为该客户没有信用卡,而微小rev则代表客户一定有信用卡
因此没用过信用卡的人可能缺少信贷概念,自然就会比用过信用卡的人要差一些
2. rev>2时,反而比rev在(1.2,2]的更好一些
rev>1时,在贷额度比授信额度还要大,这代表客户的信贷额度被缩减了
而rev极大,则代表客户在贷额度也较大,即曾经的授信额度较大,即曾经质量很好
所以,曾经质量较好的客户(rev>2),会比一般授信缩减客户的质量要好一些
备注:这些业务解释未必是唯一的、绝对合理的,但至少要存在一个说得通的解释
本节展示上节变量分箱过程中,所有的代码实现
rev变量分箱的代码示例
上述的分箱过程只是一种思路,它可以使用任意编程软件实现
在bbbrisk中,上述分箱过程的实现代码如下:
import bbbrisk as br
from bbbrisk import bins
# 加载数据
data = br.datasets.load_bloan() # 加载数据
x = data['rev'] # rev变量
y = data['is_bad'] # 标签
br.display.pd.set(width=300,max_colwidth=30,max_rows=30) # 美化pandas的显示方式
# 将变量等距分为10个箱
bin_set = bins.merge.eDist(x,10) # 将变量进行等距分箱
bin_stat = bins.Bins(bin_set).binStat(x,y) # 统计分箱结果
print('\n',bin_stat) # 显示分箱结果
# 将变量在(-inf,1830]等距分为10个箱,(1830,+inf]分为1个箱
bin_set = bins.merge.eDist(x,[('-',1830,10),(1830,'+',1)]) # 将变量进行等距分箱
bin_stat = bins.Bins(bin_set).binStat(x,y) # 统计分箱结果
print('\n',bin_stat) # 显示分箱结果
# 将变量在(-inf,0]分为1一个箱,(0,0.1]等距分为5个箱,(0.1,1]等距分为10个箱...
bin_set = bins.merge.eDist(x,[('-',0,1),(0,0.1,5),(0.1,1,10),(1,2,5),(2,'+',1)]) # 将变量进行等距分箱
bin_stat = bins.Bins(bin_set).binStat(x,y) # 统计分箱结果
print('\n',bin_stat) # 显示分箱结果
# 将变量分箱为(-inf,0],(0,0.1],(0.1,0.37],(0.37,0.64],(0.64,1.2],(1.2,2],(2,inf]
bin_set = [['-',0],[0,0.1],[0.1,0.37],[0.37,0.64],[0.64,1.2],[1.2,2],[2,'+']] # 设置变量的分箱
bin_stat = bins.Bins(bin_set).binStat(x,y) # 统计分箱结果
print('\n',bin_stat) # 显示分箱结果
# 将变量分箱为(0,0.1],(-inf,0]或(0.1,0.37],(0.37,0.64],(0.64,1.2]或(2,inf],(1.2,2]
bin_set = [[0,0.1],(['-',0],[0.1,0.37]),[0.37,0.64],([0.64,1.2],[2,'+']),[1.2,2]] # 设置变量的分箱
bin_stat = bins.Bins(bin_set).binStat(x,y) # 统计分箱结果
print('\n',bin_stat) # 显示分箱结果
运行结果如下:
![]()
这就是上节中各种分箱的结果了,在实际过程中,一般是通过一步一步的调整来得到
好了,以上就是如何使用bbbrisk来进行分箱的步骤与代码了~
End