申请评分卡分析及建模

邮箱:dengzy95@163.com   欢迎交流建议

项目简介

信用评分技术是一种应用统计模型,其作用是对贷款申请人做风险评估分值的方法。在互金公司等各种贷款业务机构中,普遍使用信用评分,对客户实行打分制,以期对客户有一个优质与否的评判。评分卡主要分为三类A卡(申请评分卡)、B卡(行为评分卡)、C卡(贷后评分卡)。我们主要讨论的是A卡即申请评分卡,用于贷前审批阶段对借款申请人的量化评估;

评分卡原理:

申请评分卡是一种统计模型,它可基于对当前申请人的各项资料进行评估并给出一个分数,该评分能定量对申请人的偿债能力作出预判。

客户申请评分卡由一系列特征项组成,每个特征项相当于申请表上的一个问题(例如,年龄、银行流水、收入等)。每一个特征项都有一系列可能的属性,相当于每一个问题的一系列可能答案(例如,对于年龄这个问题,答案可能就有30岁以下、30到45等)。在开发评分卡系统模型中,先确定属性与申请人未来信用表现之间的相互关系,然后给属性分配适当的分数权重,分配的分数权重要反映这种相互关系。分数权重越大,说明该属性表示的信用表现越好。一个申请的得分是其属性分值的简单求和。如果申请人的信用评分大于等于金融放款机构所设定的界限分数,此申请处于可接受的风险水平并将被批准;低于界限分数的申请人将被拒绝或给予标示以便进一步审查。

数据来源

数据集来自kaggle中GiveMeSomeCredit项目。地址:https://www.kaggle.com/c/GiveMeSomeCredit/data

开发流程

一、导入数据集

二、数据预处理

三、数据探索

四、特征工程

五、建立模型

六、建立评分卡

一、数据集导入

数据集相对来说比较干净我们可以直接导入数据。

#先加载后续分箱需要用到的包和模块import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

df = pd.read_csv("E:\python\data\GiveMeSomeCredit\cs-training.csv")
df.head()

特征名称比较阅读起来比较困难,让我们重命名为中文形式。

states={"Unnamed: 0":"用户ID",
        "SeriousDlqin2yrs":"好坏客户",
        "RevolvingUtilizationOfUnsecuredLines":"可用额度比值", #
        "age":"年龄",
        "NumberOfTime30-59DaysPastDueNotWorse":"逾期30-59天笔数",
        "DebtRatio":"负债率",
        "MonthlyIncome":"月收入",
        "NumberOfOpenCreditLinesAndLoans":"信贷数量",
        "NumberOfTimes90DaysLate":"逾期90天笔数",
        "NumberRealEstateLoansOrLines":"固定资产贷款量",
        "NumberOfTime60-89DaysPastDueNotWorse":"逾期60-89天笔数",
        "NumberOfDependents":"家属数量"}
df.rename(columns=states,inplace=True)
df.head()

二、数据预处理

2.1查看数据信息

df.info()

可以看出数据类型为浮点数和整数形式,样本总量在15000其中月收入和家属数量特征中有缺失数据。

#计算特征的缺失比例round(df.isnull().sum()/df.好坏客户.count(),3)

2.2数据中‘月收入’的缺失值过多,我们利用均值来进行缺失值的填补工作。

对于缺失值较少的‘家属数量’我们可以直接删除缺失值。及对数据集进行去重处理。

df = df.fillna({‘月收入‘:df[‘月收入‘].mean()})
  df1 = df.dropna()

df1 = df.drop_duplicates()#删除重复项
df.info()

2.3异常值检测及处理

利用箱型图对特征进行可视化来检测异常数据。

x4=df1["逾期30-59天笔数"]
x5=df1["逾期60-89天笔数"]
x6=df1["逾期90天笔数"]
fig=plt.figure(3)
ax=fig.add_subplot(111)
ax.boxplot([x4,x5,x6])
ax.set_xticklabels(["逾期30-59天笔数","逾期60-89天笔数","逾期90天笔数"])

通过以上特征可视化我们可以对明显偏离的样本,比如年龄为0,或是逾期次数过高进行盖帽或者是删除操作,这里采用直接删除。

#异常值过滤
df1=df1[df1["可用额度比值"]<=1]
df1=df1[df1["年龄"]>0]
df1=df1[df1["逾期30-59天笔数"]<80]
df1=df1[df1["固定资产贷款量"]<50]

