Focal Loss for Dense Object Detection
RetinaNet 是目前目标检测最为优秀的方法之一,在COCO数据集上达到了单个模型的state of art 的效果, 由Kaiming He团队所作。
作者发现导致one-stage算法性能劣于two-stage算法的主要原因是region proposal时前景和背景的类别不平衡,为了解决这个问题,提出了关键大招Focal Loss,改写了传统的分类交叉熵损失函数,在训练过程中能够实现自动降低容易分类的类别的权重,从而可以把优化网络的关注点放在难分类的目标上。因此,RetinaNet既解决了one-stage region proposal 产生大量的非目标区域特征导致loss计算不平衡的问题,保留了faster RCNN检测精度高的优点,又属于One-Stage算法,减少了重复计算,算法速度相对于two-stage得到了极大的提升。
博主对于" 从而可以把优化网络的关注点放在难分类的目标上 "的理解:
我们知道,原损失函数(-log(Pt)),当样本被正确分类时,其loss损失值也是一个不小的值,那么当所有易分样本的损失值相加起来,就会主导训练过程,其损失值会压倒稀有类别。那么,对于像背景类这样的易分类样本,往往就会导致对于难分类的前景类的识别的影响。通过减少易分类样本的权重(loss),从而使得模型在训练的时候更关注难分类的样本。
object detection的算法主要可以分为两大类:two-stage detector和one-stage detector。前者是指类似Faster RCNN,RFCN这样需要region proposal的检测算法,这类算法可以达到很高的准确率,但是速度较慢。虽然可以通过减少proposal的数量或降低输入图像的分辨率等方式达到提速,但是速度并没有质的提升。后者是指类似YOLO,SSD这样不需要region proposal , 直接回归的检测算法, 这类算法速度很快, 但是准确率不如前者。
作者认定训练过程中的类别不均衡是阻碍单阶段检测器得到最好的准确率的主要障碍,并提出了一种新的损失函数,去除这个障碍。
作者提出focal loss的出发点:是希望one-stage detector可以达到two-stage detector的准确率,同时不影响原有的速度。
one−stage 检测器对目标可能的位置进行密集采样,相比于 two−stage two-stagetwo−stage 方法更简单、速度更快,但是精度稍显不足。
作者发现,检测器训练过程中,背景-前景类别极端不平衡是导致这一结果的主要原因。
类别不均衡会带来什么后果呢?:
(1) training is inefficient as most locations are easy negatives that contribute no useful learning signal;
(2) en masse, the easy negatives can overwhelm training and lead to degenerate models.
也就是说:负样本数量太大,占总的loss的大部分,而且多是容易分类的,因此使得模型的优化方向并不是我们所希望的那样。
其实先前也有一些算法来处理类别不均衡的问题,比如OHEM(online hard example mining),OHEM的主要思想可以用原文的一句话概括:
In OHEM each example is scored by its loss, non-maximum suppression (nms) is then applied, and a minibatch is constructed with the highest-loss examples。
OHEM算法虽然增加了错分类样本的权重,但是OHEM算法忽略了容易分类的样本。
为了解决这一问题,作者重构了标准交叉熵(CE CECE)损失来减小分类正确的样本的损失权重。Focal Loss Focal~LossFocal Loss 聚焦于难分样本的训练,并且减小数量较多的易分负样本的影响。
为了证明focal loss的有效性,作者设计了一个dense detector:RetinaNet,并且在训练时采用focal loss训练。实验证明RetinaNet不仅可以达到one-stage detector的速度,也能有two-stage detector的准确率。
下面就是解释这个损失函数,为什么能够使得模型在训练时更专注于难分类的样本!
FL(pt)=−αt(1−pt ) γlog(pt)(处理一下上标!!!)
其实公式是非常简单的,主要是怎么去理解这个公式在训练过程中发挥的作用?以及通过调制系数,在训练过程中发挥的作用?来降低易分类样本的权重,使得模型更专注于难分类的样本?
博主个人的认为,这里应该先去解释loss值的大小对模型的训练的影响,通过loss值,再来看公式,就可以更好的理解公式发挥的作用了。
损失函数:函数用来表征模型的预测yˆ 与真实的输出y 之间的损失,而模型的训练就是要通过样本将损失函数最小化。
也就是说,如果当前损失值的比例是,易分类的损失值占大头,那么,模型肯定是倾向于,对易分类的样本进行不断的优化,使损失值达到最小,然后忽略占小头的难分类样本的分类识别。所以,原先的损失函数,当正确分类的时候,其loss的损失值也是一个不小的数,那么当所有易分类样本的损失值相加就会主导训练的过程了,使得模型倾向于易分类样本的分类,从而使得难分类的样本被忽略。
那么目标就很明确了,当它是易分类的样本,就使得损失值更小。难分类的样本虽然损失值也会小,但小的幅度是很小的,也就能够使得模型在训练时更专注于难分类的样本了。接下来的看具体解释。
focal loss的含义可以看如下图,横坐标是pt,纵坐标是loss。CE(pt)表示标准的交叉熵公式(γ=0的蓝色曲线就是标准的交叉熵损失),FL(pt)表示focal loss中用到的改进的交叉熵,和原来的交叉熵对比多了一个调制系数(modulating factor)。
加上这个调制系数的目的是:通过减少易分类样本的权重,从而使得模型在训练时更专注于难分类的样本。首先pt的范围是0到1,所以不管γ是多少,这个调制系数都是大于等于0的。易分类的样本再多,你的权重很小,那么对于total loss的共享也就不会太大。那么怎么控制样本权重呢?
举个例子,假设一个二分类,样本x1属于类别1的pt=0.9,样本x2属于类别1的pt=0.6,显然前者更可能是类别1(也就是属于易分类),假设γ=1,那么对于pt=0.9,调制系数则为0.1;对于pt=0.6,调制系数则为0.4,这个调制系数就是这个样本对loss的贡献程度,也就是权重,所以难分的样本(pt=0.6)的权重(调制系数为0.4)更大。
在介绍focal loss之前,先来看看交叉熵损失,这里以二分类为例,p表示概率,公式如下:
因为是二分类,所以y的值是正1或负1,p的范围为0到1。当真实label是1,也就是y=1时(理解为正样本),假如某个样本x预测为1这个类的概率p=0.6,那么损失就是-log(0.6) ,注意这个损失是大于等于0的。如果p=0.9,那么损失就是-log(0.9),所以p=0.6的损失要大于p=0.9的损失,这很容易理解。
为了方便,用pt代替p,如下公式2:。这里的pt就是上面坐标图中的横坐标。
接下来介绍一个最基本的对交叉熵的改进,也将作为本文实验的baseline,如下公式3。什么意思呢?增加了一个系数at,跟pt的定义类似,当label=1的时候,at=a;当label=-1的时候,at=1-a,a的范围也是0到1。因此可以通过设定a的值(假如1这个类的样本数比-1这个类的样本数多很多,那么a会取0到0.5来增加-1这个类的样本的权重)来控制正负样本对总的loss的共享权重。
显然前面的公式3虽然可以控制正负样本的权重,但是没法控制容易分类和难分类样本的权重,于是就有了focal loss:
注:这里的γ称作focusing parameter,γ>=0。(1−pt ) γ 。 称为调制系数(modulating factor)
这里介绍下focal loss的两个重要性质:
focal loss的两个性质算是核心,其实就是用一个合适的函数去度量难分类和易分类样本对总的损失的贡献。
作者在实验中采用的是公式5的focal loss(结合了公式3和公式4,这样既能调整正负样本的权重,又能控制难易分类样本的权重):
在实验中a的选择范围也很广,一般而言当γ增加的时候,a需要减小一点(实验中γ=2,a=0.25的效果最好)
总结:乘上该权重所带来的影响:
loss量级 | 量大的类别 (如background) | 量少的类别 |
---|---|---|
被正确分类时的loss | 大幅↓↓ | 稍微↓↓ |
被错误分类时的loss | 适当↓↓ | 近乎保持不变 |
以上的公式解析过程主要是参考该篇博客,部分括号后的注释是博主自己根据自己的理解进行添加解释说明。如有错误的地方,还请指出,互相学习,共同进步。
作者的评估,参考文章:
论文中,作者认为单阶段目标检测器不能超过最好的两阶段检测器的主要原因是类别不均衡。为解决这个问题,提出了focal loss,对交叉熵使用了一个调制项,以聚焦难以分类的负样本的学习。作者的方法非常简单高效。他们设计了一个全卷积的单阶段检测器,进行广泛的试验并分析,结果表明取得了目前最好的准确率和速度,证明了focal loss的有效性。
什么是“类别不平衡”呢?
详细来说,检测算法在早期会生成一大波的bbox。而一幅常规的图片中,顶多就那么几个object。这意味着,绝大多数的bbox属于background。
“类别不平衡”又如何会导致检测精度低呢?
因为bbox数量爆炸。
正是因为bbox中属于background的bbox太多了,所以如果分类器无脑地把所有bbox统一归类为background,accuracy也可以刷得很高(不断的关注于background类,那么损失值就会越小,accuracy也就越高了)。于是乎,分类器的训练就失败了。分类器训练失败,检测精度自然就低了。
那为什么two-stage系就可以避免这个问题呢?
因为two-stage系有RPN罩着。
第一个stage的RPN会对anchor进行简单的二分类(只是简单地区分是前景还是背景,并不区别究竟属于哪个细类)。经过该轮初筛,属于background的bbox被大幅砍削。虽然其数量依然远大于前景类bbox,但是至少数量差距已经不像最初生成的anchor那样夸张了。就等于是从 “类别 极 不平衡” 变成了 “类别 较 不平衡” 。
不过,其实two-stage系的detector也不能完全避免这个问题,只能说是在很大程度上减轻了“类别不平衡”对检测精度所造成的影响。
接着到了第二个stage时,分类器登场,在初筛过后的bbox上进行难度小得多的第二波分类(这次是细分类)。这样一来,分类器得到了较好的训练,最终的检测精度自然就高啦。但是经过这么两个stage一倒腾,操作复杂,检测速度就被严重拖慢了。
那为什么one-stage系无法避免该问题呢?
因为one stage系的detector直接在首波生成的“类别极不平衡”的bbox中就进行难度极大的细分类,意图直接输出bbox和标签(分类结果)。而原有交叉熵损失(CE)作为分类任务的损失函数,无法抗衡“类别极不平衡”,容易导致分类器训练失败。因此,one-stage detector虽然保住了检测速度,却丧失了检测精度。