深度学习目标检测算法之RetinaNet算法


  • 💂 个人主页:风间琉璃
  • 🤟 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主
  • 💬 如果文章对你有帮助欢迎关注点赞收藏(一键三连)订阅专栏

前言

提示:这里可以添加本文要记录的大概内容:

在RetinaNet之前,目标检测领域普遍认为one-stage算法,如YOLO系列和SSD,在准确性上不及two-stage算法,如Faster R-CNN。这种差异主要源于以下两个原因:

  • two-stage算法的流程包括使用RPN(Region Proposal Network)生成一系列的建议框,随后在这些建议框的基础上利用Fast R-CNN进行精细化调整,这一双阶段的设计使得结果更为精确。
  • 样本不平衡问题在one-stage算法中尤为突出。在Faster R-CNN中,正负样本的比例被明确设定为1:3,而one-stage算法中的正负样本比可能极端失衡,有时甚至达到1:1000。这种不平衡导致在训练过程中,梯度主要被简单样本所驱动,而复杂样本因为占比小,在损失函数的计算中被大量简单样本的影响所淹没。

RetinaNet的提出,在一定程度上解决了这一问题,它使得one-stage算法也能达到与two-stage算法相媲美的准确性。RetinaNet 原始论文为发表于 2017 ICCV 的 Focal Loss for Dense Object Detection。one-stage 网络首次超越 two-stage 网络,拿下了 best student paper,仅管其在网络结构部分并没有颠覆性贡献。

论文地址:https://arxiv.org/pdf/1708.02002.pdf


RetinaNet 算法原理

1.RetinaNet 简介

单阶段目标检测经过不断发展,虽然在检测速度上能够满足实时性的要求,但在精度上与 R-CNN 系列为代表的两阶段目标检测仍有着一定的差距。一个主要原因是正负样本数量的不均衡,对训练过程产生负面影响, He 等人提出基于Focal Loss的RetinaNet 模型,来改善样本间的不均衡性,以达到两阶段检测方法同等的精度。
在这里插入图片描述
如上图所示,RetinaNet 网络主要由ResNet主干网络FPN特征金字塔分类子网络边框回归子网络组成。其中,主干网络由 ResNet 与 FPN 共同构成,以实现对目标的特征提取分类子网络与边框回归子网络分别负责对== FPN 输出的特征图进行目标分类与位置回归==。在锚点的设计上,为了使锚框与目标边框的重合度更高, RetinaNet 设置了三种长宽比为 1:2、 1:1、 2:1,尺寸为 2 0 、 2 1 / 3 、 2 2 / 3 2^0、2^{1/3}、2^{2/3} 2021/322/3 的锚框,并使锚框的大小跟随特征层的增加而增加,使之能够匹配不同特征层上大小尺度不同的目标。

2.backbone 部分

在这里插入图片描述
RetinaNet的网络结构如图所示,与FPN网络相比,FPN在构建过程中融合了C2层的特征,而RetinaNet则跳过了C2层。这一省略是出于对计算资源的有效利用考虑,因为C2层产生的P2特征图会显著增加计算的复杂度。因此,RetinaNet的设计者选择了从C3层直接开始生成P3特征图。

RetinaNet的backbone部分与FPN在结构上相似,在P6特征图的生成上,RetinaNet的实现与原始论文描述的不同。原论文建议通过最大池化操作来下采样C5层的特征图以获得P6,而在实际的pytorch实现中,采用了一种更为高效的方法——通过一个3×3的卷积层来进行下采样。RetinaNet与FPN在特征图的尺度上也有所不同。FPN构建了一个从P2到P6的特征金字塔,而RetinaNet则构建了一个从P3到P7的特征金字塔。

3.FPN特征金字塔

