当前位置: 首页 > news >正文

【项目实战】金融风控之信用评分卡模型

一、背景介绍

信用风险计量体系包括主体评级模型和债项评级两部分。
主体评级和债项评级均有一系列评级模型组成,其中主体评级模型可用“四张卡”来表示,分别是A卡(贷前申请评分卡)、B卡(贷中行为评分)、C卡(贷后评分卡)和F卡(贷前反欺诈评分卡);债项评级模型通常按照主体的融资用途,分为企业融资模型、现金流融资模型和项目融资模型等。 我们主要讨论主体评级模型的开发过程。

二、项目流程

主要开发流程如下:
1)数据获取,包括机构客户和个人客户;
2)数据预处理,包括数据清洗、缺失值处理、异常值处理;
3)探索性数据分析,获取样本总体的大概情况,描述样本总体情况的指标主要有直方图、箱型图等;
4)变量选择,该步骤主要通过统计学的方法,筛选出对违约状态影响最显著的指标。主要有单变量特征选择方法和基于机器学习模型的方法;
5)模型开发,该步骤主要包括变量分段、变量的WOE(证据权重)变换和逻辑回归估算三部分;
6)模型评估,该步骤主要是评估模型的区分能力、预测能力、稳定性,并形成模型评估报告,得出模型是否可以使用的结论;
7)信用评分,根据逻辑回归的系数和WOE等确定信用评分的方法。将logistic模型转换为标准评分的形式;
8)建立评分系统,根据信用评分方法,简历自动信用评分系统;

三、数据集介绍

以下给出该数据集的前三行,是一个信用卡数据集,各个特征及其含义已给出

SeriousDlqin2yrsRevolvingUtilizationOfUnsecuredLinesageNumberOfTime30-59DaysPastDueNotWorseDebtRatioMonthlyIncomeNumberOfOpenCreditLinesAndLoansNumberOfTimes90DaysLateNumberRealEstateLoansOrLinesNumberOfTime60-89DaysPastDueNotWorseNumberOfDependents
10.7661266094520.8029829120130602
00.9571510194000.121876201260040001
00.658180143810.085113375304221000

SeriousDlqin2yrs:是否是好客户,其中好客户为0,违约客户为1
RevolvingUtilizationOfUnsecuredLines:无担保循环信贷额度使用率
age :年龄
NumberOfTime30-59DaysPastDueNotWorse:逾期30-59天且未恶化次数
DebtRatio :负债比率
NumberOfOpenCreditLinesAndLoans:未结清信贷额度与贷款数量
NumberOfTimes90DaysLate:逾期90天的次数
NumberRealEstateLoansOrLines:房地产贷款或额度数量
NumberOfTime60-89DaysPastDueNotWorse:逾期60-89天次数未恶化
NumberOfDependents:抚养人数

可以看到labelY即是SeriousDlqin2yrs,我们需要用剩余的特征去预测一个样本是否延期。

3.0 特征解读

1、RevolvingUtilizationOfUnsecuredLines无担保循环信贷额度使用率
计算公式:使用率 = (所有循环信贷账户的当前总欠款 / 所有循环信贷账户的总授信额度) × 100%

使用率高低有什么影响?

  • 对个人信用评分
    • 高使用率(>30%):会被解读为过度依赖信贷、财务状况紧张,从而拉低信用评分。银行会认为你的违约风险较高;
    • 低使用率(<30%):表明你管理信贷的能力良好,是负责人借款人的信号,有助于提升信用评分。
  • 对带宽审批和额度管理
    • 影响新贷款审批:即使未使用的额度不计入负债,但银行在审批房贷、车贷时,会关注你的总授信和近期平均使用率。过高的手心总额或过多的信贷账户,都可能让银行认为你“资金紧张”而变得谨慎。
    • 触发风控导致“锁额”:如果每次都把额度用尽,风控系统会判定“资金缺口过大,风险过高”,可能导致额度被冻结或降低。相反,如果额度长期闲置不用,平台也可能判定你需求低而主动降低额度。

该数据是数值型数据,以下展示其训练集的分布

2、逾期指标

  • NumberOfTime30-59DaysPastDueNotWorse (30-59天):衡量轻微、早期的逾期行为;
  • NumberOfTime60-89DaysPastDueNotWorse (60-89天):衡量中等程度的逾期行为;
  • NumberOfTimes90DaysLate (90天及以上):衡量严重的逾期行为,这通常被直接定义为“坏账”或“违约”的代理变量。
    与M0\M1\M2的对应关系如下:
行业术语对应逾期天数本项目特征名称
M0无逾期/逾期1-29天-
M1逾期30-59天NumberOfTime30-59DaysPastDueNotWorse
M2逾期60-89天NumberOfTime60-89DaysPastDueNotWorse
M3逾期90-119天NumberOfTimes90DaysLate