三、数据可视化分析

3.1单变量可视化

cut_bins=[0,5000,10000,15000,20000,100000]
month_cut=pd.cut(df1["月收入"],cut_bins)
month_cut_grouped=df1["好坏客户"].groupby(month_cut).count()
month_cut_grouped1=df1["好坏客户"].groupby(month_cut).sum()
df3=pd.merge(pd.DataFrame(month_cut_grouped), pd.DataFrame(month_cut_grouped1),right_index=True,left_index=True)
df3.rename(columns={"好坏客户_x":"好客户","好坏客户_y":"坏客户"},inplace=True)
df3.insert(2,"坏客户率",df3["坏客户"]/df3["好客户"])

plt.figure()
ax23=df3[["好客户","坏客户"]].plot.bar()
ax23.set_xticklabels(df3.index,rotation=15)
ax23.set_ylabel("客户数")
ax23.set_title("好坏客户数与月收入关系")

plt.figure()
ax231=df3["坏客户率"].plot()
ax231.set_ylabel("坏客户率")
ax231.set_title("月收入与坏客户率关系")

可以看出客户主体集中在月收入10000以下的人群,月收入在15000之前的坏客率和月收入呈负相关收入越高坏客率越低,后进入一段平稳但当收入超过20000后,坏客率又在上升。这表明收入在15000以下的人群收入比较稳定,随着收入越高坏账率也就越高。而收入大于20000的人群可能从事炒股,创业等风险较大的工作,所以坏账率增大。

cut_bins=[0,2,4,20]
family_cut=pd.cut(df1["家属数量"],cut_bins)
family_cut_grouped=df1["好坏客户"].groupby(family_cut).count()
family_cut_grouped1=df1["好坏客户"].groupby(family_cut).sum()
df4=pd.merge(pd.DataFrame(family_cut_grouped), pd.DataFrame(family_cut_grouped1),right_index=True,left_index=True)
df4.rename(columns={"好坏客户_x":"好客户","好坏客户_y":"坏客户"},inplace=True)
df4.insert(2,"坏客户率",df4["坏客户"]/df4["好客户"])

plt.figure()
ax24=df4[["好客户","坏客户"]].plot.bar()
ax24.set_xticklabels(df4.index,rotation=15)
ax24.set_ylabel("客户数")
ax24.set_title("好坏客户数与家属数量关系")

plt.figure()
ax241=df4["坏客户率"].plot()
ax241.set_ylabel("坏客户率")
ax241.set_title("坏客户率与家属数量的关系")

可以看出客户的家属数量的主要集中在0-2之间,家属数量和坏客率呈线性相关,也就是说随着家属数量提升,坏客率也在显著提升。可能是由于家属数量大,家庭的支出也就增大,所以更容易出现坏账的情况。

3.2多变量可视化

通过变量直接的相关性系数,建立相关性矩阵,观察变量之间的关系,可以进行初步的多重共线性筛选。

plt.rcParams["font.sans-serif"]=‘SimHei‘
plt.rcParams[‘axes.unicode_minus‘] = False
corr = df1.corr()#计算各变量的相关性系数
xticks = list(corr.index)
yticks = list(corr.index)
fig = plt.figure(figsize=(10,7))
ax1 = fig.add_subplot(1, 1, 1)
sns.heatmap(corr, annot=True, cmap="rainbow",ax=ax1,linewidths=.5, annot_kws={‘size‘: 9, ‘weight‘: ‘bold‘, ‘color‘: ‘blue‘})
ax1.set_xticklabels(xticks, rotation=35, fontsize=10)
ax1.set_yticklabels(yticks, rotation=0, fontsize=10)
plt.show()

热力图的颜色表示变量之间的相关性程度,可以看出变量之间没有相关性过高的情况,所以暂时不需要考虑多重共线性的问题。

四、特征工程

4.1 特征分箱

在建立风控评分卡中,一般会对特征进行分箱,以提高模型的稳定性和健壮性,消除了异常波动对评分结果的影响。

