目录
单阶段检测器网络的架构一般分为,图像输入模块,backbone主干网络,Neck颈部模块,检测头Dense Prediction检测模块。
在Yolov5中,作者没有单独给出Neck颈部模块, 而是打包一起放在了头部模块。
YOLOv5包括
. (主干网络)Backbone: Focus, BottleneckCSP,SPP
. (头部)Head: PANet + Detect (YOLOv3/v4 Head)
Backbone:主干网络,是用来提取特征的网络,其作用就是提取图片中的信息,以供后面的网络使用。
可视化:Netron
netron对pt格式的权重文件兼容性不好,直接使用netron工具打开,无法显示整个网络。
可使用YOLOv5代码中models/export.py脚本将pt权重文件转换为onnx格式,再用netron工具打开,就可以看YOLOv5网络的整体架构。
下面就来看一下代码:
一:yolo5s.yaml
1:param
# parameters
nc: 2 # number of classes所训练的类别数
depth_multiple: 0.33 # model depth multiple控制模型的深度(BottleneckCSP数)
width_multiple: 0.50 # layer channel multiple控制Conv通道个数(卷积核数量)
# depth_multiple表示BottleneckCSP模块的层缩放因子,
#yolov5s中设置为0.33,假设yolov5l中有三个Bottleneck,那yolov5s中就只有一个Bottleneck。
#将所有的Bo用来控制模型的深度(BottleneckCSP数), 在number≠1时启用;
#第一个C3层的参数设置为[-1, 3, C3, [128]],
#number=3表示含有1个C3(3*0.33)ttleneckCSP模块的Bottleneck乘上该参数得到最终个数。
# width_multiple表示卷积通道的缩放因子,
#就是将配置里面的backbone和head部分有关Conx通道的设置,全部乘以该系数。
#主要是用于设置arguments,作用于args中的ch_out;
#例如yolov5s设置为0.5,Focus就变成[32, 3],Conv就变成[64, 3, 2]。
#以此类推,卷积核的个数都变成了设置的一半。
#通过这两个参数就可以实现不同复杂度的模型设计。
这里需要注意的是这两个参数depth_multiple用于控制模型的深度(BottleneckCSP数),width_multiple用于控制conv通道个数 (卷积核数量)。只要牵涉到CSP操作和conv操作的时候就要用该参数,去乘上重复次数,已达到对模型深度的控制。
2:anchor先验框的配置
anchors:
- [10,13, 16,30, 33,23] # P3/8 8倍下采样的层面 [宽度,高度]
- [30,61, 62,45, 59,119] # P4/16 16倍下采样的层面
- [116,90, 156,198, 373,326] # P5/32 32倍下采样的层面
anchors其实就是在训练之前人为设定的先验框,网络输出结果的框就是在anchors的基础上进行调整的。所以说先验框设定的好坏对于模型的输出效果影响还是挺大的。
在YOLO网络里面,一张图片进入模型编码之后会输出三个feature map(特征层),分别用小特征层(20,20)、中特征层(40,40)和大特征层(80,80)来表示。(其中小特征层用于检测大物体,中特征层用于检测中等物体,大特征层用于检测小物体)anchors是在特征层上进行调整的,但最开始的anchors是相对于原图的,我们需要将anchors的大小以及物体的中心也对应到feature map上。我们可以从feature map上获取到物体中心以及框的宽高的偏移量offset_x, offset_y, offset_w, offset_h, 然后根据偏移量对先验框进行调整。
yolov5 中的 anchor,是由 wh 宽高组成,用的是原图的像素尺寸,表示数据样本中样本的大概形状,有三种大小的 anchor,而 featureMap 又分成了 3 个不同尺寸的通道,总共有 9 个不一样的 anchor。在分类前的最后一层 featureMap 中,每一个像素都有 3 个 anchor 负责识别,每个 anchor 负责一类的识别,通常这 3 个 anchor 都会被训练成识别同一类,所以实在不得不考虑一下只用一个 anchor 行不行。 使用 anchor 可以认为模型一开始就记住了数据样本的形状了,这样就能加快正负样本的学习,比如你的相机是 640 * 10 的像素 (比如),然后你用来拍一根长木棍和一台电视机,相机的拍摄尺寸正好能把木棍完全拍进去,而不能把一台电视机完全拍进去,除非隔得非常远,这样我们能够识别我们拍出来的木棍,但是拍出来的电视机因为只拍了一部分,所以识别错误的几率就大大增加了。
3:backbone
backbone:
# [from, number, module, args]
# from:当前模块输入来自哪一层,-1表示上一层输入,-2表示上两层输入
# number:本模块重复次数,1表示只有一个,3表示有3个相同的模块
# conv卷积层 C3:BottleneckCSP SPPF:SPP模块
#SPP、Conv、Bottleneck、BottleneckCSP的代码可以在 ./models/common.py中获取到。
[[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4 128表示有128个卷积核,3表示3×3的卷积核,
#2表示步长为2
[-1, 3, C3, [128]], # 这里的重复次数,要乘上一开始的缩放因子
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 6, C3, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 9, C3, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 3, C3, [1024]],
[-1, 1, SPPF, [1024, 5]], # 9
]
"""
[-1, 1, Conv, [64, 6, 2, 2]
input:3x640x640
[ch_out, kernel, stride, padding]=[64, 6, 2, 2]
新通道数为64x0.5=32
特征图计算公式: Feature_new = (Feature_old - kernel + 2 * padding) / stride + 1
新特征图尺寸为: Feature_new = (640 - 6 + 2 * 2) / 2 + 1 = 320
"""
4:head部分
# 作者没有区分neck模块, 所以里面包含了PANet + Detect部分
head:
[[-1, 1, Conv, [512, 1, 1]], # 卷积层
[-1, 1, nn.Upsample, [None, 2, 'nearest']], # 上采样
[[-1, 6], 1, Concat, [1]], # cat backbone P4 拼接层
[-1, 3, C3, [512, False]], # 13 这里的重复次数,要乘上一开始的缩放因子
[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 4], 1, Concat, [1]], # cat backbone P3
[-1, 3, C3, [256, False]], # 17 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, C3, [512, False]], # 20 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, C3, [1024, False]], # 23 (P5/32-large)
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]
*head检测头 **:一般表示的是经过主干网后输出的特征图,特征图输入head中进行检测,包括类别和位置的检测。
常用模块介绍:Yolo v5的改进思想 (qq.com)
1:focus:进行切片操作,一切四再拼接,减少计算量加快速度
2: CSP(跨阶段局部网络):加强网络特征融合能力,缓解以往工作需要从网络架构角度进行大量推理计算的问题。
【CSPNet】一种增强学习能力的跨阶段局部网络 - 知乎 (zhihu.com)
通过将基础层的特征图划分为两个部分,然后通过提出的跨阶段层次结构将它们合并
3:SPP:SPP模块(空间金字塔池化模块), 分别采用5、9、13的最大池化,再进行concat融合,提高感受野。
空间金字塔池化:无论CNN_Pre输出的feature maps尺寸是怎样,都能输出固定的维度传给CNN_Post。
4:Conv:(87条消息) 在卷积层的运用_Conv 卷积层_weixin_39588983的博客-CSDN博客
参考链接:带图讲解,深度学习YOLO里面的anchors的进阶理解-物联沃-IOTWORD物联网
[图像算法]-Yolov5代码解释(yolov5l.Yaml) - 简书 (jianshu.com)
(87条消息) Yolov5网络架构和组件_反正也没人看我的昵称的博客-CSDN博客_yolov5网络架构
(86条消息) YOLOv5 backbone(一)_小于同学饿了的博客-CSDN博客_yolov5 backbone