DDOD(Disentangle Your Dense Object Detector)解析

news2025/1/22 9:12:54

paper:Disentangle Your Dense Object Detector

official implementation:https://github.com/zehuichen123/DDOD

third-party implementation:https://github.com/open-mmlab/mmdetection/tree/main/configs/ddod

存在的问题

现有的目标检测模型的设计中存在许多联结conjunctions,本文研究了三种conjunction:1)只有在分类head中分配为positive的样本才被用来训练回归head。2)在当前分类和回归两个平行分支的设计中,两个head共享相同的输入特征。3)在计算损失时,对分布在不同FPN level的样本进行同等的对待。作者首先进行了一系列实验证明解耦这些联结可以持续提升性能。基于这些方法,作者提出了Disentangled Dense Object Detector(DDOD),其中设计了简单有效的解耦机制并且集成到了目前SOTA的密集目标检测模型中。

本文的创新点

本文通过实验证明了解耦上述三种联结可以显著提升模型性能。对于标签分配的联结,针对分类和回归设计了分离的label assigner,从而可以分别为两个分支挑选出最合适的训练集。对于空间特征的联结,基于可变形卷积提出了一种自适应特征解耦模块(adaptive feature disentanglement module),可以自动关注有利于分类和回归的不同特征。对于FPN监督的联结,设计了一种重加权机制,基于每一层的正样本,自适应的调整不同FPN层的监督大小。结合上述三点,提出了一种新的dense detector,DDOD(Disentangled Dense Object Detector)。

预实验

作者首先做了一些预实验来验证三种联结对模型的负作用。

Label Assignment Conjunction

回归损失只应用于分类分支中的“前景”样本这种conjunction是出于历史原因。只有与GT box的IoU大于设定阈值的样本才视为正样本,但是这个阈值不需要与分类的阈值一致,并且在推理时不存在“正样本”的概念因为每个anchor box或center point都会被用于预测的回归器。因此为边界框的回归单独设置一个阈值时合理的。为了验证这个假设,作者用不同的分类和回归IoU阈值训练了RetinaNet,结果如表1所示。可以看出,当分类头的IoU为0.5回归的IoU为0.4时性能最好。因此在DDOD中,通过在分类和回归分支上采用不同的label assigner来解耦assignment conjunction。

Spatial Feature Conjunction

像RetinaNet这种分类和回归是两个平行且结构相同的设计,意味着它们在特征图中对应的感受区域也是相同的。但如TSD中提到的,分类和回归任务关注的区域是不同的:语义信息丰富的区域有助于分类而轮廓区域对于回归是至关重要的。作者使用GradCAM对于分类和回归的sensitive region进行了可视化,如图2所示,可以看出两个任务关注的区域确实是不同的。

Supervision Conjunction in FPN

目前基于FPN的密集检测模型的常用实现是将不同层的输出“flatten and concatenated”然后计算损失,这使得不同层的监督变得联结。但因为不同层的样本分布明显不平衡,随着特征分辨率的增加,特征的大小也以二次指数的形式增加,这使得训练被低层的样本dominate,高层的样本缺乏监督,从而影响大目标的检测。一个克服这个问题的简单想法是给高层样本赋予更大的权重来弥补监督的缺失,作者采用了不同的重加权策略进行了实验,结果如表2所示,其中只设置了最低层和最高处的权重,其余层的权重用插值计算得到。可以看到,最好的策略是从1线性增加到2,最坏的策略是从3到1线性递减。

方法介绍

DDOD的完整结构如图3所示

Label Assignment Disentanglement

基于上述实验结果,本文对分类和回归分支分别设计了不同的标签分配策略。对于输入图片 \(I\),假设有 \(N\) 个GT,基于预设anchor有 \(P\) 个预测,对于每个候选(anchor或center point)\(P_{i}\),输出每个类别的前景概率 \(\hat{p}(i)\) 和回归的bounding box \(\hat{b}(i)\)。基于此,cost matrix如下

其中 \(C_{i,\pi(i)}\in[0,1]\) 表示第 \(\pi(i)\) 个预测的匹配质量,\(\Omega_{i}\) 表示第 \(i\) 个GT的候选预测。为了稳定训练过程加速收敛,只有中心点落入GT box的候选才被认为是可能的前景。标签分配时,从FPN每层选择cost value最大的K个预测。如果候选对象的匹配质量超过了用ATSS等batch statistics计算得到的自适应阈值时,将其分配为前景样本。、

为了解耦分类和回归的标签分配,本文还引入了一个超参 \(\alpha\) 来平衡两者的贡献,然后通过消融实验确定了 \(\alpha\) 的最佳值。

Spatial Feature Disentanglement

借助可变形卷积,模型可以关注到特征图中不同的空间区域,作者提出了自适应特征解耦模块,其中在每个位置 \(p_{n}\) 预测一个可学习的卷积偏移,从而针对当前任务学习自适应的挑选空间特征。对于特征图 \(F\) 上的位置 \(p_{i}\) 有

关于可变形卷积的具体介绍见https://blog.csdn.net/ooooocj/article/details/128539972

Pyramid Supervision Disentanglement

对于FPN conjunction,本文提出了FPN分层损失。不平衡的根本原因在于每层样本的不平衡,因此本文直接用每层的样本数量作为指标来确定该层监督的权重应该增加还是降低。\(L_{i}\) 层上关于损失 \(L\) 的重加权系数 \(w\) 根据下式得到

其中 \(n_{cls}^{i}\) 和 \(n_{reg}^{i}\) 分别是第 \(i\) 层FPN上的正负样本数量,\(N_{cls}\) 和 \(N_{reg}\) 分别是所有层 \(n_{cls}^{i}\) 和 \(n_{reg}^{i}\) 的集和。此外作者还采用了moving average的方式来缓解不同图片上样本的分布差异。具体来说,每个interation \(J\),采用每个FPN层 \(i\) 上正样本的累积数量 \( {\textstyle \sum_{j=0}^{J}} n^{i}_{cls/reg}\) 来计算 \(w\)。

代码解析

这里以mmdetection中的实现为例,其中具体实现在mmdet/models/dense_heads/ddod_head.py中。

首先是label assignment的解耦,从配置文件中可以看出分类和回归分别采用了ATSSAssigner,并且alpha值不同。

在具体实现atss_assigner.py中,具体实现如下。这里变量alpha只在DDOD中不为None,其它情况就是原始的ATSS。最后一行overlaps的实现对应论文中的式(1),alpha值越小,对应项overlaps**self.alpha越大,表示cost matirx更关注回归的质量,反之亦然。 

# compute iou between all bbox and gt
if self.alpha is None:
    # ATSSAssigner
    overlaps = self.iou_calculator(priors, gt_bboxes)
    if ('scores' in pred_instances or 'bboxes' in pred_instances):
        warnings.warn(message)

else:
    # Dynamic cost ATSSAssigner in DDOD
    assert ('scores' in pred_instances
            and 'bboxes' in pred_instances), message
    cls_scores = pred_instances.scores
    bbox_preds = pred_instances.bboxes

    # compute cls cost for bbox and GT
    cls_cost = torch.sigmoid(cls_scores[:, gt_labels])

    # compute iou between all bbox and gt
    overlaps = self.iou_calculator(bbox_preds, gt_bboxes)

    # make sure that we are in element-wise multiplication
    assert cls_cost.shape == overlaps.shape

    # overlaps is actually a cost matrix
    overlaps = cls_cost**(1 - self.alpha) * overlaps**self.alpha

然后是两个检测头spatial feature的解耦,具体实现就是每个分支的第一个卷积改成了可变形卷积,具体实现如下

def _init_layers(self) -> None:
    """Initialize layers of the head."""
    self.relu = nn.ReLU(inplace=True)
    self.cls_convs = nn.ModuleList()
    self.reg_convs = nn.ModuleList()
    for i in range(self.stacked_convs):
        chn = self.in_channels if i == 0 else self.feat_channels
        self.cls_convs.append(
            ConvModule(
                chn,
                self.feat_channels,
                3,
                stride=1,
                padding=1,
                conv_cfg=dict(type='DCN', deform_groups=1)
                if i == 0 and self.use_dcn else self.conv_cfg,
                norm_cfg=self.norm_cfg))
        self.reg_convs.append(
            ConvModule(
                chn,
                self.feat_channels,
                3,
                stride=1,
                padding=1,
                conv_cfg=dict(type='DCN', deform_groups=1)
                if i == 0 and self.use_dcn else self.conv_cfg,
                norm_cfg=self.norm_cfg))

