YOLOv9改进策略【Neck】| 使用CARAFE轻量级通用上采样算子

news2024/12/28 20:01:28

一、本文介绍

本文记录的是利用CARAFE上采样对YOLOv9的颈部网络进行改进的方法研究YOLOv9采用传统的最近邻插值的方法,仅考虑子像素邻域,无法捕获密集预测任务所需的丰富语义信息,从而影响模型在密集预测任务中的性能。CARAFE通过在大感受野内聚合信息、能够实时适应实例特定内容且保持计算效率。

文章目录

  • 一、本文介绍
  • 二、CARAFE介绍
    • 2.1、CARAFE原理
    • 2.2、优势
  • 三、CARAFE的实现代码
  • 四、添加步骤
    • 4.1 修改common.py
    • 4.2 修改yolo.py
  • 五、yaml模型文件
    • 5.1 模型改进
  • 六、成功运行结果


二、CARAFE介绍

CARAFE内容感知的特征重新组合

CARAFE(Content - Aware ReAssembly of FEatures)是一种用于特征上采样的操作符,其设计原理和优势如下:

2.1、CARAFE原理

  • 总体框架CARAFE由两个关键组件组成,即核预测模块内容感知重组模块。给定大小为 C × H × W C×H×W C×H×W的特征图 x x x和上采样比例 σ \sigma σ(假设 σ \sigma σ是整数),CARAFE将产生大小为 C × σ H × σ W C×\sigma H×\sigma W C×σH×σW的新特征图 X ′ X' X
  • 核预测模块:负责以内容感知的方式生成重组核。每个源位置 x x x上对应 σ 2 \sigma^{2} σ2个目标位置 X ′ X' X上,每个目标位置需要一个 k u p × k u p k_{u p}×k_{u p} kup×kup的重组核,因此该模块将输出大小为 C u p × H × W C_{u p}×H×W Cup×H×W的重组核,其中 C u p = σ 2 k u p 2 C_{u p} = \sigma^{2}k_{u p}^{2} Cup=σ2kup2。该模块由三个子模块组成,分别是通道压缩器、内容编码器和核归一化器。
    • 通道压缩器:采用 1 × 1 1×1 1×1卷积层将输入特征通道从 C C C压缩到 C m C_{m} Cm,减少特征图的通道数,从而减少后续步骤的参数和计算成本,使CARAFE更高效。
    • 内容编码器:使用核大小为 k e n c o d e r k_{encoder} kencoder的卷积层根据输入特征的内容生成重组核,编码器的参数为 k e n c o d e r × k e n c o d e r × C m × C u p k_{encoder}×k_{encoder}×C_{m}×C_{u p} kencoder×kencoder×Cm×Cup。增大 k e n c o d e r k_{encoder} kencoder可以扩大编码器的感受野,利用更大区域内的上下文信息,但计算复杂度也会随之增加。通过研究, k e n c o d e r = k u p − 2 k_{encoder} = k_{u p} - 2 kencoder=kup2是性能和效率之间的良好平衡。
    • 核归一化器:在将每个 k u p × k u p k_{u p}×k_{u p} kup×kup重组核应用于输入特征图之前,使用softmax函数对其进行空间归一化,使核值之和为 1 1 1,这是对局部区域的软选择。
  • 内容感知重组模块:对于目标位置 l ′ l' l和以 l = ( i , j ) l = (i, j) l=(i,j)为中心的相应方形区域 N ( X l , k u p ) N(X_{l}, k_{u p}) N(Xl,kup),重组过程如公式 X l ′ ′ = ∑ n = − r r ∑ m = − r r W l ′ ( n , m ) ⋅ X ( i + n , j + m ) \mathcal{X}_{l'}' = \sum_{n = -r}^{r}\sum_{m = -r}^{r}\mathcal{W}_{l'(n, m)}·\mathcal{X}_{(i + n, j + m)} Xl=n=rrm=rrWl(n,m)X(i+n,j+m)所示,其中 r = ⌊ k u p / 2 ⌋ r = \lfloor k_{u p} / 2\rfloor r=kup/2。通过重组核,区域 N ( X l , k u p ) N(X_{l}, k_{u p}) N(Xl,kup)中的每个像素根据特征的内容而不是位置的距离对上采样像素 l ′ l' l的贡献不同,使得重组后的特征图的语义比原始特征图更强。

