样本不平衡 pytorch_样本类别不均衡问题

样本不平衡 pytorch_样本类别不均衡问题_第1张图片

样本类别不均衡是机器学习实践中经常会遇到的问题,很多时候我们只有少量的正样本和非常多的负样本,当然这种情况在多分类问题中也会经常遇到。

这种现象会对机器学习模型的性能带来很大影响。因为负样本很多,负样本在总的损失函数中的占比很大,使得模型会专注与学习负样本相关的信息来减小损失,对于正样本的关注度不足,导致最终模型对正样本以及与正样本相似的负样本的分类效果较差。

下面介绍一些解决类别不均衡问题的常用方法,个人理解有局限,大家看到有误的地方还请及时指出:

1、样本层面

问题既然是样本在类别上的分布不均衡,首先能想到的就是改变样本数量,使类别分布均衡。

1)上采样

通过采样对样本进行扩充,简单的重复样本不是和好方法,最好使用数据增强的方式生成相对自然又有新信息的样本。

2)下采样

通过随机采样、分层采样、加权采样等方式对样本进行筛选,保留比较有代表性的样本,去掉大量重复的相似的样本。

3)样本权重

样本数量多类别,样本权重小一些;样本数量少的类别,样本权重大一些。比如,

,其中Nc为类别c的样本数。

2、模型层面

1)Focal Loss

《Focal Loss for Dense Object Detection》ICCV2017 RBG,Kaiming

消除正负样本比例不平衡,并且增强对难样本的处理能力(一些很难区分的样本,其对立就是很容易识别准确的简单样本,简单样本带来的loss很小,在训练后期大量简单样本会浪费大量的训练时间)。

Focal loss是在交叉熵损失函数基础上进行的修改,降低了大量简单负样本在训练中所占的权重。首先回顾二分类交叉上损失:

79cc3439a70c6728aa1ddcc8c60d7f38.png

其中 y 是真实样本的标签(1正0负), y’ 是经过 sigmoid 激活函数的预测输出(数值在0-1之间)。可见普通的交叉熵对于正样本而言,输出概率越大损失越小。对于负样本而言,输出概率越小则损失越小。此时的损失函数在大量简单样本的迭代过程中比较缓慢且可能无法优化至最优。

在此背景下,Focal Loss函数提出来了,

1872cc89227893efe6b81361fa344545.png

它在原有的基础之上加了一个γ,其中γ>0使得减少易分类样本的损失,使得模型更关注于困难的、错分的样本

下图是γ的不同取值对损失函数曲线的影响:

样本不平衡 pytorch_样本类别不均衡问题_第2张图片

例如:γ为2时,对于正类样本而言,预测概率为0.95肯定是简单样本,这时损失函数值就变成了原来的(1-0.95)^2=0.0025 倍,而预测概率为0.5的是难样本,其损失只变成了原来的(1-0.5)^2=0.25倍,相对来说比较大,就加快了模型收敛的速度。对于负类样本也一样。

Focal Loss更加关注于这种难以区分的样本,减少了简单样本的影响。此外,加入平衡因子α,用来平衡正负样本本身的比例不均:论文中α取0.25,即正样本要比负样本占比小,这是因为负例易分

ca8084e905a29d24b4c8c192edf9021a.png

​在实验中a的选择范围也很广,一般而言当γ增加的时候,a需要减小一点(实验中γ=2,a=0.25的效果最好)。

具体实现可参考(只实现了二分类的focal loss):

CoinCheung/pytorch-loss​github.com
样本不平衡 pytorch_样本类别不均衡问题_第3张图片

2)CB Loss

Class-Balanced Loss Based on Effective Number of Samples

提出了一种新的理论框架,通过将每一个样例和一个小的邻域而不是单独的样本点关联,来衡量数据是否存在重叠。将样本的有效数据量定义为样本的体积volume,可以通过一个简单的公式进行计算。

文章设计了一种基于每种类别有效样本数的加权策略,来重新平衡损失,得到类别平衡的损失函数。

计算有效样本数

(1)随机覆盖的数据采样方法

