处理样本不平衡的LOSS—Focal Loss

0 前言

Focal Loss是为了处理样本不平衡问题而提出的,经时间验证,在多种任务上,效果还是不错的。在理解Focal Loss前,需要先深刻理一下交叉熵损失,和带权重的交叉熵损失。然后我们从样本权利的角度出发,理解Focal Loss是如何分配样本权重的。Focal是动词Focus的形容词形式,那么它究竟Focus在什么地方呢?详细的代码请看Gitee

1 交叉熵

1.1 交叉熵损失(Cross Entropy Loss)

有\(N\)个样本,输入一个\(C\)分类器,得到的输出为\(X\in \mathcal{R}^{N\times C}\),它共有\(C\)类;其中某个样本的输出记为\(x\in \mathcal{R}^{1\times C}\),即\(x[j]\)是\(X\)的某个行向量,那么某个交叉熵损失可以写为如下公式

\[
\text{loss}\left( x,\text{class} \right)
=-\log \left( \frac{\exp \left( x\left[\text{class} \right] \right)}{\sum_j{\exp\left( x\left[ j \right] \right)}} \right)
=-x\left[\text{class} \right] +\log \left( \sum_j{\exp\left( x\left[ j \right] \right)} \right)
\tag{1-1}
\]
其中\(\text{class}\in [0,\ C)\)是这个样本的类标签,如果给出了类标签的权重向量\(W\in \mathcal{R}^{1\times C}\),那么带权重的交叉熵损失可以更改为如下公式

\[
\operatorname{loss}(x, \text {class})=W[\text {class}]\left(-x[\text {class}]+\log \left(\sum_{j} \exp (x[j])\right)\right)
\tag{1-2}
\]

最终对这个\(N\)个样本的损失求和或者求平均

\[
\ell = \begin{cases}
\sum_{i}^{N}{\text{loss}(x^{(i)},\ \text{class}^{(i)})}&\text{, sum}\ \dfrac{1}{N}\sum_{i}^{N}{\text{loss}(x^{(i)},\ \text{class}^{(i)})}&\text{, mean}
\end{cases}
\tag{1-3}
\]

这个就是我们平时经常用到的交叉熵损失了。

1.2 二分类交叉熵损失(Binary Cross Entropy Loss)

上面所提到的交叉熵损失是适用于多分类(二分类及以上)的,但是它的公式看起来似乎与我们平时在书上或论文中看到的不一样,一般我们常见的交叉熵损失公式如下:

\[
l = -y\log{\hat{y}}-(1-y)\log{(1-\hat{y})}
\]

这是一个典型的二分类交叉熵损失,其中\(y\in\{0,\ 1\}\)表示标签值,\(\hat{y}\in[0,\ 1]\)表示分类模型的类别1预测值。上面这个公式是一个综合的公式,它等价于:

\[
l = \begin{cases}
-\log{\hat{y}_0} &y=0 \ -\log{\hat{y}_1} &y=1
\end{cases}; \quad
\text{where}\quad \hat{y}_0+\hat{y}_1 = 1
\]

其中\(\hat{y}_0, \hat{y}_1\)是二分类模型输出的2个伪概率值

例:如果二分类模型是神经网络,且最后一层为: 2个神经元+Softmax,那么\(\hat{y}_0, \hat{y}_1\)就对应着这两个神经元的输出值。当然它也可以带上类别的权重。

同样地,有\(N\)个样本,输入一个2分类器,得到的输出为\(X\in \mathcal{R}^{N\times 2}\),再经过Softmax函数,\(\hat{Y}=\sigma(X)\in \mathcal{R}^{N\times 2}\),标签为\(Y\in \mathcal{R}^{N\times 2}\),每个样本的二分类损失记为\(l^{(i)}, i=0,1,2,\cdots,N\),最终对这个\(N\)个样本的损失求和或者求平均

\[
\ell = \begin{cases}
\sum_{i}^{N}l^{(i)}&\text{, sum}\ \dfrac{1}{N}\sum_{i}^{N}l^{(i)}&\text{, mean}
\end{cases}; \ \ \
l^{(i)} = -y^{(i)}\log{\hat{y}^{(i)}}-(1-y^{(i)})\log{(1-\hat{y}^{(i)})}
\]

