说到评分卡建模工具,做过评分卡的应该都能想到谢博士的scorecardpy和专为工业界模型开发设计的Python工具包--Toad,两者相比,scorecardpy更加轻量级,且依赖较少,可以满足大多数场景下的评分卡构建。
为了使评分卡建模流程更加便捷,该Python包针对建模中各个关键步骤都提供了现成的函数,如下:
数据集划分 (split_df)
变量筛选(iv, var_filter)
变量分箱(woebin, woebin_plot, woebin_adj, woebin_ply)
分数转换(scorecard, scorecard_ply)
效果评估(perf_eva, perf_psi)
基于github主页上提供的案例,对每一步操作进行详细解读:
数据准备
import scorecardpy as sc # 加载德国信用卡相关数据集 dat = sc.germancredit()
得到的数据集情况如下:
变量筛选
然后根据变量的缺失率、IV值、同值性等因素,对20个变量进行筛选,并对目标变量进行标记,该数据集中creditability为目标变量:
dt_s = sc.var_filter(dat, y="creditability")
通过 var_filter() 函数筛选后,数据集保留以下13个变量:
默认的参数配置为:iv_limit=0.02, missing_limit=0.95, identical_limit=0.95,即当某个变量的 IV 值小于0.02,或缺失率大于95%,或同值率(除空值外)大于95%,则剔除掉该变量。
此外,该方法还内置了除上述以外的其他参数:
def var_filter(dt, y, x=None, iv_limit=0.02, missing_limit=0.95, identical_limit=0.95, var_rm=None, var_kp=None, return_rm_reason=False, positive='bad|1')
其中各参数含义如下:
varrm可设置强制保留的变量,默认为空;
varkp可设置强制剔除的变量,默认为空;
return_rm_reason可设置是否返回剔除原因,默认为不返回(False);
positive可设置坏样本对应的值,默认为“bad|1”。
数据集划分
将数据集划分成训练集和测试集:
train, test = sc.split_df(dt_s, 'creditability').values()
split_df()函数包括以下参数:
def split_df(dt, y=None, ratio=0.7, seed=186)
默认的切分比例为7:3,也可自行修改参数ratio设置不同的切分比例。
变量分箱
可通过woebin()函数对全部变量进行自动分箱,并基于woe_bin的结果,使用woebin_plot对各变量分箱的count distribution和bad probability进行可视化,可观察是否存在单调性:
bins = sc.woebin(dt_s, y="creditability") sc.woebin_plot(bins)
bins为字典形式,以变量名作为key,可获得单个变量的分箱结果详情:
woebin_plot()得到的可视化结果如下:
woebin()函数包括如下参数:
def woebin(dt, y, x=None, var_skip=None, breaks_list=None, special_values=None, stop_limit=0.1, count_distr_limit=0.05, bin_num_limit=8, # min_perc_fine_bin=0.02, min_perc_coarse_bin=0.05, max_num_bin=8, positive="bad|1", no_cores=None, print_step=0, method="tree", ignore_const_cols=True, ignore_datetime_cols=True, check_cate_num=True, replace_blank=True, save_breaks_list=None, **kwargs)
woebin()可针对数值型和类别型变量生成最优分箱结果,方法可选择决策树分箱、卡方分箱或自定义分箱。其他各参数的含义如下:
var_skip: 设置需要跳过分箱操作的变量;
breaks_list: 切分点列表,默认为空。如果非空,则按设置的切分点进行分箱处理。
special_values: 设置需要单独分箱的值,默认为空。
count_distr_limit: 设置分箱占比的最小值,一般可接受范围为0.01-0.2,默认值为0.05;
stop_limit: 当IV值的增长率小于所设置的stop_limit,或卡方值小于qchisq(1-stoplimit, 1)时,停止分箱。一般可接受范围为0-0.5,默认值为0.1;
bin_num_limit: 该参数为整数,代表最大分箱数。
positive: 指定样本中正样本对应的标签,默认为"bad|1";
no_cores: 设置用于并行计算的 CPU 数目;
print_step: 该参数为非负数,默认值为1。若print_step>0,每次迭代会输出变量名。若iteration=0或no_cores>1,不会输出任何信息;
method: 设置分箱方法,可设置"tree"(决策树)或"chimerge"(卡方),默认值为"tree";
ignore_const_cols: 是否忽略常数列,默认值为True,即忽略常数列;
ignore_datetime_cols: 是否忽略日期列,默认值为True,即忽略日期列;
check_cate_num: 检查类别变量中枚举值数目是否大于50,默认值为True,即自动进行检查。若枚举值过多,会影响分箱过程的速度;
replace_blank: 设置是否将空值填为None,默认为True。
若对自动分箱结果不满意,还可手动自定义分箱:
breaks_adj = { 'age.in.years': [26, 35, 40], 'other.debtors.or.guarantors': ["none", "co-applicant%,%guarantor"] } bins_adj = sc.woebin(dt_s, y="creditability", breaks_list=breaks_adj)
于是年龄变量的分箱结果变成:
分箱完成后,使用woebin_ply()函数对变量进行woe变换,之后需要把所得到的woe值作为模型的输入:
train_woe = sc.woebin_ply(train, bins_adj) test_woe = sc.woebin_ply(test, bins_adj)
模型训练
y_train = train_woe.loc[:,'creditability'] X_train = train_woe.loc[:,train_woe.columns != 'creditability'] y_test = test_woe.loc[:,'creditability'] X_test = test_woe.loc[:,train_woe.columns != 'creditability'] # 逻辑回归 ------ from sklearn.linear_model import LogisticRegression lr = LogisticRegression(penalty='l1', C=0.9, solver='saga', n_jobs=-1) lr.fit(X_train, y_train) lr.coef_ lr.intercept_ # 预测 train_pred = lr.predict_proba(X_train)[:,1] test_pred = lr.predict_proba(X_test)[:,1]
效果评估
可使用perf_eva()函数对模型效果进行计算及可视化,基于预测的概率值和label值,提供KS(kolmogorov-smirnow), ROC, lift以及precision-recall四种评估指标:
train_perf = sc.perf_eva(y_train, train_pred, title = "train") test_perf = sc.perf_eva(y_test, test_pred, title = "test")
该函数还包括以下参数:
def perf_eva(label, pred, title=None, groupnum=None, plot_type=["ks", "roc"], show_plot=True, positive="bad|1", seed=186)
参数plot_type可设置为:"ks", "lift", "roc", "pr",默认为["ks", "roc"]。
分数转换
然后基于’woebin'的结果和sklearn.linear_model的LogisticRegression,创建scorecard()函数,用于构建评分卡,只需一行代码:
card = sc.scorecard(bins_adj, lr, X_train.columns)
生成的结果为各变量名及其分箱、对应得分组成的字典,例如:
scorecard()包括以下参数:
def scorecard(bins, model, xcolumns, points0=600, odds0=1/19, pdo=50, basepoints_eq0=False, digits=0)
各参数含义如下:
bins:由`woebin`得到的分箱信息;
model:LogisticRegression模型对象;
points0:基准分数,默认值为600;
odds0: 基准 Odds(好坏比),与真实违约概率对应,可换算得到违约概率,Odds = p/(1-p)。默认值为 1/19;
pdo: Points toDouble theOdds,即Odds变成2倍时,所增加的信用分。默认值为50。
然后基于`scorecard`的结果,用scorecard_ply()函数计算train和test数据集的信用分数:
train_score = sc.scorecard_ply(train, card, print_step=0) test_score = sc.scorecard_ply(test, card, print_step=0)
直接生成各样本的评分:
最后用perf_psi()得到该评分卡在测试数据集上的表现:
sc.perf_psi( score = {'train':train_score, 'test':test_score}, label = {'train':y_train, 'test':y_test} )
perf_psi()可计算群体稳定性指标(PSI),并提供信用分数的分布图:
参考资料
scorecardpy github主页:https://github.com/ShichenXie/scorecardpy
回复【算法】,获取最全面的机器学习算法网络图: