ASFF自适应空间特征融合

paper:Learning Spatial Fusion for Single-Shot Object Detection

official implementation:https://github.com/GOATmessi7/ASFF

背景

金字塔特征表示pyramid feature representation是解决目标检测中尺度变化挑战的常用方法。特征金字塔的一个主要缺点是在不同尺度上的不一致性,特别是对于one-shot detector。具体来说,当用feature pyramid检测物体时,采用一种启发式引导的特征选择:大目标与深层特征图关联,小目标与浅层特征图关联。当一个对象在某一层的特征图中被视为positive时,其它level的特征图中相应的区域就被视为背景。因此,如果一个图像既包含小物体又包含大物体,不同层次特征之间的冲突往往占据特征金字塔的主要部分。这种不一致性干扰了训练过程中的梯度计算,并降低了特征金字塔的有效性。

本文的创新点

本文提出了一种新的数据驱动的金字塔特征融合策略,称为自适应空间特征融合(adaptively spatial feature fusion, ASFF)。它学习对冲突信息进行空间过滤以抑制不一致性的方法,从而提高了特征的尺度不变性,并几乎没有增加额外开销。

该方法使网络能够直接学习如何在其它层对特征进行空间过滤,从而只保留有用信息进行融合。对于某个level的特征,首先将其它level的特征整合并调整到相同的分辨率,然后通过训练找到最优融合。在每个空间位置,不同level的特征被自适应的融合,即一些特征可能因为在该位置带有矛盾的信息而被过滤掉,一些特征因为带有更具差异性的信息而在该位置占主导。

ASFF具有以下几点优势

  1. 由于搜索最优融合的操作是可微的,因此可以在反向传播中学习
  2. 它对于backbone是不可知的,并应用于带有特征金字塔结构的单阶段目标检测模型中
  3. 实现简单,增加的计算成本可以忽略

方法介绍

Feature Resizing

我们将 \(l\) 层的特征记为 \(\mathbf{x}^{l}\)(对于YOLOv3 \(l\in\{1,2,3\}\))。对于层 \(l\),我们将其它层 \(n(n\ne l)\) 的特征 \(\mathbf{x}^n\) resize到和 \(\mathbf{x}^{l}\) 一样的分辨率。由于YOLOv3中三个level的特征具有不同的分辨率和不同的通道数,因此我们相应地修改了每个尺度的上采样和下采样策略。对于上采样,我们首先通过1x1卷积将特征的通道数压缩到 \(l\) 层对应的通道数,然后通过插值进行上采样。对于1/2比例的下采样,我们通过stride=2的3x3卷积通过修改分辨率和通道数。对于1/4的下采样,我们在2-stride卷积之前添加一个2-stride的max pooling层。

Adaptive Fusion

我们用 \(\mathbf{x}_{ij}^{n\to l}\) 表示从 \(n\) 层resize到 \(l\) 层的特征图上位置 \((i,j)\) 处的特征向量,我们在 \(l\) 层上按下式进行融合

其中 \(\mathbf{y}_{ij}^l\) 表示输出特征图 \(\mathbf{y}^l\) 沿通道的第 \((i,j)\) 个向量。\(\alpha_{ij}^l,\beta_{ij}^l,\gamma_{ij}^l\) 表示三个不同level对level \(l\) 特征图的空间重要性权重,它们是网络自适应学习到的。注意 \(\alpha_{ij}^l,\beta_{ij}^l,\gamma_{ij}^l\) 可以是标量变量,所有通道共享。我们使 \(\alpha_{ij}^l+\beta_{ij}^l+\gamma_{ij}^l=1\),\(\alpha_{ij}^l,\beta_{ij}^l,\gamma_{ij}^l\in [0,1]\),并定义

 

这里 \(\alpha_{ij}^l,\beta_{ij}^l,\gamma_{ij}^l\) 通过对 \(\lambda^{l}_{\alpha_{ij}},\lambda^{l}_{\beta_{ij}},\lambda^{l}_{\gamma_{ij}}\) 使用softmax计算得到,我们使用1x1卷积从 \(\mathbf{x}^{1\to l},\mathbf{x}^{2\to l},\mathbf{x}^{3\to l}\) 得到权重标量 \(\lambda^{l}_{\alpha},\lambda^{l}_{\beta},\lambda^{l}_{\gamma}\)。

