DAMO-YOLO的Neck( Efficient RepGFPN)详解

这篇具有很好参考价值的文章主要介绍了DAMO-YOLO的Neck( Efficient RepGFPN)详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

DAMO-YOLO的Neck( Efficient RepGFPN)详解

 这个图是有点问题的,在GiraffeNeckV2代码中只有了5个Fusion Block(图中有6个)

https://github.com/tinyvision/DAMO-YOLO/blob/master/damo/base_models/necks/giraffe_fpn_btn.py

代码中只有5个CSPStage

所以我自己画了一个总体图,在github上提了个issue,得到了原作者的肯定

I think the pictures in your paper are not rigorous in several places · Issue #91 · tinyvision/DAMO-YOLO · GitHub

DAMO-YOLO的Neck( Efficient RepGFPN)详解

 

想要看懂Neck部分,只需要看懂Fusion Block在做什么就行了,其他部分和PAN差不太多

class CSPStage(nn.Module):   
    def __init__(self,
                 block_fn,
                 ch_in,
                 ch_hidden_ratio,
                 ch_out,
                 n,
                 act='swish',
                 spp=False):
        super(CSPStage, self).__init__()

        split_ratio = 2
        ch_first = int(ch_out // split_ratio)
        ch_mid = int(ch_out - ch_first)
        self.conv1 = ConvBNAct(ch_in, ch_first, 1, act=act)
        self.conv2 = ConvBNAct(ch_in, ch_mid, 1, act=act)
        self.convs = nn.Sequential()

        next_ch_in = ch_mid
        for i in range(n):
            if block_fn == 'BasicBlock_3x3_Reverse':
                self.convs.add_module(
                    str(i),
                    BasicBlock_3x3_Reverse(next_ch_in,
                                           ch_hidden_ratio,
                                           ch_mid,
                                           act=act,
                                           shortcut=True))
            else:
                raise NotImplementedError
            if i == (n - 1) // 2 and spp:
                self.convs.add_module(
                    'spp', SPP(ch_mid * 4, ch_mid, 1, [5, 9, 13], act=act))
            next_ch_in = ch_mid
        self.conv3 = ConvBNAct(ch_mid * n + ch_first, ch_out, 1, act=act)

    def forward(self, x):
        y1 = self.conv1(x)
        y2 = self.conv2(x)

        mid_out = [y1]
        for conv in self.convs:
            y2 = conv(y2)
            mid_out.append(y2)
        y = torch.cat(mid_out, axis=1)
        y = self.conv3(y)
        return y

以上是CSPStage的代码,要想看懂,我们得先看懂ConvBNAct、BasicBlock_3x3_Reverse这两个类

class ConvBNAct(nn.Module):
    """A Conv2d -> Batchnorm -> silu/leaky relu block"""
    def __init__(
        self,
        in_channels,
        out_channels,
        ksize,
        stride=1,
        groups=1,
        bias=False,
        act='silu',
        norm='bn',
        reparam=False,
    ):
        super().__init__()
        # same padding
        pad = (ksize - 1) // 2
        self.conv = nn.Conv2d(
            in_channels,
            out_channels,
            kernel_size=ksize,
            stride=stride,
            padding=pad,
            groups=groups,
            bias=bias,
        )
        if norm is not None:
            self.bn = get_norm(norm, out_channels, inplace=True)
        if act is not None:
            self.act = get_activation(act, inplace=True)
        self.with_norm = norm is not None
        self.with_act = act is not None

    def forward(self, x):
        x = self.conv(x)
        if self.with_norm:
            x = self.bn(x)
        if self.with_act:
            x = self.act(x)
        return x

    def fuseforward(self, x):
        return self.act(self.conv(x))

ConvBNAct还是很好看懂的,Conv +BN + SiLU就完事了(也可用别的激活函数,文章用SiLU)

DAMO-YOLO的Neck( Efficient RepGFPN)详解

 如果设置了groups参数就变成了组卷积了

DAMO-YOLO的Neck( Efficient RepGFPN)详解

class BasicBlock_3x3_Reverse(nn.Module):
    def __init__(self,
                 ch_in,
                 ch_hidden_ratio,
                 ch_out,
                 act='relu',
                 shortcut=True):
        super(BasicBlock_3x3_Reverse, self).__init__()
        assert ch_in == ch_out
        ch_hidden = int(ch_in * ch_hidden_ratio)
        self.conv1 = ConvBNAct(ch_hidden, ch_out, 3, stride=1, act=act)
        self.conv2 = RepConv(ch_in, ch_hidden, 3, stride=1, act=act)
        self.shortcut = shortcut

    def forward(self, x):
        y = self.conv2(x)
        y = self.conv1(y)
        if self.shortcut:
            return x + y
        else:
            return y

要看懂BasicBlock_3x3_Reverse这个类,就得了解RepConv类,这个类就是根据RepVGG网络的RepVGGBlock改的

class RepConv(nn.Module):
    '''RepConv is a basic rep-style block, including training and deploy status
    Code is based on https://github.com/DingXiaoH/RepVGG/blob/main/repvgg.py
    '''
    def __init__(self,
                 in_channels,
                 out_channels,
                 kernel_size=3,
                 stride=1,
                 padding=1,
                 dilation=1,
                 groups=1,
                 padding_mode='zeros',
                 deploy=False,
                 act='relu',
                 norm=None):
        super(RepConv, self).__init__()
        self.deploy = deploy
        self.groups = groups
        self.in_channels = in_channels
        self.out_channels = out_channels

        assert kernel_size == 3
        assert padding == 1

        padding_11 = padding - kernel_size // 2

        if isinstance(act, str):
            self.nonlinearity = get_activation(act)
        else:
            self.nonlinearity = act

        if deploy:
            self.rbr_reparam = nn.Conv2d(in_channels=in_channels,
                                         out_channels=out_channels,
                                         kernel_size=kernel_size,
                                         stride=stride,
                                         padding=padding,
                                         dilation=dilation,
                                         groups=groups,
                                         bias=True,
                                         padding_mode=padding_mode)

        else:
            self.rbr_identity = None
            self.rbr_dense = conv_bn(in_channels=in_channels,
                                     out_channels=out_channels,
                                     kernel_size=kernel_size,
                                     stride=stride,
                                     padding=padding,
                                     groups=groups)
            self.rbr_1x1 = conv_bn(in_channels=in_channels,
                                   out_channels=out_channels,
                                   kernel_size=1,
                                   stride=stride,
                                   padding=padding_11,
                                   groups=groups)

    def forward(self, inputs):
        '''Forward process'''
        if hasattr(self, 'rbr_reparam'):
            return self.nonlinearity(self.rbr_reparam(inputs))

        if self.rbr_identity is None:
            id_out = 0
        else:
            id_out = self.rbr_identity(inputs)

        return self.nonlinearity(
            self.rbr_dense(inputs) + self.rbr_1x1(inputs) + id_out)

    def get_equivalent_kernel_bias(self):
        kernel3x3, bias3x3 = self._fuse_bn_tensor(self.rbr_dense)
        kernel1x1, bias1x1 = self._fuse_bn_tensor(self.rbr_1x1)
        kernelid, biasid = self._fuse_bn_tensor(self.rbr_identity)
        return kernel3x3 + self._pad_1x1_to_3x3_tensor(
            kernel1x1) + kernelid, bias3x3 + bias1x1 + biasid

    def _pad_1x1_to_3x3_tensor(self, kernel1x1):
        if kernel1x1 is None:
            return 0
        else:
            return torch.nn.functional.pad(kernel1x1, [1, 1, 1, 1])

    def _fuse_bn_tensor(self, branch):
        if branch is None:
            return 0, 0
        if isinstance(branch, nn.Sequential):
            kernel = branch.conv.weight
            running_mean = branch.bn.running_mean
            running_var = branch.bn.running_var
            gamma = branch.bn.weight
            beta = branch.bn.bias
            eps = branch.bn.eps
        else:
            assert isinstance(branch, nn.BatchNorm2d)
            if not hasattr(self, 'id_tensor'):
                input_dim = self.in_channels // self.groups
                kernel_value = np.zeros((self.in_channels, input_dim, 3, 3),
                                        dtype=np.float32)
                for i in range(self.in_channels):
                    kernel_value[i, i % input_dim, 1, 1] = 1
                self.id_tensor = torch.from_numpy(kernel_value).to(
                    branch.weight.device)
            kernel = self.id_tensor
            running_mean = branch.running_mean
            running_var = branch.running_var
            gamma = branch.weight
            beta = branch.bias
            eps = branch.eps
        std = (running_var + eps).sqrt()
        t = (gamma / std).reshape(-1, 1, 1, 1)
        return kernel * t, beta - running_mean * gamma / std

    def switch_to_deploy(self):
        if hasattr(self, 'rbr_reparam'):
            return
        kernel, bias = self.get_equivalent_kernel_bias()
        self.rbr_reparam = nn.Conv2d(
            in_channels=self.rbr_dense.conv.in_channels,
            out_channels=self.rbr_dense.conv.out_channels,
            kernel_size=self.rbr_dense.conv.kernel_size,
            stride=self.rbr_dense.conv.stride,
            padding=self.rbr_dense.conv.padding,
            dilation=self.rbr_dense.conv.dilation,
            groups=self.rbr_dense.conv.groups,
            bias=True)
        self.rbr_reparam.weight.data = kernel
        self.rbr_reparam.bias.data = bias
        for para in self.parameters():
            para.detach_()
        self.__delattr__('rbr_dense')
        self.__delattr__('rbr_1x1')
        if hasattr(self, 'rbr_identity'):
            self.__delattr__('rbr_identity')
        if hasattr(self, 'id_tensor'):
            self.__delattr__('id_tensor')
        self.deploy = True

DAMO-YOLO的Neck( Efficient RepGFPN)详解

 RepConv的特点是结构重参数化,训练时采用三条分支,推理时将三个分支融合在一起,大大减少了推理时间(建议看看RepVGG的讲解视频),我图画得太丑了

DAMO-YOLO的Neck( Efficient RepGFPN)详解

  RepConv采用的两分支的结构(a)

DAMO-YOLO的Neck( Efficient RepGFPN)详解

DAMO-YOLO的Neck( Efficient RepGFPN)详解

 其他细节有缘再更,代码不难,慢慢看完全能懂。有写的不对的地方请见谅文章来源地址https://www.toymoban.com/news/detail-442329.html

到了这里,关于DAMO-YOLO的Neck( Efficient RepGFPN)详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • YOLO Air:YOLO科研改进论文推荐 | 改进组合上千种搭配,包括Backbone,Neck,Head,注意力机制,适用于YOLOv5、YOLOv7、YOLOX等算法

    🔥🔥🔥YOLOAir开源算法库!!! 💡统一使用 YOLOv5、YOLOv7 代码框架, 结合不同模块来构建不同的YOLO目标检测模型。 🌟本项目包含大量的改进方式,降低改进难度,改进点包含 【Backbone特征主干】 、 【Neck特征融合】 、 【Head检测头】 、 【注意力机制】 、 【IoU损失函数】

    2024年02月01日
    浏览(39)
  • 【YOLOv5】Backbone、Neck、Head各模块详解

    Yolov5是一种目标检测算法,采用基于Anchor的检测方式,属于单阶段目标检测方法。相比于Yolov4,Yolov5有着更快的速度和更高的精度,是目前业界领先的目标检测算法之一。 Yolov5基于目标检测算法中的one-stage方法,其主要思路是将整张图像划分为若干个网格,每个网格预测出该

    2024年02月03日
    浏览(26)
  • CSDN独家首发!万字长文,YOLOv5/v7/v8算法模型yaml文件史上最详细解析与教程!小白也能看懂!掌握了这个就掌握了魔改YOLO的核心!

    看完这篇你能学会什么? 掌握根据 yaml 文件画出模型结构图的能力 掌握根据模型结构图写 yaml 文件的能力 掌握添加模块后写配置文件 args 参数的能力 掌握修改模型配置文件的能力 模型 尺寸 (像素) mAP val 50-95 mAP val 50 推理速度 CPU b1 (ms) 推理速度 V100 b1 (ms) 速度 V10

    2024年02月02日
    浏览(39)
  • 这个 归并排序详解过程 我能吹一辈子!!!

    1945年,约翰·冯·诺依曼(John von Neumann)发明了归并排序,这是典型的分治算法的应用。 归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使

    2024年02月05日
    浏览(22)
  • YOLO V3详解(二):输出介绍

    YOLO V3详解(一):网络结构介绍 YOLO V3详解(二):输出介绍 YOLO V3详解(三):损失介绍 YOLO V3详解(四):进行目标检测 DarkNet53: YOLO v3中的Backbone 在学习Yolo v3时,不知道有没有小伙伴对它的输出感觉很疑惑。 以20类分类任务为例:为什么输出的是13*13*75、26*26*75以及52*52*75的。这些最

    2024年02月16日
    浏览(23)
  • 【目标检测】YOLO系列——YOLOv1详解

    本篇是关于目标检测算法YOLOv1的学习笔记。网上的博客大多是摘抄翻译论文中的重点内容加上自己的理解,或者是梳理论文的大致思路,在没看过原文的情况下可能总会有些看不懂的地方。所以强烈建议博客搭配原文食用。 原文链接:You Only Look Once: Unified, Real-Time Object Dete

    2024年02月05日
    浏览(33)
  • 如何配置静态路由?这个实例详解交换机的静态路由配置

    静态路由 是一种 路由的方式 ,它需要通过 手动配置。 静态路由与动态路由不同, 静态路由是固定的,不会改变。 一般来说,静态路由是由网络管理员逐项加入路由表,简单来说,就是需要手动添加的。 问:手动添加有什么好处呢? 答:稳定,可靠 静态路由在交换机中有

    2024年02月04日
    浏览(46)
  • 【1】从零开始学习目标检测:YOLO算法详解

    在过去的十年中,深度学习技术的发展引起了极大的关注,并成为人工智能领域中不可或缺的技术之一。深度学习在计算机视觉领域的应用越来越广泛,其中目标检测是备受关注的领域之一。目标检测是指在图像或视频中检测出目标的位置和边界框,然后对目标进行分类或识

    2023年04月15日
    浏览(31)
  • YOLO学习笔记(2):YOLOV1算法详解

    SAY YOU ONLY LOOK ONCE AGAIN!!! SAY YOU ONLY LOOK ONCE AGAIN!!! SAY YOU ONLY LOOK ONCE AGAIN!!! 本文章主要参考up主同济子豪兄的视频的基础上整理的笔记,建议读者务必观看原视频,受益匪浅 注:在文章中大量使用,所以注解较为全面,可以在阅读文章前只大致浏览,在正文部分不断回顾

    2024年04月22日
    浏览(25)
  • 【YOLO系列】YOLOv5超详细解读(网络详解)

    吼吼!终于来到了YOLOv5啦! 首先,一个热知识:YOLOv5没有发表正式论文哦~ 为什么呢?可能YOLOv5项目的作者Glenn Jocher还在吃帽子吧,hh 前言 一、YOLOv5的网络结构  二、输入端 (1)Mosaic数据增强 (2)自适应锚框计算 (3)自适应图片缩放 三、Backbone (1)Focus结构 (2)CSP结构

    2023年04月09日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包