其他的指标比如DebtRatio负债比率、NumberOfOpenCreditLinesAndLoans未结清信贷额度与贷款数量、NumberRealEstateLoansOrLines房地产贷款或额度数量、NumberOfDependents受抚养人数较好理解,此处不做过多赘述。

3.1探索性数据分析

拿到一个数据集,我习惯是先看看整个数据的大小、分布、以及缺失值情况

3.1.1数据集基本信息

(0)数据读取

#载入数据data=pd.read_csv('cs-training.csv')

(1)数据集大小

""" 探索性数据分析 """data.shape data.columns data.info()

3.2 数据清洗

3.2.1 缺失值处理

""" 缺失值 """# 判断哪些列有空值data.isnull().any()# 每列空值的数量data.isnull().sum()

可以看到MonthlyIncome、NumberOfDependents有空值。
由于NumberOfDependents缺失样本仅占整个训练集的2.6%,故直接删除NumberOfDependents缺失的样本。
接下来采用随机森林的方法对MonthlyIncome进行缺失值补全

# 用随机森林对缺失值预测填充函数defset_missing(df):# 把已有的数值型特征取出来process_df=df.iloc[:,[5,0,1,2,3,4,6,7,8,9]]# 分成已知该特征和未知该特征两部分known=process_df[process_df.MonthlyIncome.notnull()].as_matrix()unknown=process_df[process_df.MonthlyIncome.isnull()].as_matrix()# X为特征属性值X=known[:,1:]# y为结果标签值y=known[:,0]# fit到RandomForestRegressor之中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)print(predicted)# 用得到的预测结果填补原缺失数据df.loc[(df.MonthlyIncome.isnull()),'MonthlyIncome']=predictedreturndf data=set_missing(data)#用随机森林填补比较多的缺失值data=data.dropna()#删除比较少的缺失值data=data.drop_duplicates()#删除重复项data.to_csv('MissingData.csv',index=False)

3.2.2 异常值处理

缺失值处理完毕后,我们还需要进行异常值处理。异常值是指明显偏离大多数抽样数据的数值,比如个人客户的年龄为0时,通常认为该值为异常值。找出样本总体中的异常值,通常采用离群值检测的方法。
首先,我们发现变量age中存在0,显然是异常值,直接剔除:

# 年龄等于0的异常值进行剔除data=ata[data['age']>0]

对于变量NumberOfTime30-59DaysPastDueNotWorse、NumberOfTimes90DaysLate、NumberOfTime60-89DaysPastDueNotWorse这三个变量,均存在异常值,且由unique函数可以得知均存在96、98两个异常值,因此予以剔除。同时会发现剔除其中一个变量的96、98值,其他变量的96、98两个值也会相应被剔除。
剔除变量NumberOfTime30-59DaysPastDueNotWorse、NumberOfTimes90DaysLate、NumberOfTime60-89DaysPastDueNotWorse的异常值。另外,数据集中好客户为0,违约客户为1,考虑到正常的理解,能正常履约并支付利息的客户为1,所以我们将其取反。

#剔除异常值data=data[data['NumberOfTime30-59DaysPastDueNotWorse']<90]#变量SeriousDlqin2yrs取反data['SeriousDlqin2yrs']=1-data['SeriousDlqin2yrs']

3.2.3 数据切分

from sklearn.cross_validation import train_test_split
Y=data['SeriousDlqin2yrs']X=data.ix[:,1:]#测试集占比30%X_train,X_test,Y_train,Y_test=train_test_split(X,Y,test_size=0.3,random_state=0)# print(Y_train)train=pd.concat([Y_train,X_train],axis=1)test=pd.concat([Y_test,X_test],axis=1)clasTest=test.groupby('SeriousDlqin2yrs')['SeriousDlqin2yrs'].count()train.to_csv('TrainData.csv',index=False)test.to_csv('TestData.csv',index=False)

3.3 探索性数据分析

在建立模型前,通常会对现有数据进行探索性数据分析,这样可以帮助我们初步了解数据分布,在尽量少的先验假定下进行探索。常用的探索性数据分析方法有:直方图、散点图、箱线图等。


以上是对客户年龄分布的可视化,可以看到大体是呈现正态分布的。

3.4变量选择

3.4.1分箱处理