在这里插入图片描述

2.2、优势

  • 大视野:与之前仅利用子像素邻域的工作不同,CARAFE可以在大感受野内聚合上下文信息。
  • 内容感知处理CARAFE能够根据实例特定的内容进行实时处理,为每个样本生成自适应的内核,而不是使用固定的内核。
  • 轻量且计算快速CARAFE引入的计算开销很小,可以很容易地集成到现代网络架构中。
  • 通用性和有效性:在对象检测、实例分割、语义分割、图像修复等广泛的密集预测任务中,CARAFE都能显著提升性能。

论文:https://arxiv.org/abs/1905.02188
源码:https://github.com/tiny-smart/dysample

三、CARAFE的实现代码

CARAFE模块的实现代码如下:

class CARAFE(nn.Module):
    def __init__(self, c, k_enc=3, k_up=5, c_mid=64, scale=2):
        """ The unofficial implementation of the CARAFE module.
        The details are in "https://arxiv.org/abs/1905.02188".
        Args:
            c: The channel number of the input and the output.
            c_mid: The channel number after compression.
            scale: The expected upsample scale.
            k_up: The size of the reassembly kernel.
            k_enc: The kernel size of the encoder.
        Returns:
            X: The upsampled feature map.
        """
        super(CARAFE, self).__init__()
        self.scale = scale
 
        self.comp = Conv(c, c_mid)
        self.enc = Conv(c_mid, (scale * k_up) ** 2, k=k_enc, act=False)
        self.pix_shf = nn.PixelShuffle(scale)
 
        self.upsmp = nn.Upsample(scale_factor=scale, mode='nearest')
        self.unfold = nn.Unfold(kernel_size=k_up, dilation=scale,
                                padding=k_up // 2 * scale)
 
    def forward(self, X):
        b, c, h, w = X.size()
        h_, w_ = h * self.scale, w * self.scale
 
        W = self.comp(X)  # b * m * h * w
        W = self.enc(W)  # b * 100 * h * w
        W = self.pix_shf(W)  # b * 25 * h_ * w_
        W = torch.softmax(W, dim=1)  # b * 25 * h_ * w_
 
        X = self.upsmp(X)  # b * c * h_ * w_
        X = self.unfold(X)  # b * 25c * h_ * w_
        X = X.view(b, c, -1, h_, w_)  # b * 25 * c * h_ * w_
 
        X = torch.einsum('bkhw,bckhw->bchw', [W, X])  # b * c * h_ * w_
        return X


四、添加步骤

4.1 修改common.py

此处需要修改的文件是models/common.py

common.py中定义了网络结构的通用模块,我们想要加入新的模块就只需要将模块代码放到这个文件内即可。

CARAFE模块添加后如下:

在这里插入图片描述

注意❗:在4.2小节中的yolo.py文件中需要声明的模块名称为:CARAFE

4.2 修改yolo.py

此处需要修改的文件是models/yolo.py

yolo.py用于函数调用,我们只需要将common.py中定义的新的模块名添加到parse_model函数下即可。

def parse_model(d, ch)中将CARAFE模块添加后如下:

在这里插入图片描述

elif m in [CARAFE]:
    args = [ch[f], *args[0:]]

五、yaml模型文件

5.1 模型改进

在代码配置完成后,配置模型的YAML文件。

此处以models/detect/yolov9-c.yaml为例,在同目录下创建一个用于自己数据集训练的模型文件yolov9-c-CARAFE.yaml

yolov9-c.yaml中的内容复制到yolov9-c-CARAFE.yaml文件下,修改nc数量等于自己数据中目标的数量。

📌 修改方法是将CARAFE模块替换YOLOv9颈部网络中的上采样模块nn.Upsample

# YOLOv9

# parameters
nc: 1  # number of classes
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple
#activation: nn.LeakyReLU(0.1)
#activation: nn.ReLU()

# anchors
anchors: 3

# YOLOv9 backbone
backbone:
  [
   [-1, 1, Silence, []],  
   
   # conv down
   [-1, 1, Conv, [64, 3, 2]],  # 1-P1/2

   # conv down
   [-1, 1, Conv, [128, 3, 2]],  # 2-P2/4

   # elan-1 block
   [-1, 1, RepNCSPELAN4, [256, 128, 64, 1]],  # 3

   # avg-conv down
   [-1, 1, ADown, [256]],  # 4-P3/8

   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 256, 128, 1]],  # 5

   # avg-conv down
   [-1, 1, ADown, [512]],  # 6-P4/16

   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 7(可替换)

   # avg-conv down
   [-1, 1, ADown, [512]],  # 8-P5/32

   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 9(可替换)
  ]

