赞
踩
目录
RFAConv模块原论文链接:https://arxiv.org/pdf/2304.03198.pdf
空间注意力已被广泛用于改进卷积神经网络的性能。然而,它具有一定的局限性。在RFAConv模块原论文中,作者提出了一个关于空间注意力效果的新视角,即空间注意力机制本质上是解决卷积核参数共享的问题。然而,空间注意力生成的注意力图中包含的信息对于大尺寸卷积核来说是不足的。因此,作者提出了一种新颖的注意力机制,称为感受野注意力(RFA)。现有的空间注意力,如卷积块注意力模块(CBAM)和协同注意力(CA)只关注空间特征,这并不能完全解决卷积核参数共享的问题。相比之下,RFA不仅关注感受野空间特征,还为大尺寸卷积核提供有效的注意力权重。由RFA开发的感受野注意力卷积操作(RFAConv)代表了一种替代标准卷积操作的新方法。它几乎没有增加计算成本和参数,同时显著提高了网络性能。作者在ImageNet-1k、COCO和VOC数据集上进行了一系列实验,证明了此方法的优越性。特别重要的是,作者认为现在是将焦点从空间特征转移到感受野空间特征的时候了,通过这种方式,我们可以进一步提高网络性能,取得更好的结果。相关任务的代码和预训练模型可以在https://github.com/Liuchen1997/RFAConv中找到。
关于感受野空间特征,我们提出了感受野注意力(RFA)。这种方法不仅强调感受野滑块内不同特征的重要性,还优先考虑感受野空间特征。通过这种方法,卷积核参数共享的问题被完全解决。感受野空间特征根据卷积核的大小动态生成,因此,RFA是卷积的固定组合,不能脱离卷积操作的帮助,同时依赖于RFA来提高性能,因此我们提出了感受野注意力卷积(RFAConv)。具有3×3大小卷积核的RFAConv的总体结构如图所示。由RFAConv的详细结构可知,它动态地决定了每个特征在接受域中的重要性,并解决了参数共享的问题。
如下图所示基于YOLOv5n和VisDrone数据集的对象检测实验,说明了在GroupConv上构建的RFAConv的优势。
作者在COCO2017数据集上进行目标检测实验,重新评估作者所提出的方法。COCO2017包含118287个训练集和5000个验证集。我们选择了YOLOv5n、YOLOv7-tiny和YOLOv8n模型进行一系列实验。除了迭代次数和批量大小外,所有参数均设置为默认值。作者将每个模型训练300个epochs,批量大小为32。为了与分类相似,作者用注意力机制构建的新型卷积操作替换基线模型中的一些卷积操作。具体来说,作者用注意力卷积替换了YOLOv5和YOLOv8的yaml文件中的所有3×3卷积操作。对于YOLOv7,作者替换了骨干网络中所有ELAN [34]中的第一个3×3卷积操作。按照之前的工作,并分别报告AP50、AP75、AP、APS、APM和APL。此外,为了更好地显示不同网络的性能,作者选择了YOLOv5n的训练过程进行可视化,展示了AP50随迭代次数的变化情况。结果图如下图所示:
由不同注意卷积构造的YOLOv5n在训练过程中AP50的变化如下图所示:
在 ultralytics/nn/modules/conv.py 中增加如下代码:
- class CAConv(nn.Module):
- def __init__(self, channel, reduction=32):
- super(CAConv, self).__init__()
- self.pool_h = nn.AdaptiveAvgPool2d((None, 1))
- self.pool_w = nn.AdaptiveAvgPool2d((1, None))
-
- mip = max(8, channel // reduction)
-
- self.conv1 = nn.Conv2d(channel, mip, kernel_size=1, stride=1, padding=0)
- self.bn1 = nn.BatchNorm2d(mip)
- self.act = nn.Hardswish()
-
- self.conv_h = nn.Conv2d(mip, channel, kernel_size=1, stride=1, padding=0)
- self.conv_w = nn.Conv2d(mip, channel, kernel_size=1, stride=1, padding=0)
-
-
- def forward(self, x):
- identity = x
- n, c, h, w = x.size()
- x_h = self.pool_h(x)
- x_w = self.pool_w(x).permute(0, 1, 3, 2)
- y = torch.cat([x_h, x_w], dim=2)
- y = self.conv1(y)
- y = self.bn1(y)
- y = self.act(y)
- x_h, x_w = torch.split(y, [h, w], dim=2)
- x_w = x_w.permute(0, 1, 3, 2)
- a_h = self.conv_h(x_h).sigmoid()
- a_w = self.conv_w(x_w).sigmoid()
- out = identity * a_w * a_h
-
- return out
-
-
- class RFACA(nn.Module):
- def __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):
- super(RFACA, self).__init__()
- self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)
- self.avg_pool = nn.AdaptiveAvgPool2d(1)
- self.group_conv1 = nn.Conv2d(c2, 9 *c2,1, 1, autopad(1, None, 1), groups=c2)
- self.group_conv2 = nn.Conv2d(c2, 9 *c2,3, 1, autopad(3, None, 1), groups=c2)
- self.group_conv3 = nn.Conv2d(c2, 9 *c2,5, 1, autopad(5, None, 1), groups=c2)
- self.softmax = nn.Softmax(dim=1)
- self.group_conv4 = Conv(c2, 9 * c2, k=k, g=c2)
- self.group_conv5 = Conv(c2, 9 * c2, k=k, g=c2)
- self.group_conv6 = Conv(c2, 9 * c2, k=k, g=c2)
- self.CA = CAConv(c2)
- self.convDown = Conv(c2, c2, k=3, s=3)
- def forward(self, x):
- x=self.conv(x)
- y = self.avg_pool(x)
- group1 = self.softmax(self.group_conv1(y))
- group2 = self.softmax(self.group_conv2(y))
- group3 = self.softmax(self.group_conv3(y))
- g1 = self.group_conv4(x)
- g2 = self.group_conv5(x)
- g3 = self.group_conv6(x)
- out1 = g1 * group1.expand_as(g1)
- out2 = g2 * group2.expand_as(g2)
- out3 = g3 * group3.expand_as(g3)
- out = out1+out2+out3
- batch_size, channels, height, width = out.shape
- output_channels = channels // 9
- out = out.view(batch_size, output_channels, 3,3, height,width).permute(0, 1, 4,2,5,3).reshape(batch_size,
- output_channels, 3 * height, 3 * width)
- out = self.CA(out)
- out = self.convDown(out)
- return out
- from .block import (C1, C2, C3, C3TR, DFL, SPP, SPPF, Bottleneck, BottleneckCSP, C2f, C3Ghost, C3x, GhostBottleneck, HGBlock, HGStem, Proto, RepC3)
- from .conv import (CBAM, ChannelAttention, Concat, Conv, Conv2, ConvTranspose, DWConv, DWConvTranspose2d, Focus, GhostConv, LightConv, RepConv, SpatialAttention,RFACA)
- from .head import Classify, Detect, Pose, RTDETRDecoder, Segment
- from .transformer import (AIFI, MLP, DeformableTransformerDecoder,
- DeformableTransformerDecoderLayer, LayerNorm2d,
- MLPBlock, MSDeformAttn, TransformerBlock,
- TransformerEncoderLayer, TransformerLayer)
-
-
- __all__ = [
- 'Conv', 'Conv2', 'LightConv', 'RepConv', 'DWConv', 'DWConvTranspose2d', 'ConvTranspose', 'Focus', 'GhostConv',
- 'ChannelAttention', 'SpatialAttention', 'CBAM', 'Concat',
- 'TransformerLayer', 'TransformerBlock', 'MLPBlock',
- 'LayerNorm2d', 'DFL', 'HGBlock', 'HGStem', 'SPP', 'SPPF', 'C1', 'C2', 'C3',
- 'C2f', 'C3x', 'C3TR', 'C3Ghost',
- 'GhostBottleneck', 'Bottleneck', 'BottleneckCSP', 'Proto', 'Detect', 'Segment', 'Pose', 'Classify',
- 'TransformerEncoderLayer', 'RepC3', 'RTDETRDecoder', 'AIFI', 'DeformableTransformerDecoder',
- 'DeformableTransformerDecoderLayer', 'MSDeformAttn', 'MLP',"RFACA"]
- from ultralytics.nn.modules import (AIFI, C1, C2, C3, C3TR, SPP, SPPF, Bottleneck, BottleneckCSP, C2f, C3Ghost, C3x, Classify, Concat, Conv, Conv2, ConvTranspose,
- Detect, DWConv, DWConvTranspose2d, Focus, GhostBottleneck, GhostConv, HGBlock, HGStem, Pose, RepC3, RepConv, RTDETRDecoder, Segment,RFACA)
另外在task.py中if m in {Classify,Conv,ConvTranspose,GhostConv, .......的最后添加RFACA
最后修改yolov8.yaml文件,将backbone中的Conv替换为RFACA
- backbone:
- # [from, repeats, module, args]
- - [-1, 1, RFACA, [64, 3, 2]] # 0-P1/2
- - [-1, 1, RFACA, [128, 3, 2]] # 1-P2/4
- - [-1, 3, C2f, [128, True]]
- - [-1, 1, RFACA, [256, 3, 2]] # 3-P3/8
- - [-1, 6, C2f, [256, True]]
- - [-1, 1, RFACA, [512, 3, 2]] # 5-P4/16
- - [-1, 6, C2f, [512, True]]
- - [-1, 1, RFACA, [1024, 3, 2]] # 7-P5/32
- - [-1, 3, C2f, [1024, True]]
- - [-1, 1, SPPF, [1024, 5]] # 9
这样我们就完成了使用RFAConv代替Conv,希望对你有所帮助,实现快速涨点。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。