YOLOv7 Backbone| 原文源码详解

news2024/9/22 21:26:30
YOLOv7 Backbone结构详解

在之前的文章中,我们以YOLOv5为对象,详细解剖了一只麻雀的内部构造,包括anchor机制、backbone的结构、neck的结构和head的结构。在本篇文章中,我们将以YOLOv7v0.1版本的代码为目标,结合作者团队的YOLOv7原文,详细介绍一下其骨架网络的整体架构及各部分的实现原理,并结合网络配置文件yolov7.yaml以及common.py中网络组件进行细节剖析。

backbone整体架构

在这里插入图片描述

首先解读一下网络架构图。

1-P1/2;16-P3/8:这个是在画结构图过程中为了避免标错中间特征尺寸而做的标记。第一个数字代表当前模块的索引;Pn是表示当前模块下采样的次数,所以会看到有Pn出现的地方特征图尺寸就会改变;Pn之后的数字则是下采样的倍数

CBS:蓝色的CBS模块就是Conv+BatchNorm+SiLU的集成模块,主要负责进行特征提取。其参数主要是kernel尺寸和stride步长,kernel的尺寸不会影响输出特征图长宽的变化,因为在yolo中会使用autopid这个函数进行图像的自动填充( p = k / / 2 p=k//2 p=k//2);改变特征图大小的操作只有stride步长,具体而言 w o u t = w i n / s , h o u t = h i n / s w_out=w_in /s,h_out=h_in /s wout=win/s,hout=hin/s

ELAN1:YOLOv7的Backbone中特有的聚合网络,受DenseNet与ResNet启发而设计的模块,聚合过程中特征图的通道数和尺寸都不会发生改变。

MPConv:一种比较特别的池化结构,主要目的还是有效缩减特征图的尺寸,减少运算量和参数量,加快计算速度并防止过拟合。

总体来说,YOLOv7的backbone整体网络架构与v5的差别还是挺大的(集成度越来越高,同时也越来越麻烦,小白读起来越来越费劲),所以咱们还是按照老套路,将其中的模块拆解开来步步为营。

CBS:主要的特征提取模块

其实一个大厦无论多么辉煌瑰丽,都需要使用水泥和砖头一点一点堆砌,而CBS模块就是YOLOv7的水泥和砖头了,这里我直接把YOLOv5中对CBS的解释搬过来,并更新一些新的观点。

在这里插入图片描述

Conv

CBS模块其实没什么好稀奇的,就是Conv+BatchNorm+SiLU,这里着重讲一下Conv的参数,就当复习pytorch的卷积操作了,先上CBL源码:

class Conv(nn.Module):
    # Standard convolution
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        super().__init__()
        self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
        self.bn = nn.BatchNorm2d(c2)
        #其中nn.Identity()是网络中的占位符,并没有实际操作,在增减网络过程中,可以使得整个网络层数据不变,便于迁移权重数据;nn.SiLU()一种激活函数(S形加权线性单元)。
        self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())

    def forward(self, x):#正态分布型的前向传播
        return self.act(self.bn(self.conv(x)))

    def forward_fuse(self, x):#普通前向传播
        return self.act(self.conv(x))

由源码可知:Conv()包含7个参数,这些参数也是二维卷积Conv2d()中的重要参数。ch_in, ch_out, kernel, stride没什么好说的,展开说一下后三个参数:

autopad

从我现在看到的主流卷积操作来看,大多数的研究者不会通过kernel来改变特征图的尺寸,如googlenet中3x3的kernel设定了padding=1,所以当kernel≠1时需要对输入特征图进行填充。当指定p值时按照p值进行填充,当p值为默认时则通过autopad函数进行填充:

def autopad(k, p=None):  # kernel, padding
    # Pad to 'same'
    if p is None:
        p = k // 2 if isinstance(k, int) else [x // 2 for x in k]  # auto-pad
        #如果k是整数,p为k与2整除后向下取整;如果k是列表等,p对应的是列表中每个元素整除2。
    return p

这里作者考虑到对不同的卷积操作使用不同大小的卷积核时padding也需要做出改变,所以这里在为p赋值时会首先检查k是否为int,如果k为列表则对列表中的每个元素整除。

act

决定是否对特征图进行激活操作,SiLU表示使用Sigmoid进行激活。

ELAN:高效的网络聚合模块

这部分结构其实并不复杂,但是为了读者对这部分结构有更深刻的认识,我还是打算沿着YOLOv7的原文中的描述,对其进行系统地介绍,首先让我们来看看作者在论文中提出的聚合模块的演变历程。

ELAN PaperReading

在这里插入图片描述

VoVNet