# YOLOv9 head
head:
  [
   # elan-spp block
   [-1, 1, SPPELAN, [512, 256]],  # 10

   # up-concat merge
   [-1, 1, CARAFE, []],
   [[-1, 7], 1, Concat, [1]],  # cat backbone P4

   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 13

   # up-concat merge
   [-1, 1, CARAFE, []],
   [[-1, 5], 1, Concat, [1]],  # cat backbone P3

   # elan-2 block
   [-1, 1, RepNCSPELAN4, [256, 256, 128, 1]],  # 16 (P3/8-small)

   # avg-conv-down merge
   [-1, 1, ADown, [256]],
   [[-1, 13], 1, Concat, [1]],  # cat head P4

   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 19 (P4/16-medium)

   # avg-conv-down merge
   [-1, 1, ADown, [512]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5

   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 22 (P5/32-large)
   
   
   # multi-level reversible auxiliary branch
   
   # routing
   [5, 1, CBLinear, [[256]]], # 23
   [7, 1, CBLinear, [[256, 512]]], # 24
   [9, 1, CBLinear, [[256, 512, 512]]], # 25
   
   # conv down
   [0, 1, Conv, [64, 3, 2]],  # 26-P1/2

   # conv down
   [-1, 1, Conv, [128, 3, 2]],  # 27-P2/4

   # elan-1 block
   [-1, 1, RepNCSPELAN4, [256, 128, 64, 1]],  # 28

   # avg-conv down fuse
   [-1, 1, ADown, [256]],  # 29-P3/8
   [[23, 24, 25, -1], 1, CBFuse, [[0, 0, 0]]], # 30  

   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 256, 128, 1]],  # 31

   # avg-conv down fuse
   [-1, 1, ADown, [512]],  # 32-P4/16
   [[24, 25, -1], 1, CBFuse, [[1, 1]]], # 33 

   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 34

   # avg-conv down fuse
   [-1, 1, ADown, [512]],  # 35-P5/32
   [[25, -1], 1, CBFuse, [[2]]], # 36

   # elan-2 block
   [-1, 1, RepNCSPELAN4, [512, 512, 256, 1]],  # 37
   
   
   
   # detection head

   # detect
   [[31, 34, 37, 16, 19, 22], 1, DualDDetect, [nc]],  # DualDDetect(A3, A4, A5, P3, P4, P5)
  ]


六、成功运行结果

分别打印网络模型可以看到CARAFE模块已经加入到模型中,并可以进行训练了。

