中心思想

  • 探究为什么one-stage detection(dense approach)会比two-stage(sparse approach)性能低。查出:根本原因是分类分支中前景&背景的比例严重失衡
  • 为了解决这个问题,从Loss入手提出了focal loss,用于调整Loss低(分得比较好的)样本的权重,从而防止Loss高的少量样本被大量Loss低的样本淹没
  • 为了验证focal loss的正确性提出了retinanet

Class Imbalance Problem:

  • 对于Two-stage来说,这个问题能够得到缓解的原因是:
    1. RPN已经提取出了若干个ROI,这些ROI相对于原图的所有anchor来说是稀疏的(只有1-2k),过滤掉了大部分的background samples
    2. 还有一个优势在于这些ROI取的地方往往都在目标的附近,从而避免了大量了easy nagative
    3. 正负样本的比例非常均衡(能够启发式地保证正负样本比例在1:3,或者采用OHEM)
  1. 但是One-stage做分类的时候就不能通过RPN来过滤(因为分类是在回归前面的)
    1. 通常需要在100k左右的anchor中做分类,具体来说:
      1. 输出的feature map里面大部分都是容易被分类的负样本(背景),也就是easy nagative,不会贡献太多有用的信息
      2. 整体上看,这些easy nagative对模型不会有帮助
      3. 一种常用的办法是在线难样本挖掘(OHEM),取Loss比较大的负样本,其余忽略
  • 虽然也能加上OHEM或者手工设定的参数去均衡正负样本,但是训练过程中依然很容易被容易分的样本所主导。
  • 为了解决这种问题,提出了一种更有效的途径:Focal Loss

Focal Loss

  • 核心作用:用于解决正负样本极度不均衡的问题(e.g. 1:1000)

  • 从binary CE Loss的函数曲线来看,哪怕模型对样本的输出概率p>0.5p>0.5,仍然会产生一个比较大的Loss,以至于不可忽略时

  • 当有很多个这样的p>0.5p>0.5(easy negative)时,这些小loss积小成多,会总的loss产生一个不可忽视的主导作用

  • 一个比较常见的缓解方式是加上一个系数αt\alpha_tCE(pt)=αtlog(pt),α[0,1]CE(p_t)=-\alpha_t \log(p_t), \alpha \in [0,1] alpha如果对正样本就是α\alpha,负样本就是1α1 - \alpha,从而在正样本/负样本产生的Loss之间做权衡

  • 但是这种Loss只考虑了正负样本,没有考虑到难易样本,一种直观的延伸是我们在前面加上一个与难易程度(其实也就是ptp_t)有关的项:FL(pt)=(1pt)γlog(pt)FL(p_t) = -(1-p_t)^\gamma \log(p_t)ptp_t得分很高的时候,也就是这是个easy sample,给一个很低的权重,否则给一个很高的权重 γ\gamma是一个可以调节的参数

  • 实践中发现:γ=2\gamma = 2的时候有比较好的效果,这个时候如果pt=0.9p_t = 0.9,Loss就比原来低了100倍,而pt0.5p_t \leq 0.5时,只比原来低了4倍。(个人认为考虑到基数问题,倍数不一定都能反馈出真实的难易Loss变化,但整体来说难样本的比重还是会高一点的)

  • 不同的γ\gamma的曲线如下图所示:
    论文笔记:Focal Loss for Dense Object

  • 实践中会加入一个平衡系数α\alpha从而防止Loss过小:FL(pt)=αt(1pt)γlog(pt)FL(p_t) = -\alpha_t (1-p_t)^\gamma \log(p_t)(这里的α\alpha 可以认为γ\gamma已经缓解了类别不均衡的问题,所以不用取太大)

  • 实际上Focal Loss的具体形式不重要

Focal Loss在多分类下的应用

  • 上文中提到的ptp_t本质上是**函数的输出(sigmoid),在二分类中,由于两类别得分之和是互斥的,相加为1,因此用(1p)(1-p)就能够得到结果。因此上文中的CE可以改写为CE(p)=ylog(p)+(1y)log(1p)CE(p) = ylog(p) + (1-y)log(1-p)
  • 但是多分类中CE(p)=ylog(p)CE(p) = ylog(p),相应地,只需要改成FL(p)=αt(1p)γylog(p)FL(p) = -\alpha_t (1-p)^\gamma y\log(p)