#数据分箱
cut1=pd.qcut(df1["可用额度比值"],4,labels=False)
cut2=pd.qcut(df1["年龄"],8,labels=False)
bins3=[-1,0,1,3,5,13]
cut3=pd.cut(df1["逾期30-59天笔数"],bins3,labels=False)
cut4=pd.qcut(df1["负债率"],3,labels=False)
cut5=pd.qcut(df1["月收入"],4,labels=False)
cut6=pd.qcut(df1["信贷数量"],4,labels=False)
bins7=[-1, 0, 1, 3,5, 20]
cut7=pd.cut(df1["逾期90天笔数"],bins7,labels=False)
bins8=[-1, 0,1,2, 3, 33]
cut8=pd.cut(df1["固定资产贷款量"],bins8,labels=False)
bins9=[-1, 0, 1, 3, 12]
cut9=pd.cut(df1["逾期60-89天笔数"],bins9,labels=False)
bins10=[-1, 0, 1, 2, 3, 5, 21]
cut10=pd.cut(df1["家属数量"],bins10,labels=False)

4.2 woe转换

接下来给分箱后的数据计算woe值,woe算是一种编码形式,但是和普通的编码它实际代表了响应客户和未响应客户之间的差异情况。
公式如下:

#好坏客户比率
rate=df1["好坏客户"].sum()/(df1["好坏客户"].count()-df1["好坏客户"].sum())

#定义woe计算函数
def get_woe_data(cut):
    grouped=df1["好坏客户"].groupby(cut,as_index = True).value_counts()
    woe=np.log(pd.DataFrame(grouped).unstack().iloc[:,1]/pd.DataFrame(grouped).unstack().iloc[:,0]/rate)#计算每个分组的woe值
    return woe
cut1_woe=get_woe_data(cut1)
cut2_woe=get_woe_data(cut2)
cut3_woe=get_woe_data(cut3)
cut4_woe=get_woe_data(cut4)
cut5_woe=get_woe_data(cut5)
cut6_woe=get_woe_data(cut6)
cut7_woe=get_woe_data(cut7)
cut8_woe=get_woe_data(cut8)
cut9_woe=get_woe_data(cut9)
cut10_woe=get_woe_data(cut10)

4.3 IV值计算

IV的全称是Information Value,中文意思是信息价值,或者信息量。它的作用其实和gini和信息熵类似,都是用来衡量变量的预测能力,可以通过IV值来达到特征筛选的目的。

#定义IV值计算函数
def get_IV_data(cut,cut_woe):
    grouped=df1["好坏客户"].groupby(cut,as_index = True).value_counts()
    cut_IV=((pd.DataFrame(grouped).unstack().iloc[:,1]/df1["好坏客户"].sum()-pd.DataFrame(grouped).unstack().iloc[:,0]/(df1["好坏客户"].count()-df1["好坏客户"].sum()))*cut_woe).sum()
    return cut_IV
#计算各分组的IV值
cut1_IV=get_IV_data(cut1,cut1_woe)
cut2_IV=get_IV_data(cut2,cut2_woe)
cut3_IV=get_IV_data(cut3,cut3_woe)
cut4_IV=get_IV_data(cut4,cut4_woe)
cut5_IV=get_IV_data(cut5,cut5_woe)
cut6_IV=get_IV_data(cut6,cut6_woe)
cut7_IV=get_IV_data(cut7,cut7_woe)
cut8_IV=get_IV_data(cut8,cut8_woe)
cut9_IV=get_IV_data(cut9,cut9_woe)
cut10_IV=get_IV_data(cut10,cut10_woe)
#各组的IV值可视化
df_IV=pd.DataFrame([cut1_IV,cut2_IV,cut3_IV,cut4_IV,cut5_IV,cut6_IV,cut7_IV,cut8_IV,cut9_IV,cut10_IV],index=df1.columns[2:])
df_IV.plot(kind="bar")

通过特征IV的可视化,可以很直观的观察特征之间的差异,我们选择IV较高的特征代入模型。

#定义一个替换函数
def replace_data(cut,cut_woe):
    a=[]
    for i in cut.unique():
        a.append(i)
        a.sort()
    for m in range(len(a)):
        cut.replace(a[m],cut_woe.values[m],inplace=True)
    return cut

#进行替换
df_new = pd.DataFrame()
df_new[‘可用额度比值‘]=replace_data(cut1,cut1_woe)
df_new["年龄"]=replace_data(cut2,cut2_woe)
df_new["逾期30-59天笔数"]=replace_data(cut3,cut3_woe)
df_new["逾期90天笔数"]=replace_data(cut7,cut7_woe)
df_new["逾期60-89天笔数"]=replace_data(cut9,cut9_woe)

五、建立模型

建立logistics模型,logistics回归是广义线性回归,它的在建立后和线性回归一样会赋值给特征不同的权重,很符合建立评分卡的概念。

