跳转至

11.3 分类样本不平衡问题

11.3 分类样本不平衡问题⚓︎

11.3.1 什么是样本不平衡⚓︎

英文名叫做Imbalanced Data。

在一般的分类学习方法中都有一个假设,就是不同类别的训练样本的数量相对平衡。

以二分类为例,比如正负例都各有1000个左右。如果是1200:800的比例,也是可以接受的,但是如果是1900:100,就需要有些措施来解决不平衡问题了,否则最后的训练结果很大可能是忽略了负例,将所有样本都分类为正类了。

如果是三分类,假设三个类别的样本比例为:1000:800:600,这是可以接受的;但如果是1000:300:100,就属于不平衡了。它带来的结果是分类器对第一类样本过拟合,而对其它两个类别的样本欠拟合,测试效果一定很糟糕。

类别不均衡问题是现实中很常见的问题,大部分分类任务中,各类别下的数据个数基本上不可能完全相等,但是一点点差异是不会产生任何影响与问题的。在现实中有很多类别不均衡问题,它是常见的,并且也是合理的,符合人们期望的。

在前面,我们使用准确度这个指标来评价分类质量,可以看出,在类别不均衡时,准确度这个评价指标并不能work。比如一个极端的例子是,在疾病预测时,有98个正例,2个反例,那么分类器只要将所有样本预测为正类,就可以得到98%的准确度,则此分类器就失去了价值。

11.3.2 如何解决样本不平衡问题⚓︎

平衡数据集⚓︎

有一句话叫做“更多的数据往往战胜更好的算法”。所以一定要先想办法扩充样本数量少的类别的数据,比如目前的正负类样本数量是1000:100,则可以再搜集2000个数据,最后得到了2800:300的比例,此时可以从正类样本中丢弃一些,变成500:300,就可以训练了。

一些经验法则:

  • 考虑对大类下的样本(超过1万、十万甚至更多)进行欠采样,即删除部分样本;
  • 考虑对小类下的样本(不足1万甚至更少)进行过采样,即添加部分样本的副本;
  • 考虑尝试随机采样与非随机采样两种采样方法;
  • 考虑对各类别尝试不同的采样比例,比一定是1:1,有时候1:1反而不好,因为与现实情况相差甚远;
  • 考虑同时使用过采样(over-sampling)与欠采样(under-sampling)。

尝试其它评价指标⚓︎

从前面的分析可以看出,准确度这个评价指标在类别不均衡的分类任务中并不能work,甚至进行误导(分类器不work,但是从这个指标来看,该分类器有着很好的评价指标得分)。因此在类别不均衡分类任务中,需要使用更有说服力的评价指标来对分类器进行评价。如何对不同的问题选择有效的评价指标参见这里。

常规的分类评价指标可能会失效,比如将所有的样本都分类成大类,那么准确率、精确率等都会很高。这种情况下,AUC是最好的评价指标。

尝试产生人工数据样本⚓︎

一种简单的人工样本数据产生的方法便是,对该类下的所有样本每个属性特征的取值空间中随机选取一个组成新的样本,即属性值随机采样。你可以使用基于经验对属性值进行随机采样而构造新的人工样本,或者使用类似朴素贝叶斯方法假设各属性之间互相独立进行采样,这样便可得到更多的数据,但是无法保证属性之前的线性关系(如果本身是存在的)。

有一个系统的构造人工数据样本的方法SMOTE(Synthetic Minority Over-sampling Technique)。SMOTE是一种过采样算法,它构造新的小类样本而不是产生小类中已有的样本的副本,即该算法构造的数据是新样本,原数据集中不存在的。该基于距离度量选择小类别下两个或者更多的相似样本,然后选择其中一个样本,并随机选择一定数量的邻居样本对选择的那个样本的一个属性增加噪声,每次处理一个属性。这样就构造了更多的新生数据。具体可以参见原始论文。

使用命令:

pip install imblearn
可以安装SMOTE算法包,用于实现样本平衡。

尝试一个新的角度理解问题⚓︎

我们可以从不同于分类的角度去解决数据不均衡性问题,我们可以把那些小类的样本作为异常点(outliers),因此该问题便转化为异常点检测(anomaly detection)与变化趋势检测问题(change detection)。

异常点检测即是对那些罕见事件进行识别。如通过机器的部件的振动识别机器故障,又如通过系统调用序列识别恶意程序。这些事件相对于正常情况是很少见的。

变化趋势检测类似于异常点检测,不同在于其通过检测不寻常的变化趋势来识别。如通过观察用户模式或银行交易来检测用户行为的不寻常改变。

将小类样本作为异常点这种思维的转变,可以帮助考虑新的方法去分离或分类样本。这两种方法从不同的角度去思考,让你尝试新的方法去解决问题。

修改现有算法⚓︎

  • 设超大类中样本的个数是极小类中样本个数的L倍,那么在随机梯度下降(SGD,stochastic gradient descent)算法中,每次遇到一个极小类中样本进行训练时,训练L次。
  • 将大类中样本划分到L个聚类中,然后训练L个分类器,每个分类器使用大类中的一个簇与所有的小类样本进行训练得到。最后对这L个分类器采取少数服从多数对未知类别数据进行分类,如果是连续值(预测),那么采用平均值。
  • 设小类中有N个样本。将大类聚类成N个簇,然后使用每个簇的中心组成大类中的N个样本,加上小类中所有的样本进行训练。

无论你使用前面的何种方法,都对某个或某些类进行了损害。为了不进行损害,那么可以使用全部的训练集采用多种分类方法分别建立分类器而得到多个分类器,采用投票的方式对未知类别的数据进行分类,如果是连续值(预测),那么采用平均值。 在最近的ICML论文中,表明增加数据量使得已知分布的训练集的误差增加了,即破坏了原有训练集的分布,从而可以提高分类器的性能。这篇论文与类别不平衡问题不相关,因为它隐式地使用数学方式增加数据而使得数据集大小不变。但是,我认为破坏原有的分布是有益的。

集成学习⚓︎

一个很好的方法去处理非平衡数据问题,并且在理论上证明了。这个方法便是由Robert E. Schapire于1990年在Machine Learning提出的”The strength of weak learnability” ,该方法是一个boosting算法,它递归地训练三个弱学习器,然后将这三个弱学习器结合起形成一个强的学习器。我们可以使用这个算法的第一步去解决数据不平衡问题。

  1. 首先使用原始数据集训练第一个学习器L1;
  2. 然后使用50%在L1学习正确和50%学习错误的那些样本训练得到学习器L2,即从L1中学习错误的样本集与学习正确的样本集中,循环一边采样一个;
  3. 接着,使用L1与L2不一致的那些样本去训练得到学习器L3;
  4. 最后,使用投票方式作为最后输出。

那么如何使用该算法来解决类别不平衡问题呢?

假设是一个二分类问题,大部分的样本都是true类。让L1输出始终为true。使用50%在L1分类正确的与50%分类错误的样本训练得到L2,即从L1中学习错误的样本集与学习正确的样本集中,循环一边采样一个。因此,L2的训练样本是平衡的。L使用L1与L2分类不一致的那些样本训练得到L3,即在L2中分类为false的那些样本。最后,结合这三个分类器,采用投票的方式来决定分类结果,因此只有当L2与L3都分类为false时,最终结果才为false,否则true。