yolov9-c-CARAFE

                 from  n    params  module                                  arguments                     
  0                -1  1         0  models.common.Silence                   []                            
  1                -1  1      1856  models.common.Conv                      [3, 64, 3, 2]                 
  2                -1  1     73984  models.common.Conv                      [64, 128, 3, 2]               
  3                -1  1    212864  models.common.RepNCSPELAN4              [128, 256, 128, 64, 1]        
  4                -1  1    164352  models.common.ADown                     [256, 256]                    
  5                -1  1    847616  models.common.RepNCSPELAN4              [256, 512, 256, 128, 1]       
  6                -1  1    656384  models.common.ADown                     [512, 512]                    
  7                -1  1   2857472  models.common.RepNCSPELAN4              [512, 512, 512, 256, 1]       
  8                -1  1    656384  models.common.ADown                     [512, 512]                    
  9                -1  1   2857472  models.common.RepNCSPELAN4              [512, 512, 512, 256, 1]       
 10                -1  1    656896  models.common.SPPELAN                   [512, 512, 256]               
 11                -1  1     90696  models.common.CARAFE                    [512]                         
 12           [-1, 7]  1         0  models.common.Concat                    [1]                           
 13                -1  1   3119616  models.common.RepNCSPELAN4              [1024, 512, 512, 256, 1]      
 14                -1  1     90696  models.common.CARAFE                    [512]                         
 15           [-1, 5]  1         0  models.common.Concat                    [1]                           
 16                -1  1    912640  models.common.RepNCSPELAN4              [1024, 256, 256, 128, 1]      
 17                -1  1    164352  models.common.ADown                     [256, 256]                    
 18          [-1, 13]  1         0  models.common.Concat                    [1]                           
 19                -1  1   2988544  models.common.RepNCSPELAN4              [768, 512, 512, 256, 1]       
 20                -1  1    656384  models.common.ADown                     [512, 512]                    
 21          [-1, 10]  1         0  models.common.Concat                    [1]                           
 22                -1  1   3119616  models.common.RepNCSPELAN4              [1024, 512, 512, 256, 1]      
 23                 5  1    131328  models.common.CBLinear                  [512, [256]]                  
 24                 7  1    393984  models.common.CBLinear                  [512, [256, 512]]             
 25                 9  1    656640  models.common.CBLinear                  [512, [256, 512, 512]]        
 26                 0  1      1856  models.common.Conv                      [3, 64, 3, 2]                 
 27                -1  1     73984  models.common.Conv                      [64, 128, 3, 2]               
 28                -1  1    212864  models.common.RepNCSPELAN4              [128, 256, 128, 64, 1]        
 29                -1  1    164352  models.common.ADown                     [256, 256]                    
 30  [23, 24, 25, -1]  1         0  models.common.CBFuse                    [[0, 0, 0]]                   
 31                -1  1    847616  models.common.RepNCSPELAN4              [256, 512, 256, 128, 1]       
 32                -1  1    656384  models.common.ADown                     [512, 512]                    
 33      [24, 25, -1]  1         0  models.common.CBFuse                    [[1, 1]]                      
 34                -1  1   2857472  models.common.RepNCSPELAN4              [512, 512, 512, 256, 1]       
 35                -1  1    656384  models.common.ADown                     [512, 512]                    
 36          [25, -1]  1         0  models.common.CBFuse                    [[2]]                         
 37                -1  1   2857472  models.common.RepNCSPELAN4              [512, 512, 512, 256, 1]       
 38[31, 34, 37, 16, 19, 22]  1  21542822  DualDDetect                             [1, [512, 512, 512, 256, 512, 512]]
yolov9-c-CARAFE summary: 982 layers, 51180982 parameters, 51180950 gradients, 239.2 GFLOPs

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

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

相关文章

Linux服务器Java启动脚本

Linux服务器Java启动脚本 1、初版2、优化版本3、常用脚本仓库 本文章介绍了如何在Linux服务器上执行Java并启动jar包, 通常我们会使用nohup直接启动,但是还是需要手动停止然后再次启动, 那如何更优雅的在服务器上启动jar包呢,让我…

设计模式之工厂模式(通俗易懂--代码辅助理解【Java版】)

文章目录 1、工厂模式概述1)特点:2)主要角色:3)工作流程:4)优点5)缺点6)适用场景 2、简单工厂模式(静态工厂模式)1) 在简单工厂模式中,有三个主要角色&#x…

基于SpringBoot的宠物服务系统+uniapp小程序+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

浏览器插件利器--allWebPluginV2.0.0.20-alpha版发布

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品,致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX控件直接嵌入浏览器,实现插件加载、界面显示、接口调用、事件回调等。支持Chrome、Firefo…

小琳AI课堂:深入学习BERT

大家好,这里是小琳AI课堂。今天我们来聊聊BERT,这个在自然语言处理(NLP)领域掀起革命风潮的模型。 出现背景 在BERT之前,NLP领域主要依赖RNN或CNN模型,这些模型大多只能单向处理文本,从左到右…

【全网首创】大模型LLM-RAG知识库问答项目实战课

在大数据和人工智能迅猛发展的今天,大模型和知识库的结合成为了理论探索和实际应用的重要方向。LLM-RAG项目课程正是围绕这一热点展开,旨在通过系统性的教学,帮助学员掌握从项目部署、模块开发到实际应用的完整流程。课程共有43课时&#xff…

SprinBoot+Vue公交智能化系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质…

高可用架构模式

架构里比较重要的是高性能、高可用、高扩展性。上次是高性能,这次是高可用。 对一般的项目而言,高可用主要用公司提供的基建,如多机房部署、主从等。但有些项目确实需要思考更多高可用的事项,如资源不足的情况下要做好限流或者降…

gdb中使用python脚本