VoVNet是2019年的文献中提出的一种方法,对比了当时主要的聚合网络结构DenseNet和ResNet,并提出DenseNet的聚合方式要优于ResNet的结论。因为 DenseNet 利用 concat的方式相比于 ResNet利用sum 的方式,能够使网络特征图获得多个感知域(尺度)内的信息,对于下游的检测、分割任务是极为有用的。

其实Concat也是现在使用比较广泛、作用机制清晰、实现方便的一种信息聚合方式,在single-stream的多模态模型结构中,大多数情况下都是直接concat image embedding和text embedding,反而要比单独处理文本图像信息效果要好,其更底层的原理之前在知乎一个回答下看到过,如果有时间整理一下,这里先占个坑。

但是在实际应用中呢,作者发现DenseNet并没有理论上说的那么efficient,作者总结有以下几点原因:

  • Densenet是一种稠密连接的结构,每一层计算都会用到之前的所有特征层,例如下图a所示,这会导致大量内存消耗,即memory access cost(MAC)
  • Densenet在concat的过程中会成倍增大channel数,为了减小计算量只能像ResNet的bottleblock一种,利用1x1的卷积先降维再计算,但是这种小的卷积核又不能很好的利用GPU进行并行计算

在这里插入图片描述

因此VoVNet中中提出了One-Shot Aggregation的方法,如上图b所示,亦如本节最开始的(a)VoVNet所示。

其实图注里已经写的很清楚了,就是只在每一个module的最后阶段进行特征聚合,这样既保留了DenseNet中concat的优势,又能够优化对GPU的利用方式,缓解了MAC的问题。

CSPVoVNet

再往后的PRN和CSPVoVNet等结构是从梯度优化的角度来考虑模型设计的,因为梯度得到优化之后,网络可以在更少参数量的基础上获得更稳定的表现。

CSP其实要基于PRN(short connection的过程中只选取部分channel,能够获得更丰富的梯度信息,取得更好的训练效果),PRN 证明了丰富的梯度对于训练更好的模型有帮助,以此推理,让所有的 channel 都接收不同的梯度信息能够让模型训练的最好,但是这样并不高效,因此兼顾性能要求,就进一步设计出 CSPNet:

在这里插入图片描述

CSPDenseNet 一方面可以和 DenseNet 一样可以获得更丰富的梯度信息,另一方面也通过 cross stage partial operation 操作避免了过多重复的梯度信息。

ELAN

ELAN这篇文章是今年6月份左右刚挂到arxiv上的,比较新,我主要看了一下作者第三章的分析部分,谈一下自己的理解。

在这里插入图片描述

文章中首先指出DenseNet效果比ResNet好的原因就在于DenseNet使用的是相同时间戳下的不同梯度源,而非ResNet中相同时间戳下的相同输入源,并且认为文中提出的PRN结构相较于残差网络只选取部分通道进行残差链接,其实就相当于Dropout的机制(感兴趣的小伙伴可以看我之前写的dropout机制的那篇博客),也就增加了原始的梯度源信息,提高了网络的泛化性

其次,CSPNet仅使用了简单的通道分割、跨阶段连接和少量额外的过渡层,在不改变原有网络计算单元的情况下,成功地完成了预定的目标。也就是说,CSPNet通过channel split的手段,一方面增加了梯度源的信息,另一方面又减少了计算量,一举两得。

最后就是属于比较工程化的经验了:搭建网络使不仅要考虑最短的梯度路径,而且要保证每一层的最短梯度路径都能得到有效的训练。至于整个网络的最长梯度路径的长度,它将大于或等于任意一层的最长梯度路径的长度。因此,在实施网络级梯度路径设计策略时,需要考虑网络中所有层的最长最短梯度路径长度,以及整个网络的最长梯度路径长度。

ELAN CodeReading

说了这么多,其实最主要的一点就是ELAN这样的结构能够提升整个网络的鲁棒性、能够减少网络的参数量加速计算过程,所以ELAN用在这里最主要的一点是因为它足够高效,下面再看一下ELAN的代码实现,首先看一下ELAN的网络结构。

在这里插入图片描述

这个网络结构其实跟论文中的©ELAN含义是相同的,只不过画法不同而已,结合下面的ELAN网络配置进行解读:

# ELAN1
[-1, 1, Conv, [64, 1, 1]],# -6
[-2, 1, Conv, [64, 1, 1]],# -5
[-1, 1, Conv, [64, 3, 1]],
[-1, 1, Conv, [64, 3, 1]],# -3
[-1, 1, Conv, [64, 3, 1]],
[-1, 1, Conv, [64, 3, 1]],# -1
[[-1, -3, -5, -6], 1, Concat, [1]],
[-1, 1, Conv, [256, 1, 1]],  # 11