from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve, auc

x=df_new
y=df1.iloc[:,1]

x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.4,random_state=0)

#模型训练
model=LogisticRegression()
clf=model.fit(x_train,y_train)
print("测试成绩:{}".format(clf.score(x_test,y_test)))
y_pred=clf.predict(x_test)
y_pred1=clf.decision_function(x_test)

模型测试效果看起来不错,但是准确率并不能反映模型的真实效果,下面利用ROC曲线来评估模型。

#绘制ROC曲线以及计算AUC值
fpr, tpr, threshold = roc_curve(y_test, y_pred1)
roc_auc = auc(fpr, tpr)
plt.plot(fpr, tpr, color=‘darkorange‘,
          label=‘ROC curve (area = %0.2f)‘ % roc_auc)
plt.plot([0, 1], [0, 1], color=‘navy‘,  linestyle=‘--‘)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.0])
plt.xlabel(‘False Positive Rate‘)
plt.ylabel(‘True Positive Rate‘)
plt.title(‘ROC_curve‘)
plt.legend(loc="lower right")
plt.show()

模型在ROC曲线上大致表现不错,AUC也达到了0.84。

六、建立评分卡

根据资料查得评分卡创建公式

coe = clf.coef_
factor = clf.intercept_
import numpy as np
factor = 20 / np.log(2)
offset = 600 - 20 * np.log(20) / np.log(2)

#定义变量分数计算函数
def get_score(coe,woe,factor):
    scores=[]
    for w in woe:
        score=round(coe*w*factor,0)
        scores.append(score)
    return scores

将数据集代入到自定义函数,计算评分标准。

#计算每个变量得分
x1 = get_score(coe[0][0], cut1_woe, factor)
x2 = get_score(coe[0][1], cut2_woe, factor)
x3 = get_score(coe[0][2], cut3_woe, factor)
x7 = get_score(coe[0][3], cut7_woe, factor)
x9 = get_score(coe[0][4], cut9_woe, factor)

#打印输出每个特征对应的分数
print("可用额度比值对应的分数:{}".format(x1))
print("年龄对应的分数:{}".format(x2))
print("逾期30-59天笔数对应的分数:{}".format(x3))
print("逾期90天笔数对应的分数:{}".format(x7))
print("逾期60-89天笔数对应的分数:{}".format(x9))

将用户数据代入到评分标准后求和,就可以得到该用户的总分。得分越高代表其越有可能成为坏账客户。

总结

本文通过对kaggle上的Give Me Some Credit数据的挖掘分析,结合信用评分卡的建立原理,从数据的预处理、变量选择、建模分析到创建信用评分,创建了一个简单的信用评分系统。
基于AI 的机器学习评分卡系统可通过把旧数据(某个时间点后,例如2年)剔除掉后再进行自动建模、模型评估、并不断优化特征变量,使得系统更加强大。

原文地址:https://www.cnblogs.com/dzy1995/p/10556226.html

时间: 2024-08-26 15:06:33

申请评分卡分析及建模的相关文章

评分卡系列(一):讲讲评分系统的构建

