特征工程(4)不平衡数据集*
不平衡数据问题
实际上,很多时候,数据不平衡并没有啥负面影响,并不是数据不平衡了,就一定要处理。如果你只是为了做而做,我有99%的自信告诉你,你做了也是白做,啥收益都没有。
为什么很多模型在训练数据不均衡时会出问题?
本质原因是:模型在训练时优化的目标函数和在测试时使用的评价标准不一致。这种”不一致“可能是训练数据的样本分布与测试数据分布不一致;
一、不平衡数据集的主要处理方式?
1.1 数据的角度
主要方法为采样,分为欠采样和过采样以及对应的一些改进方法。[python imblearn库]尊重真实样本分布,人为主观引入样本权重,反而可能得出错误的结论。
业务角度:
- 时间因素,对近期样本提高权重,较远样本降低权重。这是考虑近期样本与未来样本之间的“相似度”更高,希望模型学到更多近期样本的模式。
- 贷款类型,不同额度、利率、期限的样本赋予不同权重,这需要结合业务未来的发展方向。例如,未来业务模式希望是小额、短期、低利率,那就提高这批样本的权重。
- 样本分群,不同群体赋予不同权重。例如,按流量获客渠道,如果未来流量渠道主要来自平台A,那么就提高这批样本权重。
技术角度:
欠采样:
EasyEnsemble:从多数类\(S_{max}\)上随机抽取一个子集,与其他类训练一个分类器;重复若干次,多个分类器融合。
BalanceCascade:从多数类\(S_{max}\)上随机抽取一个子集,与其他类训练一个分类器;剔除能被分类正确的分类器,重复若干次,多个分类器融合。
NearMIss:利用K邻近信息挑选具有代表性的样本。
one-side Selection:采用数据清洗技术。
过采样:
随机采样
SMOTE算法:对少数类\(S_{min}\)中每个样本x的K近邻随机选取一个样本y,在x,y的连线上随机选取一个点作为新的样本点。
Borderline-SMOTE、ADASYN改进算法等
分层抽样技术:批量训练分类器的「分层抽样」技术。当面对不平衡类问题时,这种技术(通过消除批次内的比例差异)可使训练过程更加稳定。
1.2 算法的角度
考虑不同误分类情况代价的差异性对算法进行优化,主要是基于代价敏感学习算法(Cost-Sensitive Learning),代表的算法有adacost。实现基于代价敏感的AdaCost算法
代价函数:可以增加小类样本的权值,降低大类样本的权值(这种方法其实是产生了新的数据分布,即产生了新的数据集),从而使得分类器将重点集中在小类样本身上。刚开始,可以设置每个类别的权值与样本个数比例的倒数,然后可以使用过采样进行调优。
这种方法的难点在于设置合理的权重,实际应用中一般让各个分类间的加权损失值近似相等。当然这并不是通用法则,还是需要具体问题具体分析。
XGB自定义损失函数 /Imbalance-XGBoost【Focal Loss】:
\[ L_w=-\sum_{i=1}^m \hat{y}_i\left(1-y_i\right)^\gamma \log \left(y_i\right)+\left(1-\hat{y}_i\right) y_i^\gamma \log \left(1-y_i\right) \]
1.3 分类方式
可以把小类样本作为异常点(outliers),把问题转化为异常点检测问题(anomaly detection)。此时分类器需要学习到大类的决策分界面,即分类器是一个单个类分类器(One Class Classifier)。代表的算法有 One-class SVM。
一类分类算法:
不平衡数据集的一类分类算法:https://machinelearningmastery.com/one-class-classification-algorithms/
一类分类是机器学习的一个领域,它提供了异常值和异常检测的技术,如何使一类分类算法适应具有严重偏斜类分布的不平衡分类,如何拟合和评估 SVM、隔离森林、椭圆包络、局部异常因子等一类分类算法。
不平数据集的划分方法?
K折交叉验证?
自助法?
不平数据集的评价方法?
G-Mean和ROC曲线和AUC。Topk@P
- AP衡量的是学出来的模型在每个类别上的好坏,mAP衡量的是学出的模型在所有类别上的好坏,得到AP后mAP的计算就变得很简单了,就是取所有AP的平均值。
二、「类别不平衡」如何得到一个不错的分类器?
机器学习中常常会遇到数据的类别不平衡(class imbalance),也叫数据偏斜(class skew)。以常见的二分类问题为例,我们希望预测病人是否得了某种罕见疾病。但在历史数据中,阳性的比例可能很低(如百分之0.1)。在这种情况下,学习出好的分类器是很难的,而且在这种情况下得到结论往往也是很具迷惑性的。
以上面提到的场景来说,如果我们的分类器总是预测一个人未患病,即预测为反例,那么我们依然有高达99.9%的预测准确率。然而这种结果是没有意义的,这提出了今天的第一个问题,如何有效在类别不平衡的情况下评估分类器?
当然,本文最终希望解决的问题是:在数据偏斜的情况下,如何得到一个不错的分类器?如果可能,是否可以找到一个较为简单的解决方法,而规避复杂的模型、数据处理,降低我们的工作量。
2.1 类别不平衡下的评估问题?
而当类别不平衡时,准确率就非常具有迷惑性,而且意义不大。给出几种主流的评估方法:
- ROC是一种常见的替代方法,全名receiver operating curve,计算ROC曲线下的面积是一种主流方法
- Precision-recall curve和ROC有相似的地方,但定义不同,计算此曲线下的面积也是一种方法
- Precision@n是另一种方法,特制将分类阈值设定得到恰好n个正例时分类器的precision
- Average precision也叫做平均精度,主要描述了precision的一般表现,在异常检测中有时候会用
- 直接使用Precision也是一种想法,但此时的假设是分类器的阈值是0.5,因此意义不大
本文的目的不是介绍一般的分类评估标准,简单的科普可以参看:如何解释召回率与准确率?
2.2 解决类别不平衡中的“奇淫巧技”有什么?
对于类别不平衡的研究已经有很多年了,在资料[1]中就介绍了很多比较复杂的技巧。结合我的了解举几个简单的例子:
[1] He, H. and Garcia, E.A., 2009. Learning from imbalanced data. IEEE Transactions on knowledge and data engineering, 21(9), pp.1263-1284.
- 对数据进行采用的过程中通过相似性同时生成并插样“少数类别数据”,叫做SMOTE算法
- 对数据先进行聚类,再将大的簇进行随机欠采样或者小的簇进行数据生成
- 把监督学习变为无监督学习,舍弃掉标签把问题转化为一个无监督问题,如异常检测
- 先对多数类别进行随机的欠采样,并结合boosting算法进行集成学习
2.3 简单通用的算法有哪些?
- 对较多的那个类别进行欠采样(under-sampling),舍弃一部分数据,使其与较少类别的数据相当
- 对较少的类别进行过采样(over-sampling),重复使用一部分数据,使其与较多类别的数据相当
- 阈值调整(threshold moving),将原本默认为0.5的阈值调整到 较少类别/(较少类别+较多类别)即可
当然很明显我们可以看出,第一种和第二种方法都会明显的改变数据分布,我们的训练数据假设不再是真实数据的无偏表述。在第一种方法中,我们浪费了很多数据。而第二类方法中有无中生有或者重复使用了数据,会导致过拟合的发生。
因此欠采样的逻辑中往往会结合集成学习来有效的使用数据,假设正例数据n,而反例数据m个。我们可以通过欠采样,随机无重复的生成(k=n/m)个反例子集,并将每个子集都与相同正例数据合并生成k个新的训练样本。我们在k个训练样本上分别训练一个分类器,最终将k个分类器的结果结合起来,比如求平均值。这就是一个简单的思路,也就是Easy Ensemble [5]。
但不难看出,其实这样的过程是需要花时间处理数据和编程的,对于很多知识和能力有限的人来说难度比较大。特此推荐两个简单易行且效果中上的做法:
- 简单的调整阈值,不对数据进行任何处理。此处特指将分类阈值从0.5调整到正例比例
- 使用现有的集成学习分类器,如随机森林或者xgboost,并调整分类阈值
提出这样建议的原因有很多。首先,简单的阈值调整从经验上看往往比过采样和欠采样有效 [6]。其次,如果你对统计学知识掌握有限,而且编程能力一般,在集成过程中更容易出错,还不如使用现有的集成学习并调整分类阈值。
2.4 一个简单但有效的方案
经过了上文的分析,我认为一个比较靠谱的解决方案是:
- 不对数据进行过采样和欠采样,但使用现有的集成学习模型,如随机森林
- 输出随机森林的预测概率,调整阈值得到最终结果
- 选择合适的评估标准,如precision@n
三、脉脉:数据集不平衡应该思考什么
首先, 猜测一下, 你研究的数据存在着较 大的不平衡, 你还是比较关注正类(少数类) 样本的, 比如【想要识别出 有信用风险 的 人】那么就要谈一下你所说的【模型指标还行】这个问题。auc这种复合指标先不提, precision代表的是, 你预测的信用风险人群, 其中有多少是真的信用风险人群。recall 代表的是, "真的信用风险人群"有多少被你识别出来了;
- 所以, 倘若你比较关注的是【我想要找出 所有"可能有违约风险的人"】宁可错杀也不 放过。那么你应该重点关注的就是召回率 recall。在此基础上, 尽量提高precision。
- 你把训练集的正负样本控制在64左右, 那 么你是怎么控制的呢, 是单纯用了数据清理技术, 还是单纯生成了一些新的样本, 还是怎么做的?
- 如果条件允许, 可以查看一下你被错分的 样本, 看看被错分的原因可能是什么, 是因为类重叠, 还是有少数类的分离还是单纯的因为不平衡比太夸张所以使分类器产生偏倚?
- 不知道你用的什么模型, 但是现在有一些把重采样和分类器结合在一起的集成学习方法, 可以试试看。
- 维度太高的时候, 特征的提取很重要呀!
- 当做异常检测问题可能会好一些?
四、样本准备与权重指标
样本权重对逻辑回归评分卡的影响探讨: https://zhuanlan.zhihu.com/p/110982479
风控业务背景
在统计学习建模分析中,样本非常重要,它是我们洞察世界的窗口。在建立逻辑回归评分卡时,我们也会考虑对样本赋予不同的权重weight,希望模型学习更有侧重点。
诚然,我们可以通过实际数据测试来检验赋权前后的差异,但我们更希望从理论上分析其合理性。毕竟理论可以指导实践。本文尝试探讨样本权重对逻辑回归评分卡的影响,以及从业务和技术角度分析样本权重调整的操作方法。
Part 1. 样本加权对WOE的影响
在《WOE与IV指标的深入理解应用》一文中, 我们介绍了WOE的概念和计算方法。在逻辑回归评分卡中, 其具有 重要意义。其公式定义如下:
\[ W_O=\ln \left(\frac{\text { Good }_i}{\text { Good }_T} / \frac{\text { Bad }_i}{\operatorname{Bad}_T}\right)=\ln \left(\frac{\text { Good }_i}{\text { Bad }_i}\right)-\ln \left(\frac{\text { Good }_T}{\operatorname{Bad}_T}\right) \] 现在,我们思考在计算WOE时,是否要考虑样本权重呢?
如图1所示的样本, 我们希望对某些样本加强学习, 因此对年龄在46岁以下的样本赋予权重1.5, 而对46岁以上的样本赋予权重1.0, 也就是加上权重列weight。此时再计算WOE值, 我们发现数值发生变化。这是因为权重的改 变, 既影响了局部bucket中的 odds,也影响了整体的 odds 。
我们有2种对样本赋权后的模型训练方案,如图2所示。
- 方案1: WOE变换利用原训练集,LR模型训练时利用加权后的样本。
- 方案2: WOE变换和LR模型训练时,均使用加权后的样本。
个人更倾向于第一种方案,原因在于:WOE变换侧重变量的可解释性,引入样本权重会引起不可解释的困扰。
Part 2. 采样对LR系数的影响
我们定义特征向量 \(\mathbf{x}=x_1, x_2, \ldots, x_n\) 。记 \(G=\operatorname{Good}, B=B a d\), 那么逻辑回归的公式组成便是: \[ \begin{aligned} & \operatorname{Ln}(\text { odds }(G \mid \mathbf{x}))=\operatorname{Ln}\left(\frac{p_G f(\mathbf{x} \mid G)}{p_B f(\mathbf{x} \mid B)}\right)=\operatorname{Ln}\left(\frac{p_G}{p_B}\right)+\operatorname{Ln}\left(\frac{f(\mathbf{x} \mid G)}{f(\mathbf{x} \mid B)}\right) \\ & =\operatorname{Ln}\left(\frac{p_G}{p_B}\right)+\operatorname{Ln}\left(\frac{f\left(x_1, x_2, \ldots, x_n \mid G\right)}{f\left(x_1, x_2, \ldots, x_n \mid B\right)}\right) \\ & =\operatorname{Ln}\left(\frac{p_G}{p_B}\right)+\operatorname{Ln}\left(\frac{f\left(x_1 \mid G\right)}{f\left(x_1 \mid B\right)}\right)+\operatorname{Ln}\left(\frac{f\left(x_2 \mid G\right)}{f\left(x_2 \mid B\right)}\right)+\ldots+\operatorname{Ln}\left(\frac{f\left(x_n \mid G\right)}{f\left(x_n \mid B\right)}\right) \\ & =L n\left(\text { odd } s_{\text {pop }}\right)+\operatorname{Ln}\left(\text { odd } s_{i n f o}(\mathbf{x})\right) \\ & \end{aligned} \] 其中, 第2行到第3行的变换是基于朴素贝叶斯假设, 即自变量 \(x_i\) 之间相互独立。
- \(o d d s_{p o p}\) 是指总体 (训练集) 的 \(o d d s\), 指先验信息 \(o d d s\) 。
- \(o d d s_{i n f o}(\mathbf{x})\) 是指自变量引起的 \(o d d s\) 变化, 我们称为后验信息 \(o d d s 。\)
因此,随着观察信息的不断加入,对群体的好坏 \(o d d s\) 判断将越来越趋于客观。
样本权重调整直接影响先验项,也就是截距。那对系数的影响呢?
接下来,我们以过采样(Oversampling)和欠采样(Undersampling)为例,分析采样对LR系数的影响。如图4所示,对于不平衡数据集,过采样是指对正样本简单复制很多份;欠采样是指对负样本随机抽样。最终,正负样本的比例将达到1:1平衡状态。
我们同样从贝叶斯角度进行解释: \[ \begin{gathered} P(B \mid \mathbf{x})=\frac{P(\mathbf{x} \mid B) P(B)}{P(\mathbf{x})}=\frac{P(\mathbf{x} \mid B) P(B)}{P(\mathbf{x} \mid B) P(B)+P(\mathbf{x} \mid G) P(G)} \\ \Leftrightarrow \frac{1}{P(B \mid \mathbf{x})}=1+\frac{P(\mathbf{x} \mid G) P(G)}{P(\mathbf{x} \mid B) P(B)} \\ \Leftrightarrow \operatorname{Ln}\left(\frac{P(\mathbf{x} \mid G)}{P(\mathbf{x} \mid B)}\right)=\operatorname{Ln}\left(\frac{1}{P(B \mid \mathbf{x})}-1\right)-\operatorname{Ln}\left(\frac{P(G)}{P(B)}\right) \\ \Leftrightarrow \operatorname{Ln}\left(\frac{P(G \mid \mathbf{x})}{P(B \mid \mathbf{x})}\right)=\operatorname{Ln}\left(\frac{P(\mathbf{x} \mid G)}{P(\mathbf{x} \mid B)}\right)+\operatorname{Ln}\left(\frac{P(G)}{P(B)}\right) \end{gathered} \] 假设采样处理后的训练集为 \(\mathbf{x}^{\prime}\) 。记 \(\# B\) 和 \(\# G\) 分别表示正负样本数, 那么显然: \[ o d d s=\frac{\# G}{\# B} \neq \frac{\# G^{\prime}}{\# B^{\prime}}=o d d s^{\prime} \] 由于 \(\operatorname{Ln}\left(\frac{P(G)}{P(B)}\right)=\operatorname{Ln}\left(\frac{\# G}{\# B}\right)\) ,因此对应截距将发生变化。
无论是过采样, 还是欠采样, 处理后的新样本都和原样本服从同样的分布, 即满足: \[ \begin{aligned} & P(\mathbf{x} \mid G)=P\left(\mathbf{x}^{\prime} \mid G^{\prime}\right) \\ & P(\mathbf{x} \mid B)=P\left(\mathbf{x}^{\prime} \mid B^{\prime}\right) \end{aligned} \] 因此, \(\operatorname{Ln}\left(\frac{P(\mathbf{x} \mid G)}{P(\mathbf{x} \mid B)}\right)=\operatorname{Ln}\left(\frac{P\left(\mathbf{x}^{\prime} \mid G^{\prime}\right)}{P\left(\mathbf{x}^{\prime} \mid B^{\prime}\right)}\right)\), 即系数不发生变化。
实践证明,按照做评分卡的方式,做WOE变换,然后跑LR,单变量下确实只有截距影响。而对于多变量,理想情况下,当各自变量相互独立时,LR的系数是不变的,但实际自变量之间多少存在一定的相关性,所以还是会有一定的变化。
Part 3. 样本准备与权重指标
风控建模的基本假设是末来样本和历史样本的分布是一致的。模型从历史样本中拟合 \(X_{\text {old }}\) 和 \(y\) 之间的关系,并 根据末来样本的 \(X_{\text {new }}\) 进行预测。因此, 我们总是在思考, 如何选择能代表末来样本的训练样本。
如图5所示,不同时间段、不同批次的样本总是存在差异,即服从不同的总体分布。因此,我们需要从多个维度来衡量两个样本集之间的相似性。
从迁移学习的角度看,这是一个从源域(source domain)中学习模式,并应用到目标域(target domain)的过程。在这里,源域是训练集,目标域指测试集,或者未来样本。
这就会涉及到一些难点:
- 假设测试集OOT与未来总体分布样本基本一致,但未来样本是不可知且总是在发生变化。
- 面向测试集效果作为评估指标,会出现在测试集上过拟合现象。
那么,建模中是否可以考虑建立一个权重指标体系,即综合多方面因素进行样本赋权?我们采取2种思路来分析如何开展。
业务角度:
- 时间因素,对近期样本提高权重,较远样本降低权重。这是考虑近期样本与未来样本之间的“相似度”更高,希望模型学到更多近期样本的模式。
- 贷款类型,不同额度、利率、期限的样本赋予不同权重,这需要结合业务未来的发展方向。例如,未来业务模式希望是小额、短期、低利率,那就提高这批样本的权重。
- 样本分群,不同群体赋予不同权重。例如,按流量获客渠道,如果未来流量渠道主要来自平台A,那么就提高这批样本权重。
结合以上各维度,可得到总体采样权重的一种融合方式为: \[ w=w_1 * w_2 * w_3 \] 这种业务角度的方案虽然解释性强,但实际拍定多大的权重显得非常主观,实践中往往需要不断尝试,缺少一些理论指导。
技术角度:
- 过采样、欠采样等,从样本组成上调整正负不平衡。
- 代价敏感学习,在损失函数对好坏样本加上不同的代价。比如,坏样本少,分错代价更高。
- 借鉴Adaboost的做法,对误判样本在下一轮训练时提高权重。
在机器学习中,有一个常见的现象——Covariate Shift,是指当训练集的样本分布和测试集的样本分布不一致的时候,训练得到的模型无法具有很好的泛化 (Generalization) 能力。
其中一种做法,既然是希望让训练集尽可能像测试集,那就让模型帮助我们做这件事。如图6所示,将测试集标记为1,训练集标记为0,训练一个LR模型,在训练集上预测,概率越高,说明这个样例属于测试集的可能性越大。以此达到样本权重调整的目的。
Part 4. 常见工具包的样本赋权
现有Logistic Regression模块主要来自sklearn和scipy两个包。很不幸,scipy包并不支持直接赋予权重列。这是为什么呢?有统计学家认为, 尊重真实样本分布,人为主观引入样本权重,反而可能得出错误的结论。
因此,我们只能选择用scikit-learn。样本权重是如何体现在模型训练过程呢?查看源码后,发现目前主要是体现在损失函数中,即代价敏感学习。
1 | # Logistic loss is the negative of the log of the logistic function. |
样本权重对决策分割面的影响:
以下是scikit-learn包中的逻辑回归参数列表说明,可以发现调节样本权重的方法有两种:
- 在class_weight参数中使用balanced
- 在调用fit函数时,通过sample_weight调节每个样本权重。
如果同时设置上述2个参数,那么样本的真正权重是class_weight * sample_weight.
那么,在评估模型的指标时,是否需要考虑抽样权重,即还原真实场景下的模型评价指标?笔者认为,最终评估还是需要还原到真实场景下。例如,训练集正负比例被调节为1:1,但这并不是真实的\(odds\),在预测时将会偏高。因此,仍需要进行模型校准。
Part 5. 总结
本文系统整理了样本权重的一些观点,但目前仍然没有统一的答案。据笔者所知,目前在实践中还是采取以下几种方案:
- 尊重原样本分布,不予处理,LR模型训练后即为真实概率估计。
- 结合权重指标综合确定权重,训练完毕模型后再进行校准,还原至真实概率估计。
值得指出的是,大环境总是在发生变化,造成样本分布总在偏移。因此,尽可能增强模型的鲁棒性,以及策略使用时根据实际情况灵活调整,两者相辅相成,可能是最佳的使用方法。欢迎大家一起讨论业界的一些做法。
参考文献
- 机器学习中不平衡数据的预处理:https://capallen.gitee.io/2019/Deal-with-imbalanced-data-in-ML.html
- 如何处理数据中的「类别不平衡」?:https://zhuanlan.zhihu.com/p/32940093
- 不平衡数据集处理方法:https://blog.csdn.net/asialee_bird/article/details/83714612
- 不平衡数据究竟出了什么问题?:https://www.zhihu.com/column/jiqizhixin
- 数据挖掘时,当正负样本不均,代码如何实现改变正负样本权重? - 十三的回答 - 知乎 https://www.zhihu.com/question/356640889/answer/2299286791
- 样本权重对逻辑回归评分卡的影响探讨 - 求是汪在路上的文章 - 知乎 https://zhuanlan.zhihu.com/p/110982479