首先看Concat这部分,可以确定最后是有4个特征图进行拼接的,其输入来源分别是从concat往前数第一个(-1)一直到从concat往前数第六个(-6),这部分参数如果不理解可以去YOLOv5Backbone详解看一下。确定了concat的特征图来源,再看其特征图尺寸。虽然这些特征图的kernel size不都相同,但是根据yolo的autopad机制,可以确定其特征图输出都跟输入的尺寸相同(只有s改变特征图尺寸),所以这里其实就是作不同深度不同语义上的信息融合,融合之后只有通道数变为原来四倍(64->256),也就是ELAN之前的128通道变成了ELAN模块之后的256通道。**结论:ELAN不改变图像的尺寸,只会将channel数double。**这部分看起来挺麻烦,但是讲代码的话其实没那么难理解,几句话就说完了。

MPConv

先贴一下模块的网络结构图:

在这里插入图片描述

再贴一下模块的网络配置:

# MPConv
[-1, 1, MP, []],# maxpooling:k=2 s=2
[-1, 1, Conv, [128, 1, 1]],
[-3, 1, Conv, [128, 1, 1]],
[-1, 1, Conv, [128, 3, 2]],
[[-1, -3], 1, Concat, [1]],  # 16-P3/8

还是先看concat,按图索骥,找到concat的两个输入,得出结论:MPConv模块不改变输入尺寸,只会增加channel数目,将其double

先写到这,等以后想起什么来再补充。

[1] Lee Y, Hwang J, Lee S, et al. An energy and GPU-computation efficient backbone network for real-time object detection[C]//Proceedings of the IEEE/CVF conference on computer vision and pattern recognition workshops. 2019: 0-0.

