• 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

    1. class GSConv(nn.Module):
    2. # GSConv https://github.com/AlanLi1997/slim-neck-by-gsconv
    3. def __init__(self, c1, c2, k=1, s=1, g=1, act=True):
    4. super().__init__()
    5. c_ = c2 // 2
    6. self.cv1 = Conv(c1, c_, k, s, None, g, act)
    7. self.cv2 = Conv(c_, c_, 5, 1, None, c_, act)
    8. def forward(self, x):
    9. x1 = self.cv1(x)
    10. x2 = torch.cat((x1, self.cv2(x1)), 1)
    11. # shuffle
    12. b, n, h, w = x2.data.size()
    13. b_n = b * n // 2
    14. y = x2.reshape(b_n, 2, h * w)
    15. y = y.permute(1, 0, 2)
    16. y = y.reshape(2, -1, n // 2, h, w)
    17. 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

    1. class GSBottleneck(nn.Module):
    2. # GS Bottleneck https://github.com/AlanLi1997/slim-neck-by-gsconv
    3. def __init__(self, c1, c2, k=3, s=1):
    4. super().__init__()
    5. c_ = c2 // 2
    6. # for lighting
    7. self.conv_lighting = nn.Sequential(
    8. GSConv(c1, c_, 1, 1),
    9. GSConv(c_, c2, 1, 1, act=False))
    10. # for receptive field
    11. self.conv = nn.Sequential(
    12. GSConv(c1, c_, 3, 1),
    13. GSConv(c_, c2, 3, 1, act=False))
    14. self.shortcut = Conv(c1, c2, 3, 1, act=False)
    15. def forward(self, x):
    16. return self.conv_lighting(x) + self.shortcut(x)

    2、VoVGSCSP

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

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

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

    1. class GSConv(nn.Module):
    2. # GSConv https://github.com/AlanLi1997/slim-neck-by-gsconv
    3. def __init__(self, c1, c2, k=1, s=1, g=1, act=True):
    4. super().__init__()
    5. c_ = c2 // 2
    6. self.cv1 = Conv(c1, c_, k, s, None, g, act)
    7. self.cv2 = Conv(c_, c_, 5, 1, None, c_, act)
    8. def forward(self, x):
    9. x1 = self.cv1(x)
    10. x2 = torch.cat((x1, self.cv2(x1)), 1)
    11. # shuffle
    12. b, n, h, w = x2.data.size()
    13. b_n = b * n // 2
    14. y = x2.reshape(b_n, 2, h * w)
    15. y = y.permute(1, 0, 2)
    16. y = y.reshape(2, -1, n // 2, h, w)
    17. return torch.cat((y[0], y[1]), 1)
    18. class GSBottleneck(nn.Module):
    19. # GS Bottleneck https://github.com/AlanLi1997/slim-neck-by-gsconv
    20. def __init__(self, c1, c2, k=3, s=1):
    21. super().__init__()
    22. c_ = c2 // 2
    23. # for lighting
    24. self.conv_lighting = nn.Sequential(
    25. GSConv(c1, c_, 1, 1),
    26. GSConv(c_, c2, 1, 1, act=False))
    27. # for receptive field
    28. self.conv = nn.Sequential(
    29. GSConv(c1, c_, 3, 1),
    30. GSConv(c_, c2, 3, 1, act=False))
    31. self.shortcut = nn.Identity()
    32. def forward(self, x):
    33. return self.conv_lighting(x)
    34. class VoVGSCSP(nn.Module):
    35. # VoV-GSCSP https://github.com/AlanLi1997/slim-neck-by-gsconv
    36. def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
    37. super().__init__()
    38. c_ = int(c2 * e)
    39. self.cv1 = Conv(c1, c_, 1, 1)
    40. self.cv2 = Conv(2 * c_, c2, 1)
    41. self.m = nn.Sequential(*(GSBottleneck(c_, c_) for _ in range(n)))
    42. def forward(self, x):
    43. x1 = self.cv1(x)
    44. 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模块(红色框里所示),如果有知道的大佬望在评论区指点一下。

  • 相关阅读:
    php+mysql计算机公共课在线学习网站
    stm32单片机个人学习笔记3(GPIO输出)
    MySQL服务复制
    窄边极简折叠玻璃门,实现自由推拉及折叠,遥控随意切换透明与磨砂效果
    物联网开发笔记(7)- 使用Wokwi仿真ESP32开发板实现LED灯点亮、按钮使用
    迪克森电荷泵
    mysql学习笔记--单张表上的增删改查
    06-Linux用户管理
    深度学习入门(三十七)计算性能——硬件(TBC)
    仿`gRPC`功能实现像调用本地方法一样调用其他服务器方法
  • 原文地址:https://blog.csdn.net/m0_56247038/article/details/126546033