Blog > 使用 R 语言开发评分卡模型
使用 R 语言开发评分卡模型
By 谢士晨 in CreditRisk
January 5, 2018
为了提高评分卡模型的开发效率,我为 R 语言社区贡献了一个开源项目 scorecard 包 (HomePage, Github, CRAN)。该 R 包提供了评分卡开发过程中的常用功能,包括变量粗筛、分箱与 woe 转换、模型评估、评分刻度转换等。
评分卡模型的开发流程通常包括以下五个主要步骤:数据准备、WOE 分箱、模型拟合、模型评估、评分卡刻度。下面结合 scorecard 包完成一个简单的评分卡模型开发案例。更加详细的评分卡模型开发介绍请参考幻灯片。
数据准备
首先加载 scorecard 包,并载入包内自带的德国信贷数据集。该数据集包含了1000个借款人的信贷数据,20个 X 特征与1个 Y 值。其详细信息参见 UCI 的德国信贷数据集网站。
library(scorecard)
# load germancredit data
data(germancredit)
载入数据集后,可先通过变量的 IV 值、缺失率以及单类别率对 X 特征进行初步筛选。var_filter 函数默认删除信息值小于0.02、缺失率大于95%或单类别比例大于95%的变量。var_filter 函数还能够人为设定需要删除或保留的变量,以及够返回变量删除的原因列表。
# filter variable via missing rate, iv, identical rate
dt = var_filter(germancredit, y = 'creditability')
## ✔ 1 variables are removed via identical_rate
## ✔ 6 variables are removed via info_value
## ✔ Variable filtering on 1000 rows and 20 columns in 00:00:00
## ✔ 7 variables are removed in total
将经过初筛的数据集拆分为训练集与测试集。在 split_df 函数中如果指定了 y 变量,那么将基于 y 变量分层拆分,如果没有指定,则随机拆分数据集。ratio 为拆分后两个数据集的样本量占比。 seed 为随机种子,用于重现拆分的样本。
# breaking dt into train and test
dt_list = split_df(dt, y="creditability", ratio = 0.6, seed = 30)
## Warning in split_df.data.frame(dt, y = "creditability", ratio = 0.6, seed = 30):
## The ratios is set to c(0.6, 0.4)
label_list = lapply(dt_list, function(x) x$creditability)
WOE分箱
接下来对数据集进行分箱与 woe 值转换。由于这个数据集样本量比较小,我们可以直接对全样本进行分箱处理。如果数据量允许,应该使用训练集进行分箱,并使用训练集得到的 woe 值对其他数据集进行woe替换。
woebin 函数提供了树形 tree、卡方合并 chimerge、等宽 width 与等高 freq 四种分箱方法。以树形分箱为例,默认情形是当信息值增益率 stop_limit 小于0.1, 或分箱数 bin_num_limit 大于8(缺失值除外)时停止分箱,同时确保每一个分箱的样本占比 count_distr_limit 不小于5%。当然还能够通过 breaks_list 手动设定分箱节点。
woebin 函数输出的结果为多个 data.frame 组成的 list,可通过 data.table::rbindlist 或 dplyr::bind_rows 函数合并为一个数据框然后保存。当然 woebin 函数也能够直接输出一个由分箱切割点组成的 list 并保存,下次使用时直接通过 woebin 函数对 breaks_list 参数对新的数据集进行分箱。
woebin_adj 函数可逐个观察每个变量的分箱情况。如果不满意默认的分箱结果,可以手动修改。最终返回一个经过手动调整的分箱节点。
分箱之后,需要使用 woebin_ply 函数将训练集与测试集转换为对应的 woe 值。
# woe binning
bins = woebin(dt, "creditability", print_step=0)
## ℹ Creating woe binning ...
## ✔ Binning on 1000 rows and 14 columns in 00:00:01
bins[[12]]
## variable bin count count_distr neg pos posprob
## 1: other.installment.plans bank%,%stores 186 0.186 110 76 0.4086022
## 2: other.installment.plans none 814 0.814 590 224 0.2751843
## woe bin_iv total_iv breaks is_special_values
## 1: 0.4775508 0.04593584 0.05759207 bank%,%stores FALSE
## 2: -0.1211786 0.01165623 0.05759207 none FALSE
woebin_plot(bins[[12]])
## $other.installment.plans
# converting train and test into woe values
dt_woe_list = lapply(dt_list, function(x) woebin_ply(x, bins))
## ℹ Converting into woe values ...
## ✔ Woe transformating on 620 rows and 13 columns in 00:00:00
## ℹ Converting into woe values ...
## ✔ Woe transformating on 380 rows and 13 columns in 00:00:00
模型拟合
当获得了 woe 值替换之后的数据集,可以使用逻辑回归进行拟合,并通过AIC、LASSO等方法对变量进一步筛选。下面使用基于 AIC 的逐步回归进一步筛选变量,最终得到了一个拥有13个变量的模型。
# lr
m1 = glm( creditability ~ ., family = binomial(), data = dt_woe_list$train)
# vif(m1, merge_coef = TRUE) # summary(m1)
# Select a formula-based model by AIC (or by LASSO for large dataset)
m_step = step(m1, direction="both", trace = FALSE)
m2 = eval(m_step$call)
vif(m2, merge_coef = TRUE) # summary(m2)
## variable Estimate
## 1: (Intercept) -0.9447617
## 2: status.of.existing.checking.account_woe 0.7755755
## 3: duration.in.month_woe 0.7962735
## 4: credit.history_woe 0.8308455
## 5: purpose_woe 0.8632479
## 6: credit.amount_woe 0.7669247
## 7: savings.account.and.bonds_woe 0.8545206
## 8: installment.rate.in.percentage.of.disposable.income_woe 1.8621446
## 9: other.debtors.or.guarantors_woe 2.1018289
## 10: age.in.years_woe 1.0153514
## 11: other.installment.plans_woe 0.7622579
## 12: housing_woe 0.7610232
## Std. Error z value Pr(>|z|) gvif
## 1: 0.1094 -8.6385 0.0000 NA
## 2: 0.1380 5.6189 0.0000 1.042054
## 3: 0.2291 3.4758 0.0005 1.180689
## 4: 0.2035 4.0823 0.0000 1.064307
## 5: 0.2755 3.1331 0.0017 1.042651
## 6: 0.2838 2.7021 0.0069 1.251179
## 7: 0.2606 3.2790 0.0010 1.038610
## 8: 0.6822 2.7296 0.0063 1.093569
## 9: 0.8922 2.3559 0.0185 1.036908
## 10: 0.3001 3.3831 0.0007 1.032968
## 11: 0.4347 1.7537 0.0795 1.059956
## 12: 0.3665 2.0767 0.0378 1.034594
模型评估
通过逻辑回归获得各变量的拟合系数之后,可以计算出各个样本为坏客户的概率,然后评估模型的预测效果。 perf_eva 函数能够计算的评估指标包括 mse, rmse, logloss, r2, ks, auc, gini,以及绘制多种可视化图形 ks, lift, gain, roc, lz, pr, f1, density。
## predicted proability
pred_list = lapply(dt_woe_list, function(x) predict(m2, x, type='response'))
## performance
perf = perf_eva(pred = pred_list, label = label_list)
评分卡刻度
当我们获得了各个变量的分箱结果,并且确定了最终进入模型的变量以及系数,则可以创建标准评分卡。
有了评分卡之后,可用于对新样本进行打分,从而评估该客户的信用水平,并最终作出审批决策。
最后,评分卡模型的开发过程,还需要对模型的稳定性进行评估,即计算psi。
## scorecard
card = scorecard(bins, m2)
## credit score
score_list = lapply(dt_list, function(x) scorecard_ply(x, card))
## psi
perf_psi(score = score_list, label = label_list)
## $pic
## $pic$score
##
##
## $psi
## variable dataset psi
## 1: score train_test 0.03933412
以上代码均可以在该项目的主页获取。