数据集:类别不平衡的数据集#
这一节的任务是回答下面三个问题:
类别平衡的数据集和类别不平衡的数据集,差别到底在哪?
为什么使用不平衡的数据集训练一个模型这么难?
该怎么绕开不平衡数据集带来的种种麻烦?
类别平衡与类别不平衡数据集#
先从一个熟悉的数据集说起。假设某份数据的标签是类别型的,取值只有「正类」和「负类」两种。
在这样一份数据中,如果正类和负类的数量大致相当——比如 235 个正类、247 个负类,此时我们就说它是一个类别平衡的数据集。
而在类别不平衡的数据集里,一个标签的出现频率会明显压过另一个。但是在真实世界中,类别不平衡的数据集远比类别平衡的常见:在信用卡交易数据里,欺诈交易可能连 0.1% 都占不到;在医疗诊断数据里,患某种罕见病毒的病人占比可能不到 0.01%。
在类别不平衡的数据集里:
出现更多的那个标签,叫做多数类(majority class)。
出现更少的那个标签,叫做少数类(minority class)。
使用不平衡数据集为什么这么难#
训练模型的目标是造出一个能把正类和负类分清楚的模型。要做到这一点,每个批次(batch)里都得同时含有足够多的正类样本和负类样本。
如果只是轻度不平衡,这倒不成什么问题——哪怕批次很小,通常也能凑齐正负两类样本。但一旦不平衡得很厉害,少数类的样本可能根本不够撑起一次像样的训练。
举个例子,图 6 展示的这份数据集:
200 个标签属于多数类。
2 个标签属于少数类。

如果批次大小是 20,大多数批次里一个少数类样本都没有;如果批次大小是 100,每个批次平均也只摊到 1 个少数类样本,这点量根本不够训练。就算把批次再放大,比例依旧悬殊,模型照样可能训不出来。
注意: 在类别不平衡的数据集上,准确率通常不是一个衡量模型好坏的好指标。细节可以看分类:准确率、召回率与精确率。
使用类别不平衡的数据集训练#
训练过程中,模型其实要同时学会两件事:
每个类别长什么样——也就是说,什么样的特征值对应什么类别。
每个类别有多常见——也就是说,各类之间的相对分布是什么样的。
常规的训练方式会把这两件事混在一起。而下面这个两步走的技巧——对多数类别下采样并上调其权重——能把它们拆开,让模型两个目标都能达成。
注意: 很多同学读到下面两节时会冒出这么一句:「这不对吧?」——先打个预防针:对多数类别样本下采样、再上调权重,这件事确实有点反直觉。
第一步:对多数类下采样#
下采样(downsampling),指的是只用偏低比例的多数类样本参与训练。换句话说,就是人为地把一份不平衡的数据集掰得平衡一点,也就是训练时从多数类里舍掉大量样本。
下采样能大幅提高「每个批次都含有足够多的少数类样本」的概率,模型因此才能正常、高效地训练。
比如图 6 那份数据集里,99% 是多数类、1% 是少数类。若按 25 倍的倍数对多数类下采样,就能人为造出一份更平衡的训练集——80% 多数类对 20% 少数类,就像图 7 所示:

第二步:给下采样后的类别上调权重#
下采样会引入预测偏差:你拿给模型看的,是一个「类别比现实更均衡」的人为世界。要把这个偏差纠回来,就得按你下采样的那个倍数,给多数类上调权重(upweighting)。所谓上调权重,就是让多数类样本上的损失比少数类样本上的损失更「狠」。
举个例子:我们按 25 倍下采样了多数类,那就必须按 25 倍上调它的权重。也就是说,当模型错误地判成了多数类时,就当这次损失是 25 个错误(把常规损失乘以 25)。

那么,下采样和上调权重的倍数到底取多少才合适?这个问题只能靠试验:像调其他超参数一样,换不同的下采样倍数和加权倍数试一试。
这套技巧带来的好处#
对多数类下采样并上调权重,能带来两方面的收益:
更好的模型: 最终得到的模型同时「知道」两件事:
特征与标签之间的关联
类别在真实世界中的真实分布
更快的收敛: 训练过程中,模型见到少数类的次数明显变多,这有助于它更快地收敛。
关键术语:
批次
类别平衡的数据集
类别不平衡的数据集
数据集
下采样
超参数
多数类
少数类
预测偏差
上调权重