欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > YOLOv5改进 | 模块缝合 | C3 融合RFAConv增强感受野空间特征 【完整代码 + 自研创新】

YOLOv5改进 | 模块缝合 | C3 融合RFAConv增强感受野空间特征 【完整代码 + 自研创新】

2024/10/25 3:28:36 来源:https://blog.csdn.net/m0_67647321/article/details/141993945  浏览:    关键词:YOLOv5改进 | 模块缝合 | C3 融合RFAConv增强感受野空间特征 【完整代码 + 自研创新】

修改后的完整代码获取点击:👆或者👉3. 完整代码分享  


秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转


💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡


专栏目录 :《YOLOv5入门 + 改进涨点》专栏介绍 & 专栏目录 |目前已有80+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进


空间注意力虽提高卷积神经网络性能,但有局限。本文介绍了感受野注意力(RFA)新机制,解决大尺寸卷积核参数共享问题RFA关注感受野空间特征,为大型卷积核提供有效权重。RFAConv操作几乎不增加计算成本,显著提升网络性能。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。

专栏地址 YOLOv5改进+入门——持续更新各种有效涨点方法 点击即可跳转 

目录

1.原理 

2. 将C3_RFAConv添加到yolov8网络中

2.1 C3_RFAConv代码实现

2.2 C3_RFAConv的神经网络模块代码解析 

2.3 新增yaml文件

2.4 注册模块

2.5 执行程序

3. 完整代码分享  

4. GFLOPs

5. 进阶

6. 总结


1.原理 

论文地址:RFAConv: Innovating Spatial Attention and Standard Convolutional Operation——点击即可跳转

官方代码:官方代码仓库——点击即可跳转

RFAConv(受体场注意卷积)是一种新颖的卷积运算,旨在解决标准卷积和现有空间注意机制的局限性,特别是在参数共享和大型卷积核方面。

RFAConv 背后的关键原则:

  1. 受体场空间特征:与专注于单个空间特征的传统空间注意不同,RFAConv 强调受体场空间特征,这些特征是根据卷积核的大小动态生成的。这种方法通过关注受体场内不同特征的重要性来增强特征提取。

  2. 解决参数共享问题:在标准卷积中,内核参数在整个输入中共享,限制了网络跨空间位置捕获不同信息的能力。RFAConv 通过将注意力机制与卷积相结合来解决此问题,为每个受体场创建非共享参数。

  3. 注意力机制集成:RFAConv 集成了一种注意力机制,该机制为接受场中的每个特征分配重要性,使网络能够专注于最重要的信息。此过程避免了 CBAM 和 CA 等传统注意力机制的局限性,这些机制在不同空间区域之间共享注意力权重。

  4. 高效轻量:尽管引入了注意力机制,但 RFAConv 仅增加了极少的计算开销和参数。它还使用组卷积等技术来高效提取接受场空间特征,使其适用于实时应用。

  5. 性能提升:通过解决空间注意力和卷积参数共享的局限性,RFAConv 增强了神经网络在分类、对象检测和分割等任务中的性能,在许多情况下优于 CBAM 和 CA 等其他基于注意力的方法。

综上所述,RFAConv 通过关注感受野空间特征进行创新,提供了一种更灵活、更强大的方法来替代标准卷积,同时保持效率并提高网络性能。

2. 将C3_RFAConv添加到yolov8网络中

2.1 C3_RFAConv代码实现

关键步骤一 将下面的代码粘贴到\yolov5\models\common.py中


