分类问题中类别不平衡问题的有效解决方法

本篇文章记录在分类问题中如何有效地类别不平衡问题,主要当作自己的读书笔记,所以写得可能有些乱。。。

由于包imbalanced-learn(github地址)已经非常有效地实现了各种常见的处理类别不平衡问题的有效解决方法。因此,本文把侧重点放在了方法原理的介绍上,当然这些方法绝大部分都是在imbalanced-learn包中有实现的

文章目录

  • 一、引言
  • 二、过采样
    • 2.1 随机过采样
    • 2.2 SMOTE算法
    • 2.3 Borderline-SMOTE算法
  • 三、欠采样
    • 3.1 随机欠采样
    • 3.2 EasyEnsemble算法
    • 3.3 BalanceCascade算法
  • 四、综合采样
    • 4.1 SMOTE+Tomek Links
      • 4.1.1 Tomek Links方法
      • 4.1.2 SMOTE+Tomek Links
    • 4.2 SMOTE+ENN
  • 五、常见机器学习模型本身处理类不平衡
    • 5.1 LightGBM
      • 5.1.1 二分类处理
      • 5.1.2 多分类处理
    • 5.2 Xgboost
  • 参考文献

一、引言

什么是类别不平衡问题?

类别不平衡(class-imbalance)就是指分类任务中不同类别的训练样例数目差别很大的情况。在现实的分类学习任务中,我们经常会遇到类别不平衡,以下是一些例子:

  • 每年,约 2% 的信用卡账户是伪造的。(多数的欺诈检测领域是极其不平衡的)

  • 针对某一病征的医学筛查通常涵盖了许多没有此病征的人,以检查出少数患者(例:美国的 HIV 感染率约为 0.4%)

  • 每年,硬盘驱动器故障的发生率约为 1%

  • 在线广告的转化率在 10^-3 到 10^-6 的范围区间内

  • 工厂的产品缺陷率一般在 0.1% 左右

如果不同类别的训练样例数目稍有差别,通常影响不大,但若差别很大,则会对学习过程造成困扰。例如有998个反例,但是正例只有2个,那么学习方法只需要返回一个永远将新样本预测为反例的学习器,就能达到99.8%的精度;然而这样的学习器往往没有价值,因为它不能预测出任何正例。

因此有必要了解类别不平衡性处理的基本方法。接下来,我们重点介绍常见的方法。

二、过采样

对训练集里的少数类进行“过采样”(oversampling),即增加一些少数类样本使得正、反例数目接近,然后再进行学习。即是过采样。

2.1 随机过采样

随机过抽样是增加少数类样本数量,可以事先设置多数类与少数类最终的数量比例,在保留多数类样本不变的情况下,根据比例随机复制少数类样本,在使用的过程中为了保证所有的少数类样本信息都会被包含,可以先完全复制一份全量的少数类样本,再随机复制少数样本使得满足数量比例,具体步骤如下:

  1. 首先在少数类 S m i n S_{min} Smin集合中随机选中一些少数类样本
  2. 然后通过复制所选样本生成样本集合 E E E
  3. 将它们添加到 S m i n S_{min} Smin中来扩大原始数据集从而得到新的少数类集合 S m i n − n e w S_{min-new} Sminnew

S m i n S_{min} Smin中的总样本数增加了 |E|个新样本,且 S m i n − n e w S_{min-new} Sminnew的类分布均衡度进行了相应的调整,如此操作可以改变类分布平衡度从而达到所需水平。

缺点:

对于随机过采样,由于需要对少数类样本进行复制来扩大数据集,造成模型训练复杂度加大。另一方面也容易造成模型的过拟合问题,因为随机过采样是简单的对初始样本进行复制采样,这就使得学习器学得的规则过于具体化,不利于学习器的泛化性能,造成过拟合问题。

为了解决随机过采样中造成模型过拟合问题,又能保证实现数据集均衡的目的,出现了过采样法代表性的算法SMOTE和Borderline-SMOTE算法

2.2 SMOTE算法

SMOTE全称是Synthetic Minority Oversampling即合成少数类过采样技术。

