跳转至

风控模型的一般步骤

在开始数据建模工作之前,博主其实看了蛮多关于数据挖掘的书籍。但是,真正从事数据建模工作后,可以说只能用 “纸上谈兵” 来形容自己,我甚至搞不清楚在数据建模分为几个阶段,要先做什么后做什么,模型原理更是一知半解。随着自我的学习以及大佬们的指教,慢慢懂得数据挖掘工作一般步骤与套路,熟记这些建模的步骤与讨论,能让你明确当前任务是什么,下一步任务又是什么,每一步任务中应该注意的一些问题。

下面内容为整理的对建模的一般步骤,内容也仅作参考。值得注意的是,这里的一般步骤只是建模的常规套路,关于模型的原理部分还需要自己去深入了解。

1. 明确问题的类型

机器学习中最常见的两类问题是有监督学习和无监督学习,关于其概念这里不做非常详细的解释,百度上有很好的博客解释这个概念,后续会有专门一篇博客讲解有监督学习和无监督学习的相关概念,以及都有哪些模型属于有监督学习,哪些模型属于无监督学习。

首先,需要明确的是需要解决的问题是属于哪一类问题,是有监督学习下的分类问题还是回归问题?还是无监督学习下的聚类问题等。接下来,需要先确定模型的 Target (即 \(y\)),也就是你最终想要预测的东西是什么。

对于大多数模型开发而言,本质上是为了解决业务上的实际问题,比如客户质量的分群、产品销售量的预测等等,所以理清楚模型应用的业务背景是非常重要的,这涉及到如何去定义模型的 Target,以及将来模型如何在实际场景中进行应用。

关于模型 Target 定义所花费的时间个人认为应该占到整个模型开发时间的 20%,这就好比在解数学题时如果审题不清,即便你洋洋洒洒写了一大篇解题过程,其实答案从一开始就是错误的。花了很多时间和精力去做模型的开发,最终发现模型开发好后没办法进行实际业务的应用。

关于模型 Target 的定义,你需要考虑以下几件事:

  1. 模型的 Target 如何定义?
  2. Target 的定义是否合理,是否与实际业务常识相悖?
  3. 开发好的模型将来如何在实际业务场景中进行应用?

本篇博客以最常见的二分类问题,讲述一下建模的一般步骤。

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 变量评价和筛选

变量的工作完成后,需要来评价你所创建的变量效果如何,通常有以下几个手段来对变量进行评价:

  1. Profiling :

    • 首先,需要查看 target rate 的分布,如果 target rate 过低则需要结合实际情况进行 over sample 或者 down sample 的操作。
    • 其次,通过查看变量下的 Target Rate(目标响应率),来检验该变量是否具有区分度。有时单变量的分析并不能让你直观地看出该变量与 Target 的关系,这时你需要**多变量的交叉分析**,即固定某一个变量的类型,查看其他变量与 Target 的关系。
  2. 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。

  3. 相关性分析 : 有很大可能创建出来的变量中,部分变量存在很强的相关性。对于某些模型你可能并不需要进行变量的相关性分析,例如 LightGBM、XGBoost 等 boosting 算法,但是对于 LR(Logistic Regression)模型,相关性分析确实比不可少的。通过相关性分析,可以减少变量的共线性问题,这也是**特征选择**中最常见的筛变量的手段,可以通过**相关性矩阵( correlation matrics)** 来查看该变量与哪些变量具有相关性,其相关系数如何。
  4. VIF(多重共线性) : 变量之间可能存在多重共线性问题,即一个变量可能与多个变量有关系。比如 v1 变量与 v2~v10 的相关系数值为 value2 ~ value10,你可以将变量 v1 的 VIF 值理解为 value2 ~ value10 的总和,但其实 VIF 值并不是简简单单的加减,而是有其内在的一套计算逻辑的。一般 VIF <= 2 表示变量的多重共线性不强,但其实 5 ≤≤ VIF ≤≤ 10 也是可选的,也是需要具体问题具体分析。
  5. IV 值 : 变量的 iv 值是通过对该变量进行 WOE 变量,评价每个分区内 Target 响应率。一般 iv ≤≤ 0.02 就表明该变量在模型中并不会其中很大的作用。
  6. Missing Rate : 缺失值会对某些模型造成很大的影响,对于缺失率的选择需要根据具体情况具体分析。一般该变量的 Target Rate 还不错,其 Missing Rate 一般取 80% 左右;如果变量的 Target Rate 比较低,Missing Rate 一般取 95% 。对于通过缺失率来进行变量的筛选比较灵活,没有什么特别固定的筛选方法,需要结合变量的变现具体分析。
  7. FI(Feature Importance,特征重要性) : 评价一个变量在模型中是否重要,可以用过一些集成算法来得到,比如 LightGBM 和 XGBoost。比如你有100 个变量,可以先通过 XGBoost 训练得到各变量的 FI,再取 FI 前 Top20 的变量分析其**相关性、VIF、IV** 等。
  8. L1(lasso) : 通过 Lasso 训练可以得出变量的一个稀疏矩阵,不重要变量的系数经过训练后得到结果会是 0 ,如果你有 100 个变量经过 Lasso 训练后,可能其中有 40个变量的系数为 0,那么你就可以跳出 60个变量出来。当然,L1 并不是很好用。
  9. RFE(递归特征消除) : Scikit-Learn 提供了 RFE 包,同时还提供了 RFECV ,通过交叉验证来对特征进行排序。