注:如果一次只训练一个样本,即\(N=1\),那么上面带类别权重的损失中的权重是无效的。因为权重是相对的,某一个样本的权重大,那么必然需要有另一个样本的权重小,这样才能体现出这一批样本中某些样本的重要性。\(N=1\)时,已没有权重的概念,它是唯一的,也是最重要的。\(N=1\),或者说batch_size=1这种情况在训练视频\文章数据时,是会常出现的。由于我们显示/内存的限制,而视频/文章数据又比较大,一次只能训练一个样本,此时我们就需要注意权重的问题了。

2 Focal Loss

2.1 基本思想

一般来讲,Focal Loss(以下简称FL)[1]是为解决样本不平衡的问题,但是更准确地讲,它是为解决难分类样本(Hard Sample)易分类样本(Easy Sampel)的不平衡问题。对于样本不平衡,其实通过上面的带权重的交叉熵损失便可以一定程度上解决这个问题,但是在实际问题中,以权重来解决样本不平衡问题的效果不够理想,此时我们应当思考,表面上我们的样本不平衡,但实质上导致效果不好的原因也许并不是简单地因为样本不平衡,而是因为样本中存在一些Hard Sample,同时存在许多Easy Sample,Easy Sample虽然容易被分类器分辨,损失较小,但是由于其数量大,它们累积起来依然于大于Hard Sample的Loss值,因此我们需要给Hard Sample较大的权重,而Easy Sample较小的权重

那么什么叫Hard Sample,什么叫Easy Sample呢?看下面的图就知道了。

图2-1 Hard Sample 图2-2 Easy Sample1 图2-3 Easy Sample2 图2-4 Sample Space

假设,我们的任务是训练一个分类器,分类出人和马,对于上面的三张图,图2-2和图2-3应该是非常容易判断出来的,但是图2-1就是不那么容易了,它即有人的特征,又有马的特征,非常容易混淆。这种样本虽然在数据集中出现的频率可能并不高,但是想要提高分类器的性能,需要着力解决这种样本分类问题。

提出Hard Sample和Easy Sample后,可以将样本空间划分为如图2-4所示的样本空间。其中纵轴为多数类样本(Majority Class)少数类样本(Minority Class),上面的带权重的交叉熵损失只能解决Majority Class和Minority Class的样本不平衡问题,并没有考虑Hard Sample和Easy Sample的问题,Focal Loss的提出就是为解决这个难易样本的分类问题。

2.2 Focal Loss解决方案

要解决难易样本的分类问题,首先就需要找出Hard Sample和Easy Sample。这对于神经网络来说,应该是一件比较容易的事情。如图2-6所示,这是一个5分类的网络,神经网络的最后一层输出时,加上一个Softmax或者Sigmoid就会得到输出的伪概率值,代表着模型预测的每个类别的概率,

图2-6 Easy Sample Classifier Output 图2-7 Hard Sample Classifier Output

图2-6中,样本标签为1,分类器输出值最大的为第1个神经元(以0开始计数),这刚好预测准确,而且其输出值2也比其它神经元的输出值要大不少,因此可以认为这是一个易分类样本(Easy Sample);图2-7的样本标签是3,分类器输出值最大的为第4个神经元,并且这几个神经元的输出值都相差不大,神经网络无法准确判断这个样本的类别,所以可以认为这是一个难分类样本(Hard Sample)。其实说白了,判断Easy/Hard sample的方法就是看分类网络的最后的输出值。如果网络预测准确,且其概率较大,那么这是一个Easy Sample,如果网络输出的概率较小,这是一个Hard Sample。下面用数学公式严谨地表达来Focal Loss的表达式。

令一个\(C\)类分类器的输出为\(\boldsymbol{y}\in \mathcal{R}^{C\times 1}\),定义函数\(f\)将输出\(\boldsymbol{y}\)转为伪概率值\(\boldsymbol{p}=f(\boldsymbol{y})\),当前样本的类标签为\(t\),记\(p_t=\boldsymbol{p}[t]\),它表示分类器预测为\(t\)类的概率值,再结合上面的交叉熵损失,定义Focal Loss为:

\[
\text{FL} = -(1-p_t)\log(p_t)
\tag{2-1}
\]

