论文题目: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模块。考虑了卷积方法、特征融合结构、计算效率、计算成本效益等诸多因素。

- 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呢?希望知道的朋友在评论区指点一下~~~

- 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)

- 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

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