深度神经网络学习到的特征中,浅层特征学到的是物理信息,如物体的角点、边缘的细节信息,而深层特征学到的是语义信息,更加high-level和抽象化。对于分类任务来说,深层网络学到的特征可能更为重要,而对于定位任务来说,深层次和浅层次的特征同样重要,因为要想精准的定位,浅层的物理细节信息是必不可少的。
在这里插入图片描述
FPN之前的目标检测算法,多数只采用顶层特征来做预测,所含的细节信息比较粗略,即使采用了特征融合的方法,也一般是采用融合后的特征进行预测的。FPN提出了特征金字塔网络,可以在不同的特征层上独立进行预测。FPN 通过自下向上、自上向下以及横向连接,可以融合不同层的特征图,得到更加丰富的信息,如上图所示。
在这里插入图片描述

  • 图(a)
    先对原始图像构造图像金字塔,然后对图像金字塔的每一层提取不同的特征并进行相应的预测。优点:精度不错;缺点:计算量大,占用内存大。

  • 图(b)
    通过对原始图像进行卷积和池化操作来获得不同尺寸的特征图,在图像的特征空间中构造出金字塔。因为浅层的网络更关注于细节信息,高层的网络更关注于语义信息,更有利于准确检测出目标,因此利用最后一个卷积层上的feature map来进行预测分类。优点:速度快、内存少。缺点:仅关注深层网络中最后一层的特征,却忽略了其它层的特征。

  • 图(c )
    在图(b)的基础之上,同时利用低层特征和高层特征,首先在原始图像上面进行深度卷积,然后分别在不同的特征层上面进行预测。优点:在不同的层上面输出对应的目标,不需要经过所有的层才输出对应的目标(即对于有些目标来说,不用进行多余的前向操作),速度更快,又提高了算法的检测性能。缺点:获得的特征不鲁棒,都是一些弱特征(因为很多的特征都是从较浅的层获得的)。

  • 图(d)
    FPN(Feature Pyramid Network)即特征金字塔:自下而上,自上而下,横向连接和卷积融合
    (1)自下而上:即神经网络的前向传播过程,特征图经过卷积核计算,通常会越变越小。对于ResNet,使用每个阶段的最后一个residual block输出的特征激活输出。对于conv2,conv3,conv4和conv5输出,将这些最后residual block的输出表示为{C2,C3,C4,C5},如下图所示,并且它们相对于输入图像具有{4, 8, 16, 32} 的步长。由于其庞大的内存占用,不会将conv1纳入金字塔中。
    (2)自上而下把更抽象、语义更强的高层特征图进行上采样(upsampling),而横向连接则是将上采样的结果和自底向上生成的相同大小的feature map进行融合(merge)。横向连接的两层特征在空间尺寸相同,这样做可以利用底层定位细节信息。将低分辨率的特征图做2倍上采样(为了简单起见,使用最近邻上采样)。然后通过按元素相加,将上采样映射与相应的自底而上映射合并。这个过程是迭代的,直到生成最终的分辨率图。 为了开始迭代,只需在C5上附加一个1×1卷积层来生成低分辨率图P5。最后,在每个合并的图上附加一个3×3卷积来生成最终的特征映射,这是为了减少上采样的混叠效应。这个最终的特征映射集称为{P2,P3,P4,P5},分别对应于{C2,C3,C4,C5},它们具有相同的尺寸。 由于金字塔的所有层次都像传统的特征化图像金字塔一样使用共享分类器/回归器,因此在所有特征图中固定特征维度(通道数,记为d),文中设置d = 256,因此所有额外的卷积层都有256个通道的输出。
    (3)横向连接:采用1×1的卷积核进行连接(减少特征图数量)。
    在这里插入图片描述

在RetinaNet网络中,输入特征经ResNet50骨干网络特征提取后,送入FPN特征金字塔中进行特征融合,以得到目标的多尺度信信息,丰富特征语义。 RetinaNet 中的特征金字塔对 FPN 部分改进,FPN 接收 C3、 C4、 C5 特征图,输出 P3-P7 五个特征图,其中 P5 上采样和 P4 进行融合, P4 上采样与 P3 进行融合, P6 和 P7 为 P5 下采样得到,目的是增大感受野,获得图片的全局信息,具体结构如下图所示。
在这里插入图片描述

4.分类和预测

在这里插入图片描述
融合后的特征层送入分类子网络(Class Subnet)边界框子网络(Box Subnet)中,分类子网络中先进行 4 次卷积核为 256 的 3×3 的卷积操作,并且在每次卷积后都使用一次 Relu 激活函数,再进行一次卷积核为K×A3×3 卷积操作,其中== K 为目标的类别数==,== A 为锚框的数量==,最后使用 Softmax 函数得到每个锚框的置信度,训练时候选择达到置信度阈值的锚框使用Focal Loss计算分类损失,并对网络进行学习优化,分类子网络和边界框框子网络之间不共享参数,但对特征层之间实现参数共享。

5.Focal Loss

基于回归的目标检测算法由于没有候选区域生成这一步骤,因此在使用锚点对目标进行预测时,会出现正负样本不平衡和难易样本不平衡问题,这将使简单负样本占据网络模型训练中的大部分损失值,导致网络模型的优化效果不佳,影响网络模型对难样本的训练,进而使得网络模型对目标的检测效果不好。