这实质就是交叉熵损失前加了一个权重,只不过这个权重有点不一样的来头。为了更好地控制前面权重的大小,可以给前面的权重系数添加一个指数\(\gamma\),那么更改式(2-1):

\[
\text{FL} = -(1-p_t)^\gamma\log(p_t)
\tag{2-2}
\]

其中\(\gamma\)一值取值为2就好,\(\gamma\)取值为0时与交叉熵损失等价,\(\gamma\)越大,就越抑制Easy Sample的损失,相对就会越放大Hard Sample的损失。同时为解决样本类别不平衡的问题,可以再给式(2-2)添加一个类别的权重\(\alpha_t\)(这个类别权重上面的交叉熵损失已经实现):

\[
\text{FL} = -\alpha_t(1-p_t)^\gamma\log(p_t)
\tag{2-3}
\]

到这里,Focal Loss理论就结束了,非常简单,但是有效。

3 Focal Loss实现(Pytorch)

3.1 交叉熵损失实现(numpy)

为了更好的理解Focal Loss的实现,先理解交叉熵损失的实现,我这里用numpy简单地实现了一下交叉熵损失。

import numpy as np

def cross_entropy(output, target):
    out_exp = np.exp(output)
    out_cls = np.array([out_exp[i, t] for i, t in enumerate(target)])
    ce = -np.log(out_cls / out_exp.sum(1))
    return ce

代码中第5行,可能稍微有点难以理解,它不过是为了找出标签对应的输出值。比如第2个样本的标签值为3,那它分类器的输出应当选择第2行,第3列的值。

3.2 Focal Loss实现

下面的代码的10~12行:依据输出,计算概率,再将其转为focal_weight;15~16行,将类权重和focal_weight添加到交叉熵损失,得到最终的focal_loss;18~21行,实现meansum两种reduction方法,注意求平均不是简单的直接平均,而是加权平均

class FocalLoss(nn.Module):
    def __init__(self, gamma=2, weight=None, reduction='mean'):
        super(FocalLoss, self).__init__()
        self.gamma = gamma
        self.weight = weight
        self.reduction = reduction

    def forward(self, output, target):
        # convert output to presudo probability
        out_target = torch.stack([output[i, t] for i, t in enumerate(target)])
        probs = torch.sigmoid(out_target)
        focal_weight = torch.pow(1-probs, self.gamma)

        # add focal weight to cross entropy
        ce_loss = F.cross_entropy(output, target, weight=self.weight, reduction='none')
        focal_loss = focal_weight * ce_loss

        if self.reduction == 'mean':
            focal_loss = (focal_loss/focal_weight.sum()).sum()
        elif self.reduction == 'sum':
            focal_loss = focal_loss.sum()

        return focal_loss

注:上面实现中,output的维度应当满足output.dim==2,并且其形状为(batch_size, C),且target.max()<C

总结

Focal Loss从2017年提出至今,该论文已有2000多引用,足以说明其有效性。其实从本质上讲,它也只不过是给样本重新分配权重,它相对类别权重的分配方法,只不过是将样本空间进行更为细致的划分,从图2-4很容易理角,类别权重的方法,只是将样本空间划分为蓝色线上下两个部分,而加入难易样本的划分,又可以将空间划分为左右两个部分,如此,样本空间便被划分4个部分,这样更加细致。其实借助于这个思想,我们是否可以根据不同任务的需求,更加细致划分我们的样本空间,然后再相应的分配不同的权重呢?

参考文献

[1] Lin, T.-Y., Goyal, P., Girshick, R., He, K., & Dollár, P. (2017). Focal loss for dense object detection. Paper presented at the Proceedings of the IEEE international conference on computer vision.

原文地址:https://www.cnblogs.com/endlesscoding/p/12155588.html

时间: 2024-07-30 21:37:05

处理样本不平衡的LOSS—Focal Loss的相关文章

Focal Loss 的理解

论文:<Focal Loss for Dense Object Detection> Focal Loss 是何恺明设计的为了解决one-stage目标检测在训练阶段前景类和背景类极度不均衡(如1:1000)的场景的损失函数.它是由二分类交叉熵改造而来的. 标准交叉熵 其中,p是模型预测属于类别y=1的概率.为了方便标记,定义: 交叉熵CE重写为: α-平衡交叉熵: 有一种解决类别不平衡的方法是引入一个值介于[0; 1]之间的权重因子α:当y=1时,取α; 当y=0时,取1-α. 这种方法,当

