YOLOv5改进之YOLOv5+GSConv+Slim Neck

论文题目:Slim-neck by GSConv: A better design paradigm of detector architectures for autonomous vehicles

论文:https://arxiv.org/abs/2206.02424

代码:https://github.com/AlanLi1997/Slim-neck-by-GSConv

直接步入正题~~~

目标:为YOLOv5模型构建一个简单高效的Neck模块。考虑了卷积方法、特征融合结构、计算效率、计算成本效益等诸多因素。

一、GSConv

class GSConv(nn.Module):
    # GSConv https://github.com/AlanLi1997/slim-neck-by-gsconv
    def __init__(self, c1, c2, k=1, s=1, g=1, act=True):
        super().__init__()
        c_ = c2 // 2
        self.cv1 = Conv(c1, c_, k, s, None, g, act)
        self.cv2 = Conv(c_, c_, 5, 1, None, c_, act)
    def forward(self, x):
        x1 = self.cv1(x)
        x2 = torch.cat((x1, self.cv2(x1)), 1)
        # shuffle
        b, n, h, w = x2.data.size()
        b_n = b * n // 2
        y = x2.reshape(b_n, 2, h * w)
        y = y.permute(1, 0, 2)
        y = y.reshape(2, -1, n // 2, h, w)
        return torch.cat((y[0], y[1]), 1)

将YOLOv5s.yaml的Neck模块中的Conv换成GSConv

1、将GSConv代码加入common.py文件中

2、找到yolo.py文件里的parse_model函数,将类名加入进去

3、修改配置文件,将YOLOv5s.yaml的Neck模块中的Conv换成GSConv 

~~~此处有一个疑问,官方给出的GSConv代码中为什么没用DWConv呢?希望知道的朋友在评论区指点一下~~~

二、GSConv+Slim Neck

1、GSBottleneck

class GSBottleneck(nn.Module):
    # GS Bottleneck https://github.com/AlanLi1997/slim-neck-by-gsconv
    def __init__(self, c1, c2, k=3, s=1):
        super().__init__()
        c_ = c2 // 2
        # for lighting
        self.conv_lighting = nn.Sequential(
            GSConv(c1, c_, 1, 1),
            GSConv(c_, c2, 1, 1, act=False))
        # for receptive field
        self.conv = nn.Sequential(
            GSConv(c1, c_, 3, 1),
            GSConv(c_, c2, 3, 1, act=False))
        self.shortcut = Conv(c1, c2, 3, 1, act=False)

    def forward(self, x):
        return self.conv_lighting(x) + self.shortcut(x)

2、VoVGSCSP

class VoVGSCSP(nn.Module):
    # VoV-GSCSP https://github.com/AlanLi1997/slim-neck-by-gsconv
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
        super().__init__()
        c_ = int(c2 * e)
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(2 * c_, c2, 1)
        self.m = nn.Sequential(*(GSBottleneck(c_, c_) for _ in range(n)))
    def forward(self, x):
        x1 = self.cv1(x)
        return self.cv2(torch.cat((self.m(x1), x1), dim=1))

将YOLOv5s.yaml的Neck模块中的Conv换成GSConv,C3模块换为VoVGSCSP模块

1、将以下代码加入common.py文件中

class GSConv(nn.Module):
    # GSConv https://github.com/AlanLi1997/slim-neck-by-gsconv
    def __init__(self, c1, c2, k=1, s=1, g=1, act=True):
        super().__init__()
        c_ = c2 // 2
        self.cv1 = Conv(c1, c_, k, s, None, g, act)
        self.cv2 = Conv(c_, c_, 5, 1, None, c_, act)
    def forward(self, x):
        x1 = self.cv1(x)
        x2 = torch.cat((x1, self.cv2(x1)), 1)
        # shuffle
        b, n, h, w = x2.data.size()
        b_n = b * n // 2
        y = x2.reshape(b_n, 2, h * w)
        y = y.permute(1, 0, 2)
        y = y.reshape(2, -1, n // 2, h, w)
        return torch.cat((y[0], y[1]), 1)

class GSBottleneck(nn.Module):
    # GS Bottleneck https://github.com/AlanLi1997/slim-neck-by-gsconv
    def __init__(self, c1, c2, k=3, s=1):
        super().__init__()
        c_ = c2 // 2
        # for lighting
        self.conv_lighting = nn.Sequential(
            GSConv(c1, c_, 1, 1),
            GSConv(c_, c2, 1, 1, act=False))
        # for receptive field
        self.conv = nn.Sequential(
            GSConv(c1, c_, 3, 1),
            GSConv(c_, c2, 3, 1, act=False))
        self.shortcut = nn.Identity()
    def forward(self, x):
        return self.conv_lighting(x)


class VoVGSCSP(nn.Module):
    # VoV-GSCSP https://github.com/AlanLi1997/slim-neck-by-gsconv
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
        super().__init__()
        c_ = int(c2 * e)
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(2 * c_, c2, 1)
        self.m = nn.Sequential(*(GSBottleneck(c_, c_) for _ in range(n)))
    def forward(self, x):
        x1 = self.cv1(x)
        return self.cv2(torch.cat((self.m(x1), x1), dim=1))

2、找到yolo.py文件里的parse_model函数,将类名加入进去,注意有两处需要添加的地方

3、修改配置文件,将YOLOv5s.yaml的Neck模块中的Conv换成GSConv ,C3模块换为VoVGSCSP

 

Appendix

下图是原论文中给出的结构图,个人对照源码后觉得这里多画了一个GSConv模块(红色框里所示),如果有知道的大佬望在评论区指点一下。

### YOLOv8 中 GSConv改进方法和实现技巧 #### 1. GSConv 结构概述 GSConv 是一种结合了标准卷积 (SC) 和深度可分离卷积 (DSC) 特性的新型卷积结构。通过混洗操作,可以有效地将 SC 层生成的信息均匀地融合到 DSC 层的输出中[^2]。 ```python import torch.nn as nn class GSConv(nn.Module): def __init__(in_channels, out_channels, kernel_size=3, stride=1, padding=1): super(GSConv, self).__init__() self.sc_conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding) self.dsc_conv = nn.Conv2d(out_channels, out_channels, kernel_size, stride, padding, groups=out_channels) self.shuffle = ChannelShuffle(groups=2) def forward(self, x): sc_out = self.sc_conv(x) dsc_out = self.dsc_conv(sc_out) shuffled_output = self.shuffle(dsc_out) return shuffled_output ``` #### 2. Slim Neck 设计理念 Slim Neck 被设计用于优化模型性能,在保持较高精度的同时减少计算资源消耗。具体来说,在骨干网络中保留传统的 SC 卷积层,而在颈部部分采用更高效的 GSConv 替代传统卷积层。 ```python class SlimNeck(nn.Module): def __init__(self, in_channels, mid_channels, out_channels): super(SlimNeck, self).__init__() self.gconv1 = GSConv(in_channels, mid_channels) self.gconv2 = GSConv(mid_channels, out_channels) def forward(self, x): x = self.gconv1(x) x = self.gconv2(x) return x ``` #### 3. 实现细节与注意事项 为了进一步提高模型效率并改善检测效果: - **参数调整**:适当增加或减少 GSConv 中的标准卷积核数量以及其对应的膨胀率。 - **激活函数选择**:尝试不同的非线性变换方式如 ReLU、LeakyReLU 或者 Swish 来寻找最适合当前任务的最佳配置方案。 - **正则化手段**:引入 DropBlock 等高级正则项来增强泛化能力防止过拟合现象发生。 - **多尺度训练**:利用图像金字塔或多分辨率输入数据集来进行更加鲁棒的目标识别学习过程。 #### 4. 性能评估指标 通过对不同版本模型进行全面测试比较各项关键性能指标(mAP@0.5:0.95),最终确定最优设计方案。
评论 62
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值