最后是FPN监督的解耦,具体实现如下

def calc_reweight_factor(self, labels_list: List[Tensor]) -> List[float]:
    """Compute reweight_factor for regression and classification loss."""
    # get pos samples for each level
    bg_class_ind = self.num_classes
    for ii, each_level_label in enumerate(labels_list):
        pos_inds = ((each_level_label >= 0) &
                    (each_level_label < bg_class_ind)).nonzero(
                        as_tuple=False).squeeze(1)
        self.cls_num_pos_samples_per_level[ii] += len(pos_inds)
    # get reweight factor from 1 ~ 2 with bilinear interpolation
    min_pos_samples = min(self.cls_num_pos_samples_per_level)
    max_pos_samples = max(self.cls_num_pos_samples_per_level)
    interval = 1. / (max_pos_samples - min_pos_samples + 1e-10)
    reweight_factor_per_level = []
    for pos_samples in self.cls_num_pos_samples_per_level:
        factor = 2. - (pos_samples - min_pos_samples) * interval
        reweight_factor_per_level.append(factor)
    return reweight_factor_per_level

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1403379.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker命令---搜索镜像

介绍 使用docker命令搜索镜像。 命令 docker search 镜像命令:版本号示例 以搜索ElasticSearch镜像为例 docker search ElasticSearch

华而有实,维乐Prevail Glide带你领略风景线,成为风景线~

大家都知道呢&#xff01;骑行&#xff0c;不仅是一种运动&#xff0c;更是一种生活态度。在骑行装备的世界里&#xff0c;一个好的坐垫对于骑行的舒适度和安全性至关重要。那今天&#xff0c;我要为大家推荐一款备受赞誉的坐垫——维乐坐垫美学系列-Prevail Glide。    为…

学习笔记——克里金插值

有一篇大神的文章写得非常的具体&#xff0c; https://xg1990.com/blog/archives/222 下面写下一些学习笔记&#xff1a; 1、关于克里金插值的基本原理 克里金插值来源于地理学&#xff0c;它的前提是地理学第一定律&#xff1a;所有事物都与其他事务相关&#xff0c;但是近…

Linux性能监控命令-top

简介 top 命令用于实时监视系统的性能和进程信息。它提供了一个动态的、交互式的界面&#xff0c;列出了当前运行的进程&#xff0c;并显示了它们的 CPU 和内存使用情况。通过该命令可以对硬件性能瓶颈做出基本判断。 1. 语法 top top [参数] top 有 2 种指定参数方式&#xff…

Python 生成 图片网页列表 显示路径和建立时间 笔记

Python 一键 生成 图片网页列表 显示路径和建立时间 &#xff08;方便查看复制路径、重复一键生成&#xff09; 支持格式&#xff1a;jpg \png\ svg\ webp 图片网页列表 图示&#xff1a; 参考代码&#xff1a; # -*- coding: utf-8 -*- import os import datetime# 指定图片…

自己构建webpack+vue3+ts

先看看我的目录结构&#xff08;我全局使用TS&#xff09;&#xff1a; 一、安装配置webpack打包 安装esno npm install esnoesno 是基于 esbuild 的 TS/ESNext node 运行时,有了它&#xff0c;就可以直接通过esno *.ts的方式启动脚本&#xff0c;package.json中添加 type:…

【动态规划】【C++算法】801. 使序列递增的最小交换次数

作者推荐 【动态规划】【广度优先搜索】【状态压缩】847 访问所有节点的最短路径 本文涉及知识点 动态规划汇总 数组 LeetCode801使序列递增的最小交换次数 我们有两个长度相等且不为空的整型数组 nums1 和 nums2 。在一次操作中&#xff0c;我们可以交换 nums1[i] 和 num…

【Java程序员面试专栏 专业技能篇】MySQL核心面试指引(二):核心机制策略

关于MySQL部分的核心知识进行一网打尽,包括三部分:基础知识考察、核心机制策略、性能优化策略,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 本篇Blog为第二部分:核心机制策略,子节点表示追问或同级提问 日志机制 关于MySQL的几…

【Web前端开发基础】CSS的结构伪类选择器、伪元素、浮动