Focal Loss for Dense Object Detection(RetinaNet)

Focal Loss for Dense Object Detection ICCV2017 RBG和Kaiming大神的新作. 论文目标 我们知道object detection的算法主要可以分为两大类:two-stage detector和one-stage detector.前者是指类似Faster RCNN,RFCN这样需要region proposal的检测算法,这类算法可以达到很高的准确率,但是速度较慢.虽然可以通过减少proposal的数量或降低输入图像的分辨率等方式达到提速,但是

Focal Loss

转自:https://blog.csdn.net/u014380165/article/details/77019084 论文:Focal Loss for Dense Object Detection 论文链接:https://arxiv.org/abs/1708.02002 优化版的MXNet实现:https://github.com/miraclewkf/FocalLoss-MXNet RBG和Kaiming大神的新作. 我们知道object detection的算法主要可以分为两大类:t

focal loss for multi-class classification

转自:https://blog.csdn.net/Umi_you/article/details/80982190 Focal loss 出自何恺明团队Focal Loss for Dense Object Detection一文,用于解决分类问题中数据类别不平衡以及判别难易程度差别的问题.文章中因用于目标检测区分前景和背景的二分类问题,公式以二分类问题为例.项目需要,解决Focal loss在多分类上的实现,用此博客以记录过程中的疑惑.细节和个人理解,Keras实现代码链接放在最后. 框架:K

[论文理解]Focal Loss for Dense Object Detection(Retina Net)

Focal Loss for Dense Object Detection Intro 这又是一篇与何凯明大神有关的作品,文章主要解决了one-stage网络识别率普遍低于two-stage网络的问题,其指出其根本原因是样本类别不均衡导致,一针见血,通过改变传统的loss(CE)变为focal loss,瞬间提升了one-stage网络的准确率.与此同时,为了测试该loss对网络改进的影响,文章还特地设计了一个网络,retina net,证明了其想法. Problems 为啥one-stage网

Focal Loss for Dense Object Detection 论文阅读

何凯明大佬 ICCV 2017 best student paper 作者提出focal loss的出发点也是希望one-stage detector可以达到two-stage detector的准确率,同时不影响原有的速度.one-stage detector的准确率不如two-stage detector的原因,作者认为原因是:样本的类别不均衡导致的.因此针对类别不均衡问题,作者提出一种新的损失函数:focal loss,这个损失函数是在标准交叉熵损失基础上修改得到的.这个函数可以通过减少易

Focal Loss解读

Focal loss论文详解 链接:https://zhuanlan.zhihu.com/p/49981234 何恺明大神的「Focal Loss」,如何更好地理解? 链接:https://zhuanlan.zhihu.com/p/32423092 原文地址:https://www.cnblogs.com/kandid/p/11453572.html

正负样本不平衡处理方法总结【转】

转自:watersink 1, Bootstrapping,hard negative mining最原始的一种方法,主要使用在传统的机器学习方法中.比如,训练cascade类型分类模型的时候,可以将每一级分类错误的样本继续添加进下一层进行训练. 比如,SVM分类中去掉那些离分界线较远的样本,只保留离分界线较近的样本. 2, heuristic sampling 标准的faster-RCNN中,假设正样本IOU(0.7~1.0).负样本IOU(0.1~0.3),hard 负样本IOU(0.0~0

L1 loss, L2 loss以及Smooth L1 Loss的对比

总结对比下\(L_1\) 损失函数,\(L_2\) 损失函数以及\(\text{Smooth} L_1\) 损失函数的优缺点. 均方误差MSE (\(L_2\) Loss) 均方误差(Mean Square Error,MSE)是模型预测值\(f(x)\) 与真实样本值\(y\) 之间差值平方的平均值,其公式如下 \[ MSE = \frac{\sum_{i=1}^n(f_{x_i} - y_i)^2}{n} \] 其中,\(y_i\)和\(f(x_i)\)分别表示第\(i\)个样本的真实值及其