数据挖掘项目:银行信用评分卡建模分析(下篇)

本文介绍了银行信用评分卡建模分析的下篇,重点涉及特征工程,包括特征衍生、相关性分析、数据分箱与WOE值计算。通过构建逻辑回归模型并调整参数,评估模型的ROC-AUC曲线和KS值,最终建立了评分卡。在特征选择中,违约次数、抵押贷款、房地产贷款数量等因素被识别为关键特征。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下是银行信用评分卡建模分析下篇的内容,包括特征工程,构建模型,模型评估,评分卡建立这四部分。其中如果有一些地方分析的不正确,希望大家多多指正,感谢!
上篇文章的链接:数据挖掘项目:银行信用评分卡建模分析(上篇)

4.特征工程

特征处理和特征生成

特征衍生

构建三个新的特征:总违约数,违约计数和每个月的支出。

def get_more_features(data):
    data['AllNumlate']=data['NumberOfTime30-59DaysPastDueNotWorse']+data['NumberOfTime60-89DaysPastDueNotWorse']+data['NumberOfTimes90DaysLate']
    data['Monthlypayment']=data['DebtRatio']*data['MonthlyIncome']
    return data

特征相关性

correlation_table = pd.DataFrame(train_data.corr())
fig = plt.figure(figsize=(15,15))
ax1 = fig.add_subplot(1,1,1)
sns.heatmap(correlation_table,annot=True,ax=ax1,square = True,  vmax=1.0,vmin=-1.0,linewidths=.5,annot_kws={
   'size': 12, 'weight': 'bold', 'color': 'blue'})

在这里插入图片描述

  • 总违约数和30-59天的违约数之间有很大的相关性,0.84。因为30-59天的违约数相比于60-89和90天以上的次数过多。但这个还是选择保留该特征,一是因为有比较重要的实际意义。

划分测试集和训练集

from sklearn.model_selection import train_test_split
X = pd.DataFrame(X)
y = pd.DataFrame(y)

X_train, X_vali, Y_train, Y_vali = train_test_split(X,y,test_size=0.3,random_state=0)
# 训练集
model_data = pd.concat([Y_train, X_train], axis=1)
model_data.index = range(model_data.shape[0])
model_data.columns = train_data.columns
#验证集
vali_data = pd.concat([Y_vali, X_vali], axis=1)
vali_data.index = range(vali_data.shape[0])
vali_data.columns = train_data.columns

数据分箱

关于WOE和IV值的概念在数据分箱、WOE、IV的意义中有比较详细的描述。

这里让WOE的值单调是为了让woe(x)与y之间具备线性的关系,更有助于人们的理解。

数据分箱的大体思路如下:

  1. 等频分箱。由于不同的数据分组不一样,因此不采用等距分箱。这里等频分箱的分箱数一定要选的足够大20-40之间,因为有的样本占比太大,分箱数少的话,没有区分性
  2. 确保每个箱内都有正负样本。由于要计算WOE和IV值,从公式上可以看出,要计算这两个值,需要每个分组内都包含正负样本。
  3. 卡方分箱。卡方可以检验两类别的相似性。可对等频分箱后的结果,进行更为精确的分箱。但这里并不采用卡方检验的p值决定最终的分箱。
  4. 根据WOE和IV值确定最佳分箱数。这里WOE要满足单调性,IV值要在一定的范围内,过大过小都说明该特征有问题。
    在这里插入图片描述

以下为代码部分。

def graphforbestbin(DF, X, Y, n=5,q=20,graph=True):
    global bins_df
    DF = DF[[X,Y]].copy()
    
    # 等频分箱
    DF["qcut"],bins = pd.qcut(DF[X], retbins=True, q=q,duplicates="drop")
    coount_y0 = DF.loc[DF[Y]==0].groupby(by="qcut").count()[Y]
    coount_y1 = DF.loc[DF[Y]==1].groupby(by="qcut").count()[Y]
    num_bins = [*zip(bins,bins[1:],coount_y0,coount_y1)]
    
    # 判断分箱后每个箱内是否都有好坏样本,没有的进行合并
    for i in range(q):
        if 0 in num_bins[0][2:]:
            num_bins[0:2] = [(
                num_bins[0][0],
                num_bins[1][
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值