往期回顾:YOLOv5源码解读1.0-目录_汉卿HanQ的博客-CSDN博客
前面学习了detect train test三个部分的源码,接下来就是对yolov5的网络进行学习。网络结构包括yolo.py和common.py,在具体学习网络结构。yolov5中网络结构采用yaml配置文件,yolov5配置了4种模型,这篇我们以yolov5s.yaml为例来介绍其网络结构 。
目录
1.yaml
2.参数
3.anchor配置
4.backbone
5.head
6.整体代码
# ----------------------------------1.yaml----------------------------------
#yaml是一种专门些配置文件得标记语言,类似JSON XML等数据序列化语言
#与其不同得是,yaml以数据为中心而不是标记为中心
#yaml包括 yaml数据定义 和 如何被调用
# ----------------------------------2.参数----------------------------------
# Parameters
nc: 2 # 数据集类别个数 如person+car=2
depth_multiple: 0.33 # 模型层数因子。控制模型深度 可以起到动态调整模型得作用
width_multiple: 0.50 # 模型通道因子,控制Conv中得channel数 可以起到动态调节模型宽度得作用
# ----------------------------------3.anchor配置----------------------------------
#
# v5使用k-means聚类 选择三个scale 每个scale选择3个聚类 共选择9个anchor
# 这9个anchor在特征金字塔中使用,每个feature map得每个grid_cell都有三个anchor进行预测
#
# 特征图 13*13 26*26 52*52
# 感受野 大 中 小
# 分辨率 大 中 小
# 下采样 大 中 小
# 适合预测 大物体 中 小物体
# anchor (116*30)(156* 198)(373*326) (30*31)(32*45)(59*119) (10*13)(16*30)(32*23)
anchors: # 9个anchor
- [10,13, 16,30, 33,23] # P3/8 FPN接主干网络下采样8倍后的anchor大小 检测小目标
- [30,61, 62,45, 59,119] # P4/16 FPN接主干网络下采样4倍后的anchor大小 检测中目标
- [116,90, 156,198, 373,326] # P5/32 FPN接主干网络下采样2倍后的anchor大小 检测大目标
# ---------
# ----------------------------------4.backbone----------------------------------
# YOLOv5 v6.0 backbone
backbone:
# [from, number, module, args]
# from 模块的输入来自哪一层的输出 -1代表上一层
# number 当前模块重复次数,和depth_multiple共同决定模型深度
# module 模块名称
# args 初始化参数
[[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2 0层 输入原始图像 模型数=1 模型名Conv [channel=64,kernel_size=6,padding=2,stride=2] 若初始640*640*3 此层输出为320*320*64
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4 1层 输入是上一次输出 模型数=1 模型名Conv [channel=128,kernel_size=3,stride=2] 160*160*128
[-1, 3, C3, [128]], # 2层 输入是上一次输出 模型数=3 模型名C3 [channel=128] 160*160*128
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8 3层 输入是上一次输出 模型数=1 模型名Conv [channel=256,kernel_size=3,stride=2] 80*80*256
[-1, 6, C3, [256]],#-P3 4层 输入是上一次输出 模型数=3 模型名C3 [channel=256] 80*80*256
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16 5层 输入是上一次输出 模型数=1 模型名Conv [channel=512,kernel_size=3,stride=2] 40*40*512
[-1, 9, C3, [512]],#-P4 6层 输入是上一次输出 模型数=3 模型名C3 [channel=512] 40*40*512
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32 7层 输入是上一次输出 模型数=1 模型名Conv [channel=1024,kernel_size=3,stride=2] 20*20*1024
[-1, 3, C3, [1024]],#P5 8层 输入是上一次输出 模型数=3 模型名C3 [channel=1024] 20*20*1024
[-1, 1, SPPF, [1024, 5]], # SSPF层 输入是上一次输出 模型数=1 模型名SSPF [channel=1024,kernel_size=5] 本层对不同尺度特征图进行融合 20*20*1024
# 到这里 backbone会有4 6 9层三个输出 80*80*256 40*40*512 20*20*1024
]
# ----------------------------------5.head----------------------------------
# YOLOv5 v6.0 head
head:
# ----------------------------------4.1 上concat----------------------------------
[[-1, 1, Conv, [512, 1, 1]], # 10层 输入是上一次输出 模型数=1 模型名Conv [channel=512,kernel_size=1,stride=1] 20*20*512
[-1, 1, nn.Upsample, [None, 2, 'nearest']], # 11层 输入是上一次输出 模型数=1 模型名 nn.Upsample [size(尺寸)=None,scale_factor(输入尺寸倍数)=2,model='nearest'(默认是nearest)] 此层不改变通道数 但特征图长宽增加一倍 40*40*512
[[-1, 6], 1, Concat, [1]], # cat backbone P4 12层 输入是上一次输出和第6层(P4 40*40*512) 模型数=1 模型名Concat [拼接维度=1] 该层与6层特征图融合40*40*1024
[-1, 3, C3, [512, False]], # 13层 输入是上一次输出 模型数=3 模型名C3 [channel=512,没有残差模块] 40*40*512
[-1, 1, Conv, [256, 1, 1]],# 14层 输入是上一次输出 模型数=1 模型名Conv [channel=256,kernel_size=1,stride=1] 40*40*256
[-1, 1, nn.Upsample, [None, 2, 'nearest']],# 15 输入是上一次输出 模型数=1 模型名nn.Upsample [size(尺寸)=None,scale_factor(输入尺寸倍数)=2,model='nearest'(默认是nearest)] 此层不改变通道数 但特征图长宽增加一倍 80*80*256
[[-1, 4], 1, Concat, [1]], # cat backbone P3 16层 输入是上一次输出和第4层(P3 80*80*256) 模型数=1 模型名Concat [拼接维度=1] 该层与4层特征图融合80*80*512
[-1, 3, C3, [256, False]], # 17 (P3/8-small) 17层 输入是上一次输出 模型数=3 模型名C3 [channel=512,没有残差模块] 80*80*256
# ----------------------------------4.2b下connect----------------------------------
[-1, 1, Conv, [256, 3, 2]], # 18层 输入是上一次输出 模型数=1 模型名Conv [channel=512,kernel_size=3,stride=2] 40*40*256
[[-1, 14], 1, Concat, [1]], # cat head P4 19层 输入是上一次输出和第14层(40*40*256) 模型数=1 模型名Concat [拼接维度=1] 该层与6层特征图融合40*40*512
[-1, 3, C3, [512, False]], # 20 (P4/16-medium) 20层 输入是上一次输出 模型数=3 模型名C3 [channel=512,没有残差模块] 40*40*512
[-1, 1, Conv, [512, 3, 2]], # 21 输入是上一次输出 模型数=1 模型名Conv [channel=512,kernel_size=3,stride=2] 20*20*512
[[-1, 10], 1, Concat, [1]], # cat head P5 输入是上一次输出和第10层(20*20*512) 模型数=1 模型名Concat [拼接维度=1] 该层与6层特征图融合20*20*1024
[-1, 3, C3, [1024, False]], # 23 (P5/32-large) 23层 输入是上一次输出 模型数=3 模型名C3 [channel=1024,没有残差模块] 20*20*1024
# ----------------------------------4.3 检测层----------------------------------
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) 输入是17 20 23层 模块数=1 模块名Detect [nc为参数个数,anchors超参数anchors值] 20*10*1024
]
# YOLOv5 by Ultralytics, GPL-3.0 license
# ----------------------------------1.yaml----------------------------------
#yaml是一种专门些配置文件得标记语言,类似JSON XML等数据序列化语言
#与其不同得是,yaml以数据为中心而不是标记为中心
#yaml包括 yaml数据定义 和 如何被调用
# ----------------------------------2.参数----------------------------------
# Parameters
nc: 2 # 数据集类别个数 如person+car=2
depth_multiple: 0.33 # 模型层数因子。控制模型深度 可以起到动态调整模型得作用
width_multiple: 0.50 # 模型通道因子,控制Conv中得channel数 可以起到动态调节模型宽度得作用
# ----------------------------------3.anchor配置----------------------------------
#
# v5使用k-means聚类 选择三个scale 每个scale选择3个聚类 共选择9个anchor
# 这9个anchor在特征金字塔中使用,每个feature map得每个grid_cell都有三个anchor进行预测
#
# 特征图 13*13 26*26 52*52
# 感受野 大 中 小
# 分辨率 大 中 小
# 下采样 大 中 小
# 适合预测 大物体 中 小物体
# anchor (116*30)(156* 198)(373*326) (30*31)(32*45)(59*119) (10*13)(16*30)(32*23)
anchors: # 9个anchor
- [10,13, 16,30, 33,23] # P3/8 FPN接主干网络下采样8倍后的anchor大小 检测小目标
- [30,61, 62,45, 59,119] # P4/16 FPN接主干网络下采样4倍后的anchor大小 检测中目标
- [116,90, 156,198, 373,326] # P5/32 FPN接主干网络下采样2倍后的anchor大小 检测大目标
# ----------------------------------4.backbone----------------------------------
# YOLOv5 v6.0 backbone
backbone:
# [from, number, module, args]
# from 模块的输入来自哪一层的输出 -1代表上一层
# number 当前模块重复次数,和depth_multiple共同决定模型深度
# module 模块名称
# args 初始化参数
[[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2 0层 输入原始图像 模型数=1 模型名Conv [channel=64,kernel_size=6,padding=2,stride=2] 若初始640*640*3 此层输出为320*320*64
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4 1层 输入是上一次输出 模型数=1 模型名Conv [channel=128,kernel_size=3,stride=2] 160*160*128
[-1, 3, C3, [128]], # 2层 输入是上一次输出 模型数=3 模型名C3 [channel=128] 160*160*128
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8 3层 输入是上一次输出 模型数=1 模型名Conv [channel=256,kernel_size=3,stride=2] 80*80*256
[-1, 6, C3, [256]],#-P3 4层 输入是上一次输出 模型数=3 模型名C3 [channel=256] 80*80*256
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16 5层 输入是上一次输出 模型数=1 模型名Conv [channel=512,kernel_size=3,stride=2] 40*40*512
[-1, 9, C3, [512]],#-P4 6层 输入是上一次输出 模型数=3 模型名C3 [channel=512] 40*40*512
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32 7层 输入是上一次输出 模型数=1 模型名Conv [channel=1024,kernel_size=3,stride=2] 20*20*1024
[-1, 3, C3, [1024]],#P5 8层 输入是上一次输出 模型数=3 模型名C3 [channel=1024] 20*20*1024
[-1, 1, SPPF, [1024, 5]], # SSPF层 输入是上一次输出 模型数=1 模型名SSPF [channel=1024,kernel_size=5] 本层对不同尺度特征图进行融合 20*20*1024
# 到这里 backbone会有4 6 9层三个输出 80*80*256 40*40*512 20*20*1024
]
# ----------------------------------5.head----------------------------------
# YOLOv5 v6.0 head
head:
# ----------------------------------4.1 上concat----------------------------------
[[-1, 1, Conv, [512, 1, 1]], # 10层 输入是上一次输出 模型数=1 模型名Conv [channel=512,kernel_size=1,stride=1] 20*20*512
[-1, 1, nn.Upsample, [None, 2, 'nearest']], # 11层 输入是上一次输出 模型数=1 模型名 nn.Upsample [size(尺寸)=None,scale_factor(输入尺寸倍数)=2,model='nearest'(默认是nearest)] 此层不改变通道数 但特征图长宽增加一倍 40*40*512
[[-1, 6], 1, Concat, [1]], # cat backbone P4 12层 输入是上一次输出和第6层(P4 40*40*512) 模型数=1 模型名Concat [拼接维度=1] 该层与6层特征图融合40*40*1024
[-1, 3, C3, [512, False]], # 13层 输入是上一次输出 模型数=3 模型名C3 [channel=512,没有残差模块] 40*40*512
[-1, 1, Conv, [256, 1, 1]],# 14层 输入是上一次输出 模型数=1 模型名Conv [channel=256,kernel_size=1,stride=1] 40*40*256
[-1, 1, nn.Upsample, [None, 2, 'nearest']],# 15 输入是上一次输出 模型数=1 模型名nn.Upsample [size(尺寸)=None,scale_factor(输入尺寸倍数)=2,model='nearest'(默认是nearest)] 此层不改变通道数 但特征图长宽增加一倍 80*80*256
[[-1, 4], 1, Concat, [1]], # cat backbone P3 16层 输入是上一次输出和第4层(P3 80*80*256) 模型数=1 模型名Concat [拼接维度=1] 该层与4层特征图融合80*80*512
[-1, 3, C3, [256, False]], # 17 (P3/8-small) 17层 输入是上一次输出 模型数=3 模型名C3 [channel=512,没有残差模块] 80*80*256
# ----------------------------------4.2b下connect----------------------------------
[-1, 1, Conv, [256, 3, 2]], # 18层 输入是上一次输出 模型数=1 模型名Conv [channel=512,kernel_size=3,stride=2] 40*40*256
[[-1, 14], 1, Concat, [1]], # cat head P4 19层 输入是上一次输出和第14层(40*40*256) 模型数=1 模型名Concat [拼接维度=1] 该层与6层特征图融合40*40*512
[-1, 3, C3, [512, False]], # 20 (P4/16-medium) 20层 输入是上一次输出 模型数=3 模型名C3 [channel=512,没有残差模块] 40*40*512
[-1, 1, Conv, [512, 3, 2]], # 21 输入是上一次输出 模型数=1 模型名Conv [channel=512,kernel_size=3,stride=2] 20*20*512
[[-1, 10], 1, Concat, [1]], # cat head P5 输入是上一次输出和第10层(20*20*512) 模型数=1 模型名Concat [拼接维度=1] 该层与6层特征图融合20*20*1024
[-1, 3, C3, [1024, False]], # 23 (P5/32-large) 23层 输入是上一次输出 模型数=3 模型名C3 [channel=1024,没有残差模块] 20*20*1024
# ----------------------------------4.3 检测层----------------------------------
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) 输入是17 20 23层 模块数=1 模块名Detect [nc为参数个数,anchors超参数anchors值] 20*10*1024
]
这便是v5s的网络结构,在后面yolo.py和common.py中都会看到
图片来自 【YOLO系列】YOLOv5、YOLOX、YOOv6、YOLOv7网络模型结构_yolov5模型结构图_DearAlbert的博客-CSDN博客
结合图片更容易理解网络结构