信用卡“坏账”客户分析(二)

时间:2022-05-08
本文章向大家介绍信用卡“坏账”客户分析(二),主要内容包括1.共线性检测、2.特征选择、2.2WOE值计算、2.3IV值计算、1.WOE值替换、2.模型训练及测试、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

总第98篇

信用卡“坏账”客户分析(二)终于来了,本篇主要针对信用卡客户进行建模,建立评分卡,给每个客户进行打分,通过该客户的得分来判断该客户的“好坏”。

传送门:信用卡“坏账”客户分析(一)

前言

前面的推文《信用卡坏账客户分析》对一些[坏账客户]做了一些基本的描述性分析,这篇将针对所有的信用卡用户建立一个评分标准,即评分卡,类似于芝麻信用分一样,用来评判用户的履约能力和违约风险。

一些数据预处理以及描述性分析,在前文中已经写过,本篇不再赘述,直接进入评分卡建立阶段。

特征选择

1.共线性检测

共线性是指线性回归模型中的特征之间由于存在精确相关关系或高度相关关系而使模型估计失真或难以估计准确,而本次我们使用的LR模型是广义线性模型,所以需要进行共线性检测,具体的检测原理就是查看各变量之间的相关性大小。

可以看到,各变量之间的相关性都是比较小,所以不存在共线性问题。

2.特征选择

特征选择是指过滤掉一些对于目标变量影响权重较小的特征变量,机器学习中常用的特征选择方法有如下几种:,本篇中我们选用评分卡模型中常用IV值筛选。

在开始具体的计算之前,先了解一下WEO和IV的概念,可以看看这篇文章,讲述的很清楚:http://blog.csdn.net/kevin7658/article/details/50780391,我就不再赘述了。

具体筛选流程如下:

2.1WOE分箱

所谓的woe分箱就是将连续变量离散化,即切分成不同的区间,离散化后的变量具有很好的稳定性,比如年龄这个连续变量,如果是连续值的时候21和29就是两个不同的值,对模型的效果也不一样,但是如果离散化成20-30的时候,这两个年龄对模型的效果就是一样,更加稳定。

#数据分箱
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)

2.2WOE值计算

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值
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)

2.3IV值计算

IV的全称是Information Value,中文意思是信息价值,或者信息量。是评判变量的预测能力的一个指标,值越大,说明预测能力越强,可以用来进行特征选择。

#定义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")
for a,b in zip(range(10),df3.values):
    plt.text(a,b,'%.2f' % b, ha='center', va= 'bottom',fontsize=9)

以看到["负债率","月收入","信贷数量","固定资产贷款量","家属数量"]这几个特征的IV值过低,对目标变量的影响较小,将其过滤掉。

建立模型

1.WOE值替换

在建立模型之前我们需要将原始数据用离散化后的woe值替代,具体实现如下:

#定义一个替换函数
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["可用额度比值"]=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)

2.模型训练及测试

j将值替换完成以后就可以开始训练模型了,在模型方面我们选择LR模型,并利用sklearn库进行实现,具体实现如下:

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

x=df_new.iloc[:,2:]
y=df_new.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曲线以及计算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()

模型的预测准确率为0.94,AUC值0.84,之所以这样是正负样本不平衡造成的,在中有说过,这里我们选用AUC值来评判模型效果。

评分

上面的模型的输出结果可以为每个客户的客户类别(好客户还是客户),也可以说出每个客户是好客户/坏客户对应的概率值。这种结果看起来不直观,我们需要把LR模型的结果值转化为对应的分数(0-999分)。

根据资料查得: a=log(p_good/P_bad) Score = offset + factor * log(odds)

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))

上面是不同特征值对应的分数,评分越高,说明该用户越有可能响应目标变量,即成为为坏账客户。

特征划分区间值是依次递增的,可以看到特征区间值与得分是相对应的,年龄越大,坏账的可能性越低;逾期笔数越多,坏账可能性越大,得分越高;

最后将所有的变量对应的分值相加就是每个用户的总得分。