样本不均衡的处理方法

样本不均衡

样本不均衡指的是给定数据集中有的类别数据多,有的数据类别少,且数据占比较多的数据类别样本与占比较小的数据类别样本两者之间达到较大的比例。

常见解决办法
  • 数据层面:采样,数据增强,数据合成等;
  • 算法层面:修改损失函数值,难例挖掘等。
1. 数据层面

数据层面主要包括对数据的采样与合成操作,采样指的是以一定的概率对数据进行选择,合成指的是重新生成与数据集样本数据类似的样本将其添加到原始数据集中,以达到对小样本数据进行扩充的操作。

采样

随机过采样:从少数类样本集中随机重复抽取样本(有放回)以得到更多的样本;
随机欠采样:从多数类样本集中随机选择较少的样本(有放回/无放回);
随机采样的缺点

  • 过采样对少数样本进行了复制多份,虽然扩大了数据规模,但是也容易造成过拟合;
  • 欠采样中丢失了部分样本,可能损失有用的信息,造成模型对某些特征的欠拟合。
合成

图像领域数据合成方法与文本领域的数据合成方法是不一致的,图像是属于连续空间的,而文本是离散的,如可以对图像使用SMOTE方法进行数据的合成,但是对文本领域该方法似乎不适用。
图像领域的数据合成方法:裁剪,翻转,旋转,加噪声,SMOTE方法等;
文本领域的数据合成方法:去停用词,同义词替换,加噪声,回翻译等。

2. 算法层面

(1)带权值的损失函数:
简单粗暴地为小样本标签增加损失函数的权值,加权之后可以简单地理解是:对于小样本一个数据顶多个使用,这里的多就是我们要设置的权值,有点类似于对小样本数据进行了过采样的操作;

(2)难例挖掘
难例挖掘:指的就是挖掘出模型预测效果较差的样本,模型预测效果较差即就是在难样本上的预测损失函数值很大,挖掘出这些难训练的样本,然后对这些样本再进行重新训练等。

想一想为什么这个可以部分解决样本不均衡的问题呢?
其实,很简单的可以理解这个方法为什么可以work,难例挖掘,对于我们的小样本数据,模型的预测效果可想而知肯定预测的不好啦,预测的不好,那么不就会被挖掘出来当作难例了吗?模型对这些样本再次处理,对小样本数据就有了特殊的待遇,有种成绩不好的学生被老师带到办公室再学习的感觉,那么成绩不好的学生怎么说也会有点提高吧,模型不也就能够相应的提高performance了!

(3)Focal loss
focal loss 出自于论文Focal Loss for Dense Object Detection
具体的讲解可以去看这篇文章:https://zhuanlan.zhihu.com/p/32423092

此处简单介绍一下:focal loss在原来带权值的loss函数的基础上进行了改进,改进的方向也是损失函数的权值。
再瞅一眼二分类交叉熵损失函数的表达式:

L = − [ y l o g p + ( 1 − y ) l o g ( 1 − p ) ] L = -[ylogp +(1-y)log(1-p)] L=[ylogp+(1y)log(1p)]

这个是二分类的交叉熵损失函数,假设我们二分类的样本不均衡怎么办呢?
第一种方案,带权的损失函数值,计算表达式可如下:

L = − [ α t y t l o g p t + ( 1 − α t ) ( 1 − y t ) l o g ( 1 − p t ) ] L = -[\alpha_t y_tlogp_t +(1-\alpha_t)(1-y_t)log(1-p_t)] L=[αtytlogpt+(1αt)(1yt)log(1pt)]

哪个标签的样本数据较小,我们就将其对应的权值设置的大一点。
但是上边的损失损失函数的表达式并没有做到对难例进行挖掘,怎么对难例挖掘呢?请看下边的表达式:

L = − ( 1 − p t ) γ l o g p t L = -(1-p_t)^\gamma logp_t L=(1pt)γlogpt

浅看这个式子,无法看出它能够挖掘出难以预测的样本数据,下边举个例子帮忙解释一下:

假设现在有两个样本,一个样本是正样本数据 y = 1 y=1 y=1,模型将其预测为正样本标签的概率为0.9,另外一个样本是负样本 y = − 1 y=-1 y=1,但是由于数据的不均衡,我们将负样本也预测为正样本了,且其预测概率为0.8,怎么通过上述式子找到这个预测不准的例子呢?
针对这两个样本模型,计算损失函数值,不加权值时的损失函数值为:
L = − l o g 0.9 − l o g ( 1 − 0.8 ) L = -log0.9 - log (1-0.8) L=log0.9log(10.8)
按照上述方式增加权值之后,我们的损失函数值变成了如下形式:
L = − ( 1 − 0.9 ) γ l o g 0.9 − 0. 8 γ l o g ( 1 − 0.8 ) , γ = 2 L = -(1-0.9)^\gamma log0.9 - 0.8^\gamma log (1-0.8), \gamma=2 L=(10.9)γlog0.90.8γlog(10.8),γ=2
L = − 0.01 l o g 0.9 − 0.64 l o g ( 1 − 0.8 ) L = -0.01 log0.9 - 0.64 log (1-0.8) L=0.01log0.90.64log(10.8)

按照上述例子,是否发现我们对于预测错误的样本的损失函数值的权值相比预测正确的权值大了很多,原始两者比例是1:1,现在的比例是1:64,相当于对于预测错误的样本,我们对其处理是权值增加了63倍。
这种对损失函数修改权值的方法,是依据概率而修改的,不像直接修改损失函数的权值,直接修改显得有些生硬。

记住到这里我们挖掘出来的是预测错误的,而没有针对数据不平衡进行操作(当然数据不平衡也会导致预测错误),我们继续对损失函数加上权值,此时的权值就是对类别不平衡的处理,表达式如下:

L = − α t ( 1 − p t ) γ l o g p t L = -\alpha _t(1-p_t)^\gamma logp_t L=αt(1pt)γlogpt

这个就是focal loss 的计算表达式,论文有些对与 α , γ \alpha, \gamma α,γ的具体设值,个人认为 α \alpha α的大小一般依据数据集的平衡程度来设置, γ \gamma γ可按照论文设置2。

python 实现focal loss

def focal_loss(labels, logits, gamma, alpha):
    labels = tf.cast(labels, tf.float32)
    probs = tf.sigmoid(logits)
    ce_loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=labels, logits=logits)
    alpha_t = tf.ones_like(logits) * alpha
    alpha_t = tf.where(labels > 0, alpha_t, 1.0 - alpha_t)
    probs_t = tf.where(labels > 0, probs, 1.0 - probs)
    focal_matrix = alpha_t * tf.pow((1.0 - probs_t), gamma)

    loss = focal_matrix * ce_loss
    loss = tf.reduce_mean(loss)
    return loss

注意: 对于多分类而言,这里的 α t \alpha _t αt的设置要小心咯!

参考资料:
[1].https://blog.csdn.net/weixin_35653315/article/details/78327408
[2].https://www.zhihu.com/question/56662976/answer/611707139
[3]. https://zhuanlan.zhihu.com/p/32423092
[4]. Focal Loss for Dense Object Detection, https://arxiv.org/pdf/1708.02002.pdf

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值