给定一个类别,定义这个类特征空间的所有可能的数据集合为
。假设
的体积为
并且
。定义每一个数据都是
的子集并且体积都是单位体积
1,每个数据都有可能和其他数据重叠。考虑随机覆盖数据采样的过程,每个数据(也就是子集)都有可能被采样,最终目的是能够覆盖集合
的全部可能。采样的数据越多,对集合
的覆盖越好。采样数据的期望体积会随机数据量的增加而增加,最终的边界是

(2)定义:样本的有效数据量是样本的期望体积(expected volume)。

为了保证这个问题是可解的,我们假设一个新的采样数据只能通过两种方式和之前采样的数据进行交互:

  • 新样本存在于之前采样数据中的可能性为
  • 新样本在之前采样数据之外的可能性为

随着采样数据点的增多,

值会越来越大。对于一个类别来说,体积
可以看做不同原型的数量。

(3)定义有效样本数为

,其中
表示样本的总数。显然,当样本总数只有1个时,
;现在假设之前采样了
个样例,接着采样第
个样例,已采样数据的体积设为
,那么新采样数据有
概率和之前的样例重叠,所以经过第
次采样之后,期望体积为:

现在假设

,那么:

  • 上式表明样例的有效数据量是总数
    的指数函数,超参数
    控制
    随着
    的增长速度。

(4)通过

的渐近性质可以发现:
  • 很大时,有效数据量的大小等于样本数
    ,这表明没有数据时重叠的,所以的样例都是唯一的。
  • 时,则表明所有的数据都只有一个原型,其他数据都是从该原型经过数据增强得到的。

类别平衡损失函数

(1)类别平衡损失用来处理不平衡数据集的问题,方法主要是通过引入一个加权因子,这个因子则和有效样本数成反比

(2)假设输入样例

的标签为
,这里
表示类别总数。假设模型得到的概率分布
,这里
。定义损失函数为
,假设类别
的样例数为
,根据上一节的公式可知对于类别
,这里
  • 通常来说,如果没有更多关于数据的信息,那么对每个类别来说很难找到合适的超参
    。所以,通常假设
    是独立的,并且对于每个类别都有

(3)为了平衡损失,引入权重因子

,它和每个类的有效样本数成反比;为了保证总损失和之前大致一致,需要对权重因子归一化,得到
。为了简化,接下来使用
表示归一化的权重因子。

(4)对于一个类别为

的样例(对应的数量为
),在损失函数前加上权重因子
,其中
,那么类别平衡损失可以表示为(
权重未归一化):

  • 表示训练集中类别为
    的数量。

类别平衡损失函数的应用

(1)Softmax Cross-Entropy

假设模型的输出为

,这里
表示类别数;显然,模型输出要经过softmax得到属于每个类别的概率,即
。假设一个样本的标签为
,这个标签类别的训练样本数为
,则经过类别平衡后的损失为:

(2)Sigmoid Cross-Entropy

使用sigmoid函数的多分类假设不同类别之间是互相独立的,其实就是一种OvA的分类思想,转化为多个二分类问题;对于每一个类别,都是预测属于这个类和不属于这个类的概率。这种损失函数的两个优势

  • Sigmoid函数不具有排他性,而在现实世界中,一些类可能和另外的类非常相似,尤其在一些类别数比较多的细粒度分类场景下。
  • 由于每个类别被认为是独立的,都有自己的概率值,非常适用于多标签预测的场景。

使用和上面相同的标记,定义

为:

类别平衡的sigmoid cross-entropy

(3)Class-Balanced MultiLabel Focal Loss

FL通过添加一个修正因子来降低已经比较好进行分类的样例的损失,关注比较难分类的样例。定义与上面相同的

,则
,对应的损失可以写为:

其中每个类别的平衡系数可设为 :

类别平衡后的损失为:

  • 其实原始的Focal Loss存在
    平衡系数,而这里的类别平衡系数则取代了
    的功能。

文章引用自:

莫冉:[论文] 不平衡数据集处理方法-CB Loss​zhuanlan.zhihu.com

具体实现可参考:

https://github.com/vandit15/Class-balanced-loss-pytorch/blob/master/class_balanced_loss.py​github.com

你可能感兴趣的:(样本不平衡,pytorch)