本文独家改进: 采用 GSConv 方法的 Slim-Neck 可缓解 DSC 缺陷对模型的负面影响,并充分利用深度可分离卷积 DSC 的优势,引入RT-DETR二次创新;
1)代替Upsample进行使用;
推荐指数:五星
1.GSConv Slim Neck介绍
论文地址:https://arxiv.org/ftp/arxiv/papers/2206/2206.02424.pdf
github: GitHub - AlanLi1997/slim-neck-by-gsconv: Pytorch implementation of the 'Slim-neck by GSConv: A better design paradigm of detector architectures for autonomous vehicles'
本文贡献:
- 引入了一种新方法
GSConv
来代替SC
操作。该方法使卷积计算的输出尽可能接近SC
,同时降低计算成本; - 提供了一种新的设计范式,即带有标准
Backbone
的Slim-Neck
设计;
图2(a)和(b)展示了深度可分离卷积(DSC
)和标准卷积(SC)的网络结构,但是深度可分离卷积这种设陷导致特征提取和融合能力比 SC
低得多。
1.2 Slim-Neck
采用 GSConv 方法的 Slim-Neck 可缓解 DSC 缺陷对模型的负面影响,并充分利用深度可分离卷积 DSC 的优势。
2. GSConv Slim Neck引入RT-DETR
2.1 加入ultralytics/nn/neck/SlimNeck.py
核心代码:
代码语言:javascript复制
###################### slim-neck-by-gsconv #### start ###############################
import torch
import torch.nn as nn
import math
from ..modules.conv import Conv, DWConv, GhostConv, LightConv, RepConv
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, 1, act)
self.cv2 = Conv(c_, c_, 5, 1, None, c_, 1 , act)
def forward(self, x):
x1 = self.cv1(x)
x2 = torch.cat((x1, self.cv2(x1)), 1)
# shuffle
# y = x2.reshape(x2.shape[0], 2, x2.shape[1] // 2, x2.shape[2], x2.shape[3])
# y = y.permute(0, 2, 1, 3, 4)
# return y.reshape(y.shape[0], -1, y.shape[3], y.shape[4])
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 GSConvns(GSConv):
# GSConv with a normative-shuffle https://github.com/AlanLi1997/slim-neck-by-gsconv
def __init__(self, c1, c2, k=1, s=1, g=1, act=True):
super().__init__(c1, c2, k=1, s=1, g=1, act=True)
c_ = c2 // 2
self.shuf = nn.Conv2d(c_ * 2, c2, 1, 1, 0, bias=False)
def forward(self, x):
x1 = self.cv1(x)
x2 = torch.cat((x1, self.cv2(x1)), 1)
# normative-shuffle, TRT supported
return nn.ReLU(self.shuf(x2))
class GSBottleneck(nn.Module):
# GS Bottleneck https://github.com/AlanLi1997/slim-neck-by-gsconv
def __init__(self, c1, c2, k=3, s=1, e=0.5):
super().__init__()
c_ = int(c2 *e)
# for lighting
self.conv_lighting = nn.Sequential(
GSConv(c1, c_, 1, 1),
GSConv(c_, c2, 3, 1, act=False))
self.shortcut = Conv(c1, c2, 1, 1, act=False)
def forward(self, x):
return self.conv_lighting(x) self.shortcut(x)
class DWConv(Conv):
# Depth-wise convolution class
def __init__(self, c1, c2, k=1, s=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
super().__init__(c1, c2, k, s, g=math.gcd(c1, c2), act=act)
class GSBottleneckC(GSBottleneck):
# cheap GS Bottleneck https://github.com/AlanLi1997/slim-neck-by-gsconv
def __init__(self, c1, c2, k=3, s=1):
super().__init__(c1, c2, k, s)
self.shortcut = DWConv(c1, c2, k, s, act=False)
class VoVGSCSP(nn.Module):
# VoVGSCSP module with GSBottleneck
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
super().__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c1, c_, 1, 1)
# self.gc1 = GSConv(c_, c_, 1, 1)
# self.gc2 = GSConv(c_, c_, 1, 1)
# self.gsb = GSBottleneck(c_, c_, 1, 1)
self.gsb = nn.Sequential(*(GSBottleneck(c_, c_, e=1.0) for _ in range(n)))
self.res = Conv(c_, c_, 3, 1, act=False)
self.cv3 = Conv(2 * c_, c2, 1) #
def forward(self, x):
x1 = self.gsb(self.cv1(x))
y = self.cv2(x)
return self.cv3(torch.cat((y, x1), dim=1))
class VoVGSCSPC(VoVGSCSP):
# cheap VoVGSCSP module with GSBottleneck
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
super().__init__(c1, c2)
c_ = int(c2 * 0.5) # hidden channels
self.gsb = GSBottleneckC(c_, c_, 1, 1)
###################### slim-neck-by-gsconv #### end ###############################
详见:
https://blog.csdn.net/m0_63774211/article/details/134407373
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!