本篇博文主要想谈一谈类别不平衡问题是什么和如何解决类别不平衡问题。
类别不平衡问题是什么?
类别不平衡是分类任务中一个典型的问题。简而言之,即数据集中,每个类别下的样本数量相差很大。例如,在一个二分类问题中,共有 100 个样本(100 行数据,每一行数据为一个样本的表征),其中 80 个样本属于类别 1,其余的 20 个样本属于类别 2,$类别 1:类别 2=80:20=4:1$,这便属于类别不平衡。当然,类别不平衡同样会发生在多分类任务中。它们的解决方法是一样的。因此,为了便于讨论与理解,我们从二分类任务入手进行讲解,我们称样本数量多的类别为大类,样本数量少的类别为小类。
类别不平衡问题的解决方案
1. 扩大数据集
当遇到类别不均衡问题时,首先应该想到,是否可能再增加数据(一定要有小类样本数据),更多的数据往往能够战胜更好的算法。因为机器学习是使用现有的数据近似整个数据的分布来进行估计,因此更多的数据往往能够得到更多的分布信息,以及更好分布估计。即使在增加小类样本数据的同时,又增加了更多的大类样本数据,可以移除一部分大类数据(即对大类数据进行欠采样)。
2. 尝试其它评价指标
Accuracy 这个评价指标在类别不平衡的分类任务中并不能 work,甚至产生了误导。因此在类别不平衡分类任务中,需要使用更有说服力的评价指标来对分类器进行评价:
- 混淆矩阵(Confusion Matrix):使用一个表格对分类器所预测的类别与其真实的类别的样本统计,分别为:TP、FN、FP 与 TN。
- 精确度(Precision)
- 召回率(Recall)
- F1值(F1 Score):精确度与召回率的加权平均
- Kappa(Cohen kappa)
- AUC 值或者 ROC 曲线
3. 对数据集进行重采样
可以使用一些策略该减轻数据的不平衡程度。该策略便是采样(Sampling),主要有两种采样方法来降低数据的不平衡性:
- 对小类的数据样本进行采样来增加小类的数据样本个数,即过采样(over-sampling)
- 对大类的数据样本进行采样来减少该类数据样本的个数,即欠采样(under-sampling)
采样算法往往很容易实现,并且其运行速度快,并且效果也不错。这里有一些经验法则:
- 考虑对大类下的样本(超过 1 万、十万甚至更多)进行欠采样,即删除部分样本
- 考虑对小类下的样本(不足 1 甚至更少)进行过采样,即添加部分样本的副本
- 考虑尝试随机采样与非随机采样两种采样方法
- 考虑对各类别尝试不同的采样比例,比一定是 1:1,有时候 1:1 反而不好,因为与现实情况相差甚远
- 考虑同时使用过采样与欠采样
4. 尝试产生人工数据样本
一种简单的人工样本数据产生的方法是:对该类下的所有样本每个属性特征的取值空间中随机选取一个,构成新的样本,即属性值随机采样。你可以使用基于经验对属性值进行随机采样而构造新的人工样本,或者使用类似朴素贝叶斯方法假设各属性之间互相独立进行采样,这样便可得到更多的数据,但是无法保证属性之间的线性关系(如果本身是存在的)。
比较经典的构造人工数据样本的方法是 SMOTE(Synthetic Minority Over-sampling Technique)。SMOTE 是一种过采样算法,该算法构造的数据是新样本,原数据集中不存在的。基于距离度量,它选择小类别下两个或者更多的相似样本,然后选择其中一个样本,并随机选择一定数量的邻居样本对选择的那个样本的一个属性增加噪声,每次处理一个属性。这样就构造了很多的新样本。
5. 尝试不同的分类算法
强烈建议不要对待每一个分类都使用自己喜欢而熟悉的分类算法。应该使用不同的算法对其进行比较,因为不同的算法使用于不同的任务与数据。
决策树往往在类别不平衡数据上表现不错。它使用基于类变量的划分规则去创建分类树,因此可以强制地将不同类别的样本分开。
6. 尝试对模型进行惩罚
你可以使用相同的分类算法,但是使用一个不同的角度,比如你的分类任务是识别那些小类,那么可以对分类器的小类样本数据增加权值,降低大类样本的权值(这种方法其实是产生了新的数据分布,即产生了新的数据集),从而使得分类器将重点集中在小类样本身上。一个具体做法是,在训练分类器时,若分类器将小类样本分错时额外增加分类器一个小类样本分错代价,这个额外的代价可以使得分类器更加“关心”小类样本。如 penalized-SVM 和 penalized-LDA 算法。
如果你锁定了一个具体的算法时,并且无法通过使用重采样来解决不平衡问题而得到较差的分类结果。这样你便可以使用惩罚模型来解决不平衡问题。但是,设置惩罚矩阵是一个复杂的事,因此你需要根据你的任务尝试不同的惩罚矩阵,并选取一个较好的惩罚矩阵。
7. 尝试一个新的角度理解问题
我们可以从不同于分类的角度去解决类别不平衡问题,我们可以把那些小类的样本作为异常点(Outliers),因此该问题便转化为异常点检测(Anomaly Detection)与变化趋势检测问题(Change Detection)。
异常点检测即是对那些罕见事件进行识别。如通过机器的部件的振动识别机器故障,又如通过系统调用序列识别恶意程序。这些事件相对于正常情况是很少见的。
变化趋势检测类似于异常点检测,不同在于其通过检测不寻常的变化趋势来识别。如通过观察用户模式或银行交易来检测用户行为的不寻常改变。
将小类样本作为异常点这种思维的转变,可以帮助考虑新的方法去分离或分类样本。这两种方法从不同的角度去思考,让你尝试新的方法去解决问题。
8. 尝试创新
仔细对你的问题进行分析与挖掘,是否可以将你的问题划分成多个更小的问题,而这些小问题更容易解决。例如:
- 将你的大类压缩成小类
- 使用 One Class 分类器(将小类作为异常点)
- 使用集成方式,训练多个分类器,然后联合这些分类器进行分类
- …