作者:JSong 时间:2017.12 我想通过几篇文章,给评分卡的全流程一个中等粒度的介绍.另外我的本职工作不是消费金融的数据分析,所以本系列的文章会偏技术一些. 数据分析工具主要有Python3及pandas.sklearn等科学计算包,另外也会有自己的工具包reportgen. 信用记录数据采用Lending Club的公开数据,特征数目和样本数都比较理想.大家可以到官网(www.lendingclub.com)下载,或者关注我的微信公众号后台回复:?数据集 ? 下载(含变量介绍和中文对照

信用评分中的评分卡中的A卡、B卡和C卡

A卡(Application score card)申请评分卡 B卡(Behavior score card)行为评分卡 C卡(Collection score card)催收评分卡 评分机制的区别在于: 1.使用的时间不同.分别侧重贷前.贷中.贷后: 2.数据要求不同.A卡一般可做贷款0-1年的信用分析,B卡则是在申请人有了一定行为后,有了较大数据进行的分析,一般为3-5年,C卡则对数据要求更大,需加入催收后客户反应等属性数据. 3.每种评分卡的模型会不一样.在A卡中常用的有逻辑回归,AHP等

kaggle-制作评分卡

https://blog.csdn.net/zpxcod007/article/details/80118580 制作A卡,申请评分卡 数据集:15万个样本,特征 主要预处理手段:缺失值,异常值,样本不平衡的处理,划分数据集,做分箱处理(离散化),将样本的每个特征都映射到WOE空间 之后建模,这里采用:逻辑回归,决策树和随机森林建模,在auc-roc指标上,随机森林表现最优秀,这里选取了随机森林做后续的制作评分卡(利用得到变量系数并自行拟定了评分标准建立了评分卡.). 建立评分卡: 以上论文资料

3分钟搞明白信用评分卡模型&amp;模型验证

信用评分卡模型在国外是一种成熟的预测方法,尤其在信用风险评估以及金融风险控制领域更是得到了比较广泛的使用,其原理是将模型变量WOE编码方式离散化之后运用logistic回归模型进行的一种二分类变量的广义线性模型. 本文重点介绍模型变量WOE以及IV原理,为表述方便,本文将模型目标标量为1记为违约用户,对于目标变量为0记为正常用户:则WOE(weight of Evidence)其实就是自变量取某个值的时候对违约比例的一种影响,怎么理解这句话呢?我下面通过一个图标来进行说明. Woe公式如下: A

信用评分卡模型开发中双峰分布原因及解决方案

信用评分卡模型开发中双峰分布原因及解决方案 文: 郑旻圻 邹钰 刘巧莉 转自:  数信互融 在信用评分卡模型开发过程中,正态性是检验模型信用评分分布是否有效的一个重要指标.正常情况下,标准的正态分布是单峰分布:但是在实际建模过程中,会遇到信用评分分布出现双峰的情况. 双峰分布出现时,数据规律一致性的假设被打破,我们需要从不同的角度考察其出现双峰分布的原因,对模型加以调整,使之准确地反映业务和数据中的规律,以便模型准确适用. 根据为数十家互联网金融企业建立评分卡模型的实践经验,我们总结了一些造成双

信用评分卡模型入门(智能算法)

信用评分卡模型入门 2016-07-26 智能算法 智能算法 一.背景介绍:   4.数据整理(数据清理过程) 大量取样的数据要真正最后进入模型,必须经过数据整理.在数据处理时应注意检查数据的逻辑性.区分"数据缺失"和"0".根据逻辑推断某些值.寻找反常数据.评估是否真实.可以通过求最小值.最大值和平均值的方法,初步验证抽样数据是否随机.是否具有代表性. 常用清理过程包含:缺失值分析处理.单变量异常分析(LOF分析处理或聚类分析) 5.变量选择 变量选择要同时具有数

笔记︱信用风险模型(申请评分、行为评分)与数据准备(违约期限、WOE转化)

巴塞尔协议定义了金融风险类型:市场风险.作业风险.信用风险.信用风险ABC模型有进件申请评分.行为评分.催收评分. ------------------------------------ 一.数据准备 1.排除一些特定的建模客户 用于建模的客户或者申请者必须是日常审批过程中接触到的,需要排除以下两类人: 异常行为:销户.按条例拒绝.特殊账户: 特殊账户:出国.卡丢失/失窃.死亡.未成年.员工账户.VIP: 其他:欺诈(根据反欺诈评分).主动销户者(流失评分) 2.解释指标的选取 (1)申请评分

评分卡模型剖析之一(woe、IV、ROC、信息熵)

信用评分卡模型在国外是一种成熟的预测方法,尤其在信用风险评估以及金融风险控制领域更是得到了比较广泛的使用,其原理是将模型变量WOE编码方式离散化之后运用logistic回归模型进行的一种二分类变量的广义线性模型. 本文重点介绍模型变量WOE以及IV原理,为表述方便,本文将模型目标标量为1记为违约用户,对于目标变量为0记为正常用户:则WOE(weight of Evidence)其实就是自变量取某个值的时候对违约比例的一种影响,怎么理解这句话呢?我下面通过一个图标来进行说明. Woe公式如下: A

评分卡系列(二):特征工程

文章很长,理论和实现都讲的很细,大家可以先收藏,有时间再看. 在上一篇文章中,我们对LendingClub的数据有了一个大致的了解,这次我将带大家把10万多条.145个字段的原始数据一步一步处理成建模所需输入的数据. 我们先按照上次一样导入数据,这里我将逾期15天以上的都当作正类 import pandas as pd import numpy as np import reportgen as rpt import matplotlib.pyplot as plt import seaborn