目标检测算法之RetinaNet(引入Focal Loss)
其实说白了RetinaNet就是resnet-101-fpn + Focal loss。不了解resnet的可以查看我前面的博客对resnet讲的很详细。
下面我们着重来介绍一下Focal loss。
在我们的目标检测中有三类不平衡(我这里总结的很详细)问题会导致我们目标检测的最终效果不是很理想。
而我们的Focal loss解决的就是前两类不平衡问题。
第一类就是正负样本不平衡,也就是目标和背景数量差距太大。
第二类就是easy positive/negative样本太多,导致loss函数对hard positive/negative样本的作用很小。(至于什么是easy positive/negative 样本呢,就是在ground_true里面或者是距离ground_true很远的样本。)下图表示的很好了。(摘自大佬公众号,见图片右下角)
第三类就是样本种类不平衡问题。
接下来我们说一下one-Stage检测算法跟two—stage检测算法的比较:
先列出两种不平衡问题的详细解释:
(1)针对所有的negtive example,数量过多造成它的loss太大,以至于主导了损失函数,不利于收敛。
(2)针对单个negtive example来说,大多数的negative example不在前景和背景的过渡区域上,分类很明确(这种易分类的negative称为easy negative),训练时对应的背景类score会很大,换句话说就是单个example的loss很小,反向计算时梯度小。梯度小造成easy negative example对参数的收敛作用很有限,我们更需要loss大的对参数收敛影响也更大的example,即hard positive/negative example。
那么制约one-stage算法检测精度的问题是什么呢?其实就是上面提到的三种不平衡问题。下面我们着重讲前两种不平衡问题。
YOLO应对上面的不平衡问题的解决方案就是在loss函数加入权重惩罚。SSD则是利用Hard-Negtive-Mining的方式将正负样本的比例控制在1:3。可以看得出来它们虽然可以处理第1个问题,但对于第2个问题就无能为力了。
那么Faster-rcnn是怎么做的呢?Faster-RCNN在FPN阶段会根据前景分数提出最可能是前景的example(2000个回归/128个分类),这就会滤除大量背景概率高的easy negtive样本,这便解决了上面提出的第2个问题。同时,在生成样本给ROIPooling层的时候,会据IOU的大小来调整positive和negative example的比例,比如设置成1:3,这样防止了negative过多的情况(同时防止了easy negative和hard negative),就解决了前面的第1个问题。因此,相对于One-Stage检测器,Faster-RCNN的精度更高。
Focal Loss
Focal loss是基于交叉熵(我这篇文章对交叉熵写的很详细,想了解的可以顺便看一下)而来的:
那么先来解决第一个问题,正负样本不均匀。这个so easy,加一个权重参数就好了。
接下来来解决易分样本对损失函数影响大的问题,直观的解决方案就是将易分样本的权重减小不就好了!
我们取
γ
\gamma
γ等于2来只管感受一下,如果p = 0.9,那么
(
1
−
0.9
)
2
=
0.001
(1-0.9)^{2}=0.001
(1−0.9)2=0.001,损失降低了1000倍。最终Focal Loss还结合了公式(2),这很好理解,公式(3)解决了难易样本的不平衡,公式(2)解决了正负样本的不平衡,将公式(2)与(3)结合使用,同时解决正负难易2个问题!所以最终Focal Loss的形式如下:
实验中证明,当
γ
\gamma
γ取2,p取0.75的时候效果最好。
下图是RetinaNet的网络结构图。
训练RetinaNet时有几个值得注意的关键点:
1、训练时FPN每一级的所有example都被用于计算Focal Loss,loss值加到一起用来训练。
2、测试时FPN每一级只选取score最大的1000个example来做nms。
3、整个结构不同层的head部分(上图中的c和d部分)共享参数,但分类和回归分支间的参数不共享。
4、分类分支的最后一级卷积的bias初始化成前面提到的-log((1-π)/π。