样本类别不均衡处理
分类任务中样本类别不均衡是常有的事,当样本之间的不均衡程度较小的时候,可以不作处理,当正负样本比例较大(比如10:1)且训练数据较少的时候,就需要做不均衡的处理。常见的处理方式可以分为如下几类:
- 采样方法
- 下采样(或欠采样,under-sampling)
- 上采样(或过采样,over-sampling)
- 混合采样
- 数据增强
- 收集更多的数据
- 造数据
- 更改评价指标
- cost sensitive(代价敏感,class weight)
- 模型集成
- one-class classifier
采样方法
对于下采样,最简单方便的是随机采样。以两分类为例,这里涉及两个问题:
- 应该采样哪些样本?
- 采样比例应该采样为1:1么?
理想情况下,我们希望采样的样本能反应实际的数据空间分布。所以可以通过对多数类进行聚类,然后挑选中心。imblearn中的ClusterCentroids就是这种思想。imblearn还提供了其他几种样本挑选方式:
- NearMiss-1:到少数类样本的n近邻的平均距离的最小的多数样本
- NearMiss-2:到n个最远的少数类样本的平均距离的最小的多数样本
- NearMiss-3:对于每个少数类样本,先保留其多数类M近邻,再从中挑选N近邻平均距离最大的
- EditedNearestNeighbours:通过近邻,移除与邻居差异较大的样本
还有几种EditedNearestNeighbours的扩张不再赘述。以上几种方法的本质是挑选分类边界附近的样本。这一部分其实可以参考半监督学习,可参考周志华老师的一篇经典paper:Active Learning by Querying Informative and Representative Examples,挑选最具信息量和最具代表性的样本。
对于上采样,这一部分与数据增强有一部分重叠,因为其本质是生成新样本。
简单copy少数样本,新生成的样本也就是数据集中样本的一个复制,这样对有些算法是无效的。
其次,可以通过简单差值的方式生成新样本。
最后,常用的两个方法:
- the Synthetic Minority Oversampling Technique (SMOTE)
- the Adaptive Synthetic (ADASYN)
更改评价指标
一般分类问题的评价指标为,准确率和p、r、f值。当类别失衡时,准确率就不太可信。
这是还可以使用AUC和ROC,但是AUC在类别不均衡时也不太可信,一般还要综合看一下PR曲线。
代价敏感
我使用代价敏感这个词,最开始是在贝叶斯中学习得来的,有个最小风险贝叶斯估计。其中会指定一个风险矩阵,调整loss function。
一般机器学习方法的损失函数为交叉熵、log损失、最小二乘、指数损失、hinge损失等。
下面以深度学习中的交叉熵为例。
常用计算方式如下
losses = tf.nn.softmax_cross_entropy_with_logits(logits=self.scores, labels=self.input_y)
那么能不能像sklearn那样简单添加class weight的方式来调整损失呢?
答案是可以的。tf中有一个API可以帮忙解决来,tf.losses.softmax_cross_entropy。
其中有一个参数为:weights。反映的是batch中每个样本的权重,我们可以通过生成这个weights来变相实现class_weight。具体方式如下:
self.class_weight = tf.placeholder(tf.float32, shape=[1, num_classes], name='class_weight')
sample_weights = tf.reduce_sum(tf.multiply(self.input_y, self.class_weight), 1) # size of class_weights: [1, num_classes]
losses = tf.losses.softmax_cross_entropy(onehot_labels=self.input_y, logits=self.scores,
weights=sample_weights)
这里的class_weight可以手工指定,也可以通过训练数据计算得出。
categoris = np.argmax(y_train, axis=1)
train_class_weight = n_train_samples / (n_classes * np.bincount(categoris))
train_class_weight = train_class_weight.reshape(1, n_classes)
模型集成
模型集成也分为两种
- 单纯的集成方法,比如adboost、gbdt、random forest等;
- 通过数据采样来造成训练样本差异
第一种方法就不用说了,树模型天生对数据不均衡不敏感。
第二种方法,通过不同的采样率生成不同正负样本比例的数据集进行训练,然后再集成这些模型。
比如:
- 分别设置采样率为1:1, 1:2, 1:3等的采样数据集
- 保留n个少数类样本,并随机抽取10*n 个多数类样本。然后,只需将 10*n个样本分成10份,并训练10个不同的模型。
one-class classifier
转为一分类问题,one-class classifier本身为一种异常检查算法,尽量学得目标类别的边界。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!