使用这种方法,所有lelvel的特征都在每个尺度上自适应地聚合。输出 \(\{\mathbf{y}^1,\mathbf{y}^2,\mathbf{y}^3\}\) 按照YOLOv3相同的pipeline用于目标检测。

实验结果

 

代码

class ASFF(nn.Module):def __init__(self, level, rfb=False, vis=False):super(ASFF, self).__init__()self.level = levelself.dim = [512, 256, 256]self.inter_dim = self.dim[self.level]if level == 0:self.stride_level_1 = add_conv(256, self.inter_dim, 3, 2)self.stride_level_2 = add_conv(256, self.inter_dim, 3, 2)self.expand = add_conv(self.inter_dim, 1024, 3, 1)elif level == 1:self.compress_level_0 = add_conv(512, self.inter_dim, 1, 1)self.stride_level_2 = add_conv(256, self.inter_dim, 3, 2)self.expand = add_conv(self.inter_dim, 512, 3, 1)elif level == 2:self.compress_level_0 = add_conv(512, self.inter_dim, 1, 1)self.expand = add_conv(self.inter_dim, 256, 3, 1)compress_c = 8 if rfb else 16  # when adding rfb, we use half number of channels to save memoryself.weight_level_0 = add_conv(self.inter_dim, compress_c, 1, 1)self.weight_level_1 = add_conv(self.inter_dim, compress_c, 1, 1)self.weight_level_2 = add_conv(self.inter_dim, compress_c, 1, 1)self.weight_levels = nn.Conv2d(compress_c*3, 3, kernel_size=1, stride=1, padding=0)self.vis = visdef forward(self, x_level_0, x_level_1, x_level_2):  # (b,512,13,13),(b,256,26,26),(b,256,52,52)if self.level == 0:level_0_resized = x_level_0level_1_resized = self.stride_level_1(x_level_1)  # (b,512,13,13)level_2_downsampled_inter = F.max_pool2d(x_level_2, 3, stride=2, padding=1)  # (b,256,26,26)level_2_resized = self.stride_level_2(level_2_downsampled_inter)  # (b,512,13,13)elif self.level == 1:level_0_compressed = self.compress_level_0(x_level_0)  # (b,256,13,13)level_0_resized = F.interpolate(level_0_compressed, scale_factor=2, mode='nearest')  # (b,256,26,26)level_1_resized = x_level_1level_2_resized = self.stride_level_2(x_level_2)  # (b,256,26,26)elif self.level == 2:level_0_compressed = self.compress_level_0(x_level_0)  # (b,256,13,13)level_0_resized = F.interpolate(level_0_compressed, scale_factor=4, mode='nearest')  # (b,256,52,52)level_1_resized = F.interpolate(x_level_1, scale_factor=2, mode='nearest')  # (b,256,52,52)level_2_resized = x_level_2level_0_weight_v = self.weight_level_0(level_0_resized)  # (b,16,13,13)level_1_weight_v = self.weight_level_1(level_1_resized)  # (b,16,13,13)level_2_weight_v = self.weight_level_2(level_2_resized)  # (b,16,13,13)levels_weight_v = torch.cat((level_0_weight_v, level_1_weight_v, level_2_weight_v), 1)  # (b,48,13,13)levels_weight = self.weight_levels(levels_weight_v)  # (b,3,13,13)levels_weight = F.softmax(levels_weight, dim=1)fused_out_reduced = level_0_resized * levels_weight[:, 0:1, :, :] + \level_1_resized * levels_weight[:, 1:2, :, :] + \level_2_resized * levels_weight[:, 2:, :, :]out = self.expand(fused_out_reduced)  # (b,1024,13,13)if self.vis:return out, levels_weight, fused_out_reduced.sum(dim=1)else:return out

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

刷题日记——反转公约数、循环位移(厦门大学机试)

