NanoDet代码逐行精读与修改(零)Architecture

2023-05-16

--neozng1@hnu.edu.cn

NanoDet是一个单阶段的anchor-free模型,其设计基于FCOS模型,并加入了动态标签分配策略/GFL loss和辅助训练模块。由于其轻量化的设计和非常小的参数量,在边缘设备和CPU设备上拥有可观的推理速度。其代码可读性强扩展性高,是目标检测实践进阶到深入的不二选择。作者在知乎上有一篇介绍的文章,指路:超简单辅助模块加速训练收敛,精度大幅提升!移动端实时的NanoDet升级版NanoDet-Plus来了!

笔者已经为nanodet增加了非常详细的注释,代码请戳此仓库:nanodet_detail_notes: detail every detail about nanodet 。

此仓库会跟着文章推送的节奏持续更新!

话不多说,从结构上我们直接分backbone、neck、head、assist module、dynamic label assigner五个模块进行超級详细的介绍。

0. Architecture

surprise!首先当然要介绍一下整体的架构了。先看看整个模型的架构图:

img

NanoDet-Plus架构图,图源作者知乎

直观来看,最大的不同就是新增的Assign Guidance Module模块。检测框架还是FCOS式的一阶段网络,neck改为了GhostPAN,同时摒弃了FCOS的标签分配策略转向动态软标签分配并加入辅助训练模块也就是前述的AGM,它将作为教师模型帮助head获得更好的训练。头部的回归和标签预测仍然继承之前的Generalized Focal Loss

以NanoDet-m (320x320)为例让我们先看一下config/下的配置文件中和网络架构有关的选项:

	name: NanoDetPlus
    detach_epoch: 10
    backbone:
      name: ShuffleNetV2    # 默认使用shuffleNetV2
      model_size: 1.0x      # 模型缩放系数,更大的模型就是相应扩大各层feature map的大小
      out_stages: [2,3,4]   # backbone中输出特征到FPN的stage
      activation: LeakyReLU # 激活函数采用LeakyReLU
    fpn:
      name: GhostPAN        # 用ghostNet的模块对不同特征层进行融合
      in_channels: [116, 232, 464]  # 输入fpn的feature map尺寸
      out_channels: 96      # 
      kernel_size: 5        # 卷积核大小
      num_extra_level: 1    # 输出额外一层,即在最底层的基础上再上采样得到更大的feature map
      use_depthwise: True   # 是否使用深度可分离卷积
      activation: LeakyReLU # 激活函数
    head:
      name: NanoDetPlusHead # 检测头,还提供了之前的nanodet头和最简单的卷积头
      num_classes: 80	    # 类别数
      input_channel: 96     # 输入通道数
      feat_channels: 96     # 和输入通道数一致
      stacked_convs: 2		# 头的卷积层数
      kernel_size: 5   		# nanodet-plus也换用了5x5的大核卷积
      strides: [8, 16, 32, 64] # 有四个头,分别对应不同尺度特征的检测,这是不同head检测时的下采样倍数
      activation: LeakyReLU 
      reg_max: 7  # 用于DFL的参数,head的回归分支会预测框的分布,即用回归reg_max+1个离散的几个值来表示一个分布            
      norm_cfg: 
        type: BN	# head选用Batch Norm进行归一化操作
      loss:
      	# loss仍然继承了nanodet,使用GFL,并且这些loss有不同的权重
        loss_qfl:   
          name: QualityFocalLoss
          use_sigmoid: True
          beta: 2.0
          loss_weight: 1.0
        loss_dfl:
          name: DistributionFocalLoss
          loss_weight: 0.25
        loss_bbox:
          name: GIoULoss   # 选取计算IOU loss的方法为GIoU
          loss_weight: 2.0
    # Auxiliary head, only use in training time.
    # 新增的辅助训练模块,其实就是一个常规的检测头(上面的头是简化过的版本,表达能力显然不如标准头)
    aux_head:
      name: SimpleConvHead
      num_classes: 80
      input_channel: 192 # 可以看到输入通道数也比nanodet head多
      feat_channels: 192
      stacked_convs: 4   # 堆叠4层而不是上面的2层,反正是训练不是推理
      strides: [8, 16, 32, 64] # 对应nanodet head的四个头
      activation: LeakyReLU
      reg_max: 7  # 同head中的参数

