1、研究背景与意义
1.1目标检测发展路径
从图中我们可以看出RetinaNet是基于FPN网络进行改进的。
1.2下图详细地回顾了FPN的发展史
1.3RetinaNet的出发点
retinanet的出发点,作为一款单阶段检测器,在速度上是达到实时了,但是精度上依然被faster rcnn等两阶段检测器吊打,本文的重点也在于此,论文作者认为单阶段的精度差在于单阶段检测器中样本的失衡,负样本比例远远大于正样本,占据样本中多数,影响网络的优化,而两阶段就没有这样的问题么,因为第一阶段会剔除掉大量负样本,所以在第二阶段训练时候,正负样本比例失衡并不严重,尽管第一阶段也会面临这样的问题。既然负样本太多,在此之前已有相关的处理方法,比如OHEM,专门挑比较难分类的负样本进行分类,其余的负样本不参与训练,效果也是不错的,大方向思路也没问题,就是降低易分类样本的影响,OHEM的思路是让它们的影响为0,直接弃用,而本文的思路是降低它们的权重,提高难分类样本的权重,如果再加上另一种方案,即所有样本原封不动,参与训练,那么这三种方案,OHEM属于激进派,retinanet属于温和派,原封不动属于保守派,最后的实验结果表明 温和派>激进派>保守派
2、RetinaNet
RetinaNet 原始论文为发表于 2017 ICCV 的 Focal Loss for Dense Object Detection。one-stage 网络首次超越 two-stage 网络,拿下了 best student paper,仅管其在网络结构部分并没有颠覆性贡献,但是其在损失函数上改进的贡献是非常非常明显的。
2.1 backbone部分
RetinaNet 网络详细结构如下所示,与 原始的FPN 不同,FPN 会使用 C2,而 RetinaNet 则没有使用P2层,因为 C2 生成的 P2 会占用更多的计算资源,所以作者直接从 C3 开始生产 P3。关于 backbone 部分和 FPN 部分基本类似,所以具体细节部分就不细讲了。第二个不同点在于 P6 这个地方,原论文是在 C5 的基础上生成的(最大池化下采样得到的),这里是根据 pytorch 官方的实现绘制的,是通过 3 × 3 3 \times 3 3×3 的卷积层来实现下采样的。第三个不同是 FPN 是从 P2 到 P6,而 RetinaNet 是从 P3 到 P7。
上图也给出了 P3 到 P7 上使用的 scale 和 ratios。在 FPN 中每个特征层上使用了一个 scale 和三个 ratios。在 RetinaNet 中是三个 scale 和三个 ratios 共计 9 个 anchor。 注意,这里 scale 等于 32 对应的 anchor 的面积是 32 的平方的。所以在 RetinaNet 中最小的 scale 是 32,最大的则是接近 813。
2.2 subnet部分
由于 RetinaNet 是一个 one-stage 的网络,所以不用 ROI pooling,直接使用如下图所示的权重共享的基于卷积操作的预测器。预测器分为两个分支,分别预测每个 anchor 所属的类别,以及目标边界框回归参数。最后的 kA 中 k 是检测目标的类别个数,注意这里的 k 不包含背景类别,对于 PASCAL VOC 数据集的话就是 20。这里的 A 是预测特征层在每一个位置生成的 anchor 的个数,在这里就是 9。(现在基本都是这样的类别不可知 anchor 回归参数预测,也可以理解为每一类共享了同一个 anchor 回归参数预测器)
2.3 正负样本匹配
针对每一个 anchor 与事先标注好的 GT box 进行比对,如果 iou 大于 0.5 则是正样本,如果某个 anchor 与所有的 GT box 的 iou 值都小于 0.4,则是负样本。其余的进行舍弃。
2.4 损失计算
本文一个核心的贡献点就是 focal loss。总损失依然分为两部分,一部分是分类损失,一部分是回归损失。Focal loss 比较独特的一个点就是正负样本都会来计算分类损失,然后仅对正样本进行回归损失的计算。retinanet的解决方案十分的简洁,就是在原本的分类损失上进行改动,加上权重因子,减小易分类样本的权重,加大难分类样本的权重(相对而言,不是绝对的变大了),至于回归损失,保持不变。
首先看原来的分类损失,以二分类为例(多分类基本是一样的)
这就是标准的交叉熵损失,稍微变换一下就有下面公式:
对于这个公式,Pt越大,代表越容易分类,也就是越接近target,于是我们应该在Pt变大时,权重变小, 变小时,权重变大, 怎么做,加一个权重因子即可,我先来一个乞丐版的,在原公式前面乘以1-Pt。
γ(gamma,不是Y),是一个指数因子,论文里设为2。
上面的公式就是focal loss,但还不是最终版,在类别不平衡中有一种做法,是给损失加上常数项正负样本平衡因子,α,这个平衡因子是用来对正负样本的损失进行平衡,并不能区分易分类样本和难分类样本哦,最终版focal loss也加入了这一项(公式如下图),于是变成(下标t与P的下标一个意思,针对两种类别),相比公式4,效果轻微提升。
论文中给出了,Focal loss和CE的对比图,CE的loss在最上面,可以看到,越易分类的样本,Focal loss损失越小。
2.5 对于 Focal loss,总结如下:
- 无论是前景类还是背景类, p t p_t pt 越大,权重 ( 1 − p t ) γ (1-p_t)^{\gamma} (1−pt)γ 就越小,即简单样本的损失可以通过权重进行抑制;
- α t \alpha_t αt 用于调节正负样本损失之间的比例,前景类别使用 α t \alpha_t αt 时,对应的背景类别使用 1 − α t 1-\alpha_t 1−αt ;
- γ \gamma γ 和 α t \alpha_t αt 的最优值是相互影响的,所以在评估准确度时需要把两者组合起来调节。作者在论文中给出 γ = 2 , α t = 0.25 \gamma = 2, \alpha_t = 0.25 γ=2,αt=0.25 时,ResNet-101+FPN 作为 backbone 的 RetinaNet 有最优的性能。这里 α t = 0.25 \alpha_t = 0.25 αt=0.25 正样本的权重小,负样本的权重大有利于压低负样本的分类损失,尽可能将负样本的损失压低。
2.6 test和train
inference:前向推理阶段,即测试阶段,作者对金字塔每层特征图都使用0.05的置信度阈值进行筛选,然后取置信度前1000的候选框(不足1000更好) ,接下来收集所有层的候选框,进行NMS,阈值0.5,RetinaNet 会将不同尺度下检测到的候选框进行合并(多尺度),然后再进行一次 NMS。
train:训练时,与GT的IOU大于0.5为正样本,小于0.4为负样本,否则忽略
anchor:anchor的设置与FPN论文略有不同,FPN中每一层一种尺度,三种比例,而retinanet中,每一层三种尺度,三种比例,在FPN中,5层金字塔,anchor尺度范围是322到5122,而本文为每一层的尺度设置三种,20, 21/3, 22/3.比例依旧是1:1, 1:2,2:1,于是有9种anchor。
以输入为800X800,五层金字塔尺度分别为100X100,50X50,25X25,12X12,6X6,算一下anchor数量,119745, 10几万anchor覆盖在整张图像中,密密麻麻,让你知道什么是密集检测,哈哈,插句话,10几万anchor中绝大多数都是负样本,无用的计算太多,这也是现在anchor free的一个出发点。
3、总结(自己看论文的时候的一些疑问)
3.1对于一张图像在FPN输出之后存在多个尺度的特征图是怎么操作的?
每个尺度的特征图都会生成一系列锚框,并对这些锚框进行分类和边界框回归预测。这样,RetinaNet 能够在不同尺度的特征图上同时检测大目标和小目标。
3.1.1将多个尺度的特征图输入到 Subnets 的特征图
- 多尺度特征图:经过 FPN 处理后,RetinaNet 生成了一系列多尺度的特征图,通常命名为
P3
,P4
,P5
,P6
, 和P7
。这些特征图具有不同的空间分辨率,但通道数相同(通常是 256 个通道)。 - 每个特征图中的每个位置都会生成锚框(anchor box),这些锚框具有不同的尺度和纵横比,以检测不同大小和形状的目标。
- 这些特征图会被分别输入到两个子网络:分类子网(classification subnet)和回归子网(box regression subnet)。
3.1.2 输入到分类子网(Classification Subnet)
- 输入:多尺度特征图(例如
P3
,P4
,P5
,P6
,P7
)。 - 功能:分类子网的任务是对每个锚框进行分类,即预测该锚框所属的类别(包括背景类)。
- 结构:
- 分类子网通常由多个共享权重的卷积层组成,常见的是 4 个 3x3 的卷积层,每个卷积层后接 ReLU 激活函数。
- 最后使用一个 3x3 的卷积层,输出一个具有
K × A
个通道的特征图,其中K
是类别数(包括背景类),A
是每个特征图位置的锚框数量。 - 通过一个 sigmoid 函数将输出转换为概率值,表示每个锚框属于每个类别的概率。
3.1.3 回归子网(Box Regression Subnet)
- 输入:同样是多尺度特征图(例如
P3
,P4
,P5
,P6
,P7
)。 - 功能:回归子网的任务是预测每个锚框的边界框偏移量(即从锚框到真实边界框的转换)。
- 结构:
- 回归子网的结构与分类子网类似,也是由 4 个共享权重的 3x3 卷积层组成,每个卷积层后接 ReLU 激活函数。
- 最后使用一个 3x3 的卷积层,输出一个具有
4 × A
个通道的特征图,其中4
表示边界框的 4 个偏移量参数(x 偏移, y 偏移, 宽度缩放, 高度缩放),A
是每个特征图位置的锚框数量。对每个锚框输出边界框的偏移量,用于调整锚框以更好地拟合目标。
3.1.4 总结
- 输入到 Subnets 的内容:经过 FPN 生成的多尺度特征图(
P3
,P4
,P5
,P6
,P7
),每个特征图中每个位置都会产生若干个锚框,这些锚框及其对应的特征被分别输入到分类子网和回归子网。 - 输出的内容:分类子网输出每个锚框的类别概率,而回归子网输出每个锚框的边界框调整参数。这两个子网共同工作,最终生成目标的检测结果。
4、参考文献:
1) 深度学习之目标检测(五)-- RetinaNet网络结构详解_python_木卯_THU-GitCode 开源社区 (csdn.net)