from torch import nn
from einops import rearrange
import torchclass RFAConv(nn.Module):def __init__(self, in_channel, out_channel, kernel_size=3, stride=1):super().__init__()self.kernel_size = kernel_sizeself.get_weight = nn.Sequential(nn.AvgPool2d(kernel_size=kernel_size, padding=kernel_size // 2, stride=stride),nn.Conv2d(in_channel, in_channel * (kernel_size ** 2), kernel_size=1,groups=in_channel, bias=False))self.generate_feature = nn.Sequential(nn.Conv2d(in_channel, in_channel * (kernel_size ** 2), kernel_size=kernel_size, padding=kernel_size // 2,stride=stride, groups=in_channel, bias=False),nn.BatchNorm2d(in_channel * (kernel_size ** 2)),nn.ReLU())self.conv = Conv(in_channel, out_channel, k=kernel_size, s=kernel_size, p=0)def forward(self, x):b, c = x.shape[0:2]weight = self.get_weight(x)h, w = weight.shape[2:]weighted = weight.view(b, c, self.kernel_size ** 2, h, w).softmax(2)  # b c*kernel**2,h,w ->  b c k**2 h wfeature = self.generate_feature(x).view(b, c, self.kernel_size ** 2, h,w)  # b c*kernel**2,h,w ->  b c k**2 h wweighted_data = feature * weightedconv_data = rearrange(weighted_data, 'b c (n1 n2) h w -> b c (h n1) (w n2)', n1=self.kernel_size,# b c k**2 h w ->  b c h*k w*kn2=self.kernel_size)return self.conv(conv_data)def autopad(k, p=None, d=1):  # kernel, padding, dilation"""Pad to 'same' shape outputs."""if d > 1:k = d * (k - 1) + 1 if isinstance(k, int) else [d * (x - 1) + 1 for x in k]  # actual kernel-sizeif p is None:p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-padreturn pclass Conv(nn.Module):"""Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)."""default_act = nn.SiLU()  # default activationdef __init__(self, c1, c2, k=1, s=1, p=None, g=1, d=1, act=True):"""Initialize Conv layer with given arguments including activation."""super().__init__()self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p, d), groups=g, dilation=d, bias=False)self.bn = nn.BatchNorm2d(c2)self.act = self.default_act if act is True else act if isinstance(act, nn.Module) else nn.Identity()def forward(self, x):"""Apply convolution, batch normalization and activation to input tensor."""return self.act(self.bn(self.conv(x)))def forward_fuse(self, x):"""Perform transposed convolution of 2D data."""return self.act(self.conv(x))class Bottleneck_RFAConv(nn.Module):"""Standard bottleneck."""def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):"""Initializes a bottleneck module with given input/output channels, shortcut option, group, kernels, andexpansion."""super().__init__()c_ = int(c2 * e)  # hidden channelsself.cv1 = Conv(c1, c_, k[0], 1)self.cv2 = RFAConv(c_, c2)self.add = shortcut and c1 == c2def forward(self, x):"""'forward()' applies the YOLO FPN to input data."""return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))class C3_RFAConv(C3):def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):super().__init__(c1, c2, n, shortcut, g, e)c_ = int(c2 * e)  # hidden channelsself.m = nn.Sequential(*(Bottleneck_RFAConv(c_, c_, shortcut, g, k=(1, 3), e=1.0) for _ in range(n)))

2.2 C3_RFAConv的神经网络模块代码解析 

C3_RFAConv 是一种改进版的 CSP(Cross Stage Partial)瓶颈,目标是提升网络的特征表达能力并加速计算。该模块结合了 RFAConv(Receptive-Field Attention Convolution)和常规卷积,解决了标准卷积中参数共享的问题。

  1. 输入与通道分割:首先,输入通过 Conv 层处理,并被分成两个部分(通过 chunk 函数)。这两个部分中的一部分会直接用于后续拼接,另一部分将进入多层 Bottleneck 模块进行处理。

  2. 瓶颈结构:在 C3_RFAConv 中,每一个 Bottleneck_RFAConv 层包含两个卷积操作。第一个卷积将输入通道数减半(或根据扩展参数进行调整),然后通过 RFAConv 进行进一步处理。RFAConv 使用感受野注意力机制来提升不同位置特征的区分度,确保每个特征图上的信息得到充分利用。

  3. 特征融合:所有经过 Bottleneck_RFAConv 处理后的特征以及未处理的分支特征通过 torch.cat 进行拼接。这个拼接操作通过引入更多的局部信息,增强特征表达能力。

  4. 最终输出:拼接后的特征通过另一个卷积操作(cv2)进行通道压缩,形成最终输出。

整个过程能够有效捕获局部和全局的特征信息,避免传统卷积操作中的参数共享问题,提升模型的准确性和效率。

2.3 新增yaml文件

关键步骤二在下/yolov5/models下新建文件 yolov5_C3_RFAConv.yaml并将下面代码复制进去

  • 目标检测yaml文件 
# Ultralytics YOLOv5 🚀, AGPL-3.0 license# Parameters
nc: 80 # number of classes
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # 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, C3_RFAConv, [128]],[-1, 1, Conv, [256, 3, 2]], # 3-P3/8[-1, 6, C3_RFAConv, [256]],[-1, 1, Conv, [512, 3, 2]], # 5-P4/16[-1, 9, C3_RFAConv, [512]],[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32[-1, 3, C3_RFAConv, [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, C3, [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, C3, [256, False]], # 17 (P3/8-small)[-1, 1, Conv, [256, 3, 2]],[[-1, 14], 1, Concat, [1]], # cat head P4[-1, 3, C3, [512, False]], # 20 (P4/16-medium)[-1, 1, Conv, [512, 3, 2]],[[-1, 10], 1, Concat, [1]], # cat head P5[-1, 3, C3, [1024, False]], # 23 (P5/32-large)[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)]
  • 语义分割yaml文件
# Ultralytics YOLOv5 🚀, AGPL-3.0 license# Parameters
nc: 80 # number of classes
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # 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, C3_RFAConv, [128]],[-1, 1, Conv, [256, 3, 2]], # 3-P3/8[-1, 6, C3_RFAConv, [256]],[-1, 1, Conv, [512, 3, 2]], # 5-P4/16[-1, 9, C3_RFAConv, [512]],[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32[-1, 3, C3_RFAConv, [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, C3, [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, C3, [256, False]], # 17 (P3/8-small)[-1, 1, Conv, [256, 3, 2]],[[-1, 14], 1, Concat, [1]], # cat head P4[-1, 3, C3, [512, False]], # 20 (P4/16-medium)[-1, 1, Conv, [512, 3, 2]],[[-1, 10], 1, Concat, [1]], # cat head P5[-1, 3, C3, [1024, False]], # 23 (P5/32-large)[[17, 20, 23], 1, Segment, [nc, anchors, 32, 256]], # Segment (P3, P4, P5)]

温馨提示:本文只是对yolov5基础上添加模块,如果要对yolov5n/l/m/x进行添加则只需要指定对应的depth_multiple 和 width_multiple。


# YOLOv5n
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple# YOLOv5s
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # layer channel multiple# YOLOv5l 
depth_multiple: 1.0  # model depth multiple
width_multiple: 1.0  # layer channel multiple# YOLOv5m
depth_multiple: 0.67  # model depth multiple
width_multiple: 0.75  # layer channel multiple# YOLOv5x
depth_multiple: 1.33  # model depth multiple
width_multiple: 1.25  # layer channel multiple

2.4 注册模块

关键步骤三在yolo.py的parse_model函数替换添加C3_RFAConv

2.5 执行程序

在train.py中,将cfg的参数路径设置为yolov5_C3_RFAConv.yaml的路径

建议大家写绝对路径,确保一定能找到

 🚀运行程序,如果出现下面的内容则说明添加成功🚀    

               from  n    params  module                                  arguments0                -1  1      7040  models.common.Conv                      [3, 64, 6, 2, 2]1                -1  1     73984  models.common.Conv                      [64, 128, 3, 2]2                -1  3    177664  models.common.C3_RFAConv                [128, 128, 3]3                -1  1    295424  models.common.Conv                      [128, 256, 3, 2]4                -1  6   1201152  models.common.C3_RFAConv                [256, 256, 6]5                -1  1   1180672  models.common.Conv                      [256, 512, 3, 2]6                -1  9   6682624  models.common.C3_RFAConv                [512, 512, 9]7                -1  1   4720640  models.common.Conv                      [512, 1024, 3, 2]8                -1  3  10137600  models.common.C3_RFAConv                [1024, 1024, 3]9                -1  1   2624512  models.common.SPPF                      [1024, 1024, 5]10                -1  1    525312  models.common.Conv                      [1024, 512, 1, 1]11                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']12           [-1, 6]  1         0  models.common.Concat                    [1]13                -1  3   2757632  models.common.C3                        [1024, 512, 3, False]14                -1  1    131584  models.common.Conv                      [512, 256, 1, 1]15                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']16           [-1, 4]  1         0  models.common.Concat                    [1]17                -1  3    690688  models.common.C3                        [512, 256, 3, False]18                -1  1    590336  models.common.Conv                      [256, 256, 3, 2]19          [-1, 14]  1         0  models.common.Concat                    [1]20                -1  3   2495488  models.common.C3                        [512, 512, 3, False]21                -1  1   2360320  models.common.Conv                      [512, 512, 3, 2]22          [-1, 10]  1         0  models.common.Concat                    [1]23                -1  3   9971712  models.common.C3                        [1024, 1024, 3, False]        24      [17, 20, 23]  1    457725  Detect                                  [80, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [256, 512, 1024]]
YOLOv5_C3_RFAConv summary: 536 layers, 47082109 parameters, 47082109 gradients, 113.2 GFLOPs

3. 完整代码分享  

https://pan.baidu.com/s/1OkP3xMyuNgCAfPEwNlYjIg?pwd=fmfr

 提取码: fmfr 

4. GFLOPs

关于GFLOPs的计算方式可以查看:百面算法工程师 | 卷积基础知识——Convolution

未改进的GFLOPs

img

改进后的GFLOPs

5. 进阶

可以结合损失函数或者卷积模块进行多重改进

YOLOv5改进 | 损失函数 | EIoU、SIoU、WIoU、DIoU、FocuSIoU等多种损失函数——点击即可跳转

6. 总结

RFAConv(Receptive-Field Attention Convolution)是一种创新的卷积操作,旨在解决标准卷积和现有空间注意力机制在参数共享和大卷积核方面的局限性。其核心思想是通过引入感受野空间特征,动态生成与卷积核大小相关的特征区域,从而增强网络对不同位置特征的捕捉能力。传统的卷积操作在不同位置共享相同的卷积核参数,无法充分利用图像各个区域的差异性信息,而RFAConv通过将注意力机制与卷积操作相结合,为每个感受野分配不同的注意力权重,从而解决了参数共享问题。同时,RFAConv注重每个感受野内部特征的重要性,通过轻量化的设计在保持高效性的同时,极大地提升了网络性能。在分类、目标检测和语义分割等任务中,RFAConv能够以极少的计算开销和参数增长,实现显著的性能提升,特别是在与CBAM和CA等传统注意力机制的对比中表现出色。因此,RFAConv为提升卷积神经网络性能提供了一种更灵活且高效的替代方案。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com