SMOTE的主要思想是利用特征空间中少数类样本之间的相似性来建立人工数据,特别是,对于子集 S m i n ⊂ S S_{min}⊂ S SminS,对于每一个样本 x i ⊂ S m i n x_i\subset S_{min} xiSmin使用 K K K-近邻法,其中 K K K-近邻被定义为考虑 S m i n S_{min} Smin中的 K K K个元素本身与 x i x_i xi的欧氏距离在 n n n维特征空间 X X X中表现为最小幅度值的样本。由于不是简单地复制少数类样本,因此可以在一定程度上避免分类器的过度拟合,实践证明此方法可以提高分类器的性能。算法流程如下:

  1. 对于少数类中的每一个样本 x i x_i xi,以欧氏距离为标准计算它到少数类样本集 S m i n S_{min} Smin中所有样本的距离,得到 K K K近邻;
  2. 根据样本不平衡比例设置一个采样比例以确定采样倍率N,对于每一个少数类样本 x i x_i xi,从其 K K K近邻中随机选择若干个样本,假设选择的近邻为 x ~ \tilde{x} x~
  3. 对于每一个随机选出的近邻 x ~ \tilde{x} x~,分别与原样本按照如下的公式构建新的样本: x n e w = x + r a n d ( 0 , 1 ) × ( x ~ − x ) x_{new}=x+rand\left(0,1\right)\times\left(\tilde{x}-x\right) xnew=x+rand(0,1)×(x~x)

下图即为算法的示意图:

缺点:

1)由于对每个少数类样本都生成新样本,因此容易发生生成样本重叠的问题。

2)在SMOTE算法中,出现了过度泛化的问题,主要归结于产生合成样本的方法。特别是,SMOTE算法对于每个原少数类样本产生相同数量的合成数据样本,而没有考虑其邻近样本的分布特点,这就使得类间发生重复的可能性增大。

解释缺点2)的原因:结合前面所述的SMOTE算法的原理,SMOTE算法产生新的人工少数类样本过程中,只是简单的在同类近邻之间插值,并没有考虑少数类样本周围多数类样本的分布情况。如下图所示,绿色正号1、2分布在多数类样本周围,它们离多数类样本最近,这就导致它们有可能被划分成多数类样本。因此,SMOTE算法的样本生成机制存在一定的盲目性。

分类问题中类别不平衡问题的有效解决方法_第1张图片

扩展阅读:

Chawla N V, Bowyer K W, Hall L O, et al. SMOTE: synthetic minority over-sampling technique[J]. Journal of artificial intelligence research, 2002, 16: 321-357.

这篇论文提出了SMOTE算法。


2.3 Borderline-SMOTE算法

原始的SMOTE算法对所有的少数类样本都是一视同仁的,但实际建模过程中发现那些处于边界位置的样本更容易被错分,因此利用边界位置的样本信息产生新样本可以给模型带来更大的提升。Borderline-SMOTE便是将原始SMOTE算法和边界信息算法结合的算法。算法流程如下:

  1. 首先,对于每个 x i ⊂ S m i n x_{i}\subset S_{min} xiSmin确定一系列 K K K-近邻样本集,称该数据集为 S i − k N N S_{i-kNN} SikNN,且 S i − k N N ⊂ S S_{i-kNN}\subset S SikNNS
  2. 然后,对每个样本 x i x_i xi,判断出最近邻样本集中属于多数类样本的个数,即: ∣ S i − k N N ∩ S m a j ∣ |S_{i-kNN}\cap S_{maj}| SikNNSmaj
  3. 最后,选择满足下面不等式的 k 2 ≤ ∣ S i − k N N ∩ S m a j ∣ ≤ k \frac{k}{2}\le |S_{i-kNN} \cap S_{maj}|\le k 2kSikNNSmajk,将其加入危险集DANGER,

上面式子表明,只有最近邻样本集中多数类多于少数类的那些 x i x_{i} xi 才会被选中形成“危险集”(DANGER)。因此,DANGER集中的样本代表少数类样本的边界(最容易被错分的样本)。然后对DANGER集中使用SMOTE算法在边界附近产生人工合成少数类样本。

下图即为算法的示意图:

我们可以看出,如果 ∣ S i − K N N ∩ S m a j j ∣ = k \left| S_{i-KNN}\cap S_{majj} \right| = k SiKNNSmajj=k 。 即: x i x_{i} xi 的所有 k k k个最近邻样本都属于多类。如图所示的样本点C,我们就认为样本点C是噪声且它不能生成合成样本。


扩展阅读:

Han H, Wang W Y, Mao B H. Borderline-SMOTE: a new over-sampling method in imbalanced data sets learning[C]//International Conference on Intelligent Computing. Springer, Berlin, Heidelberg, 2005: 878-887.

这篇文章提出了Borderline-SMOTE算法。


三、欠采样

直接对训练集中多数类样本进行“欠采样”(undersampling),即去除一些多数类中的样本使得正例、反例数目接近,然后再进行学习。即是欠采样。

3.1 随机欠采样

随机欠采样顾名思义即从多数类 S m a j S_{maj} Smaj 中随机选择一些样样本组成样本集 E E E 。然后将样本集 E E E S m a j S_{maj} Smaj 中移除。新的数据集 S n e w − m a j = S m a j − E S_{new-maj}=S_{maj}-E Snewmaj=SmajE

缺点:

随机欠采样方法通过改变多数类样本比例以达到修改样本分布的目的,从而使样本分布较为均衡,但是这也存在一些问题。对于随机欠采样,由于采样的样本集合要少于原来的样本集合,因此会造成一些信息缺失,即将多数类样本删除有可能会导致分类器丢失有关多数类的重要信息。

Informed欠抽样算法可以解决传统随机欠采样造成的数据信息丢失问题,且表现出较好的不均衡数据分类性能。其中有一些集成(ensemble)的想法,主要有两种方法,分别是EasyEnsemble算法和BalanceCascade算法。

3.2 EasyEnsemble算法

它把数据划分为两部分,分别是多数类样本和少数类样本。算法流程如下:

1)从多数类中有放回的随机采样 n n n次,每次选取与少数类数目相近的样本个数,那么可以得到 n n n个样本集合记作 { S 1 m a j , S 2 m a j , . . . , S n m a j } \left\{ S_{1maj},S_{2maj},...,S_{nmaj} \right\} {S1maj,S2maj,...,Snmaj}

2)然后,将每一个多数类样本的子集与少数类样本合并并训练出一个模型,可以得到 n n n个模型。

3)最终将这些模型组合形成一个集成学习系统,最终的模型结果是这 n n n个模型的投票值。

可以看到,EasyEnsemble的想法是多次随机欠抽样,尽可能全面地涵盖所有信息,算法特点是利用boosting减小偏差(Adaboost)、bagging减小方差(集成分类器)。实际应用的时候可以尝试选用不同的分类器来提高分类的效果。

下图即为算法的示意图:

3.3 BalanceCascade算法

BalanceCascade算法基于Adaboost,将Adaboost作为基分类器,其核心思路是:

1)在每一轮训练时都使用多数类与少数类数量相等的训练集,训练出一个Adaboost基分类器。

2)然后使用该分类器对全体多数类进行预测,通过控制分类阈值来控制假正例率(False Positive Rate),将所有判断正确的类删除。

3)最后,进入下一轮迭代中,继续降低多数类数量。

算法流程如下:

分类问题中类别不平衡问题的有效解决方法_第2张图片

扩展阅读:

Liu X Y, Wu J, Zhou Z H. Exploratory undersampling for class-imbalance learning[J]. IEEE Transactions on Systems, Man, and Cybernetics, Part B (Cybernetics), 2009, 39(2): 539-550.

这篇论文提出了两种欠采样的方法:EasyEnsemble和BalanceCascade。


四、综合采样

目前为止我们使用的重采样方法几乎都是只针对某一类样本:对多数类样本欠采样,对少数类样本过采样。也有人提出将欠采样和过采样综合的方法,解决样本类别分布不平衡和过拟合问题,本部分介绍其中的SMOTE+Tomek Links和SMOTE+ENN。

4.1 SMOTE+Tomek Links

4.1.1 Tomek Links方法

定义:Tomek links被定义为相反类最近邻样本之间的一对连接。

符号约定:给定一个样本对 ( x i , x j ) \left(x_i,x_j\right) (xi,xj),其中 x i ∈ S m a j x_i \in S_{maj} xiSmaj x j ∈ S m i n x_j \in S_{min} xjSmin,记 d ( x i , x j ) d\left(x_i,x_j\right) d(xi,xj)是样本 x i x_i xi x j x_j xj之间的距离

