Yolov5 中添加注意力机制 CBAM

news2025/1/24 8:52:02

Yolov5 中添加注意力机制 CBAM

    • 1. CBAM
      • 1.1 Channel Attention Module
      • 1.2 Spatial Attention Module
      • 1.3 Channel attention 和 Spatial attention 如何去使用
    • 2. 在Yolov5中添加CBAM模块
      • 2.1 修改common.py 文件
      • 2.2 修改yolo.py 文件
      • 2.3 修改网络配置yolov5x-seg.yaml文件
    • 3. 训练
      • 3.1 未添加CBAM之前的结果
      • 3.2 添加CBAM之后的结果
    • 4. 参考文章

1. CBAM

CBAM(Convolutional Block Attention Module)是一种注意力机制,它通过关注输入数据中的重要特征来增强卷积神经网络(CNN)的性能。CBAM的原理可以分为两个部分:空间注意力模块和通道注意力模块。

  1. 空间注意力模块:该模块关注输入特征图的每个空间位置的重要性。它首先对特征图的每个通道进行全局平均池化,然后使用1x1卷积将通道数调整为与输入特征图相同的大小。接着,使用sigmoid激活函数对每个空间位置的激活进行归一化,最后使用全局最大池化获取最重要的空间信息。
  2. 通道注意力模块:该模块关注每个通道对最终输出贡献的重要性。它首先对每个通道的特征进行全局平均池化,然后使用1x1卷积将通道数调整为与输入特征图相同的大小。接着,使用sigmoid激活函数对每个通道的激活进行归一化,最后使用全局最大池化获取最重要的通道信息。

CBAM将这两个注意力模块嵌入到CNN的卷积层之间,以增强网络对重要特征的关注度。实验表明,CBAM可以显著提高CNN的性能,特别是在图像分类、目标检测和语义分割等任务中。

1.1 Channel Attention Module

先上一下代码:

class ChannelAttention(nn.Module):
    def __init__(self, in_planes, ratio=16):
        super(ChannelAttention, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.max_pool = nn.AdaptiveMaxPool2d(1)
           
        self.fc = nn.Sequential(nn.Conv2d(in_planes, in_planes // 16, 1, bias=False),
                               nn.ReLU(),
                               nn.Conv2d(in_planes // 16, in_planes, 1, bias=False))
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        avg_out = self.fc(self.avg_pool(x))
        max_out = self.fc(self.max_pool(x))
        out = avg_out + max_out
        return self.sigmoid(out)

在这里插入图片描述
Channel Attention的流程为:

  1. 输入一组特征;
  2. 对特征在空间维度上进行MaxPool,即最大值池化;
  3. 对特征在空间维度上进行AvgPool,即平局池化;
  4. 经过池化后的两组特征分别进入MLP网络中,分别得到两组新的特征;
  5. 然后将两组新的特征进行相应元素一一相加,再通过激活函数,就得到一组所需要的新的特征;
channel attention 主要关注输入特征中的“what”,即在这么多特征中,哪些才是有意义的部分。
MLP的作用是让特征向量不同维度之间做充分的交叉,让模型能够抓取到更多的非线性特征和组合特征的信息

其数学表达式如下:
在这里插入图片描述

1.2 Spatial Attention Module

先上一下代码:

class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=7):
        super(SpatialAttention, self).__init__()

        self.conv1 = nn.Conv2d(2, 1, kernel_size, padding=kernel_size//2, bias=False)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out, _ = torch.max(x, dim=1, keepdim=True)
        x = torch.cat([avg_out, max_out], dim=1)
        x = self.conv1(x)
        return self.sigmoid(x)

在这里插入图片描述

Spatial Attention的流程为:

  1. 输入一组特征;
  2. 对特征在通道维度上进行MaxPool,即最大值池化;
  3. 对特征在通道维度上进行AvgPool,即平局池化;
  4. 然后将两组特征进行concatenate组成新的特征;
  5. 将新的特征送入卷积,得到2D空间注意力特征图;
  6. 最后通过激活函数得到需要的特征;
spatial attention 主要关注输入特征中的“where”,即在所有特征中,哪些部分需要去关注。

1.3 Channel attention 和 Spatial attention 如何去使用

在这里插入图片描述
从上图中可以看到,前面的卷积神经网络提前特征后,分别进行两个通道注意力计算,两个通道可以并行也可以串行,但是原作者在实验中发现,串行且channel在spatial之前,性能会更好。每个注意出来后,都需要与输入进行一次对应元素的点乘;
其表达式如下:
在这里插入图片描述

2. 在Yolov5中添加CBAM模块

参考文章如下:https://blog.csdn.net/qq_27353621/article/details/125603799

2.1 修改common.py 文件

路径:models/common.py
在common.py的尾部添加如下代码,即Channel Attention 模块、Spatial Attention模块、CBAMC3模块

class ChannelAttention(nn.Module):
    def __init__(self, in_planes, ratio=16):
        super(ChannelAttention, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.max_pool = nn.AdaptiveMaxPool2d(1)

        self.f1 = nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False)
        self.relu = nn.ReLU()
        self.f2 = nn.Conv2d(in_planes // ratio, in_planes, 1, bias=False)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        avg_out = self.f2(self.relu(self.f1(self.avg_pool(x))))
        max_out = self.f2(self.relu(self.f1(self.max_pool(x))))
        out = self.sigmoid(avg_out + max_out)
        return torch.mul(x, out)


class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=7):
        super(SpatialAttention, self).__init__()

        assert kernel_size in (3, 7), 'kernel size must be 3 or 7'
        padding = 3 if kernel_size == 7 else 1

        self.conv = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out, _ = torch.max(x, dim=1, keepdim=True)
        out = torch.cat([avg_out, max_out], dim=1)
        out = self.sigmoid(self.conv(out))
        return torch.mul(x, out)


class CBAMC3(nn.Module):
    # CSP Bottleneck with 3 convolutions
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, number, shortcut, groups, expansion
        super(CBAMC3, self).__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(2 * c_, c2, 1)
        self.m = nn.Sequential(*[Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)])
        self.channel_attention = ChannelAttention(c2, 16)
        self.spatial_attention = SpatialAttention(7)

        # self.m = nn.Sequential(*[CrossConv(c_, c_, 3, 1, g, 1.0, shortcut) for _ in range(n)])

    def forward(self, x):
        # 将最后的标准卷积模块改为了注意力机制提取特征
        return self.spatial_attention(
            self.channel_attention(self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1))))

2.2 修改yolo.py 文件

路径:models/yolo.py
修改如下
在common.py的尾部添加如下代码,即Channel Attention 模块、Spatial Attention模块、CBAMC3模块

2.3 修改网络配置yolov5x-seg.yaml文件

路径:models/segment/yolov5x-seg.yaml
将C3替换为CBAMC3

# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license

# Parameters
nc: 7  # number of classes
depth_multiple: 1.33  # model depth multiple
width_multiple: 1.25  # layer channel multiple
anchors:
  - [10,13, 16,30, 33,23]  # P3/8
  - [30,61, 62,45, 59,119]  # P4/16
  - [116,90, 156,198, 373,326]  # P5/32

# YOLOv5 v6.0 backbone
backbone:
  # [from, number, module, args]
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4
   [-1, 3, CBAMC3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, CBAMC3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 9, CBAMC3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, CBAMC3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9
  ]

# YOLOv5 v6.0 head
head:
  [[-1, 1, Conv, [512, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, CBAMC3, [512, False]],  # 13

   [-1, 1, Conv, [256, 1, 1]],
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 4], 1, Concat, [1]],  # cat backbone P3
   [-1, 3, CBAMC3, [256, False]],  # 17 (P3/8-small)

   [-1, 1, Conv, [256, 3, 2]],
   [[-1, 14], 1, Concat, [1]],  # cat head P4
   [-1, 3, CBAMC3, [512, False]],  # 20 (P4/16-medium)

   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 10], 1, Concat, [1]],  # cat head P5
   [-1, 3, CBAMC3, [1024, False]],  # 23 (P5/32-large)

   [[17, 20, 23], 1, Segment, [nc, anchors, 32, 256]],  # Detect(P3, P4, P5)
  ]

