课程链接
网络可视化工具:netron
在线版本:https://lutzroeder.github.io/netron/
netron对pt格式的权重文件兼容性不好,直接使用netron工具打开,无法显示整个网络。
可使用YOLOv5代码中models/export.py脚本将pt权重文件转换为onnx格式,再用netron工具打开,就可以看到YOLOv5网络的整体架构。
# 导出onnx文件
pip install onnx>=1.7.1 -i https://pypi.tuna.tsinghua.edu.cn/simple # for ONNX export
pip install coremltools==4.0 -i https://pypi.tuna.tsinghua.edu.cn/simple # for CoreML export
python models/export.py --weights weights/yolov5s.pt --img 640 --batch 1
?yolov5s.yaml解析
# yaml 文件读取
import yaml # for torch hub
from pathlib import Path
cfg='yolov5-3.1/models/yolov5s.yaml'
yaml_file = Path(cfg).name # yolov5s.yaml
with open(cfg) as f:
yaml = yaml.load(f, Loader=yaml.SafeLoader) # model dict
ch = 3
print(yaml.get('ch', ch)) # dict 的get 方法, 没有'ch',则返回 ch
'''
yaml.load() 后的结果为 dict, Loader 参数是为了停止得到警告。其中 get 为字典的 get 方法, Path 是 python 中用于简化路径的一个模块。
'''
# yolov5s.yaml
# Parameters
nc: 80 # number of classes COCO数据集上的类别数
# 以下两个参数为缩放因子,通过这两个参数就可以实现不同复杂度的模型设计
depth_multiple: 0.33 # model depth multiple 控制模型的深度(即控制BottleneckCSP的数目)[控制网络深度]
width_multiple: 0.50 # layer channel multiple 控制Conv通道个数(卷积核数量)[控制网络宽度]
# depth_multiple表示BottleneckCSP模块层的缩放因子,将所有的BottleneckCSP模块的Bottleneck乘上该参数得到最终个数
# width_multiple表示卷积通道的缩放因子,就是将配置里面的backbone和head部分有关Conv通道的设置,全部乘以该系数
# anchors 先验框的配置
anchors:
- [10,13, 16,30, 33,23] # P3/8 第一个先验框宽为10,高为13
- [30,61, 62,45, 59,119] # P4/16 P4即stride=16(经过了16倍的下采样以后尺度上的anchor的大小)
- [116,90, 156,198, 373,326] # P5/32
# YOLOv5 backbone
backbone:
# [from, number, module, args]
# [from, number, module, args]
# from 列参数:当前模块输入来自哪一层输出; -1表示来自上一层的输出。
# number 列参数:本模块重复的次数;1表示只有一个,3表示有三个相同的模块,实际的重复次数还要由参数depth_multiple共同决定,以此决定网络模型的深度。
# model 列参数:模块类名,使用eval函数,通过这个类名去common.py中寻找相应的类,进行模块化的搭建网络。
# args:args是一个list,模块搭建所需参数,channel,kernel_size,stride,padding,bias等,其在网络搭建过程中会根据不同层进行改变。
[[-1, 1, Focus, [64, 3]], # 0-P1/2, 第0层
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4 128表示128个卷积核,3表示3×3的卷积核,2表示步长为2,width_multiple: 0.50,128×0.5=64
[-1, 3, BottleneckCSP, [128]], # depth_multiple: 0.33,3×0.33≈1
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 9, BottleneckCSP, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 9, BottleneckCSP, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 1, SPP, [1024, [5, 9, 13]]],
[-1, 3, BottleneckCSP, [1024, False]], # 9
]
# YOLOv5 head
# 作者未区分neck模块,所以head部分包含了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, BottleneckCSP, [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, BottleneckCSP, [256, False]], # 17 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, BottleneckCSP, [512, False]], # 20 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, BottleneckCSP, [1024, False]], # 23 (P5/32-large)
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]
self.model, self.save = parse_model(deepcopy(self.yaml), ch=[ch]) # model, savelist
'''
上述调用的是 deepcopy, self.yaml 是一个字典,所以是可变对象。
不可变对象:
对于浅拷贝和深拷贝, 两者效果是一样的。
可变对象:
“=”拷贝的方式, 只是拷贝了内存中的地址引用, 两个对象的地址引用一样, 即两个对象的值会随着一方的修改而修改。
对于deepcopy()来说, 拷贝内容后新对象的内存地址也会重新分配, 跟原来的内存地址不一样, 即两者任意修改变量的内容不会对另一方造成影响。
'''
YOLOv5 Architecture Made by BAI Yong
灵活配置不同复杂度的模型
YOLOv5s YOLOv5m YOLOv5l YOLOv5x depth_multiple 0.33 0.67 1.0 1.33 width_multiple 0.50 0.75 1.0 1.25 BottleneckCSP数
BCSPn(True)
1,3,3 2,6,6 3,9,9 4,12,12 BottleneckCSP数,BCSPn(False)
1 2 3 4 Conv卷积核数量 32,64,128,
256,512
48,96,192,
384,768
64,128,256,
512,1024
80,160,320,
640,1280
models/yolov5s.yaml
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
models/yolov5m.yaml
depth_multiple: 0.67
width_multiple: 0.75
models/yolov5l.yaml
depth_multiple: 1.0
width_multiple: 1.0
models/yolov5x.yaml
depth_multiple: 1.33
width_multiple: 1.25
YOLOv5的四种网络结构是depth_multiple和width_multiple两个参数,来进行控制网络的深度和宽度。其中depth_multiple控制网络的深度(BottleneckCSP数),width_multiple控制网络的宽度(卷积核数量)。
Focus
把数据切分为4份,每份数据都是相当于2倍下采样得到的,然后在channe维度进行拼接,最后进行卷积操作。
Focus() module is designed FLOPS reduction and speed increase, not mAP increase.
In YOLOv5 the author wants to reduce the cost of Conv2d computation and actually using tensor reshaping to reduce space(resolution) and increase the depth(number of channels).
Input will be transformed likes this [b, c, h, w]—>[b, c×4, h//2, w//2]
# 把宽度w和高度h的信息整合到c空间中
以YOLOv5s的结构为例,原始640×640×3的图像输入Focus结构,采用切片操作,先变成320×320×12的特征图,再经过一次32个卷积核的卷积操作,最终变成320×320×32的特征图。
CSPNet
CSP(Cross Stage Parital Network) 跨阶段局部网络
SPP(Spatial Pyramid Pooling) 空间金字塔池化
Add the SPP block over the CSP, since it significantly increase the receptive field, separates out the most significant context features and causes almost no reduction of the network operation speed.
PANet
Path-Aggregation Network 路径聚合网络
参考文章:
YOLOv5-5.0v-yaml 解析及模型构建(第二篇)_星魂非梦的博客-CSDN博客