0%

RetinaNet(Focal loss)

论文链接:https://arxiv.org/abs/1708.02002

代码链接:https://github.com/facebookresearch/Detectron


摘要

为什么two stage方法的精度要比one stage算法的精度高?
因为two stage方法使用了rpn网络产生了较好的候选区域,而one stage方法,由于采用了固定的滑框去产生prior,所以较为规律和稠密,因此影响了精度。究其原因,是前景和背景的类别不均衡产生的。

并且本paper解决这个问题的方法是,修改cross entropy loss,使得loss 更集中于hard example., : Focal Loss

另外为了验证效果,作者设计了RetinaNet,可以达到one stage的速度, two stage的精度,

要了解one stage方法以及two stage方法,请访问博客[],这里不再叙述。

为什么说正负样本不均是产生的主要原因呢?
在R-CNN系列中,通过比如Selective Search, RPN等方法产生的候选区域,约1-2k,过滤掉了大部分的背景区域,然后在进行分类的过程中,使用正负样本1:3或者OHEM方法使得正负样本较为均衡

在one-stage方法中,由于其规律的生成prior,所以一般会产生约100k左右的候选区域,会含有一定的冗余性,虽然在训练的过程中,同样采用了比如hard example mining方法,但是相对来说还是很低效的。

林外two-stage方法可以通过降低输入图像分辨率或者减少anchor的方法提高速度,但是one-stage想要提高精度需要提高计算量。

class imbalance带来的问题:

  • 训练低效,过多的负样本,对于检测框没有作用。

  • 过多简单的负样本会压制训练,使得训练效果不好。

  • training is inefficient as most locations are easy negatives that contribute no useful learning signal

  • enmasse the easy nagatives can overwhelm training and lead to degenerate models.

Focal Loss

Focal loss是在交叉熵损失基础上修改的,所以这里有必要先回顾一下交叉熵损失(cross entropy loss)

交叉熵损失的公式如下,这里给的是简单的binary crossEntropy loss,就是只有两个类别。

简化一下,我们定义$p_t$如下:

则,交叉熵损失可以表示成:

$CE(p_{t})=-log(p_{t})$

当然为了更好的分析这个函数,我们将他的图像画出来,下面的图像中的蓝色的线就是该函数的曲线了,可以发现,计算是概率比较大的简单样本 $p_{t}$ >> 0.5,依然存在一定的loss,所以当这种样本的数量较多的时候,累计起来就会比较大了,甚至会超过那些概率较小的样本(hard example),导致对于那些hard example的学习效果不佳。

那么我们该如何平衡交叉熵损失呢

最简单的方法就是在交叉熵损失前面添加一个超参数,变成$CE(p_t)=-\alpha log(p_t)$
这样就会将这条曲线往下拉一些,如下图所示,使得当概率较大的时候,其影响减小。

Focal Loss Definition

借鉴了上面的方法,所以Focal Loss并没有改变正负样本的比例,而是修改了easy/hard example的损失权重,当然$\alpha$取固定值当然不好,所以作者做了个自适应,完整的Focal Loss定义如下:

其中$\gamma$作为调节参数,控制着缩放的比例,不同的$\gamma$对应的曲线,如上图figure 1所示。

作者指出,Focal loss有两个好处:

  • 如果一个样本分类错误了,概率很小($p_t$很小),这样相乘的系数(1-$p_t$)就接近于1,对样本原本的分类影响不大。
  • $\gamma$起到了平滑的作用,作者的实验中,其等于2的效果最好。

举个例子:
取 $\gamma$==2,假如分类的概率是$\gamma$=0.9,则原来的loss=-log(0.9) =0.046,
-(1-0.9)^2 * log(0.9) = 0.00046,缩小了约100倍,加入分类概率是$\gamma$=0.968,那么就会缩小约1000倍,如果概率小于0.5,比如0.4 , -log(0.4) == 0.39, -(1-0.4)^2 * log(0.4) = 0.14,只是减少了不到3倍。

