中心思想

  • 探究为什么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的函数曲线来看,哪怕模型对样本的输出概率contorlnet seg 语义分割对照表 语义分割focal loss_多分类,仍然会产生一个比较大的Loss,以至于不可忽略时
  • 当有很多个这样的contorlnet seg 语义分割对照表 语义分割focal loss_多分类(easy negative)时,这些小loss积小成多,会总的loss产生一个不可忽视的主导作用
  • 一个比较常见的缓解方式是加上一个系数contorlnet seg 语义分割对照表 语义分割focal loss_Problem_03contorlnet seg 语义分割对照表 语义分割focal loss_权重_04 alpha如果对正样本就是contorlnet seg 语义分割对照表 语义分割focal loss_多分类_05,负样本就是contorlnet seg 语义分割对照表 语义分割focal loss_权重_06,从而在正样本/负样本产生的Loss之间做权衡
  • 但是这种Loss只考虑了正负样本,没有考虑到难易样本,一种直观的延伸是我们在前面加上一个与难易程度(其实也就是contorlnet seg 语义分割对照表 语义分割focal loss_权重_07)有关的项:contorlnet seg 语义分割对照表 语义分割focal loss_权重_08contorlnet seg 语义分割对照表 语义分割focal loss_权重_07得分很高的时候,也就是这是个easy sample,给一个很低的权重,否则给一个很高的权重 contorlnet seg 语义分割对照表 语义分割focal loss_多分类_10是一个可以调节的参数
  • 实践中发现:contorlnet seg 语义分割对照表 语义分割focal loss_Problem_11的时候有比较好的效果,这个时候如果contorlnet seg 语义分割对照表 语义分割focal loss_Problem_12,Loss就比原来低了100倍,而contorlnet seg 语义分割对照表 语义分割focal loss_Problem_13时,只比原来低了4倍。(个人认为考虑到基数问题,倍数不一定都能反馈出真实的难易Loss变化,但整体来说难样本的比重还是会高一点的)
  • 不同的contorlnet seg 语义分割对照表 语义分割focal loss_多分类_10的曲线如下图所示:
  • contorlnet seg 语义分割对照表 语义分割focal loss_多分类_15

  • 实践中会加入一个平衡系数contorlnet seg 语义分割对照表 语义分割focal loss_多分类_05从而防止Loss过小:contorlnet seg 语义分割对照表 语义分割focal loss_权重_17(这里的contorlnet seg 语义分割对照表 语义分割focal loss_多分类_05 可以认为contorlnet seg 语义分割对照表 语义分割focal loss_多分类_10已经缓解了类别不均衡的问题,所以不用取太大)
  • 实际上Focal Loss的具体形式不重要
Focal Loss在多分类下的应用
  • 上文中提到的contorlnet seg 语义分割对照表 语义分割focal loss_权重_20本质上是激活函数的输出(sigmoid),在二分类中,由于两类别得分之和是互斥的,相加为1,因此用contorlnet seg 语义分割对照表 语义分割focal loss_权重_21就能够得到结果。因此上文中的CE可以改写为contorlnet seg 语义分割对照表 语义分割focal loss_多分类_22
  • 但是多分类中contorlnet seg 语义分割对照表 语义分割focal loss_权重_23,相应地,只需要改成contorlnet seg 语义分割对照表 语义分割focal loss_权重_24

RetinaNet 检测器

整体
  • 由一个骨干网络(复用FPN的多尺度结构) + 2个特定任务的子网络组成(一个负责回归一个负责分类)
  • FPN用了p3-p7的尺度作为融合,也就是(1/8 - 1/128)
  • 整体框架如下图所示:
Anchor
  • anchor的定义方式还是沿用Faster RCNN的size + ratio的方式,每层size = contorlnet seg 语义分割对照表 语义分割focal loss_多分类_25, ratio = contorlnet seg 语义分割对照表 语义分割focal loss_多分类_26,总共9个Anchor
  • GT 与 anchor匹配的方式仍然遵循FPN,使用iou 0.5来匹配正样本(大于0.5的anchor就是Pos),contorlnet seg 语义分割对照表 语义分割focal loss_Problem_27区间的样本就是负样本,否则就是Ignore
  • 回归仅仅在匹配到GT的anchor中计算,否则是忽略的
  • 每个anchor使用K个one-hot label来表示类别信息
分类子网络(分支)
  • 过了4个3x3的卷积层,同时将feature mapchannel保持在256不变,输出contorlnet seg 语义分割对照表 语义分割focal loss_Problem_28
  • 与RPN相比,这个网络更深,而且只包含了3x3卷积
  • 并且回归&分类的卷积层没有共享
分类子网络(分支)
  • 过了4个3x3的卷积层,同时将feature mapchannel保持在256不变,输出contorlnet seg 语义分割对照表 语义分割focal loss_权重_29
  • 这里采用了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都是contorlnet seg 语义分割对照表 语义分割focal loss_权重_30的高斯分布,bias都是0
  • 分类分支的最后一层:bias contorlnet seg 语义分割对照表 语义分割focal loss_权重_31,也就是说每个anchor被标注为正样本的置信度是contorlnet seg 语义分割对照表 语义分割focal loss_多分类_32(作者发现哪怕不用Focal Loss,这样设置一个人工值,哪怕用普通的CE Loss,也能收敛,否则是不收敛的)
  • 训练过程采用的是sync SGD
Focal Loss的可视化:

contorlnet seg 语义分割对照表 语义分割focal loss_权重_33

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