1 信用评分卡模型简介
信用评分卡是一个通过个人数据对其还款能力、还款意愿进行定量评估的系统。在消费金融行业,信用评分卡主要有三种(A、B、C卡):
A卡:申请评分卡,贷前阶段使用,在客户获取期,建立信用风险评分,预测客户带来违约风险的概率大小;
B卡:行为评分卡,贷中阶段引入,在客户借款处理期,建立申请风险评分模型,预测客户违约拖欠的风险概率,我们的B卡采用的是T+1离线计算出来的,针对复借用户特别有效,针对首借用户,B卡自动转为申请评分;B卡另外的价值还在于用户授信到借款之间的时间比较长的话,通过B卡能计算用户最近的信用情况,有效阻止“好人变坏”的情形。
C卡:催收评分卡,侧重贷后,在帐户管理期,建立催收评分模型,预测用户逾期的概率,从而采取合适的催收措施,经验表明,在预测用户逾期7天的概率较高时,给予短信提示的效果不错。
%%HTML
<style type="text/css">
table.dataframe td, table.dataframe th {
border: 1px black solid !important;
color: black !important;
} #设置df表格输出样式
2 数据导入
该数据来源于kaggle网站的Give Me Some Credit
数据包括了25万条个人财务情况的样本数据,通过对于该数据集的学习,构建一个信用卡评分模型,以期望对新用户预测其违约风险。
#导入包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
#导入数据
train=pd.read_csv('cs-training.csv') #训练集
test=pd.read_csv('cs-test.csv') #测试集
#了解数据集
train.info() #给出样本数据的相关信息概览
train.head() #查看前5行数据
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150000 entries, 0 to 149999
Data columns (total 12 columns):
Unnamed: 0 150000 non-null int64
SeriousDlqin2yrs 150000 non-null int64
RevolvingUtilizationOfUnsecuredLines 150000 non-null float64
age 150000 non-null int64
NumberOfTime30-59DaysPastDueNotWorse 150000 non-null int64
DebtRatio 150000 non-null float64
MonthlyIncome 120269 non-null float64
NumberOfOpenCreditLinesAndLoans 150000 non-null int64
NumberOfTimes90DaysLate 150000 non-null int64
NumberRealEstateLoansOrLines 150000 non-null int64
NumberOfTime60-89DaysPastDueNotWorse 150000 non-null int64
NumberOfDependents 146076 non-null float64
dtypes: float64(4), int64(8)
memory usage: 13.7 MB
Unnamed: 0 | SeriousDlqin2yrs | RevolvingUtilizationOfUnsecuredLines | age | NumberOfTime30-59DaysPastDueNotWorse | DebtRatio | MonthlyIncome | NumberOfOpenCreditLinesAndLoans | NumberOfTimes90DaysLate | NumberRealEstateLoansOrLines | NumberOfTime60-89DaysPastDueNotWorse | NumberOfDependents | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 0.766127 | 45 | 2 | 0.802982 | 9120.0 | 13 | 0 | 6 | 0 | 2.0 |
1 | 2 | 0 | 0.957151 | 40 | 0 | 0.121876 | 2600.0 | 4 | 0 | 0 | 0 | 1.0 |
2 | 3 | 0 | 0.658180 | 38 | 1 | 0.085113 | 3042.0 | 2 | 1 | 0 | 0 | 0.0 |
3 | 4 | 0 | 0.233810 | 30 | 0 | 0.036050 | 3300.0 | 5 | 0 | 0 | 0 | 0.0 |
4 | 5 | 0 | 0.907239 | 49 | 1 | 0.024926 | 63588.0 | 7 | 0 | 1 | 0 | 0.0 |
可以知道样本数有15万条,特征变量有12个,具体各变量的含义如下:
因变量等1时为坏客户,因此取坏客户为正样本
#将变量名换为中文便于理解
states={
'Unnamed: 0':'id',
'SeriousDlqin2yrs':'好坏客户',
'RevolvingUtilizationOfUnsecuredLines':'可用额度比值', #无担保放款循环利用比值
'age':'年龄',
'NumberOfTime30-59DaysPastDueNotWorse':'逾期30-59天笔数',
'DebtRatio':'负债率',
'MonthlyIncome':'月收入',
'NumberOfOpenCreditLinesAndLoans':'信贷数量',
'NumberOfTimes90DaysLate':'逾期90天笔数',
'NumberRealEstateLoansOrLines':'固定资产贷款量',
'NumberOfTime60-89DaysPastDueNotWorse':'逾期60-89天笔数',
'NumberOfDependents':'家属数量'
} #创建字典
train.rename(columns=states,inplace=True)
train.head()
id | 好坏客户 | 可用额度比值 | 年龄 | 逾期30-59天笔数 | 负债率 | 月收入 | 信贷数量 | 逾期90天笔数 | 固定资产贷款量 | 逾期60-89天笔数 | 家属数量 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 0.766127 | 45 | 2 | 0.802982 | 9120.0 | 13 | 0 | 6 | 0 | 2.0 |
1 | 2 | 0 | 0.957151 | 40 | 0 | 0.121876 | 2600.0 | 4 | 0 | 0 | 0 | 1.0 |
2 | 3 | 0 | 0.658180 | 38 | 1 | 0.085113 | 3042.0 | 2 | 1 | 0 | 0 | 0.0 |
3 | 4 | 0 | 0.233810 | 30 | 0 | 0.036050 | 3300.0 | 5 | 0 | 0 | 0 | 0.0 |
4 | 5 | 0 | 0.907239 | 49 | 1 | 0.024926 | 63588.0 | 7 | 0 | 1 | 0 | 0.0 |
#对变量进行描述性统计分析
train.describe()
id | 好坏客户 | 可用额度比值 | 年龄 | 逾期30-59天笔数 | 负债率 | 月收入 | 信贷数量 | 逾期90天笔数 | 固定资产贷款量 | 逾期60-89天笔数 | 家属数量 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 150000.000000 | 150000.000000 | 150000.000000 | 150000.000000 | 150000.000000 | 150000.000000 | 1.202690e+05 | 150000.000000 | 150000.000000 | 150000.000000 | 150000.000000 | 146076.000000 |
mean | 75000.500000 | 0.066840 | 6.048438 | 52.295207 | 0.421033 | 353.005076 | 6.670221e+03 | 8.452760 | 0.265973 | 1.018240 | 0.240387 | 0.757222 |
std | 43301.414527 | 0.249746 | 249.755371 | 14.771866 | 4.192781 | 2037.818523 | 1.438467e+04 | 5.145951 | 4.169304 | 1.129771 | 4.155179 | 1.115086 |
min | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000e+00 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
25% | 37500.750000 | 0.000000 | 0.029867 | 41.000000 | 0.000000 | 0.175074 | 3.400000e+03 | 5.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
50% | 75000.500000 | 0.000000 | 0.154181 | 52.000000 | 0.000000 | 0.366508 | 5.400000e+03 | 8.000000 | 0.000000 | 1.000000 | 0.000000 | 0.000000 |
75% | 112500.250000 | 0.000000 | 0.559046 | 63.000000 | 0.000000 | 0.868254 | 8.249000e+03 | 11.000000 | 0.000000 | 2.000000 | 0.000000 | 1.000000 |
max | 150000.000000 | 1.000000 | 50708.000000 | 109.000000 | 98.000000 | 329664.000000 | 3.008750e+06 | 58.000000 | 98.000000 | 54.000000 | 98.000000 | 20.000000 |
上述描述统计表发现变量月收入和家庭数量的样本数小于15w,两个变量存在缺失值。
#求两个变量的缺失比
print("月收入缺失比:{:.2%}".format(train['月收入'].isnull().sum()/train.shape[0]))
print("家属数量缺失比:{:.2%}".format(train['家属数量'].isnull().sum()/train.shape[0]))
月收入缺失比:19.82%
家属数量缺失比:2.62%
3 缺失值处理
缺失值的类型:完全随机缺失,随机缺失,非随机缺失
处理方法:
1、删除含有缺失值的个案
2、可能值插补缺失值
(1)均值插补
(2)利用同类均值插补。
(3)极大似然估计(Max Likelihood ,ML)
(4)多重插补(Multiple Imputation,MI)
月收入的缺失比较大,应该进行缺失值的估计插补,本文采用均值插补方法,月收入变量数据为定距型,采用该变量的均值进行填补,而家属数量的缺失比较低,可以直接删除有缺失的样本。
#用均值填补月收入缺失值
train['月收入']=train['月收入'].fillna(train['月收入'].mean())
#删除存在缺失值的样本
train=train.dropna()
train.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 146076 entries, 0 to 149999
Data columns (total 12 columns):
id 146076 non-null int64
好坏客户 146076 non-null int64
可用额度比值 146076 non-null float64
年龄 146076 non-null int64
逾期30-59天笔数 146076 non-null int64
负债率 146076 non-null float64
月收入 146076 non-null float64
信贷数量 146076 non-null int64
逾期90天笔数 146076 non-null int64
固定资产贷款量 146076 non-null int64
逾期60-89天笔数 146076 non-null int64
家属数量 146076 non-null float64
dtypes: float64(4), int64(8)
memory usage: 14.5 MB
4 异常值处理
异常值即离群点,一般大于3倍标准差外的数值为异常值,可以采用箱线图判断异常值。
train.head()
id | 好坏客户 | 可用额度比值 | 年龄 | 逾期30-59天笔数 | 负债率 | 月收入 | 信贷数量 | 逾期90天笔数 | 固定资产贷款量 | 逾期60-89天笔数 | 家属数量 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 0.766127 | 45 | 2 | 0.802982 | 9120.0 | 13 | 0 | 6 | 0 | 2.0 |
1 | 2 | 0 | 0.957151 | 40 | 0 | 0.121876 | 2600.0 | 4 | 0 | 0 | 0 | 1.0 |
2 | 3 | 0 | 0.658180 | 38 | 1 | 0.085113 | 3042.0 | 2 | 1 | 0 | 0 | 0.0 |
3 | 4 | 0 | 0.233810 | 30 | 0 | 0.036050 | 3300.0 | 5 | 0 | 0 | 0 | 0.0 |
4 | 5 | 0 | 0.907239 | 49 | 1 | 0.024926 | 63588.0 | 7 | 0 | 1 | 0 | 0.0 |
'''画箱线图,采用组合图的方式'''
#建立画板和画纸
fig=plt.figure(figsize=(15,10))
a=fig.add_subplot(3,2,1)
b=fig.add_subplot(3,2,2)
c=fig.add_subplot(3,2,3)
d=fig.add_subplot(3,2,4)
e=fig.add_subplot(3,2,5)
f=fig.add_subplot(3,2,6)
a.boxplot(train['可用额度比值'])
b.boxplot([train['年龄'],train['好坏客户']])
c.boxplot([train['逾期30-59天笔数'],train['逾期60-89天笔数'],train['逾期90天笔数']])
d.boxplot([train['信贷数量'],train['固定资产贷款量'],train['家属数量']])
e.boxplot(train['月收入'])
f.boxplot(train['负债率'])
{'whiskers': [<matplotlib.lines.Line2D at 0x2623ef39ef0>,
<matplotlib.lines.Line2D at 0x2623b30b518>],
'caps': [<matplotlib.lines.Line2D at 0x2623b8ba470>,
<matplotlib.lines.Line2D at 0x262392194e0>],
'boxes': [<matplotlib.lines.Line2D at 0x2623ef39d68>],
'medians': [<matplotlib.lines.Line2D at 0x2623ed1cd30>],
'fliers': [<matplotlib.lines.Line2D at 0x2623ed3e470>],
'means': []}
处在箱线图上下边缘之外的为异常值
用公式去除异常值,计算第一和第三四分位数(Q1、Q3),异常值是位于四分位数范围之外的数据点x i:
使用四分位数乘数值k=1.5,范围限制是典型的上下晶须的盒子图。计算出来的正是箱线图的上下限。