YOLOv5加入CBAM注意力机制,实现涨点!

本文介绍如何在YOLOv5n模型中集成CBAM注意力机制,包括两种实现方式:一种是在主干网络中添加,另一种是加在卷积层上。详细步骤涉及修改common.py和yolo.py文件,调整yolov5n.yaml配置,并展示成功运行的输出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里我们讲一下如何在yolov5n文件里面加入CBAM注意力机制,我这里涨点的话一共两种加法,我们先来讲第一种。

第一种我们加在主干中,我们首先找到models文件夹里面的common.py文件

添加如下模块:

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
### 集成CBAM注意力机制YOLOv5 为了在YOLOv5中集成CBAM(Convolutional Block Attention Module),可以遵循类似的思路来修改YOLOv5的架构。这涉及到在网络的关键部分加入CBAM模块,从而增强特征表示能力。 #### 修改YOLOv5网络结构 首先,在YOLOv5项目中找到`models/yolov5s.py`或其他相应版本文件的位置。接着按照如下方式调整模型定义: ```python import torch.nn as nn from cbam import CBAM # 假设已经实现CBAM类 class YOLOv5(nn.Module): def __init__(self, num_classes): super(YOLOv5, self).__init__() self.num_classes = num_classes # 定义原有的YOLOv5骨干网和其他组件... # 插入CBAM模块于特定位置之前 self.cbam_1 = CBAM(channels=256) # 根据实际通道数设置 self.cbam_2 = CBAM(channels=512) # 同上 def forward(self, x): # 执行原有层的操作... # 在适当的地方应用CBAM处理 x = self.some_layer_before_cbam(x) x = self.cbam_1(x) # 继续后续操作... x = self.another_layer_after_cbam(x) x = self.cbam_2(x) # 输出预测结果 return x ``` 上述代码片段展示了如何通过继承自`nn.Module`创建一个新的YOLOv5子类,并在其内部适当地插入了两个CBAM实例[^2]。需要注意的是,具体的层数和参数配置应当依据原始YOLOv5的设计而定;此处仅提供了一个概念性的框架用于说明目的。 #### 实现CBAM模块 如果还没有实现CBAM,则可以根据论文描述自行编写该模块。下面给出了一种可能的简化版实现方法: ```python import torch import torch.nn.functional as F from torch import nn class BasicConv(nn.Module): def __init__(self, in_planes, out_planes, kernel_size, stride=1, padding=0, dilation=1, groups=1, relu=True, bn=True, bias=False): super(BasicConv, self).__init__() self.out_channels = out_planes self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups, bias=bias) self.bn = nn.BatchNorm2d(out_planes, eps=1e-5, momentum=0.01, affine=True) if bn else None self.relu = nn.ReLU() if relu else None def forward(self, x): x = self.conv(x) if self.bn is not None: x = self.bn(x) if self.relu is not None: x = self.relu(x) return x class ChannelGate(nn.Module): def __init__(self, gate_channels, reduction_ratio=16, pool_types=['avg', 'max']): super(ChannelGate, self).__init__() self.gate_channels = gate_channels self.mlp = nn.Sequential( Flatten(), nn.Linear(gate_channels, gate_channels // reduction_ratio), nn.ReLU(), nn.Linear(gate_channels // reduction_ratio, gate_channels) ) self.pool_types = pool_types def forward(self, x): channel_att_sum = None for pool_type in self.pool_types: if pool_type == 'avg': avg_pool = F.avg_pool2d(x, (x.size(2), x.size(3)), stride=(x.size(2), x.size(3))) channel_att_raw = self.mlp(avg_pool) elif pool_type == 'max': max_pool = F.max_pool2d(x, (x.size(2), x.size(3)), stride=(x.size(2), x.size(3))) channel_att_raw = self.mlp(max_pool) if channel_att_sum is None: channel_att_sum = channel_att_raw else: channel_att_sum += channel_att_raw scale = torch.sigmoid(channel_att_sum).unsqueeze(2).unsqueeze(3).expand_as(x) return x * scale def logsumexp_2d(tensor): tensor_flatten = tensor.view(tensor.size(0), tensor.size(1), -1) s, _ = torch.max(tensor_flatten, dim=2, keepdim=True) outputs = s + (tensor_flatten - s).exp().sum(dim=2, keepdim=True).log() return outputs class SpatialGate(nn.Module): def __init__(self): super(SpatialGate, self).__init__() kernel_size = 7 self.compress = ChannelPool() self.spatial = BasicConv(2, 1, kernel_size, stride=1, padding=(kernel_size - 1) // 2, relu=False) def forward(self, x): x_compress = self.compress(x) x_out = self.spatial(x_compress) scale = torch.sigmoid(x_out) # broadcasting return x * scale class CBAM(nn.Module): def __init__(self, gate_channels, reduction_ratio=16, pool_types=None, no_spatial=False): super(CBAM, self).__init__() self.ChannelGate = ChannelGate(gate_channels, reduction_ratio, pool_types) self.no_spatial = no_spatial if not no_spatial: self.SpatialGate = SpatialGate() def forward(self, x): x_out = self.ChannelGate(x) if not self.no_spatial: x_out = self.SpatialGate(x_out) return x_out ``` 这段代码提供了完整的CBAM构建逻辑,包括通道注意门控器(`ChannelGate`)以及空间注意门控器(`SpatialGate`)两大部分[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dandelion701

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值