RetinaNet 检测器

整体

  • 由一个骨干网络(复用FPN的多尺度结构) + 2个特定任务的子网络组成(一个负责回归一个负责分类)
  • FPN用了p3-p7的尺度作为融合,也就是(1/8 - 1/128)
  • 整体框架如下图所示:

Anchor

  • anchor的定义方式还是沿用Faster RCNN的size + ratio的方式,每层size = {20,21/3,22/3}2scale\{2^0, 2^{1/3}, 2^{2/3}\} * 2 * scale, ratio = {1:2,1:1,2:1}\{1:2, 1:1, 2:1\},总共9个Anchor
  • GT 与 anchor匹配的方式仍然遵循FPN,使用iou 0.5来匹配正样本(大于0.5的anchor就是Pos),[0,0.4)[0, 0.4)区间的样本就是负样本,否则就是Ignore
  • 回归仅仅在匹配到GT的anchor中计算,否则是忽略的
  • 每个anchor使用K个one-hot label来表示类别信息

分类子网络(分支)

  • 过了4个3x3的卷积层,同时将feature mapchannel保持在256不变,输出HW(AK)H * W * (A * K) channsel大小的feature map
  • 与RPN相比,这个网络更深,而且只包含了3x3卷积
  • 并且回归&分类的卷积层没有共享

分类子网络(分支)

  • 过了4个3x3的卷积层,同时将feature mapchannel保持在256不变,输出HW(A4)H * W * (A * 4) channsel大小的feature map
  • 这里采用了class-agnostic的方式回归,也就是说无论一个anchor多少类,都只输出一个bbox

预测时:

  1. 将图片过一遍网络,得到每一层的output feature map
  2. 为了提速,先将每个scale 的feature map中,得分小于0.05的部分都去掉,然后剩余的取前1000个bbox
  3. 将所有scale的1k个bbox都合并到一起,然后nms,iou=0.5,得到最终的预测结果

训练时:

  1. Focal Loss是应用于所有的anchor,也就是所有的分类样本都参与Focal Loss,而与SSD OHEM只取一小部分的样本算Loss不同,是一种真正的dense approach。最终的Focal Loss是所有的anchor(~100k, 输入1024x1024, 1/8到1/128尺度都有9个anchor,(128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8) * 9 = 196416),但Loss除的是正样本的数量:因为大部分的样本都是easy negatives,只产生非常小的loss,如果将这些Loss的算进去的话,会导致Loss偏小
  2. 初始化:
    • pretrain resnet50 or resnet101 backbone
    • 其余的layer初始化:除了分类分支的最后一层以外,其他的weight都是σ=0.01\sigma = 0.01的高斯分布,bias都是0
    • 分类分支的最后一层:bias b=log((1π)/π)b = -\log((1-\pi)/\pi),也就是说每个anchor被标注为正样本的置信度是π\pi(作者发现哪怕不用Focal Loss,这样设置一个人工值,哪怕用普通的CE Loss,也能收敛,否则是不收敛的)
    • 训练过程采用的是sync SGD

Focal Loss的可视化:

论文笔记:Focal Loss for Dense Object

  1. 取一个比较好的模型,训好的,然后随机取大量图片
  2. 然后取其中的  105~10^5个positive, 105~10^5个positive,分别计算Focal Loss
  3. 然后将Loss从小到大进行排序,通过累计 + 归一化的方式,输出上图中的2个曲线
  4. 总的来说,横轴代表了难样本的比例,纵轴代表了对应的Loss
    1. 正样本曲线来看,>0.8的部分,也就是20%的最难正样本,占了40%到60%左右,无论γ\gamma是多少
    2. 从负样本曲线来看,使用Focal Loss之后,易样本就被得到很大程度的抑制,Loss几乎都是由难样本控制的

相关文章: