前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >YOLOv8独家原创改进:大核卷积涨点系列 | Shift-ConvNets,具有大核效应的小卷积核 | 2024年最新论文

YOLOv8独家原创改进:大核卷积涨点系列 | Shift-ConvNets,具有大核效应的小卷积核 | 2024年最新论文

原创
作者头像
AI小怪兽
发布2024-02-08 14:42:08
64900
代码可运行
发布2024-02-08 14:42:08
举报
文章被收录于专栏:YOLO大作战
运行总次数:0
代码可运行

💡💡💡本文独家改进:大的卷积核设计成为使卷积神经网络(CNNs)再次强大的理想解决方案,Shift-ConvNets稀疏/移位操作让小卷积核也能达到大卷积核效果,创新十足实现涨点,助力YOLOv8

💡💡💡在多个私有数据集和公开数据集VisDrone2019、PASCAL VOC实现涨点

1.Shift-ConvNets原理介绍

摘要:近年来的研究表明,视觉变压器(ViTs)的卓越性能得益于大的接受野。因此,大卷积核设计成为卷积神经网络(cnn)再次伟大的理想解决方案。然而,典型的大卷积核是对硬件不友好的运算符,导致各种硬件平台的兼容性降低。因此,简单地扩大卷积核的大小是不明智的。在本文中,我们揭示了小卷积核和卷积操作可以实现大核大小的关闭效果。然后,我们提出了一种移位算子,确保cnn在稀疏机制的帮助下捕获远程依赖关系,同时保持硬件友好。实验结果表明,我们的移位算子显著提高了常规CNN的准确率,同时显著降低了计算需求。在ImageNet-1k上,我们的移位增强CNN模型优于最先进的模型。

论文:https://arxiv.org/pdf/2401.12736.pdf

大卷积核是提高cnn性能的核心要素。同时,其固有的问题也不容忽视:

1. 大卷积核的核大小过大,超出了常规算子的优化范围。各种软件和硬件平台的有限优化阻碍了它的广泛应用。

2. 增加卷积核的大小似乎具有递减的边际收益。

3. 转换器具有稀疏关注的能力,而不必关注所有输入令牌。CNN有可能引入这个功能吗?

4. 大卷积核的计算成本是其应用的一个障碍。即使是参数较少的异构卷积,如可学习的扩展卷积和DCN,也不是硬件友好的算子。

基于大卷积核的持续演化,我们提出了移位算子。改进的模块结构如图4(a)所示。具体来说,我们将大卷积核转换成一组正常的小卷积核,然后对每个卷积结果应用移位操作。

图4所示。(a)将一个M × N卷积核分解为k N × N卷积核,并使用移位操作来完成等效大卷积核运算(对于SLaK部分阶段,M=51, N=5);(b)整体模块结构。

图5所示。大卷积核的框架。(a) Shift操作,向多个方向移动特征,实现局部特征变化;(b)在xvolution中提出特征关注方法,通过转移特征建立局部特征依赖关系来近似全局特征,在cnn中廉价地使用非局部特征关注方法;(c)我们提出的移位方法,沿着一维移动特征以与小卷积核大小的网格对齐,以等效地表示大卷积核,并通过去除一些移位来建立稀疏依赖关系。

图6所示。大卷积核的框架。(a) SLaK在大卷积核中的应用。它使用两个51 × 5卷积核进行水平和垂直卷积。最后加上5×5卷积的结果。(SLaK使用细粒度稀疏性来减少参数计数);(b)我们提出的方法将一个大的51 × 5卷积核分成11个标准的5 × 5卷积核。然后我们使用特征移位和加法来达到与51 × 5大卷积核相同的效果。同时,我们利用粗粒度稀疏性实现大卷积,探索局部特征之间的稀疏相关性。

2.如何将Shift-Conv加入到YOLOv8

2.1 新建ultralytics/nn/conv/shift_wiseConv.py

核心代码:

代码语言:python
代码运行次数:0
复制
class ReparamLargeKernelConv(nn.Module):
    def __init__(
            self,
            in_channels,
            out_channels,
            kernel_size,
            small_kernel=5,
            stride=1,
            groups=1,
            small_kernel_merged=False,
            Decom=True,
            bn=True,
    ):
        super(ReparamLargeKernelConv, self).__init__()
        self.kernel_size = kernel_size
        self.small_kernel = small_kernel
        self.Decom = Decom
        # We assume the conv does not change the feature map size, so padding = k//2. Otherwise, you may configure padding as you wish, and change the padding of small_conv accordingly.
        padding = kernel_size // 2
        if small_kernel_merged:  # cpp版本的conv,加快速度
            self.lkb_reparam = get_conv2d(
                in_channels=in_channels,
                out_channels=out_channels,
                kernel_size=kernel_size,
                stride=stride,
                padding=padding,
                dilation=1,
                groups=groups,
                bias=True,
            )
        else:
            if self.Decom:
                self.LoRA = conv_bn(
                    in_channels=in_channels,
                    out_channels=out_channels,
                    kernel_size=(kernel_size, small_kernel),
                    stride=stride,
                    padding=padding,
                    dilation=1,
                    groups=groups,
                    bn=bn
                )
            else:
                self.lkb_origin = conv_bn(
                    in_channels=in_channels,
                    out_channels=out_channels,
                    kernel_size=kernel_size,
                    stride=stride,
                    padding=padding,
                    dilation=1,
                    groups=groups,
                    bn=bn,
                )

            if (small_kernel is not None) and small_kernel < kernel_size:
                self.small_conv = conv_bn(
                    in_channels=in_channels,
                    out_channels=out_channels,
                    kernel_size=small_kernel,
                    stride=stride,
                    padding=small_kernel // 2,
                    groups=groups,
                    dilation=1,
                    bn=bn,
                )

        self.bn = get_bn(out_channels)
        self.act = nn.SiLU()

    def forward(self, inputs):
        if hasattr(self, "lkb_reparam"):
            out = self.lkb_reparam(inputs)
        elif self.Decom:
            # out = self.LoRA1(inputs) + self.LoRA2(inputs)
            out = self.LoRA(inputs)
            if hasattr(self, "small_conv"):
                out += self.small_conv(inputs)
        else:
            out = self.lkb_origin(inputs)
            if hasattr(self, "small_conv"):
                out += self.small_conv(inputs)
        return self.act(self.bn(out))

    def get_equivalent_kernel_bias(self):
        eq_k, eq_b = fuse_bn(self.lkb_origin.conv, self.lkb_origin.bn)
        if hasattr(self, "small_conv"):
            small_k, small_b = fuse_bn(self.small_conv.conv, self.small_conv.bn)
            eq_b += small_b
            #   add to the central part
            eq_k += nn.functional.pad(
                small_k, [(self.kernel_size - self.small_kernel) // 2] * 4
            )
        return eq_k, eq_b

    def switch_to_deploy(self):
        if hasattr(self, 'lkb_origin'):
            eq_k, eq_b = self.get_equivalent_kernel_bias()
            self.lkb_reparam = get_conv2d(
                in_channels=self.lkb_origin.conv.in_channels,
                out_channels=self.lkb_origin.conv.out_channels,
                kernel_size=self.lkb_origin.conv.kernel_size,
                stride=self.lkb_origin.conv.stride,
                padding=self.lkb_origin.conv.padding,
                dilation=self.lkb_origin.conv.dilation,
                groups=self.lkb_origin.conv.groups,
                bias=True,
            )
            self.lkb_reparam.weight.data = eq_k
            self.lkb_reparam.bias.data = eq_b
            self.__delattr__("lkb_origin")
            if hasattr(self, "small_conv"):
                self.__delattr__("small_conv")

by CSDN AI小怪兽

我正在参与2024腾讯技术创作特训营第五期有奖征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.Shift-ConvNets原理介绍
  • 2.如何将Shift-Conv加入到YOLOv8
    • 2.1 新建ultralytics/nn/conv/shift_wiseConv.py
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档