变量分箱是连续变量离散化的一种方法。信用评分卡开发中一般常用等距分段、等深分段和最优分段:

  • 等距分段:分段的区间宽度一致,比如年龄以十年为一个分段
  • 等深分段:先确定分段数量,然后令每个分段中的样本数量大致相等
  • 最优分段(监督离散化):利用目标变量的信息,将连续变量转化为能最大化其预测能力的离散变量
    等距分段和等深分段很好理解,此处着重介绍最优分段。
  • 常见的最优分段算法
    • 基于决策树的方法:利用决策树的生长和剪枝过程来寻找最佳分割点,其中最小描述长度原则是常用的一种,它能自动平衡模型复杂度与拟合效果,避免过拟合。
    • 基于合并的方法:先进行非常细致的预分箱,然后根据某种准则(如卡方检验的P值)迭代地合并相邻箱子,直到满足停止条件。
    • 最优化方法:将分箱问题转化为一个有约束的数学优化问题,通过算法(如分支定界法)搜索在满足约束(如单调性)下使用目标函数(如信息值Ⅳ)最大的分箱方案。
  • 为什么使用最优分箱
    • 提升模型预测能力:可更好捕捉特征与目标之间的非线性关系
    • 增强模型可解释性
    • 处理数据异常值
    • 满足特定弄醒要求
      在本项目中,首先选择对连续变量进行最优分段,在连续变量的分布不满足最优分段的要求时,再考虑对连续变量进行等距分段
# 定义自动分箱函数defmono_bin(Y,X,n=20):r=0good=Y.sum()bad=Y.count()-goodwhilenp.abs(r)<1:d1=pd.DataFrame({"X":X,"Y":Y,"Bucket":pd.qcut(X,n)})d2=d1.groupby('Bucket',as_index=True)r,p=stats.spearmanr(d2.mean().X,d2.mean().Y)n=n-1d3=pd.DataFrame(d2.X.min(),columns=['min'])d3['min']=d2.min().X d3['max']=d2.max().X d3['sum']=d2.sum().Y d3['total']=d2.count().Y d3['rate']=d2.mean().Y d3['woe']=np.log((d3['rate']/(1-d3['rate']))/(good/bad))d3['goodattribute']=d3['sum']/good d3['badattribute']=(d3['total']-d3['sum'])/bad iv=((d3['goodattribute']-d3['badattribute'])*d3['woe']).sum()d4=(d3.sort_index(by='min'))print("="*60)print(d4)cut=[]cut.append(float('-inf'))foriinrange(1,n+1):qua=X.quantile(i/(n+1))cut.append(round(qua,4))cut.append(float('inf'))woe=list(d4['woe'].round(3))returnd4,iv,cut,woe

此段代码用于分箱的核心是通过暴力搜索,直到分箱后的X和分箱后的Y的Spearman相关系数的绝对值为1。之后,其关键的几个步骤是:
1)计算证据权重WOE
若指标越大代表风险越低(资质越好),即指标越大,好客户越多,则WOE随指标增大而增大;若指标越大代表风险越大(资质越差),即指标越大,好客户越少,则WOE随指标增大而减小。

趋势特征含义说明
斜率的绝对值越大区分能力越强指标值的小幅变化就能引起WOE的大幅波动,说明该指标能很好区分好/坏客户
斜率小或接近水平区分能力弱WOE值几乎不随指标变化,说明无论指标取值如何,客户风险分布差不多,这个指标没用
近似直线通常较好表示指标与风险之间存在稳定的线性关系,便于评分卡解释。若斜率太小,则区分力弱

2)计算信息值IV
IV值的作用:衡量特征“含金量”的最直接标尺,可以根据数值大小将特征划分为不同等级,直接决定是否剔除该变量。

IV值范围预测能力处理建议
< 0.02无预测能力直接剔除
0.02~0.10弱预测能力保留备用
0.10~0.30中等预测能力有效可用,常用于模型组合
0.30~0.50强预测能力优质特征,模型首选
> 0.50预测能力极强建议谨慎/暂缓(可能存在过拟合或数据泄露风险,需人工审查)
  • 注意事项
    • IV值只能用于二分类
    • 分箱数量影响IV值:分箱越多,IV值越高(易过拟合)。因此计算IV值时,必须先进行合理的预分箱,不能用原始值直接算
    • 极端IV值(>0.5)往往有问题
      我们将数据集中RevolvingUtilizationOfUnsecuredLines到NumberOfDependents这10个自变量分别定义为x1-x10,通过以下代码计算他们的IV值并绘制条形图:
corr=data.corr()#计算各变量的相关性系数xticks=['x0','x1','x2','x3','x4','x5','x6','x7','x8','x9','x10']#x轴标签yticks=list(corr.index)#y轴标签fig=plt.figure()ax1=fig.add_subplot(1,1,1)sns.heatmap(corr,annot=True,cmap='rainbow',ax=ax1,annot_kws={'size':9,'weight':'bold','color':'blue'})#绘制相关性系数热力图ax1.set_xticklabels(xticks,rotation=0,fontsize=10)ax1.set_yticklabels(yticks,rotation=0,fontsize=10)plt.show()