对此, Focal Loss 有效解决了目标检测中存在的类别不平衡问题和难易样本不平衡问题,它通过控制正负样本和难易样本的权重,具体如下:
F L ( p t ) = − α ( 1 − p t ) γ log ⁡ p t {\color{Green} FL(p_t) = -\alpha (1-p_t)^\gamma \log_{}{p_t}} FL(pt)=α(1pt)γlogpt p t = { p , p = 1 1 − p , o t h e r w i s e } {\color{Green} p_t=\begin{Bmatrix} p,p=1 \\1-p,otherwise \end{Bmatrix}} pt={p,p=11p,otherwise}式中, p t p_t pt是预测框分类的得分; α \alpha α表示用于控制正负样本平衡的参数,取值为 0.25; γ \gamma γ表示调制因子参数,是降低易分类样本在学习中所占比重的参数,取值为 2。

当样本被错误分类且置信度较低时,调制因子 ( 1 − p t ) γ (1-p_t)^\gamma (1pt)γ接近 1损失函数不受影响;当样本置信度较高时,调制因子 ( 1 − p t ) γ (1-p_t)^\gamma (1pt)γ接近于 0,可以有效减少易分类样本的损失权重Focal Loss 不仅减少简单样本对分类损失函数的贡献,并扩大错误高难度样本的损失范围,实现对分类过程中的正负样本贡献均衡,提高单阶段检测模型的检测性能。

在retinanet网络中其损失函数如下所示:
L o s s = 1 N P O S ∑ i L c l s i + 1 N P O S ∑ j L r e g j {\color{Orange} Loss = \frac{1}{N_{POS}} \sum_{i}^{} L_{cls}^i+\frac{1}{N_{POS}} \sum_{j}^{} L_{reg}^j} Loss=NPOS1iLclsi+NPOS1jLregj其中 L c l s L_{cls} Lcls表示是Sigmoid Focal Loss; L r e g L_{reg} Lreg表示的是L1 Loss; N P O S N_{POS} NPOS表示的是正样本的个数;i表示所有的正负样本;j表示所有的正样本 ;

总损失依然分为两部分,一部分是分类损失,一部分是回归损失。Focal loss 比较独特的一个点就是正负样本都会来计算分类损失,然后仅对正样本进行回归损失的计算。

结束语

感谢阅读吾之文章,今已至此次旅程之终站 🛬。

吾望斯文献能供尔以宝贵之信息与知识也 🎉。

学习者之途,若藏于天际之星辰🍥,吾等皆当努力熠熠生辉,持续前行。

然而,如若斯文献有益于尔,何不以三连为礼?点赞、留言、收藏 - 此等皆以证尔对作者之支持与鼓励也 💞。

### 解析 Import Error 的常见原因 当遇到 `ImportError: cannot import name 'Generic'` 错误时,通常意味着尝试从模块中导入的对象不存在或无法访问。此问题可能由多种因素引起: - 版本不兼容:不同库之间的版本冲突可能导致此类错误。 - 安装缺失:目标库未正确安装或路径配置有误。 - 导入语句不当:可能存在循环依赖或其他语法层面的问题。 ### 针对 Generic 类型的具体解决方案 对于特定于 `Generic` 的情况,考虑到 Python 中 `Generic` 是 typing 模块的一部分,在处理该类别的 ImportError 时可采取如下措施[^1]: #### 方法一:确认typing模块可用性 确保环境中已安装标准库中的 typing 模块,并且其版本支持所使用的特性。可以通过以下命令验证: ```bash python -c "from typing import Generic; print(Generic)" ``` 如果上述命令执行失败,则可能是由于 Python 或者相关扩展包的版本过低造成的。此时应考虑升级至更高版本的解释器以及对应的开发工具链。 #### 方法二:调整导入方式 有时直接通过顶层命名空间来获取所需组件会更稳定可靠。修改代码以采用这种做法可能会解决问题: ```python from collections.abc import Iterable # 如果是迭代器相关接口 from typing import TypeVar, Protocol # 对于协议和泛型定义 T = TypeVar('T') class MyContainer(Protocol[T]): ... ``` 注意这里并没有显式提到 `Generic` ,而是利用了更为基础的数据结构抽象基类或是其他替代方案实现相同功能[^2]。 #### 方法三:排查环境变量设置 检查系统的 PYTHONPATH 和虚拟环境配置是否正常工作。任何异常都可能导致某些第三方软件包找不到必要的资源文件而引发类似的错误提示。建议清理并重建项目专属的工作区以便排除干扰项的影响。 #### 示例修正后的代码片段 假设原始代码试图这样引入 `Generic` : ```python from some_module import Generic # 可能导致 ImportError ``` 改为遵循官方文档推荐的方式后变为: ```python from typing import Generic # 正确的做法 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super.Bear

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值