【综合案例】信用评分模型开发

一、案例背景

在上一篇文章网络贷款违约预测案例中,我们在分析属性关系时发现:FICO信用评分与分类标签之间存在极强的相关关系。如果说要选择一个属性来区分客户是否违约贷款的话,FICO评分是最理想之选。
FICO评分的主要思路是:对大量拥有多个属性的用户数据进行收集、分析、转换,使用各项统计指标对属性进行取舍、赋权、组合,最终得到一个量化的、综合的、可用于比对的分值。分值的高低既反映了用户历史信用记录的好坏,又暗示未来违约可能性的大小。
在这里插入图片描述
类似的,我们要对数据清洗之后才能进行模型训练和预测。其中,首先要重点说到的是数据分箱

二、前置知识

2.1 数据分箱

数据分箱就是将采集到的某一个属性的数据取值划分为若干段,落在同一个箱体范围内的数据,用一个统一的数字代替。例如,{1,2,3,4,5,6,7,8,9}这个数据集,若分为3段,则1:{1,2,3}、2:{4,5,6}、3:{7,8,9};取均值代替原来的数据,最终为:箱1:{2,2,2}、箱2:{5,5,5}、箱1:{8,8,8}。
数据分箱的目的是:变量变换到了相似的尺度上,便于比较;后续逻辑回归计算量减少,降低模型过拟合风险;模型更稳定,不会因为少量数据的变化导致结果大幅波动。

2.2 属性选择

在数据分析中,为了降低复杂度,往往要对数据集中的属性进行取舍,排除冗杂多余的属性,除了相关关系之外,还可以用Woe(迹象权重)和IV(信息值)指标来考察属性对目标变量的重要程度。
在这里插入图片描述
其中,pctlGood(pctlBad)表示好的、分类标签为正常的(坏的、分类标签为违约的)占所有的比重。
然后根据IV的取值来判断研究的属性与目标变量之间的关系:

IV 关系
(0,0.02) 极弱
[0.02,0.1)
[0.1,0.3) 一般
[0.3,0.5)
[0.5,1.0) 极强

最后,根据自己的需求,舍弃关系为弱以下或极弱的属性。

2.3 回归方程

由于信用评分是一个数值,二分类标签是正常/违约这样离散的量,因此需要用到之前逻辑回归中学习到的Sigmoid函数:
在这里插入图片描述
将连续值结果与阀值大小对比的结果转化为离散的分类标签,以此为基础得到用于计算信用评分的表达式。

三、数据处理

案例数据下载地址为:https://www.kaggle.com/c/GiveMeSomeCredit/data
数据包含11个属性:

变量名称 变量描述 数据类型
SeriousDlqin2yrs 逾期90天及以上 布尔值
RevolvingUtilizationOfUnsecuredLines 信用卡和个人信用额度的总余额除以总信用额度,除了房地产和没有分期付款债务,如汽车贷款 浮点型
age 借款人的年龄 整数型
NumberOfTime30-59DaysPastDueNotWorse 借款人逾期处于到期日后30-59天内的逾期次数 整数型
DebtRatio 每月还债、赡养费和生活费除以月总收入 浮点型
MonthlyIncome 月收入 整数型
NumberOfOpenCreditLinesAndLoans 贷款数量,如分期付款,汽车贷款或抵押贷款以及信用贷款(如信用卡) 整数型
NumberOfTimes90DaysLate 借款人逾期90天或以上的次数 整数型
NumberRealEstateLoansOrLines 抵押贷款和房地产贷款的数目,包括房屋净值信贷额度 整数型
NumberOfTime60-89DaysPastDueNotWorse 借款人逾期处于到期日后60-89天的逾期次数 整数型
NumberOfDependents 家庭中不包括自己的受抚养人数(配偶、子女等) 整数型

其中,第一项为分类标签,其他为变量参数。

3.1 数据清洗

首先,观察数据:

data = pd.read_csv('ch17_cs_training.csv')
print('原始数据概况:')
data.info()

在这里插入图片描述
发现部分属性数据缺失严重,需要进行处理:

from sklearn.ensemble import RandomForestRegressor
# 用随机森林对MonthlyIncome月收入缺失值进行预测填充
#参数:  df-Daraframe,Pandas数据框
#返回值:df-Daraframe,填充了MonthlyIncome缺失值的数据框
def set_missing(df):
#将第5列MonthlyIncome提前到第0列,便于后续划分数据
    print('随机森林回归填充0值:')
    process_df = df.iloc[:,[5,0,1,2,3,4,6,7,8,9]]
#分成有数值/缺失值两组
    known = process_df.loc[process_df['MonthlyIncome']!=0].values
    unknown = process_df.loc[process_df['MonthlyIncome']==0].values
    X = known[:, 1:]
    y = known[:, 0]
#用X,y训练随机森林回归算法
    rfr = RandomForestRegressor(random_state=0, n_estimators=200,max_depth=3,n_jobs=-1)
    rfr.fit(X,y)
#得到的模型进行缺失值预测
    predicted = rfr.predict(unknown[:, 1:]).round(0)
#用得到的预测结果填补原缺失数据
    df.loc[df['MonthlyIncome']==0, 'MonthlyIncome'] = predicted
    return df

这里选择了用随机森林回归算法对缺失值进行填充。

#离群点检测、删除,删除标准为:
#最小阈值=第一四分位点-1.5*(第三四分位点-第一四分位点)
#最大阈值=第三四分位点+1.5*(第三四分位点-第一四分位点)
#小于最小阈值,大于最大阈值的行将会被删除
#参数:  df-Daraframe,Pandas数据框
#       cname-字符串,进行离群点删除的列名
#返回值:df-Daraframe,完成了离群点检测删除的数据框
def outlier_processing(df,cname):
    s=df[cname]
    oneQuoter=s.quantile(0.25)
    threeQuote=s.quantile(0.75)
    irq=threeQuote-oneQuoter
    min=oneQuoter-1.5*irq
    max=threeQuote+1.5*irq
    df=df[df[cname]<=max]
    df=df[df[cname]>=min]
    return df

然后,定义函数对属性中的离群数据点(异常值)进行删除,如对MonthlyIncome列进行处理:

#对MonthlyIncome列进行数据整理
print('MonthlyIncome属性离群点原始分布:')
data[['MonthlyIncome']].boxplot()
plt.savefig('ch17_cs01.png', dpi=300, bbox_inches='tight')
plt.show()

print('删除离群点、填充缺失数据:')
data=outlier_processing(data,'MonthlyIncome')
data=set_missing(data)

print('处理MonthlyIncome后数据概况:')
data.info()
data[['MonthlyIncome']].boxplot()
plt.savefig('ch17_cs02.png', dpi=300, bbox_inches='tight')
plt.show()

在这里插入图片描述
在这里插入图片描述
同样,也可对其他的属性进行处理,但是如果处理之后发现被错误的删除大量的数据,则不能用函数处理,需要手工处理:

#以下三个属性取值过于集中,三个四分位点的值都相等。
#直接使用outlier_processing函数会导致所有取值被删除,
#因此观察分布后,手工处理
Features=['NumberOfTime30-59DaysPastDueNotWorse',
          'NumberOfTime60-89DaysPastDueNotWorse',
          'NumberOfTimes90DaysLate']
Features_labale=['30-59Days','60-89Days','90+Days']
print('NumberOfTime30-59DaysPastDueNotWorse,\
      NumberOfTime60-89DaysPastDueNotWorse,\
      NumberOfTimes90DaysLate原始分布:')
data[Features].boxplot()
plt.xticks([1,2,3],Features_labale)
plt.savefig('ch17_cs03.png', dpi=300, bbox_inches='tight')
plt.show()

print('删除离群点后:')
data= data[data['NumberOfTime30-59DaysPastDueNotWorse'] < 90]
data= data[data['NumberOfTime60-89DaysPastDueNotWorse'] < 90]
data= data[data['NumberOfTimes90DaysLate'] < 90]

data[Features].boxplot()
plt.xticks([1,2
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

貮叁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值