上面的就算添加完了,接着验证下网络是否添加成功。

3. 训练

3.1 未添加CBAM之前的结果

在这里插入图片描述

3.2 添加CBAM之后的结果

如果运行之后的网络输出中,出现CBAMC3,则说明添加成功,下面就是等待训练的结果。
在这里插入图片描述
结果出来之后,确实会比之前的结果好一点。
在这里插入图片描述

4. 参考文章

https://blog.csdn.net/qq_27353621/article/details/125603799
https://zhuanlan.zhihu.com/p/101590167
https://aistudio.baidu.com/projectdetail/1655497
https://github.com/luuuyi/CBAM.PyTorch

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

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

相关文章

TCP Header都有啥?

分析&回答 源端口号(Source Port) :16位,标识主机上发起传送的应用程序; 目的端口(Destonation Port) :16位,标识主机上传送要到达的应用程序。 源端,目…

WSL中为Ubuntu和Debian设置固定IP的终极指南

文章目录 **WSL中为Ubuntu和Debian设置固定IP的终极指南****引言/背景****1. 传统方法****2. 新方法:添加指定IP而不是更改IP****结论**WSL中为Ubuntu和Debian设置固定IP的终极指南 引言/背景 随着WSL(Windows Subsystem for Linux)的普及,越来越多的开发者开始在Windows…

网络防火墙与入侵检测系统(IDS/IPS):深入研究现代防火墙和IDS/IPS技术,提供配置和管理建议

第一章:引言 随着信息技术的飞速发展,网络安全的重要性日益凸显。在这个充满威胁的数字时代,网络防火墙和入侵检测系统(IDS/IPS)成为保护企业和个人免受网络攻击的关键工具。本文将深入研究现代防火墙和IDS/IPS技术&a…

第9章 函数

本章介绍以下内容: 关键字:return 运算符:*(一元)、&(一元) 函数及其定义方式 如何使用参数和返回值 如何把指针变量用作函数参数 函数类型 ANSI C原型 递归 如何组织程序?C的设…

