中心思想
- 探究为什么one-stage detection(dense approach)会比two-stage(sparse approach)性能低。查出:根本原因是分类分支中前景&背景的比例严重失衡
- 为了解决这个问题,从Loss入手提出了focal loss,用于调整Loss低(分得比较好的)样本的权重,从而防止Loss高的少量样本被大量Loss低的样本淹没
- 为了验证focal loss的正确性提出了retinanet
Class Imbalance Problem:
- 对于Two-stage来说,这个问题能够得到缓解的原因是:
- RPN已经提取出了若干个ROI,这些ROI相对于原图的所有anchor来说是稀疏的(只有1-2k),过滤掉了大部分的background samples
- 还有一个优势在于这些ROI取的地方往往都在目标的附近,从而避免了大量了easy nagative
- 正负样本的比例非常均衡(能够启发式地保证正负样本比例在1:3,或者采用OHEM)
- 但是One-stage做分类的时候就不能通过RPN来过滤(因为分类是在回归前面的)
- 通常需要在100k左右的anchor中做分类,具体来说:
- 输出的feature map里面大部分都是容易被分类的负样本(背景),也就是easy nagative,不会贡献太多有用的信息
- 整体上看,这些easy nagative对模型不会有帮助
- 一种常用的办法是在线难样本挖掘(OHEM),取Loss比较大的负样本,其余忽略
- 虽然也能加上OHEM或者手工设定的参数去均衡正负样本,但是训练过程中依然很容易被容易分的样本所主导。
- 为了解决这种问题,提出了一种更有效的途径:Focal Loss
Focal Loss
- 核心作用:用于解决正负样本极度不均衡的问题(e.g. 1:1000)
- 从binary CE Loss的函数曲线来看,哪怕模型对样本的输出概率,仍然会产生一个比较大的Loss,以至于不可忽略时
- 当有很多个这样的(easy negative)时,这些小loss积小成多,会总的loss产生一个不可忽视的主导作用
- 一个比较常见的缓解方式是加上一个系数: alpha如果对正样本就是,负样本就是,从而在正样本/负样本产生的Loss之间做权衡
- 但是这种Loss只考虑了正负样本,没有考虑到难易样本,一种直观的延伸是我们在前面加上一个与难易程度(其实也就是)有关的项:当得分很高的时候,也就是这是个easy sample,给一个很低的权重,否则给一个很高的权重 是一个可以调节的参数
- 实践中发现:的时候有比较好的效果,这个时候如果,Loss就比原来低了100倍,而时,只比原来低了4倍。(个人认为考虑到基数问题,倍数不一定都能反馈出真实的难易Loss变化,但整体来说难样本的比重还是会高一点的)
- 不同的的曲线如下图所示:
- 实践中会加入一个平衡系数从而防止Loss过小:(这里的 可以认为已经缓解了类别不均衡的问题,所以不用取太大)
- 实际上Focal Loss的具体形式不重要
Focal Loss在多分类下的应用
- 上文中提到的本质上是激活函数的输出(sigmoid),在二分类中,由于两类别得分之和是互斥的,相加为1,因此用就能够得到结果。因此上文中的CE可以改写为
- 但是多分类中,相应地,只需要改成
RetinaNet 检测器
整体
- 由一个骨干网络(复用FPN的多尺度结构) + 2个特定任务的子网络组成(一个负责回归一个负责分类)
- FPN用了p3-p7的尺度作为融合,也就是(1/8 - 1/128)
- 整体框架如下图所示:
Anchor
- anchor的定义方式还是沿用Faster RCNN的size + ratio的方式,每层size = , ratio = ,总共9个Anchor
- GT 与 anchor匹配的方式仍然遵循FPN,使用iou 0.5来匹配正样本(大于0.5的anchor就是Pos),区间的样本就是负样本,否则就是Ignore
- 回归仅仅在匹配到GT的anchor中计算,否则是忽略的
- 每个anchor使用K个one-hot label来表示类别信息
分类子网络(分支)
- 过了4个3x3的卷积层,同时将feature mapchannel保持在256不变,输出
- 与RPN相比,这个网络更深,而且只包含了3x3卷积
- 并且回归&分类的卷积层没有共享
分类子网络(分支)
- 过了4个3x3的卷积层,同时将feature mapchannel保持在256不变,输出
- 这里采用了class-agnostic的方式回归,也就是说无论一个anchor多少类,都只输出一个bbox
预测时:
- 将图片过一遍网络,得到每一层的output feature map
- 为了提速,先将每个scale 的feature map中,得分小于0.05的部分都去掉,然后剩余的取前1000个bbox
- 将所有scale的1k个bbox都合并到一起,然后nms,iou=0.5,得到最终的预测结果
训练时:
- 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偏小
- 初始化:
- pretrain resnet50 or resnet101 backbone
- 其余的layer初始化:除了分类分支的最后一层以外,其他的weight都是的高斯分布,bias都是0
- 分类分支的最后一层:bias ,也就是说每个anchor被标注为正样本的置信度是(作者发现哪怕不用Focal Loss,这样设置一个人工值,哪怕用普通的CE Loss,也能收敛,否则是不收敛的)
- 训练过程采用的是sync SGD
Focal Loss的可视化:
- 取一个比较好的模型,训好的,然后随机取大量图片
- 然后取其中的 个positive,个positive,分别计算Focal Loss
- 然后将Loss从小到大进行排序,通过累计 + 归一化的方式,输出上图中的2个曲线
- 总的来说,横轴代表了难样本的比例,纵轴代表了对应的Loss
- 正样本曲线来看,>0.8的部分,也就是20%的最难正样本,占了40%到60%左右,无论是多少
- 从负样本曲线来看,使用Focal Loss之后,易样本就被得到很大程度的抑制,Loss几乎都是由难样本控制的