使用过采样或欠采样处理类别不均衡的数据后,如何正确的做交叉验证?

时间:2024-05-20 13:22:48

使用过采样或欠采样处理类别不均衡的数据后,如何正确的做交叉验证?

当我们遇到数据不均衡的时候,我们该如何做:

忽略这个问题
对占比较大的类别进行欠采样
对占比较小的类别进行过采样

忽略这个问题

如果我们使用不均衡的数据来训练分类器,那么训练出来的分类器在预测数据的时候总会返回数据集中占比最大的数据所对应的类别作为结果。分类器的偏差太大,召回率为零或非常接近零,而真假率为1或非常接近于1,即所有或几乎所有记录被检测为会正常分娩,因此基本没有识别出早产的记录。
使用过采样或欠采样处理类别不均衡的数据后,如何正确的做交叉验证?

对大类样本进行欠采样

对大类样本进行欠采样。从占比较大的类别下的样本中随机选择 n 个样本,其中 n 的值等于占比较小的类别下的样本的总数,并在训练阶段使用它们,然后在验证中排除掉这些样本。解决了数据类别不均衡的问题,并且提高了模型的召回率,但是,模型的表现并不是很好,相当于一个弱学习器。
使用过采样或欠采样处理类别不均衡的数据后,如何正确的做交叉验证?
是不是相当于训练了一个弱学习器。

对少数类样本过采样

如果我们在 交叉验证 之前进行过采样会导致 过拟合 的问题。
最简单的过采样方式就是对占比类别较小下的样本进行重新采样,譬如说创建这些样本的副本,或者手动制造一些相同的数据。
但是我们注意到在其实在 N-1 份的样本中是包含了那一份用来做验证的样本的。所以这样做交叉验证完全违背了初衷。
使用过采样或欠采样处理类别不均衡的数据后,如何正确的做交叉验证?
最左边那列表示的是原始的数据,里面包含了少数类下的两个样本。我们拷贝这两个样本作为副本,然后再进行交叉验证。在迭代的过程,我们的训练样本和验证样本会包含相同的数据,如最右那张图所示,这种情况下会导致过拟合或误导的结果,合适的做法应该如下图所示。

使用过采样或欠采样处理类别不均衡的数据后,如何正确的做交叉验证?
也就是说我们每次迭代做交叉验证之前先将验证样本从训练样本中分离出来,然后再对训练样本中少数类样本进行过采样(橙色那块图所示)。在这个示例中少数类样本只有两个,所以我拷贝了三份副本。这种做法与之前最大的不同就是训练样本和验证样本是没有交集的。因为我们获得一个比之前好的结果。即使我们使用其他的交叉验证方法,譬如 k-flod ,做法也是一样的。

SMOTE 方法

通过分析少数类样本来创建新的样本 的同时对多数类样本进行欠采样。
正常来说当我们简单复制样本的时候,训练出来的分类器在预测这些复制样本时会很有信心的将他们识别出来,你为他知道这些复制样本的所有边界和特点,而不是以概括的角度来刻画这些少数类样本。但是,SMOTE 可以有效的强制让分类的边界更加的泛化,一定程度上解决了不够泛化而导致的过拟合问题。
使用 SMOTE 过采样的确会提升决策边界,但是却并没有解决前面所提到的交叉验证所面临的问题。

错误的使用交叉验证和过采样

先进行过采样,然后再进入交叉验证的循环,我们使用 SMOTE 方法合成了我们的样本。
R 包中的 SMOTE 函数可以查看 DMwR。
使用过采样或欠采样处理类别不均衡的数据后,如何正确的做交叉验证?

正确的使用过采样和交叉验证

在交叉验证中的每次循环中做特征选择一样,我们也要在每次循环中做过采样。
我们在交叉验证循环中过采样,因为验证集已经从训练样本中移除了,因为我们只需要插入那些不用于验证的样本来合成数据。
我们交叉验证的迭代次数将和样本数一样。
最后,使用了 SMOTE 过采样技术和合适交叉验证下模型的结果如下所示。
使用过采样或欠采样处理类别不均衡的数据后,如何正确的做交叉验证?
正如我们所看到,分别使用合适的过采样(第四张图)和欠采样(第二张图)在这个数据集上训练出来的模型差距并不是很大。

总结

总结一下,当在交叉验证中使用过采样时,请确保执行了以下步骤从而保证训练的结果具备泛化性:
在每次交叉验证迭代过程中,验证集都不要做任何与特征选择,过采样和构建模型相关的事情;
过采样少数类的样本,但不要选择已经排除掉的那些样本;
用对少数类过采样和大多数类的样本混合在一起的数据集来训练模型,然后用已经排除掉的样本做为验证集——重复 n 次交叉验证的过程,n 的值是你训练样本的个数(如果你使用留一交叉验证法的话)。