💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡
目标检测是计算机视觉中一个重要的下游任务。对于边缘盒子的计算平台来说,一个大型模型很难实现实时检测的要求。而且,一个由大量深度可分离卷积层构建的轻量级模型无法达到足够的准确度。我们引入了一种新的轻量级卷积技术GSConv,以减轻模型但保持准确性。GSConv在模型的准确性和速度之间实现了优秀的权衡。在本文中,给大家带来的教程是将原来的网络中的Conv模块修改为GSConv。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。
专栏地址: YOLOv5改进+入门——持续更新各种有效涨点方法——点击即可跳转
1.原理
官方代码:代码仓库地址——点击即可跳转
Slim-neck by GSConv 是一种基于 GSConv(Grouped Spatial Convolution)的神经网络结构改进技术,主要用于减小模型的计算复杂度和参数量,同时保持或提高模型的性能。以下是对 Slim-neck by GSConv 的详细讲解:
背景和动机
随着深度学习的快速发展,模型的规模和复杂度也在不断增加,这给计算资源带来了巨大的挑战。为了在保证性能的同时减少计算开销,研究人员提出了多种方法,Slim-neck by GSConv 就是其中之一。
GSConv 的基本概念
GSConv 是 Grouped Spatial Convolution 的缩写,其核心思想是通过分组卷积(Grouped Convolution)和空间卷积(Spatial Convolution)的结合来减少计算量。具体来说,GSConv 将常规卷积分解为两个步骤:
分组卷积(Grouped Convolution):将输入特征图分成若干组,每组分别进行卷积操作。这样可以减少每组卷积的计算量。
空间卷积(Spatial Convolution):在每组卷积后的输出上再进行空间卷积操作,以捕捉跨组的特征。
Slim-neck 的改进
Slim-neck 是在 GSConv 的基础上进行的改进,旨在进一步简化模型结构,特别是在网络的颈部(neck)部分。网络的颈部通常是特征提取和特征聚合的关键部分,对模型性能有重要影响。Slim-neck 通过以下几方面进行优化:
通道压缩:在网络的颈部部分,采用 GSConv 进行通道压缩,以减少特征图的通道数,从而降低计算量。
高效连接:通过引入跳跃连接(skip connection)和高效的连接策略,确保特征信息的有效传递和利用。
轻量化设计:在设计上注重轻量化,尽可能减少参数量和计算复杂度,同时保持或提高模型的性能。
Slim-neck by GSConv 的应用
Slim-neck by GSConv 在多种计算资源受限的场景下具有广泛应用,例如:
移动设备:由于移动设备的计算资源有限,Slim-neck by GSConv 能够在不显著降低模型性能的前提下,减少计算量和功耗。
嵌入式系统:嵌入式系统通常需要在低功耗和有限计算资源下运行,Slim-neck by GSConv 可以提供一种高效的解决方案。
实时应用:在需要实时处理的应用场景中,Slim-neck by GSConv 通过减少计算延迟,提高了模型的响应速度。
实验结果与性能
通过在实际任务中的实验,Slim-neck by GSConv 通常能在保持甚至提升模型精度的同时,显著减少计算开销。例如,在图像分类、目标检测等任务中,采用 Slim-neck by GSConv 的模型相较于传统模型,计算量和参数量都有明显减少,同时性能并未显著下降,甚至在某些情况下有所提升。
总结
Slim-neck by GSConv 是一种有效的神经网络优化技术,通过分组卷积和空间卷积的结合,以及在网络颈部部分的优化,达到了降低计算复杂度和参数量的目的,适用于多种计算资源受限的应用场景。
2. GSConv、VoVGSCSP代码实现
2.1 将GSConv、VoVGSCSP添加到YOLOv5中
关键步骤一: 将下面代码粘贴到/projects/yolov5-6.1/models/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
# 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 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)
Slim-neck by GSConv 的主要流程可以分为几个关键步骤
- 输入特征提取
首先,输入图像通过一个特征提取模块(通常是几个卷积层和池化层的组合),生成初步的特征图。这部分可以使用常见的卷积神经网络(如 ResNet、MobileNet 等)进行处理。
- 分组卷积(Grouped Convolution)
在特征提取之后,特征图进入分组卷积层:
特征图分组:将输入特征图分成若干组,每组包含一部分通道。
分组卷积:对每一组分别进行卷积操作。这样可以减少每组卷积的计算量,同时保持局部特征的提取能力。
- 空间卷积(Spatial Convolution)
在分组卷积之后,进行空间卷积操作:
跨组特征融合:通过空间卷积操作,在每组卷积后的输出上进行进一步的卷积,以捕捉跨组的特征。
信息整合:空间卷积有助于整合分组卷积后不同组之间的信息,提高特征表达的完整性。
- 通道压缩(Channel Compression)
在网络的颈部部分,通过 GSConv 进行通道压缩:
通道数减少:通过适当设计的 GSConv,减少特征图的通道数,从而降低计算量。
信息保持:在减少通道数的同时,通过优化卷积核和连接方式,尽量保持特征信息的完整性和表达能力。
- 高效连接策略(Efficient Connection Strategies)
在网络的设计中,采用高效的连接策略:
跳跃连接(Skip Connections):在适当的位置引入跳跃连接,确保梯度的有效传递,防止梯度消失问题。
残差连接(Residual Connections):利用残差连接提高特征的传递效率,增强网络的学习能力。
- 输出层
经过上述处理后的特征图进入最终的分类或回归层:
分类层:对于分类任务,通过全连接层或其他分类层对特征图进行分类。
回归层:对于回归任务,通过适当的回归层(如全连接层或卷积层)输出结果。