我们最终的期望是,通过尽可能少的变量来训练模型,并且能让模型达到较好的预测精度。

3.4 数据处理

完成第三步工作之后,有些模型需要对数据进行一定的正则化处理,这一步是可选的,因为有些模型并不需要。常见的正则化操作有以下几种,且 Scikit-Learn 中也提供了相应的包来使用:

方法 功能 简介
StandardScaler 标准化 均值-标准差化数据标准化
MaxMinScaler 标准化 极值化法数据标准化
Normalizer 归一化 行记录单位化
Binaizer 二值化 连续变量离散化
OneHotEncoder 分类编码 将定性数据编码为定量数据
Imputer 缺失值填补 缺失值插补
PolynomialFeatures 多项式变换 多项式数据变换

值得注意的是: 对于某些模型而言,例如 LR,做了标准化和不做标准化在某些指标上是存在一些差异的。以 z-scorecoef(变量系数) 为例,变量没有标准化时,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,看看被人是如何设置模型的参数的。当然,这样做的目的不是照抄被人的内容,而是多该想想为什么这样设置模型的参数,对于你自己的应用场景应该如何改动。还有最重要的一点,多去看看官方文档,可能会找到你想要的答案

4.3 不同模型的比较

正常来说,不同模型应该分开训练和调优,但是 Scikit-Learn 中也提供了 Pipeline 来一次训练多个模型,并得出不同模型下的预测结果,从而将不同模型一次性进行对比。

课外扩展

有兴趣的同学,可以参考: https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html。值得一提的是,在 SparkML 中也有 Pipeline 组件,非常好用。但是目前自己在真实建模项目中,还没有用到。

5. 模型评估

模型训练好之后,一般会对模型的预测效果进行评估,一般会用到召回率、精准率、准确率、KS、AUC 等评价指标,最常用的是 KSAUC

  • 召回率(Recall) :样本中的正例有多少被预测准确了,预测对的正例数占真正的正例数的比率,TP / (TP+FN)
  • 精准率(Precision) :针对预测结果而言,预测为正的样本有多少是真正的正样本,预测正确的正例数占预测为正例总量的比率, TP / (TP+FP)
  • 准确率(Accuracy) :Accuracy=(TP+TN) / (TP+FP+TN+FN)

AUC曲线

精确率与召回率图解

  • 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;否则大于 0
  • missrate : 缺失率
  • IV : 变量的 IV(Information Value),一般情况下 IV 至少大于等于 0.01,否则不具有参考意义;有时还需要根据实际情况实际分析,并不是 IV 越低就不能用。
  • VIF : 变量共线性值,一般要求小于等于 2
  • FI : 通过 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表现

  • 横轴 : 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 开发,可以做一个所有模型的监控系统,这样每次想要查看的话可以随时查看相应监控,避免每日查找相应的邮件。