1、入门案例 首先有1个a.cpp&#xff0c;代码如下&#xff1a; #include <map> #include <set> #include <iostream> #include <string>using namespace std;struct MyStruct {std::string mName;std::map<int, std::string> mField1;std::set…

SpringBoot3 简单集成 Mybatis plus

SpringBoot3 集成 Mybatis plus 1、引入Mybatisplus的starter <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.7</version></dependency>2、引入数据…

JVM3-双亲委派机制

目录 概述 作用 如何指定加载类的类加载器&#xff1f; 面试题 打破双亲委派机制 自定义类加载器 线程上下文类加载器 Osgi框架的类加载器 概述 由于Java虚拟机中有多个类加载器&#xff0c;双亲委派机制的核心是解决一个类到底由谁加载的问题 双亲委派机制&#xff…

Qt中window frame的影响

window frame 在创建图形化界面的时候&#xff0c;会创建窗口主体&#xff0c;上面会多出一条&#xff0c;周围多次一圈细边&#xff0c;这就叫window frame窗口框架&#xff0c;这是操作系统自带的。 这个对geometry的一些属性有一定影响&#xff0c;主要体现在Qt坐标系体系…

安装Seata-Service,Seata服务中心安装,并完成Nacos注册

一、下载服务器软件包 从 Releases apache/incubator-seata GitHub ,下载服务器软件包&#xff0c;将其解压缩。 版本选择&#xff1a; 1可以从官网查询版本对照。 2.可以在项目中&#xff0c;倒入seata版依赖 <!-- seata--><dependency><groupId&…

嘉立创中秋福利来啦!

单笔订单商品实付慢2万送良品铺子月饼 多品牌折扣 快来立创商城一探究竟吧~ 立创商城_一站式电子元器件采购自营商城_嘉立创电子商城 (szlcsc.com)

深度学习中常见的权重参数初始化方法

在深度学习中&#xff0c;权重参数的初始化对模型的训练过程和性能有着非常重要的影响。一个好的权重初始化方法能够帮助模型更快收敛、避免梯度爆炸或梯度消失等问题。以下是几种常见的权重初始化方法及其背后的原理。 1. 零初始化&#xff08;Zero Initialization&#xff0…

每天学习一个字符串类函数之memmove函数

目录 前言&#xff1a; 一、头文件 二、memmove函数的作用 三、理解memmove函数的定义 1、返回类型 2、参数 四、使用memmove函数 案例1&#xff1a; 案例2&#xff1a; 五、解决数据拷贝之前被覆盖的方法 六、模拟实现memmove函数 前言&#xff1a; 上一篇博客&#xff0c;我…

【C++】STL容器详解【上】

目录 一、STL基本概念 二、STL的六大组件 三、string容器常用操作 3.1 string 容器的基本概念 3.2 string 容器常用操作 3.2.1 string 构造函数 3.2.2 string基本赋值操作 3.2.3 string存取字符操作 3.2.4 string拼接字符操作 3.2.5 string查找和替换 3.2.6 string比…

Unity Shader实现简单的各向异性渲染(采用各向异性形式的GGX分布)

目录 准备工作 BRDF部分 Unity部分 代码 实现的效果 参考 最近刚结束GAMES202的学习&#xff0c;准备慢慢过渡到GAMES103。GAMES103的作业框架为Unity&#xff0c;并没有接触过&#xff0c;因此准备先学一点Unity的使用。刚好101和202都是渲染相关的&#xff0c;因此先学习…

如何查看Mac的处理器架构‌‌是ARM还是x86

‌通过命令行查看Mac的处理器架构‌‌ 打开终端&#xff08;Terminal&#xff09;。输入命令 uname -m 并回车。如果输出结果是 arm64&#xff0c;则表示你的Mac使用的是ARM架构&#xff1b;如果输出结果是 x86_64&#xff0c;则表示你的Mac使用的是x86架构。 如图&#xff1…

牛客JZ36 二叉搜索树与双向链表 C++

牛客JZ36 二叉搜索树与双向链表 C 思路&#x1f9d0;&#xff1a; 由图所示&#xff0c;我们看出该链表走的是中序&#xff0c;所以我们可以使用中序遍历的方式来解决这个问题&#xff0c;在遍历过程中&#xff0c;我们创建一个前驱和一个后继结点&#xff0c;来进行链接。 并且…