题目 分析 将输入的数字看作字符串&#xff0c;然后将字符串转成真实值计算两个真实值&#xff0c;然后从1开始遍历公约数&#xff0c;每次发现一个更大的公约数就替换&#xff0c;直到找不到公约数 代码 #include <cstdio> #include <map> #include <string…

Spring Boot整合canal实现数据一致性解决方案解析-部署+实战

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 1.前言 2.canal部署安装 3.Spring Boot整合canal 3.1数据库与缓存一致性问题…

内存操作函数

memcpy mem--memory--内存 指向计算机内存 cpy-copy-拷贝 也就是内存拷贝 针对内存的函数 void* memcpy(void * destination,const void * source,size_t num) 把source的空间 复制到 destination的部分 长度是num 如果source 和 dest 的部分有重叠,会复制的结果是未定义的(建…

memcpy函数及其模拟实现

一、 函数原型 void *memcpy(void *destin, void *source, size_t n);二、参数 destin-- 指向用于存储复制内容的目标数组&#xff0c;类型强制转换为 void* 指针。 source-- 指向要复制的数据源&#xff0c;类型强制转换为 void* 指针。 n-- 要被复制的字节数。 三、返回…

软考高级:信息系统开发方法2(形式化方法、统计过程方法等)概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

Prometheus 安装部署

文章目录 1.部署Prometheus1.1.修改配置文件1.2.配置告警规则1.3.运行Docker 2.部署Alertmanager2.1.修改配置文件2.2.Prometheus监控配置2.3.运行Docker 3.部署Grafana3.1.运行Docker3.2. 配置数据源3.3. 配置dashboard 开源中间件 # Prometheushttps://iothub.org.cn/docs/m…

linux paddle For C++环境搭建

paddle介绍 Paddle是类似tesseract的文字识别ocr。因为tesseract-ocr的中文识别效果不好。因此才准备安装Paddle。Paddle最方便的安装方式的使用Python的包管理安装。pip3 install paddlepaddle。但我使用了一下感觉还是用C更加方便&#xff0c;QT OpenCV Paddle应当还不错。…

哈密顿算子的计算公式及一些常用公式总结

目录 哈密顿算子的定义式如下&#xff1a; 梯度定义&#xff1a; 散度定义&#xff1a; 旋度定义&#xff1a; 常用的一些公式&#xff1a; 注意文中字母上面没有→的是标量&#xff0c;有→的都表示矢量 哈密顿算子的定义式如下&#xff1a; 快速了解哈密顿算符&#xff…

华为组网:核心交换机旁挂防火墙,基于ACL重定向配置实验

如图所示&#xff0c;由于业务需要&#xff0c;用户有访问Internet的需求。 用户通过接入层交换机SwitchB和核心层交换机SwitchA以及接入网关Router与Internet进行通信。为了保证数据和网络的安全性&#xff0c;用户希望保证Internet到服务器全部流量的安全性&#xff0c;配置重…

基于LIO-SAM 算法的三维激光SLAM 建图

运行环境 Linux&#xff1a;Ubuntu18.04ros&#xff1a;MelodicCeres Solver 2.0.0&#xff08;Ubuntu18.04安装Ceres&#xff09;PCL 1.8.1&#xff08;Ubuntu系统的PCL、Eigen卸载和安装&#xff09;gtsam-4.0.0-alpha2 或者 4.0.2 1 背景介绍 在自动驾驶的感知方案中&…

Linux发展史目录结构Vim编辑器

Linux入门 一、Linux的发展史二、Linux的目录结构2.1 Linux系统中一切皆文件2.2 Linux中几个重要的目录 三、VIM编辑器3.1 用户名主机名 /xxx的含义3.2 一般模式3.3 编辑模式和指令模式3.4 三种模式之间的转换 一、Linux的发展史 上面俩兄弟用C语言写出了Unix操作系统(右边那个…

C++学习随笔(4)——类和对象的初探

本章我们来初步学习一下C中的类和对象&#xff01; 目录 1.类的引入 2.类的定义 类的两种定义方式&#xff1a; 3.类的访问限定符及封装 3.1 访问限定符 3.2 封装 4.类的作用域 5.类的实例化 6.类对象模型 6.1 如何计算类对象的大小 6.2 类对象的存储方式猜测 6.3 …