另外,可以增加一个参数$\alpha$,来平衡一下倍数,如下:

类别不均衡的模型初始化

类别不均衡,two-stage如何处理好的。

  • 其采用两个阶段的级联,这样rpn阶段就可以将候选区域数量控制在1-2k左右,相比于one-stage要减少很多。

  • mini-batch采样,采样并不是随便采样的,而是根究正样本的位置进行采样(比如将负样本的设定为与ground-truth的IOU在0.1-0.3之间的),这样可以干掉一大部分简单样本,另外在正负样本比例上的选择,比如1:3,同样在打破平衡性。

RetinaNet Detector

先上一张网络结构图:

下面逐一介绍一下:

  • backbone:FPN

RetinaNet的backbone采用resnet-FPN结构,并在P3-P7上建立图像金子塔$P_l$代表其缩放比例是$2^l$倍。同时作者指出,FPN结构还是很有用的,最开始作者只使用resnet最后一层的feature,结构AP(准确率)并不高。

  • anchors:

作者在原来的基础上,新增了3个size,{$2^0$,$2^{1/3}$,$2^{2/3}$}

IOU > 0.5 为正样本。
IOU [0, 0.4) 为负样本。
IOU [0.4, 0.5] 不要了。

检测部分,当然是正样本去检测就行了。

  • 分类分支:

对于每一个FPN分支,都会有一个预测分支与之对应,了解SSD的小伙伴对这里应该不会陌生,
有一句话没有理解:parameters of this subnet are shared across all pyramid levels.

分类分支包括4组3*3卷积+ReLU,最后接KA个3*3卷积。K代表类别,A代表anchor的数量。

相比较于RPN网络,这里的网络更深了。

  • box regression分支:

首先,box regression与分类分支并没有共享网络,

在网络inference中,为了提高速度,retinanet只使用前1000的prior去进行坐标回归,并且最后对所有的预测结果进行非极大值抑制,并设置阈值为0.5进行过滤,最终得到预测结果。

Focal Loss使用在分类分支中。

在训练的过程中,RetinaNet直接使用约100k左右的anchor进行训练,而不需要想SSD那样使用OHEM或者像RCNN系列那样提取候选区域,最终的loss是这100K的focal loss的和,并且作者表示,在$\gamma$=2,$\alpah$=0.25的时候,网络效果最佳。

  • 参数初始化

FPN部分参考FPN的初始化方法,其他的新添层,w采用高斯分布,$\sigma$=0.01, b=0, 最后一个卷积层 b = $-log((1-pi)/pi)$, pi = 0.1

下表是一些对比实验

  • (a) 是对crossentropy loss使用不同的系数的结果,可见当$\alpha$=0.75的时候,表现最好。
    *(b)是使用focal loss的对比结果,其中加粗的为最好的效果。
    *(c)是使用不同比例、大小的anchor的结果对比。
    *(d)是对OHEM的对比结果,作者分别对OHEM设置不同的比例,以及使用focal loss的结果,结果显示使用OHEM并没有特别大的变化,但是使用focal loss精度提升明显,这也说明了focal loss的作用。
  • (e) 是对不同尺度图像的精度以及速度的对比。

为了分析focal loss的效果,作者选取了大量的正负样本,然后分别计算FL,然后对其进行normalize操作,使其和是1,其累计分布如下图所示:

其横轴是样本的数量百分比,纵坐标是累计误差,可见,$\gamma$对于负样本的影响相对较大,特别是当$\gamma$取2的时候,负样本的loss大部分的损失都是很小的,只有一小部分的loss比较大,这也说明了focal loss起到了对简单负样本的抑制作用。

下面是网络的检测精度,以及速度,以及与state of the art网络的对比。

观察下面两张图,可以发现AP不太一样,主要原因是,其采用了一些策略,比如尺度变换等。