在信贷的风控模型中最常用、最经典的可能要属评分卡了,所谓评分卡就是给信贷客户进行打分,按照不同业务场景可为贷前、贷中、贷后和反欺诈,一般叫做ABCF卡。模型得到分数,通过设置cutoff阈值给出评估结果,结果可直接用于通过或拒绝,或者用于策略应用。
区别于xgb等机器学习模型,评分卡使用逻辑回归,之所是还在使用时因为它属于广义线性回归,在特征的解释性上非常的强。
本次和大家分享一个开源的评分卡神器toad
。从数据探索、特征分箱、特征筛选、特征WOE变换、建模、模型评估、转换分数,都做了完美的包装,可以说是一条龙的服务啊,极大的简化了建模人员的门槛。
并且东哥也仔细看过源码,基本都是通过numpy
来实现的,并且部分过程还使用了多线程提速,所以在速度上也是有一定保障的。
下面就介绍如何使用toad
建立评分卡的整个流程。安装就不说了,标准的方法,自行pip
安装。
一、读取数据、划分样本集
首先通过read_csv
读取数据,看看数据概况。
data = pd.read_csv('train.csv') print('Shape:',data.shape) data.head(10)
Shape: (108940, 167)
这个测试数据有10万条数据,167个特征。
print('month:',data.month.unique())
month: ['2019-03' '2019-04' '2019-05' '2019-06' '2019-07']
通过观察时间变量,我们发现数据的时间跨度为2019年5月到7月。为了真正测试模型效果,我们将用3月和4月数据用于训练样本,5月、6月、7月数据作为时间外样本,也叫作OOT的跨期样本。
train = data.loc[data.month.isin(['2019-03','2019-04'])==True,:] OOT = data.loc[data.month.isin(['2019-03','2019-04'])==False,:] #train = data.loc[data.month.isin(['Mar-19','Apr-19'])==True,:] #OOT = data.loc[data.month.isin(['Mar-19','Apr-19'])==False,:] print('train size:',train.shape,'\nOOT size:',OOT.shape)
train size: (43576, 167) OOT size: (65364, 167)
其实,这部分属于模型设计的阶段,是非常关键的环节。实际工作中会考虑很多因素,要结合业务场景,根据样本量、可回溯特征、时间窗口等因素制定合适的观察期、表现期、以及样本,并且还要定义合适的Y标签。本次主要介绍toad
的用法,上面的设计阶段先忽略掉。
二、EDA相关功能
1. toad.detect
EDA也叫数据探索分析,主要用于检测数据情况。toad
输出每列特征的统计性特征和其他信息,主要的信息包括:缺失值、unique values、数值变量的平均值、离散值变量的众数等。
toad.detect(train)[:10]
2. toad.quality
这个功能主要用于帮助我们进行变量的筛选,可以直接计算各种评估指标,如iv值、gini指数,entropy熵,以及unique values
,结果以iv值排序。target
为目标列,iv_only
决定是否只输出iv值。
to_drop = ['APP_ID_C','month'] # 去掉ID列和month列 toad.quality(data.drop(to_drop,axis=1),'target',iv_only=True)[:15]
注意:1. 对于数据量大或高维度数据,建议使用iv_only=True 2. 要去掉主键,日期等高unique values且不用于建模的特征
但是,这一步只是计算指标而已,呈现结果让我们分析,还并没有真的完成筛选的动作。
三、特征筛选
toad.selection.select
前面通过EDA检查过数据质量后,我们会有选择的筛选一些样本和变量,比如缺失值比例过高的、IV值过低的、相关性太强的等等。
empyt=0.9
: 缺失值大于0.9的变量被删除iv=0.02
: iv值小于0.02的变量被删除corr=0.7
: 两个变量相关性高于0.7时,iv值低的变量被删除return_drop=False
: 若为True,function将返回被删去的变量列exclude=None
: 明确不被删去的列名,输入为list格式
用法很简单,只要通过设置以下几个参数阈值即可实现,如下:
train_selected, dropped = toad.selection.select(train,target = 'target', empty = 0.5, iv = 0.05, corr = 0.7, return_drop=True, exclude=['APP_ID_C','month']) print(dropped) print(train_selected.shape)
经过上面的筛选,165个变量最终保留了32个变量。并且返回筛选过后的dataframe
和被删掉的变量列表。
当然了,上面都是一些常规筛选变量的方法,可能有些特殊的变量比如从业务角度很有用是需要保留的,但不满足筛选要求,这时候可以用exclude
排除掉。这个功能对于变量初筛非常有用,各种指标直接计算并展示出来。
四、分箱
在做变量的WOE变换之前需要做变量的分箱,分箱的好坏直接影响WOE的结果,以及变换后的单调性。toad
将常用的分箱方法都集成了,包括等频分箱、等距分箱、卡方分箱、决策树分箱、最优分箱等。
并且,toad
的分箱功能支持数值型数据和离散型分箱。 这部分东哥看过源码,toad
首先判断变量类型,如果为数值型就按数值型分箱处理,如果为非数值型,那么会判断变量唯一值的个数,如果大于10个或者超过变量总数的50%,那么也按照数值型处理。
另外,toad
还支持将空值单独分箱处理。
分箱步骤如下:
- 初始化:c =
toad.transform.Combiner()
- 训练分箱:
c.fit(dataframe, y = 'target', method = 'chi', min_samples = None, n_bins = None, empty_separate = False)
- y: 目标列
- method: 分箱方法,支持chi(卡方分箱), dt(决策树分箱), kmean, quantile, step(等步长分箱)
- min_samples: 每箱至少包含样本量,可以是数字或者占比
- n_bins: 箱数,若无法分出这么多箱数,则会分出最多的箱数
- empty_separate: 是否将空箱单独分开
- 查看分箱节点:
c.export()
- 手动调整分箱:
c.load(dict)
- apply分箱结果:
c.transform(dataframe, labels=False):
labels
: 是否将分箱结果转化成箱标签。False时输出0,1,2…(离散变量根据占比高低排序),True输出(-inf, 0], (0,10], (10, inf)。
注意:做筛选时要删去不需要分箱的列,特别是ID列和时间列。
# initialise c = toad.transform.Combiner() # 使用特征筛选后的数据进行训练:使用稳定的卡方分箱,规定每箱至少有5%数据, 空值将自动被归到最佳箱。 c.fit(train_selected.drop(to_drop, axis=1), y = 'target', method = 'chi', min_samples = 0.05) #empty_separate = False # 为了演示,仅展示部分分箱 print('var_d2:',c.export()['var_d2']) print('var_d5:',c.export()['var_d5']) print('var_d6:',c.export()['var_d6'])
结果输出:
var_d2: [747.0, 782.0, 820.0] var_d5: [['O', 'nan', 'F'], ['M']] var_d6: [['PUBLIC LTD COMPANIES', 'NON-RESIDENT INDIAN', 'PRIVAT