公式表示:如果不存在任何样本 x k x_k xk,使得 d ( x i , x k ) ≤ d ( x i , x j ) d\left( x_i,x_k \right) \le d\left( x_i,x_j \right) d(xi,xk)d(xi,xj),那么样本对 ( x i , x j ) (x_i,x_j) (xi,xj)被称为Tomek Links

使用这种方法,如果两个样本来自Tomek Links,那么他们中的一个样本要么是噪声要么它们都在两类的边界上。所以Tomek Links一般有两种用途:在欠采样中:将Tomek Links中属于是多数类的样本剔除;在数据清洗中,将Tomek Links中的两个样本都剔除。

4.1.2 SMOTE+Tomek Links

SMOTE+Tomek Links方法的算法流程非常简单:

  1. 利用SMOTE方法生成新的少数类样本,得到扩充后的数据集T
  2. 剔除T中的Tomek Links对

普通的SMOTE方法生成的少数类样本是通过线性插值得到的,在平衡类别分布的同时也扩张了少数类的样本空间,产生的问题是可能原本属于多数类样本的空间被少数类“入侵”,容易造成模型的过拟合。

Tomek Links对寻找的是那种噪声点或者边界点,可以很好地解决“入侵”的问题,下图红色加号为SMOTE产生的少数类样本,可以看到,红色样本“入侵”到原本属于多数类样本的空间,这种噪声数据问题可以通过Tomek Links很好地解决。

由于第一步SMOTE方法已经很好地平衡了类别分布,因此在使用Tomek Links对的时候考虑剔除所有的Tomek Links对。

4.2 SMOTE+ENN

SMOTE+ENN方法和SMOTE+Tomek Links方法的想法和过程都是很类似的:

  1. 利用SMOTE方法生成新的少数类样本,得到扩充后的数据集T
  2. 对T中的每一个样本使用KNN(一般K取3)方法预测,若预测结果与实际类别标签不符,则剔除该样本。

五、常见机器学习模型本身处理类不平衡

5.1 LightGBM

LightGBM解决类不平衡的思路类似于代价敏感学习。

5.1.1 二分类处理

在LGBM的文档中,可以看到有两个参数来处理类别不平衡,分别是is_unbalancescale_pos_weight
分类问题中类别不平衡问题的有效解决方法_第3张图片
在上图中的介绍中,这2个参数只能选其一,不能同时选。这说明了什么呢?这2个参数肯定是起到了相同的作用。这2个参数的关系是什么呢?在issue中找到了答案:

if is_unbalance = true, weight of each positive sample / weight of each negative sample = (num_negative_sample / num_positive_sample) * scale_pos_weight_

如果我们设置is_unbalance为True的话,那么scale_pos_weight就是默认值1,那么:每一个正样本的权重/每一个负样本的权重就等于负样本的样本数/正样本的样本数。

如果我们设置scale_pos_weight的话,那么应该设置成number of negative samples / number of positive samples,因为在上图中已经写明了:scale_pos_weight代表的是正类的权重。这样也就和is_unbalance参数的意思对应上了。(注:很多人对于设置scale_pos_weight是懵逼的,我自己已经明确给出了答案,包括xgb也是一样的。)

那么这2个参数是如何来解决类别不平衡的呢

很明显,可以看到,通过设置这两个参数,可以得到正样本和负样本的权重,样本的权重是什么意思呢?我们知道,在LGBM进行分裂的过程中,我们求出了样本的一阶导数和二阶导数,在此基础上,就会乘以样本的权重。

这里有一个issue涉及到了is_unbalance背后用的算法,方便读者进行更深入的了解。

5.1.2 多分类处理

LGBM对多分类的不平衡问题也进行了完美地处理。它设计了参数class weight。在文档中介绍如下:

分类问题中类别不平衡问题的有效解决方法_第4张图片
一共提到了以下几点:

  1. 要不传入是dict,格式是class_weight={1: 1, 0: 2}这样;要不传入"balanced";要不传入是None。
  2. 如果传入的是dict,那么每个类的权重正如你传入的那样。
  3. 如果传入的是"balanced",那么会自动根据标签的值来算出每个类的权重,每个类的权重是与每个类别样本出现的次数成反比的。具体是根据公式: n_samples / (n_classes * np.bincount(y))。np.bincount(y)是numpy的一个很有趣的函数,不了解的可以参考该篇文档。我们更形象地说明,我在这里举一个例子,假如我们有10个样本,标签分别为 [ 0 , 2 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ] [0,2,2,1,1,1,1,1,1,1] [0,2,2,1,1,1,1,1,1,1],这典型是不平衡的。那么np.bincount(y)输出的值为 [ 1 , 7 , 2 ] [1,7,2] [1,7,2],n_samples / (n_classes * np.bincount(y))输出的值分别为 10 3 ∗ 1 \frac{10}{3*1} 3110 10 3 ∗ 7 \frac{10}{3*7} 3710 10 3 ∗ 2 \frac{10}{3*2} 3210。这显然类别权重是与类别的样本个数成反比的。(注:这里有一个背景,就是lgbm中多类别必须设置为0,1,2,3…这样的形式)
  4. 如果传入的是None,那么每个类别的权重是一样的。
  5. 当然,与二分类一样,如果我们也传入了sample_weight,那么每个类的权重还要再乘以sample_weight。(注:sample_weight是LGBM是很少用到的一个功能,它一般是通过fit方法传入的,关于它的使用需要详细参考官方文档)

PS: 我在翻看相关issue的时候,有一个题目是利用贝叶斯调参处理不平衡类问题的参数设置,很受启发,相关issue。

5.2 Xgboost

XGB相比于LGBM,只有一个涉及到不平衡类的参数scale_pos_weight。在官方文档上是这么介绍的:
在这里插入图片描述
可以看到,定义与LGBM是相同的,即:如果我们设置scale_pos_weight的话,那么应该设置成number of negative samples / number of positive samples

在xgboost中特意提到了处理不平衡数据集:
分类问题中类别不平衡问题的有效解决方法_第5张图片

官网的意思大致可理解如下:

  1. scale_pos_weight 是用来调节正负样本不均衡问题的,用助于样本不平衡时训练的收敛。
  2. 如何仅仅关注预测问题的排序或者AUC指标,那么尽管可以调节此参数。
  3. 如果希望得到真正的预测概率则不能够通过此参数来平衡样本。什么意思呢,让我们来举个例子:假如我们现在需要通过体重来预测男女,有三个人体重分别为50kg、60kg、70kg。假设他们是男生的真正概率是:0.4、0.6、0.8。那么好,我现在模型预测出的概率为:0.7、0.8、0.9。如果讲预测概率的话,显然模型效果很差,但是我们预测的男生概率的排序以及 ROU 曲线(包括对应 AUC 值)都不会改变。如果我们想真正预测概率,而是利用一些参数,如将max_delta_step设置到一个有限的数(比如:1)可以获得效果提升.

(注意LGBM的scale_pos_weight与XGB的scale_pos_weight的意义是一样的,也就是说,如果我们在LGB中使用了scale_pos_weight,那么得不到的概率也不再是真正的预测概率了)!

在第3点中,如果我们想真正预测概率,当然还有其它一些参数可以调整,比如:

  • min_child_weight
    默认为1。是每个叶子里h的和至少是多少。对正负样本不均衡时的0-1分类而言,假设h在0.01附近,min_child_weight为1意味着叶子节点中最少需要包含100个样本。这个参数非常影响结果,控制叶子节点中二阶导的和的最小值,该参数值越小,越容易 overfitting。
  • eta
    shrinkage参数,用于更新叶子节点权重时,乘以该系数,避免步长过大。参数值越大,越可能无法收敛。把学习率eta设置的小一些,小学习率可以使得后面的学习更加仔细。
  • max_delta_step
    每个叶子允许输出的最大增量步长。 如果该值设置为0,则表示没有约束。 如果将其设置为正值,则可以帮助使更新步骤更加保守。 通常不需要此参数,但当类非常不平衡时,它可能有助于逻辑回归。 将其设置为值1-10可能有助于控制更新。

那么问题来了,源码到底是怎么利用 scale_pos_weight 来平衡样本的呢,在Issues 给出了如下:

if (info.labels[i] == 1.0f) w *= param_.scale_pos_weight

可以看出,增大了少数样本的权重。这一点与LGBM是一样的。

参考文献

【1】imbalanced-learn

【2】Imblearn package study(不平衡数据处理之过采样、下采样、综合采样)

【3】分类中解决类别不平衡问题

【4】机器学习算法系列(17):非平衡数据处理

【5】xgboost 参数 scale_pos_weight 详解

你可能感兴趣的:(机器学习)