MongoDB 的简介

MongoDB 趋势 对于 MongoDB 的认识 Q&A QA什么是 MongoDB? 一个以 JSON 为数据模型的文档数据库一个以 JSON 为数据模型的文档数据库文档来自于“JSON Document”,并非我们一般理解的 PDF,WORD谁开发 MongDB? 上市公司 MongoD…

POI-TL制作word

本文相当于笔记,主要根据官方文档Poi-tl Documentation和poi-tl的使用(最全详解)_JavaSupeMan的博客-CSDN博客文章进行学习(上班够用) Data AllArgsConstructor NoArgsConstructor ToString EqualsAndHashCode public …

抽象轻松c语言

目 c语言 c程序 c语言的核心在于语言,语言的作用是进行沟通,人与人之间的信息交换 人与人之间的信息交换是会有信息空白(A表达信息,B接受信息,B对信息的处理会与A所以表达的信息具有差距,这段差距称为信…

【4-5章】Spark编程基础(Python版)

课程资源:(林子雨)Spark编程基础(Python版)_哔哩哔哩_bilibili 第4章 RDD编程(21节) Spark生态系统: Spark Core:底层核心(RDD编程是针对这个)Spark SQL:…

说说HTTP 和 HTTPS 有什么区别?

分析&回答 http协议 超文本传输协议,是互联网上应用最多的协议,基于TCP/IP通讯协议来传递信息,用于从WWW服务器传输超文本到本地浏览器的传输协议。 https协议 我们可以将其看作是以安全为目标的http协议。在http协议的基础上增加了S…

不同写法的性能差异

“ 达到相同目的,可以有多种写法,每种写法有性能、可读性方面的区别,本文旨在探讨不同写法之间的性能差异 len(str) vs str "" 本部分参考自: [问个 Go 问题,字符串 len 0 和 字符串 "" ,有啥区别?](https://segmentf…

React笔记(八)Redux

一、安装和配置 React 官方并没有提供对应的状态机插件,因此,我们需要下载第三方的状态机插件 —— Redux。 1、下载Redux 在终端中定位到项目根目录,然后执行以下命令下载 Redux npm i redux 2、创建配置文件 在 React 中,…

[管理与领导-64]:IT基层管理者 - 8项核心技能 - 8 - 打造高效团队

目录 前言: 一、团队建设对于不同管理层的不同 第1节:认识自己的团队 1.1 团队的生命周期 1.2 常见的团队问题 1.3 团队角色的配置 1.4 团队水平测试 第2节:什么是高绩效团队 2.1 什么是团队 2.2 团队五个基本要素: 2.…

超图嵌入论文阅读2:超图神经网络

超图嵌入论文阅读2:超图神经网络 原文:Hypergraph Neural Networks ——AAAI2019(CCF-A) 源码:https://github.com/iMoonLab/HGNN 500star 概述 贡献:用于数据表示学习的超图神经网络 (HGNN) 框架&#xf…

2023开学礼《乡村振兴战略下传统村落文化旅游设计》许少辉新财经理工 ​​​

2023开学礼《乡村振兴战略下传统村落文化旅游设计》许少辉新财经理工 ​​​

什么是盒子模型

什么是盒子模型 盒子模型,也可以称为框模型。 所有 HTML 元素可以看作盒子。在 CSS 中,“box model” 这一术语是用来设计和布局时使用。 CSS 盒模型本质上是一个盒子,封装周围的 HTML 元素,它包括:边距&#xff0c…

CSS学习笔记05

CSS笔记05 定位 position CSS 属性position - 用于指定一个元素在文档中的定位方式。top,right,bottom 和 left 属性则决定了该元素的最终位置。position 有以下常用的属性值: position: static; - 默认值。指定元素使用正常的布局行为&am…

神经网络--感知机

感知机 单层感知机原理 单层感知机:解决二分类问题,激活函数一般使用sign函数,基于误分类点到超平面的距离总和来构造损失函数,由损失函数推导出模型中损失函数对参数 w w w和 b b b的梯度,利用梯度下降法从而进行参数更新。让1代表A类,0代…

es5的实例__proto__(原型链) prototype(原型对象) {constructor:构造函数}

现在看这张图开始变得云里雾里,所以简单回顾一下 prototype 的基本内容,能够基本读懂这张图的脉络。 先介绍一个基本概念: function Person() {}Person.prototype.name KK;let person1 new Person();在上面的例子中, Person …

Nor Flash

核心信息: 工作频率数据吞吐量 bps bit/s(传输数据速率) Hz(时钟频率) T/s 56MB/s(max)448Mb/s(数据吞吐量、4路)448MHz 112MHz(max读、时钟频率&#…

Spring @Configuration 注解解析原理

前言 ​ Configuration 注解是 Spring 3.0 版本引入的新特性(目前版本 6.0.11),它用于将一个类标记为配置类,通过配置类可以定义和组装 Spring Bean。 一般来说注解都会有相应的解析器,Configuration 注解靠 C…