根据前述基于IV值筛选变量的标准,删除了IV值小于0.1的5个变量,即DebtRatio、MonthlyIncome、NumberOfOpenCreditLinesAndLoans、NumberRealEstateLoansOrLines、NumberOfDependents。好坏用户居然跟负债率和月收入的关系较低,很出乎意料!

四、模型分析

4.1 WOE转换

# 替换成woecol_names=['RevolvingUtilizationOfUnsecuredLines','age','NumberOfTime30-59DaysPastDueNotWorse','DebtRatio','MonthlyIncome','NumberOfOpenCreditLinesAndLoans','NumberOfTimes90DaysLate','NumberRealEstateLoansOrLines','NumberOfTime60-89DaysPastDueNotWorse','NumberOfDependents']cut_list=[cutx1,cutx2,cutx3,cutx4,cutx5,cutx6,cutx7,cutx8,cutx9,cutx10]woe_list=[woex1,woex2,woex3,woex4,woex5,woex6,woex7,woex8,woex9,woex10]forcol,cut,woeinzip(col_names,cut_list,woe_list):data[col]=pd.cut(data[col],bins=cut,labels=woe,include_lowest=True)data.to_csv('WoeData.csv',index=False)

4.2 逻辑回归模型建立

# 逻辑回归模型建立importstatsmodels.apiassm data=pd.read_csv('WoeData.csv')#应变量Y=data['SeriousDlqin2yrs']#自变量,剔除对因变量影响不明显的变量X=data.drop(['SeriousDlqin2yrs','DebtRatio','MonthlyIncome','NumberOfOpenCreditLinesAndLoans','NumberRealEstateLoansOrLines','NumberOfDependents'],axis=1)X1=sm.add_constant(X)logit=sm.Logit(Y,X1)result=logit.fit()print(result.summary())


由上图知,逻辑回归各变量都通过显著性检验,满足要求

http://www.jsqmd.com/news/1195797/

相关文章:

  • 2026年7月最新亨得利官方服务项目及价格查询|详细网点地址及客服热线权威信息通告 - 亨得利官方
  • 惠阳黄金回收怎么卖不亏?2026最新行情+辨伪干货+本地正规渠道排名 - 生活测评小能手
  • C++内存访问优化:突破内存墙的缓存友好编程实践
  • 2026年7月最新嘉兴浪琴官方售后服务网点地址及客服电话一览 - 浪琴官方售后服务中心
  • GEO效果监测与数据分析:构建AI搜索优化评估体系
  • 【AI编程IDE视图管理权威白皮书】:基于127家技术团队调研数据,揭示视图切换响应延迟超300ms的5大底层诱因
  • 博客重构三次后的心得
  • 《机械工厂6S白皮书03|第2章 诊断核心:四步熵增定位法——穿透表面乱象,精准锁定机械车间混乱的真实病灶》
  • 龍魂系统 · 国家补贴点对点直发审计协议 v1.0
  • Long — 中小学生综合 Web 学习平台
  • 生鲜配送APP开发全攻略:三大角色功能一次理清,别再花冤枉钱
  • 百达翡丽中国官方售后服务中心|服务热线及具体地址权威信息声明(2026年7月最新) - 百达翡丽官方售后中心
  • 2026 年现阶段,上海到天津食品冷链物流服务团队哪个好,冷链出事:天津食品如何保住口感的秘密? - 行业推荐官【官方】
  • 亲身探访广州劳力士官方售后服务中心|官方热线及全部网点地址(2026年7月最新) - 劳力士官方服务中心
  • HarmonyOS7 ArkUI 实战:Toggle、Checkbox、Radio 构建应用设置页
  • 本地如何把github项目拉到服务器上
  • Python自然语言处理实战:NLTK核心功能与应用解析
  • 戴尔G15不开机故障排查:供电芯片短路诊断与维修指南
  • winfromTool
  • ChatGPT学英语到底有多高效?实测300小时对比传统方法,词汇记忆提速2.8倍(独家实验报告)
  • 手把手教你学pcie--PCIe 和 PCI / PCI-X 到底有什么区别?
  • 蓝牙协议栈与核心规范:从广播到连接的通信基石
  • ChatGPT写小说到底靠不靠谱?实测327部网文样稿后,我总结出这5个致命陷阱与破局公式
  • 浪琴中国官方售后服务中心|全新地址及服务热线权威信息公告(2026年7月最新) - 浪琴服务中心
  • 2026 上海奢品回收实力榜单解读,奢二网综合优势详细分析 - 讯息早知道
  • 【避坑】Claude 4.8 真实测评:这三个致命缺点没人告诉你!
  • 普通电子签名靠不住?数字签名凭什么更安全
  • 深度拆解市场四类 Qi 伪认证套路,工厂采购风控指南
  • 传统文化数字化:3D建模与AI生成技术在神话角色创作中的应用
  • 9. 【Java】运算符