下图是训练时feature的流图,backbone的输出进入两个Ghost PAN,其中一个是为AGM专门搭建的,另一个pan和head连接。AGM会将两个PAN的输出拼接在一起作为输入(猜想这样可以更好的获取当前Head的训练情况,同时也能获取更多特征),其有两个分支,分别负责生成用作标签分配的cls_pred和reg_pred。对于Ghost PAN中的不同层特征,AGM采用相同的参数(参数共享)进行运算,大大减小了训练时的参数数和运算量,提升精度的同时使得训练速度不会增加太多。AGM的输出在训练初期将会作为Head标签分配的参考,并且AGM的loss也会进行回传,帮助网络更快地收敛。经过数个epoch(默认是10个)的训练后Head的预测已经有较好的准确度,此时将AGM模块分离,直接由Head的输出自行完成标签分配的任务。

在这里插入图片描述

在训练完成进行推理时,直接去除AGM和aux_fpn,得到非常精简的网络结构。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NanoDet代码逐行精读与修改(零)Architecture 的相关文章

  • 洋葱结构与六边形结构的比较

    它们之间有什么区别 洋葱 六边形 根据我的理解 它们是相同的 它们专注于应用程序核心的领域 并且应该与技术 框架无关 如果有的话 它们之间有什么区别 另外 我认为使用其中一种架构或什至针对 N 层架构并没有真正的优势 如果做得不好 仅仅遵循
  • 如何通过WMI确定操作系统平台?

    我试图弄清楚 WMI 中是否有一个位置可以返回可在 所有 版本的 Windows 上工作的操作系统架构 即 32 位或 64 位 当我发现以下内容时 我以为我已经弄清楚了我的Win2k8系统 Win32 OperatingSystem OS
  • 什么算作失败?

    假设我有一个伪 C 程序 For i 0 to 10 x a 2 x 5 next 30 FLOPS 的 FLOP 数量是 1 x 1 x 5 1 2 x 5 10 loop 吗 我很难理解什么是失败 请注意 指示我从何处获取 操作 计数
  • 在事务结束时发送事件

    我有一个服务对象的接口 如下所示 为简洁起见进行了简化 public interface ItemService public Item getItemById String itemId int version public void c
  • 哪种语言(在 JVM 上运行)最适合创建 DSL?

    我们需要创建复杂的固定长度和可变长度字符串 这些字符串可能代表客户资料 订单等 你们建议使用哪种基于 JVM 的编程语言 想法是让最终用户使用此 DSL 创建字符串 所以我正在寻找验证 代码完成等 Groovy http docs code
  • 使用 i386 arch 而不是 x86_64 在 OSX 上构建 libFLAC

    我正在尝试构建 libFLAC 以在我的项目中使用 但是当涉及到链接时 GCC 会忽略该库 因为它说它不是为当前体系结构 i386 构建的 当我以 64 位编译程序时 它正确链接了库 这意味着该库是针对 x86 64 架构编译的 不幸的是
  • 如何以 REST方式发送 HTML 表单?

    我有一个名为 事实 的资源集合的 URI 以及该集合中每个 事实 资源的 URI 我相信 创建新 事实 的表单应该使用 GET 来请求 但我无法确定应该将其设置为哪个 URI 对集合 URI 的 GET 应返回 事实 资源 URI 的列表
  • 你现在在做MDA(模型驱动架构)吗?如果是这样,您使用什么工具,效果如何?

    模型驱动架构是这样一种想法 您创建模型 以一种不依赖任何 或至少大多数 实现技术的方式表达您需要解决的问题 然后为一个或多个特定平台生成实现 人们声称 在更高的抽象级别上工作更加强大和高效 此外 您的模型比技术更长寿 因此 当您的第一语言
  • 泛化和专业化——有什么区别

    我很难真正找到泛化和专业化之间的区别 以及何时使用其中之一 谁能启发我吗 最后还有一个使用 UML 的插图 Animal是一个概括 Dog是专业化 您的超类是一个通用类 但您的子类将是您的超类的专门继承者 当您沿着继承层次结构向下移动时 它
  • “if”在 ASP.NET MVC View (.aspx) 文件中被认为有害?

    我记得看到一个博客 或其他内容 说你不应该在 ASP NET MVC 的 aspx 文件中使用 但我不记得它说的替代方案是什么 有人记得看过这个并指出我吗 基本上 这意味着您的视图中不应该有大量的 if 语句 您的控制器和视图模型应该能够处
  • 为什么 Linux 对目录使用 getdents() 而不是 read()?

    我浏览 K R C 时注意到 为了读取目录中的条目 他们使用了 while read dp gt fd char dirbuf sizeof dirbuf sizeof dirbuf code Where dirbuf是系统特定的目录结构
  • 用于具有转换的非导航应用程序的视图控制器/NIB 架构?

    我正在修补一个 iPad 应用程序 就像许多 iPad 应用程序一样 它不使用 UINavigation 根视图控制系统 因此我没有每个应用程序 视图 的自然所有权 我基本上有两个基本视图 文档列表视图和文档编辑视图 我正在使用 UIVie
  • linq2sql,存储库模式 - 如何从两个或多个表查询数据?

    我使用存储库模式 和 linq2sql 作为数据访问 并拥有例如 ProductsRep 和 CustomersRep 在非常简单的场景中 数据库有两个表 产品 产品 ID 客户 ID 产品名称 日期 和顾客 客户 ID 名字 姓氏 每个存
  • Web 组件 - 服务/非 html 组件

    所以我来自 Angular 想看看如何创建vanilla Web components 现在 从 Angular 开始 我们倾向于将事物分开 组件 充当 HTML CSS 和一些 javascript 然后是 服务 主要负责收集数据和执行不
  • 如何在不同的分辨率/屏幕上提供相同的应用程序

    Scenario 您需要在不同的屏幕上展示相同的应用程序 假设标准的 15 英寸 17 英寸 便携式 10 英寸和移动 4 英寸 可能在不同的分辨率下工作 Question 您是否尝试采用一种根据可用空间重新排列的流动布局 或者您是否滚动
  • 从架构上来说,我应该如何用更易于管理的内容替换非常大的 switch 语句?

    EDIT 1 忘记添加嵌套属性曲线球 UPDATE 我选择了 mtazva 的答案 因为这是我的具体案例的首选解决方案 回想起来 我用一个非常具体的例子提出了一个一般性问题 我相信这最终让每个人 或者也许只是我 对问题到底是什么感到困惑 我
  • JavaFX 中的 MVC 模式与场景生成器

    我是 JavaFX 新手 根据我当前的设置 正在努力创建合适的 MVC 架构 我使用 Scene Builder 单击了一个 UI 并指定了一个 Controller 类 Startup public class Portal extend
  • SOA、客户端-服务器、Web 服务 - 有什么区别? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 在阅读了一些有关 SOA Web 服务和客户端 服务器架构主题的文献之后 我真的对这些术语感到困惑 因为看不出它们之间的真正区别 有人
  • 为什么我们需要 RESTful Web 服务?

    我将学习 RESTful Web 服务 最好说我必须这样做 因为它是 CS 硕士学位课程的一部分 我在 Wikipedia 上阅读了一些信息 还在 Sun Developer Network 上阅读了一篇有关 REST 的文章 我发现这不是
  • 分层架构中的异常处理

    我们正在分层设计中重构 当然还有重新设计 我们的服务 我们有服务操作层 BLL 网络抽象层 gt 处理网络代理 数据抽象层 但我们对我们的异常处理策略有点困惑 我们不想向外界透露太多 BLL 的信息 从其他层到bll就可以了 我们不想让 t

随机推荐