[2]He K, Zhang X, Ren S, et al. Deep residual learning for image recognition[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2016: 770-778.

[3]Huang G, Liu Z, Van Der Maaten L, et al. Densely connected convolutional networks[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2017: 4700-4708.

[4]Wang C Y, Mark Liao H Y, Chen P Y, et al. Enriching variety of layer-wise learning information by gradient combination[C]//Proceedings of the IEEE/CVF International Conference on Computer Vision Workshops. 2019: 0-0.

[5]Wang C Y, Liao H Y M, Wu Y H, et al. CSPNet: A new backbone that can enhance learning capability of CNN[C]//Proceedings of the IEEE/CVF conference on computer vision and pattern recognition workshops. 2020: 390-391.

[6]Wang C Y, Liao H Y M, Yeh I H. Designing Network Design Strategies Through Gradient Path Analysis[J]. arXiv preprint arXiv:2211.04800, 2022.

[7] https://blog.csdn.net/weixin_43427721/article/details/123613944?spm=1001.2014.3001.5501

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/67700.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

骨骼动画——2D Animation

1、2D骨骼动画 传统的序列帧动画为了达到好的动画效果,理论上来说,图片越多,动作越流畅,往往需要较多的美术资源,虽然效果好但是资源占用较多 而2D骨骼动画是利用3D骨骼动画的制作原理进行制作的,将一张2…

借助 ChatGPT 编写的 libbpf eBPF 工具开发实践教程: 通过例子学习 eBPF

这是一个基于 CO-RE(一次编译,到处运行)的 libbpf 的 eBPF 的开发教程,提供了从入门到进阶的 eBPF 开发实践指南,包括基本概念、代码实例、实际应用等内容。我们主要提供了一些 eBPF 工具的案例,帮助开发者…

大学免费查题接口

大学免费查题接口 本平台优点: 多题库查题、独立后台、响应速度快、全网平台可查、功能最全! 1.想要给自己的公众号获得查题接口,只需要两步! 2.题库: 查题校园题库:查题校园题库后台(点击跳…

设计模式-day02

4,创建型模式 4.2 工厂模式 4.2.1 概述 需求:设计一个咖啡店点餐系统。 设计一个咖啡类(Coffee),并定义其两个子类(美式咖啡【AmericanCoffee】和拿铁咖啡【LatteCoffee】);再设…

蓝牙学习六(GATT)

1.简介 GATT-Generic Attribute profle-通用属性配置文件。GATT层是传输真正数据所在的层。包括了一个数据传输和存储架构以及其基本操作。GATT用来规范attribute中的数据内容,并运用group(分组)的概念对attribute进行分类管理。没有GATT&…

查题接口系统

查题接口系统 本平台优点: 多题库查题、独立后台、响应速度快、全网平台可查、功能最全! 1.想要给自己的公众号获得查题接口,只需要两步! 2.题库: 题库:题库后台(点击跳转) 题库…

Bootstrap-jqgrid学习(十六)

jqgrid网站地址: jqGrid demos-jqGrid实例-中文-mn886.nethttps://blog.mn886.net/jqGrid/ 表格属性 分页属性: pagerstring定义翻页用的导航栏,必须是有效的html元素。翻页工具栏可以放置在html页面任意位置 显示总条数 viewrecordsbo…

#分支语句详解

第一章 C语言:分支语句 文章目录第一章 C语言:分支语句前言1、什么是语句?2.分支语句(选择结构)2.1 if语句2.1.1 悬空else2.1.2 if书写形式的对比2.2 switch语句2.2.1 在switch语句中的 break2.2.2 default子句2.2.3 练…

基于频谱的GCN的数学原理

参考链接:如何理解GCN?知乎回答:从热传导模型到GCN从CNN到GCN的联系与区别——GCN从入门到精(fang)通(qi) GCN问题本质 图中的每个结点无时无刻不因为邻居和更远的点的影响,而在改…

基于linux的操作系统的通用启动流程(一)

这篇我们讲解linux的通用启动流程,按照我们一贯的方式总分总的节奏,因为后面的每个子系统也很大,所以我们讲解子系统的时候也是按照总分总的方式。注意因为基于linux的各式各样的操作系统绝对不下100个,像嵌入式,然后我们的桌面有fedora,redhat,centos,debian,ubuntu以…

如何定位线上CPU占用过高的问题

系列文章目录 文章目录系列文章目录前言一、定位CPU的流程是什么?二、实操1.测试代码样例2.定位问题实践过程总结前言 一、定位CPU的流程是什么? 项目上线,CPU飙高不下,触发报警,如何定位排查问题。有两种办法1、通过…

JVM内存布局及GC原理

“java的内存布局以及GC原理”是java开发人员绕不开的话题,也是面试中常见的高频问题之一。 java发展历史上出现过很多垃圾回收器,各有各的适应场景,很多网上的旧文章已经跟不上最新的变化。本文详细介绍了java的内存布局以及各种垃圾回收器的…

著名运动员刘诗雯从政,迎来人生高光时刻,张继科还般配吗

曾经有这么一句话:中国男足谁都踢不过,中国乒乓球谁都打不过。也间接地说明了国球队伍人才济济。在众多优秀乒乓球队员当中,刘诗雯最近相当耀眼,听说她已经高升当官了,也和张继科拉开了距离。 据悉,公元202…

Java高效率复习-数据类型和运算符[Java]

第一篇关于JavaSE内容的文章 文章的风格比较涣散,但是都是干货,关于Java系列的,还有就是,我认为只有MySQL基础和JavaSE基础是可以做到可操作性和可执行性较强的。 如果像JavaWeb或者SSM框架这些,光看文章你是根本执行…

tensorflow的GPU加速计算

参考 tensorflow的GPU加速计算 - 云社区 - 腾讯云 一、概述 tensorflow程序可以通过tf.device函数来指定运行每一个操作的设备,这个设备可以是本地的CPU或者GPU,也可以是某一台远程的服务器。tensorflow会给每一个可用的设备一个名称,tf.…

PaO2/FiO2在临床中的应用 氧合指数

主任提问:患者呼吸衰竭时的“氧合指数”大约多少?如何计算?_腾讯新闻 (qq.com) 在 ARDS 柏林定义中,诊断低氧血症需要 PaO2/FiO2≤ 300 mmHg,并可以分为轻中重三个等级(下表)。 ARDS 患者的 PaO2/FiO2越低,死亡率越高,其中重度 ARDS 死亡率高达 45%。需要注意这里 …

生产报工管理系统可以帮助企业解决哪些问题?

随着时代的变迁和信息化技术的发展,市场对制造企业在产品价格、质量以及生产成本等方面提出了更高的要求,车间生产也逐渐向着实时化、透明化和可视化方向发展。其中产报工与跟踪是生产管理中重要的环节,自然是不可缺少信息化的。 企业在报工…

Linux基本命令

目录操作 格式:指令 -[参数] [目录] 1. pwd (Print Working Direcotry) 查看当前工作路径 2. cd (Change Direcotry) 改变 shell 工作目录 3. ls (List Files) 列出当前目录下的文件和目录 ls -[参数] [目录] ls的参数均是短命令,可以使用-后添…

经过物联网技术的设备改造有“大脑”,更智能

物联网是通讯网与互联网的拓展应用和网络延伸,通过网络传输互联,进行计算、处理和知识挖掘,实现人与物、物与物的信息交互和无缝链接,达到对物理世界的实时控制、精确管理和科学决策是目的。而物联网设备是一种非标准计算设备&…

【微信小程序】使用npm并引入vant-weapp组件库

0 前言 vant文档与微信小程序文档写得弯弯绕绕,你引用我,我引用你,还给出了多种不同情况下的选项,甚至有步骤缺失,导致踩了一点小坑,浪费了一些没必要的时间,这里给出完整可行的实现方法&#…