CSS的浮动 目录 CSS的浮动一、学习目标二、文章内容2.1 结构伪类选择器2.2 伪元素2.3 标准流2.4 浮动2.5 清除浮动2.6 拓展&#xff08;BFC&#xff09; 三、综合案例3.1 小米模块案例3.2 网页导航案例 一、学习目标 能够使用结构伪类选择器在HTML中选元素能够说出标准流元素的…

Kafka 问题排查

订单宽表数据不同步 事情的起因是专员在 ze app 上查不到订单了&#xff0c;而订单数据是从 mysql 的 order_search_info 查询的&#xff0c;order_search_info 表的数据是从 oracel 的 BZ_ORDER_INFO 表同步过来的&#xff0c;查不到说明同步有问题 首先重启&#xff0c;同步…

《WebKit 技术内幕》学习之五(2): HTML解释器和DOM 模型

2.HTML 解释器 2.1 解释过程 HTML 解释器的工作就是将网络或者本地磁盘获取的 HTML 网页和资源从字节流解释成 DOM 树结构。 这一过程中&#xff0c;WebKit 内部对网页内容在各个阶段的结构表示。 WebKit 中这一过程如下&#xff1a;首先是字节流&#xff0c;经过解码之…

终端(命令提示符或Windows PowerShell或Azure Cloud Shell)概述

终端&#xff08;命令提示符或Windows PowerShell或Azure Cloud Shell&#xff09;是一种很 不 好用的东西 就是要背&#xff0c;很 不 爽 介绍 Windows 终端是一个新式主机应用程序&#xff0c;它面向你喜爱的命令行 shell&#xff0c;如命令提示符、PowerShell 和 bash&…

力扣刷MySQL-第五弹(详细讲解)

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;力扣刷题讲解-MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出…

Python 算法交易实验67 第一次迭代总结

说明 在这里对第一次迭代&#xff08;2023.7~ 2024.1&#xff09;进行一些回顾和总结&#xff1a; 回顾&#xff1a; 1 实现了0~1的变化2 在信息隔绝的条件下&#xff0c;无控制的操作&#xff0c;导致被套 总结&#xff1a; 思路可行&#xff0c;在春暖花开的时候&#x…

设备对象(DEVICE_OBJECT)

设备对象(DEVICE_OBJECT) 每个驱动程序会创建一个或多个设备对象&#xff0c;用DEVICE_OBJECT数据结构表示。每个设备对象都会有一个指针指向下一个设备对象&#xff0c;因此就形成一个设备链。设备对象链的第一个设备是由DRIVER_OBJECT结构体中指明的。设备对象保存设…

C++ 之LeetCode刷题记录(十五)

&#x1f604;&#x1f60a;&#x1f606;&#x1f603;&#x1f604;&#x1f60a;&#x1f606;&#x1f603; 开始cpp刷题之旅。 依旧是追求耗时0s的一天。 94. 二叉树的中序遍历 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; …

C#,入门教程(28)——文件夹(目录)、文件读(Read)与写(Write)的基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(27)——应用程序&#xff08;Application&#xff09;的基础知识https://blog.csdn.net/beijinghorn/article/details/125094837 C#知识比你的预期简单的多&#xff0c;但也远远超乎你的想象&#xff01; 与文件相关的知识&#xf…

跟着我学Python进阶篇:03. 面向对象(下)

往期文章 跟着我学Python基础篇&#xff1a;01.初露端倪 跟着我学Python基础篇&#xff1a;02.数字与字符串编程 跟着我学Python基础篇&#xff1a;03.选择结构 跟着我学Python基础篇&#xff1a;04.循环 跟着我学Python基础篇&#xff1a;05.函数 跟着我学Python基础篇&#…

# Jenkins:一键部署与备份的终极解决方案

Jenkins&#xff1a;一键部署与备份的终极解决方案 引言 在持续集成和持续部署&#xff08;CI/CD&#xff09;的世界中&#xff0c;Jenkins 作为一个开源自动化服务器&#xff0c;扮演着至关重要的角色。但是&#xff0c;部署和维护 Jenkins 服务往往需要一定的技术知识和时间…

卷积和滤波对图像操作的区别

目录 问题引入 解释 卷积 滤波 问题引入 卷积和滤波是很相似的&#xff0c;都是利用了卷积核进行操作 那么他们之间有什么区别呢&#xff1f; 卷积&#xff1a;会影响原图大小 滤波&#xff1a;不会影响原图大小 解释 卷积 我们用这样一段代码来看 import torch.nn as …