风控模型的一般步骤¶
在开始数据建模工作之前,博主其实看了蛮多关于数据挖掘的书籍。但是,真正从事数据建模工作后,可以说只能用 “纸上谈兵” 来形容自己,我甚至搞不清楚在数据建模分为几个阶段,要先做什么后做什么,模型原理更是一知半解。随着自我的学习以及大佬们的指教,慢慢懂得数据挖掘工作一般步骤与套路,熟记这些建模的步骤与讨论,能让你明确当前任务是什么,下一步任务又是什么,每一步任务中应该注意的一些问题。
下面内容为整理的对建模的一般步骤,内容也仅作参考。值得注意的是,这里的一般步骤只是建模的常规套路,关于模型的原理部分还需要自己去深入了解。
1. 明确问题的类型¶
机器学习中最常见的两类问题是有监督学习和无监督学习,关于其概念这里不做非常详细的解释,百度上有很好的博客解释这个概念,后续会有专门一篇博客讲解有监督学习和无监督学习的相关概念,以及都有哪些模型属于有监督学习,哪些模型属于无监督学习。
首先,需要明确的是需要解决的问题是属于哪一类问题,是有监督学习下的分类问题还是回归问题?还是无监督学习下的聚类问题等。接下来,需要先确定模型的 Target (即 \(y\)),也就是你最终想要预测的东西是什么。
对于大多数模型开发而言,本质上是为了解决业务上的实际问题,比如客户质量的分群、产品销售量的预测等等,所以理清楚模型应用的业务背景是非常重要的,这涉及到如何去定义模型的 Target,以及将来模型如何在实际场景中进行应用。
关于模型 Target 定义所花费的时间个人认为应该占到整个模型开发时间的 20%,这就好比在解数学题时如果审题不清,即便你洋洋洒洒写了一大篇解题过程,其实答案从一开始就是错误的。花了很多时间和精力去做模型的开发,最终发现模型开发好后没办法进行实际业务的应用。
关于模型 Target 的定义,你需要考虑以下几件事:
- 模型的 Target 如何定义?
- Target 的定义是否合理,是否与实际业务常识相悖?
- 开发好的模型将来如何在实际业务场景中进行应用?
本篇博客以最常见的二分类问题,讲述一下建模的一般步骤。
3. 数据准备¶
在明确了我们需要解决的问题属于哪一类问题之后,我们就可以基本确定使用哪些模型来解决这个问题。既然模型已经确定了,那么我们下一步就需要准备相应的数据来让模型进行训练。
3.1 时间窗口(Time Window)¶
首先需要确定数据的时间窗口,我们并不需要拿全部的数据进行模型训练,只需要挑选某些月份的数据来预测下一个月的结果(或者下一天),在进行时间窗口的选择,需要注意哪些月份的数据存在异常,避免模型开发进入到后期阶段,才被别人指出所选择时间窗口的数据在业务上存在着明显的异常,这样就就显得非常尴尬了。
在确定了时间窗口之后,我们需要确定 In-Time(IT) 和 Out-of-Time(OOT) ,以及 Validation(val,也可以看作是 oot2) 数据集。这里以 20181001 ~ 20190430 作为我们模型的时间窗口,那么 In-Time 数据集时间窗口可以选用 20181001 ~ 20190228,OOT 数据集的时间窗口为 20190301 ~ 20190331,Validation 数据集的时间窗口可以选用 20190401 ~ 20190430。
这里只是初步拟定各个数据集下的时间窗口,在后边变量创建完之后,还需要回过头来填写各个时间窗口下数据集的详细信息(数据量、正样本数量、Target Rate 等),保持一个良好的记录习惯,能让你在初步完成模型开发任务之后,能够很好地回溯整个过程以及发现其中的不足。
3.2 特征工程¶
各个时间窗口被确定下来之后,接下来就是创建模型所需要的变量。创建模型的变量也是有迹可循的,一般是**常规套路**+头脑风暴。
常规套路**指的是,通过全方面能描述对象的变量。以**用户是否会购买网站会员为例,我们可以将所要创建的变量分为几个大类:
- 用户自身属性(年龄、性别、职业、省份等)
- 用户行为信息(登陆次数、页面停留时长、登陆时间、是否查看过会员页面等)
- 产品信息(产品类型、产品使用时长等)
- 历史信息(历史购买会员次数、上次购买会员的时间等)
- 其他(天气、是否是周末、这个月的第几天等)
根据实际不同的问题,所归纳出来的大类也是不同,但是**规则**是能通过这些大类的变量能够将对象全面描述出来,并对适当的变量进行向下拆分。此外你可能还需要构建一些**衍生变量**,衍生变量的创建一般可以通过 RFM(Recency、Frequency、Monetary)、WOE 等方面来构建:
- 时间变量R : 近三天、近一周、近1个月、近3个月、近6个月、近12个月 等
- (频)率变量F : 接通率、覆盖率、查看率 等
- 大小变量M : 次数(sum)、最大值(max)、最小值(min)、平均值(avg) 等
- 编码变量WOE : 金额为连续型变量,可以通过 WOE 编码转换为类别变量,将其映射为**大、中、小**金额段。值得注意的是,有一些工具是可以支持自动分 bin 的,但是很多时候需要自己去检验一些重要变量的自动分 bin 是否合理,如果不合理,还需要手动去调整 bin 值。
**头脑风暴**则指的是,跳出一般的套路之外,构建一些脑洞大开的变量,这些变量应在业务上就有着非常重要的可能性,并期盼这些变量能够在模型中起到好的效果。
3.3 变量评价和筛选¶
变量的工作完成后,需要来评价你所创建的变量效果如何,通常有以下几个手段来对变量进行评价:
-
Profiling :
- 首先,需要查看 target rate 的分布,如果 target rate 过低则需要结合实际情况进行
over sample或者down sample的操作。 - 其次,通过查看变量下的 Target Rate(目标响应率),来检验该变量是否具有区分度。有时单变量的分析并不能让你直观地看出该变量与 Target 的关系,这时你需要**多变量的交叉分析**,即固定某一个变量的类型,查看其他变量与 Target 的关系。
- 首先,需要查看 target rate 的分布,如果 target rate 过低则需要结合实际情况进行
-
EDD : 通过 EDD 查看变量整体的表现,可以有效地避免在创建变量时出现人为的错误,还可以检测变量中出现的异常值。常见的 EDD 指标包括: TYPE、VALUE_COUNT、NOMISS、MISS、UNIQUE、MEAN、STD、MIN/TOP1、P1/TOP2、P2/TOP3、P10/TOP4、P25/TOP5、MEDIAN、P75/BOT5、P90/BOT4、P95/BOT3、P99/BOT2、MAX/BOT1。
- 相关性分析 : 有很大可能创建出来的变量中,部分变量存在很强的相关性。对于某些模型你可能并不需要进行变量的相关性分析,例如 LightGBM、XGBoost 等 boosting 算法,但是对于 LR(Logistic Regression)模型,相关性分析确实比不可少的。通过相关性分析,可以减少变量的共线性问题,这也是**特征选择**中最常见的筛变量的手段,可以通过**相关性矩阵( correlation matrics)** 来查看该变量与哪些变量具有相关性,其相关系数如何。
- VIF(多重共线性) : 变量之间可能存在多重共线性问题,即一个变量可能与多个变量有关系。比如 v1 变量与 v2~v10 的相关系数值为 value2 ~ value10,你可以将变量 v1 的 VIF 值理解为 value2 ~ value10 的总和,但其实 VIF 值并不是简简单单的加减,而是有其内在的一套计算逻辑的。一般 VIF <= 2 表示变量的多重共线性不强,但其实 5 ≤≤ VIF ≤≤ 10 也是可选的,也是需要具体问题具体分析。
- IV 值 : 变量的 iv 值是通过对该变量进行 WOE 变量,评价每个分区内 Target 响应率。一般 iv ≤≤ 0.02 就表明该变量在模型中并不会其中很大的作用。
- Missing Rate : 缺失值会对某些模型造成很大的影响,对于缺失率的选择需要根据具体情况具体分析。一般该变量的 Target Rate 还不错,其 Missing Rate 一般取 80% 左右;如果变量的 Target Rate 比较低,Missing Rate 一般取 95% 。对于通过缺失率来进行变量的筛选比较灵活,没有什么特别固定的筛选方法,需要结合变量的变现具体分析。
- FI(Feature Importance,特征重要性) : 评价一个变量在模型中是否重要,可以用过一些集成算法来得到,比如 LightGBM 和 XGBoost。比如你有100 个变量,可以先通过 XGBoost 训练得到各变量的 FI,再取 FI 前 Top20 的变量分析其**相关性、VIF、IV** 等。
- L1(lasso) : 通过 Lasso 训练可以得出变量的一个稀疏矩阵,不重要变量的系数经过训练后得到结果会是 0 ,如果你有 100 个变量经过 Lasso 训练后,可能其中有 40个变量的系数为 0,那么你就可以跳出 60个变量出来。当然,L1 并不是很好用。
- RFE(递归特征消除) : Scikit-Learn 提供了 RFE 包,同时还提供了 RFECV ,通过交叉验证来对特征进行排序。
我们最终的期望是,通过尽可能少的变量来训练模型,并且能让模型达到较好的预测精度。
3.4 数据处理¶
完成第三步工作之后,有些模型需要对数据进行一定的正则化处理,这一步是可选的,因为有些模型并不需要。常见的正则化操作有以下几种,且 Scikit-Learn 中也提供了相应的包来使用:
| 方法 | 功能 | 简介 |
|---|---|---|
| StandardScaler | 标准化 | 均值-标准差化数据标准化 |
| MaxMinScaler | 标准化 | 极值化法数据标准化 |
| Normalizer | 归一化 | 行记录单位化 |
| Binaizer | 二值化 | 连续变量离散化 |
| OneHotEncoder | 分类编码 | 将定性数据编码为定量数据 |
| Imputer | 缺失值填补 | 缺失值插补 |
| PolynomialFeatures | 多项式变换 | 多项式数据变换 |
值得注意的是: 对于某些模型而言,例如 LR,做了标准化和不做标准化在某些指标上是存在一些差异的。以
z-score和coef(变量系数) 为例,变量没有标准化时,z表示变量在 LR 模型中的特征重要性,即 feature importance;当变量标准化时,coef则表示特征重要性。
4. 模型训练¶
4.1 样本切分¶
为了提高模型的**准确度**和**泛化能力**,需要对 In-Time 数据集进行切分。
- 训练数据(training dataset) : 用于训练模型,IS(In-Sample)
- 验证数据(validation dataset) : 数据对象与训练集相同,用于模型效果评估和调优,OOS(Out-of-Sample)
- 测试数据(test dataset): 数据对象与训练集相同,仅用于模型效果评估
大多数模型的训练会用到这三个数据集,但某些模型并不会用到 验证数据集,比如 LR 。验证数据集的一个作用是模型训练时用来调参,LR 模型使用梯度下降算法在 全量训练数据 上进行迭代,从而得出变量系数。而 LGBM 每次迭代只会取一部分数据进行迭代,这就需要验证数据集来帮助模型快速调优。
4.2 模型参数调优¶
模型训练的结果与参数的设置也存在很大的关系,合适的参数才能让模型得出接近于最好的效果。如果每次通过人工手动调整模型参数,会花费大量的时间,幸好 Scikit-Learn 提供了 GridSearch (网格搜索),可以一次性设置参数的范围,模型会自动这些参数依次带入模型中进行训练,并得出每组参数组合下的结果,简直就是一神器。
关于模型参数的设置,除了上述网格参数方法,也需要我们自己做一些参数的调整。例如神经网络的构建,设置几个隐藏层、每个隐藏层设置多少个神经元,这个是用 网格搜索 做不了的。这种情况下,建议大家可以去百度或者 Google,或者去看看知乎、GitHub,看看被人是如何设置模型的参数的。当然,这样做的目的不是照抄被人的内容,而是多该想想为什么这样设置模型的参数,对于你自己的应用场景应该如何改动。还有最重要的一点,多去看看官方文档,可能会找到你想要的答案。
课外扩展
有兴趣的同学可以参考: https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html 。
4.3 不同模型的比较¶
正常来说,不同模型应该分开训练和调优,但是 Scikit-Learn 中也提供了 Pipeline 来一次训练多个模型,并得出不同模型下的预测结果,从而将不同模型一次性进行对比。
课外扩展
有兴趣的同学,可以参考: https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html。值得一提的是,在 SparkML 中也有 Pipeline 组件,非常好用。但是目前自己在真实建模项目中,还没有用到。
5. 模型评估¶
模型训练好之后,一般会对模型的预测效果进行评估,一般会用到召回率、精准率、准确率、KS、AUC 等评价指标,最常用的是 KS 和 AUC。
- 召回率(Recall) :样本中的正例有多少被预测准确了,预测对的正例数占真正的正例数的比率,TP / (TP+FN)
- 精准率(Precision) :针对预测结果而言,预测为正的样本有多少是真正的正样本,预测正确的正例数占预测为正例总量的比率, TP / (TP+FP)
- 准确率(Accuracy) :Accuracy=(TP+TN) / (TP+FP+TN+FN)
- AUC(Area Under the ROC Curve) : AUC 值一般在 0.5 到 1之间,值越大模型效果越好。AUC=0.5 表示模型的预测能力与随机结果没有差别。这里也要考虑到不同数据集上的 AUC 表现,防止模型过拟合。
- KS(Kolmogorov-Smirnov) : KS 表示模型将正负样本区分开来的能力。值越大表示模型的预测能力越好。一般来讲,KS ≥≥ 0.2 即可认为模型有较好的预测准确性。
6. 模型过拟合¶
模型过拟合在模型开发中很常见,可以采取一些手段和方法来避免过拟合:
- 丰富样本
- 减少选取特征的数量
- 模型参数调优
7. 模型回溯¶
当完成最终模型的开发,你需要填写如下的表格,作为模型开发的文档。
7.1 SetUp 分析¶
| 月份 | 总样本 | 正样本 | 目标响应率 |
|---|---|---|---|
| 2018-10 | |||
| 2018-11 | |||
| 2018-12 | |||
| 2019-01 | |||
| 总计 |
7.2 变量评估¶
| var_name_orig | var_name_woe | 变量说明 | coef | std err | z | P>abs(z) |
[0.025 | 0.975] | missrate | IV | VIF | corr | FI | 类别 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| nwoe_buy_times | buy_times | 购买次数 | 0.7123 | 0.0345 | 82 | 0 | 0.11 | 0.18 | 0.2% | 0.31 | 1.34 | -0.04 | 600 | 历史行为 |
关于表格的几点解释,以 LR 模型为例:
coef: 变量的系数std err: 变量的一种方差,不是我们通常认为的方差z: 变量没有标准化时,表示变量的特征重要性,即 feature importance;当变量标准化时,coef则表示特征重要性[0.025: 该变量在训练过程中的 2.5% 分位值0.975]: 该变量在训练过程中的 97.5% 分位值P > |z|: 置信区间,如果变量的coef落在[0.025, 0.975]区间内则为 0;否则大于 0missrate: 缺失率IV: 变量的 IV(Information Value),一般情况下 IV 至少大于等于 0.01,否则不具有参考意义;有时还需要根据实际情况实际分析,并不是 IV 越低就不能用。VIF: 变量共线性值,一般要求小于等于 2FI: 通过 LGBM 或者 XGB 得出的特征重要性
7.3 模型效果图¶
模型效果图包括分别在 In-Time(train 和 test) 和OOT 的预测表,一共四张表,分别为 Train、Test、Validation、OOT 的数据表现。
关于模型的效果,你还需要记录一张表,内容如下:
| 数据集 | AUC | KS |
|---|---|---|
| Train | ||
| Test | ||
| Validation | ||
| OOT |
7.4 重要变量的 WOE 和 IV 值图¶
记录重要变量的 WOE 、IV 的表现:
- 横轴 : woe 的 bin 区间
- y轴(左侧) : 该组样本总数占全部样本的比例
- y轴(右侧) : 该组的 woe 的值
-0.07(4.50%):-0.07表示变量进行 woe 后该组的值(对应右侧 y 轴),4.5%表示 该组下的 Target rate。- 标题 : 变量 + IV 值
7.5 woe 分 bin 后的矩阵表¶
记录重要变量的 WOE 分 bin 结果。
| Var_Name | Var_Type | Bin_No | Bin_Value | Ref_Value | Count_0 | Count_1 | Total | Target_Rate | Proportion | IV |
|---|---|---|---|---|---|---|---|---|---|---|
| buy_last_days | NUM | 1 | [0, 30] | |||||||
| 2 | [30, 60] | |||||||||
| 3 | [60, 90] | |||||||||
| 4 | [90, inf] |
Var_Name: 变量Var_Type: 变量数据类型Ref_Value: WOE 值Bin_No: BIN 区间Bin_Value: BIN 下的取值范围,inf表示无穷大Count_0: 变量该 bin 下负样本数Count_1: 变量该 bin 下正样本数Total: 变量该 bin 下总样本数Target Rate: 变量该 bin 下的正样本比例Proportion: 变量该 bin 下样本量占全部样本量的比例,即**变量该 bin 下 Total / 样本总数**IV: IV 值,不多解释
7.7 变量 EDD 结果¶
EDD 包含所有变量统计结果,包含不进模型的变量。
| VAR | TYPE | VALUE_COUNT | NOMISS | MISS | MISS_RATE | UNIQUE | MEAN | STD | MIN/TOP1 | P1/TOP2 | P5/TOP3 | P10/TOP4 | P25/TOP5 | MEDIAN | P75/BOT5 | P90/BOT4 | P95/BOT3 | P99/TOP3 | MAX/BOT1 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| age | NUM |
VAR: 变量TYPE: 变量类型VALUE_COUNT: 针对与类别属性,统计每个属性下数据总量NOMISS: 非空值总数MISS: 缺失值总数MISS_RATE: 缺失率MEAN: 均值STD: 方差MIN/TOP1: 最小值P1/TOP2: 1% 分位值P5/TOP3: 5%分位值P10/TOP4: 10% 分位值P25/TOP5: 25% 分位值MEDIAN: 均值P75/BOT5: 75% 分位值P90/BOT4: 90% 分位值P95/BOT3: 95% 分位值P99/BOT2: 99% 分位值MAX/BOT1: 最大值
7.8 数据字典¶
数字字典主要记录的是所有变量的解释以及所属类别,包括不进模型的变量。
| 变量 | 变量数据类型 | 变量解释 | 所属类别 | 是否参与模型训练 |
|---|---|---|---|---|
| age | NUM | 年龄 | 用户属性 | 1 |
7.9 特征重要性¶
所有变量的 FI,包括不进模型的变量。
| VAR | TYPE | VALUE_COUNT | NOMISS | MISS | Miss_rate | FI | IV | corr | corr_abs | FI_rank | IV_rank | corr_rank | is_del |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| age | NUM |
corr: 相关系数corr_abs: 相关系数的绝对值FI_rank: FI 的 RANK 值IV_rank: IV 的 RANK 值corr_rank: 相关系数的 RANK 值is_del: 是否删除
7.10 相关系数¶
进模型训练的变量的相关系数矩阵表,最好有色阶的标注。
7.11 模型变量表现¶
横轴是按照模型分等分10分,取每一份下该woe变量的均值,下图两个变量的模型表现。如果该变量在 Train、Test、OOT 上拟合的很好(三条线几乎重合),表示该变量较为稳定(也可以说比较牛逼)。如果OOT 上与 Train、Test 上存在偏差(高或低),表示 OOT 上变量存在一定差异,也就是变量不是很稳定。可以把模型变量表现理解为 PSI。
8. 后续监控¶
模型上线后还需要做变量的 PSI 监控、案量、KS 和 AUC 监控、Target Rate 的监控等等,如果涉及到 AB Test 的话,还需要比较策略 A/B 的不同效果的监控。可以将这部分监控做成自动任务,通过邮件方式每日进行推送,频率的可以自行设置。如果会一点 Flask 或者 Django 的 web 开发,可以做一个所有模型的监控系统,这样每次想要查看的话可以随时查看相应监控,避免每日查找相应的邮件。




