1

YOLOv5全面解析教程①:网络结构逐行代码解析

 1 year ago
source link: https://blog.csdn.net/OneFlow_Official/article/details/128075629
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

YOLOv5全面解析教程①:网络结构逐行代码解析

本教程涉及到的代码在 https://github.com/Oneflow-Inc/one-yolov5,教程也同样适用于 ultralytics/yolov5 因为 one-yolov5 仅仅是换了一个运行时后端而已,计算逻辑和代码相比于 ultralytics/yolov5 没有做任何改变,欢迎 star 。详细信息请看One-YOLOv5 发布,一个训得更快的YOLOv5

YOLOv5 网络结构解析

YOLOv5针对不同大小(n, s, m, l, x)的网络整体架构都是一样的,只不过会在每个子模块中采用不同的深度和宽度,

分别应对yaml文件中的depth_multiple和width_multiple参数。

还需要注意一点,官方除了n, s, m, l, x版本外还有n6, s6, m6, l6, x6,区别在于后者是针对更大分辨率的图片比如1280x1280,

当然结构上也有些差异,前者只会下采样到32倍且采用3个预测特征层 , 而后者会下采样64倍,采用4个预测特征层。

本章将以 yolov5s为例 ,从配置文件 models/yolov5s.yaml(https://github.com/Oneflow-Inc/one-yolov5/blob/main/models/yolov5s.yaml) 到 models/yolo.py(https://github.com/Oneflow-Inc/one-yolov5/blob/main/models/yolo.py) 源码进行解读。

yolov5s.yaml文件内容:

newCodeMoreWhite.png

anchors 解读

yolov5 初始化了 9 个 anchors,分别在三个特征图 (feature map)中使用,每个 feature map 的每个 grid cell 都有三个 anchor 进行预测。 分配规则:

  • 尺度越大的 feature map 越靠前,相对原图的下采样率越小,感受野越小, 所以相对可以预测一些尺度比较小的物体(小目标),分配到的 anchors 越小。

  • 尺度越小的 feature map 越靠后,相对原图的下采样率越大,感受野越大, 所以可以预测一些尺度比较大的物体(大目标),所以分配到的 anchors 越大。

  • 即在小特征图(feature map)上检测大目标,中等大小的特征图上检测中等目标, 在大特征图上检测小目标。

backbone & head解读

[from, number, module, args] 参数

四个参数的意义分别是:

  1. 第一个参数 from :从哪一层获得输入,-1表示从上一层获得,[-1, 6]表示从上层和第6层两层获得。

  2. 第二个参数 number:表示有几个相同的模块,如果为9则表示有9个相同的模块。

  3. 第三个参数 module:模块的名称,这些模块写在common.py中。

  4. 第四个参数 args:类的初始化参数,用于解析作为 moudle 的传入参数。

下面以第一个模块Conv 为例介绍下common.py中的模块

Conv 模块定义如下:

newCodeMoreWhite.png

比如上面把width_multiple设置为了0.5,那么第一个 [64, 6, 2, 2] 就会被解析为 [3,64*0.5=32,6,2,2],其中第一个 3 为输入channel(因为输入),32 为输出channel。

关于调整网络大小的详解说明

在yolo.py(https://github.com/Oneflow-Inc/one-yolov5/blob/main/models/yolo.py)的256行 有对yaml 文件的nc,depth_multiple等参数读取,具体代码如下:

anchors, nc, gd, gw = d['anchors'], d['nc'], d['depth_multiple'], d['width_multiple']

"width_multiple"参数的作用前面介绍args参数中已经介绍过了,那么"depth_multiple"又是什么作用呢?

在yolo.py(https://github.com/Oneflow-Inc/one-yolov5/blob/main/models/yolo.py)的257行有对参数的具体定义:

 n = n_ = max(round(n * gd), 1) if n > 1 else n  # depth gain 暂且将这段代码当作公式(1)

其中 gd 就是depth_multiple的值,n的值就是backbone中列表的第二个参数:

根据公示(1)  很容易看出 gd 影响 n 的大小,从而影响网络的结构大小。

后面各层之间的模块数量、卷积核大小和数量等也都产生了变化,YOLOv5l 与 YOLOv5s 相比较起来训练参数的大小成倍数增长,

其模型的深度和宽度也会大很多,这就使得 YOLOv5l 的 精度值要比 YOLOv5s 好很多,因此在最终推理时的检测精度高,但是模型的推理速度更慢。

所以 YOLOv5 提供了不同的选择,如果想要追求推理速度可选用较小一些的模型如 YOLOv5s、YOLOv5m,如果想要追求精度更高对推理速度要求不高的可以选择其他两个稍大的模型。

如下面这张图:

2658bd5ede3fbb76ffd3388266e7bfab.png

yolov5模型复杂度比较图

Conv模块解读

网络结构预览

下面是根据yolov5s.yaml(https://github.com/Oneflow-Inc/one-yolov5/blob/main/models/yolov5s.yaml)绘制的网络整体结构简化版。

9899d54df85351ae28e29108d1f44130.png

yolov5s网络整体结构图

  1. 详细的网络结构图:https://oneflow-static.oss-cn-beijing.aliyuncs.com/one-yolo/imgs/yolov5s.onnx.png 通过export.py导出的onnx格式,并通过 https://netron.app/ 网站导出的图片(模型导出将在本教程的后续文章单独介绍)。

  2. 模块组件右边参数 表示特征图的的形状,比如 在 第 一 层( Conv )输入 图片形状为 [ 3, 640, 640] ,关于这些参数,可以固定一张图片输入到网络并通过yolov5s.yaml(https://github.com/Oneflow-Inc/one-yolov5/blob/main/models/yolov5s.yaml)的模型参数计算得到,并且可以在工程 models/yolo.py(https://github.com/Oneflow-Inc/one-yolov5/blob/main/models/yolo.py) 通过代码进行print查看,详细数据可以参考附件表2.1。

yolo.py解读

文件地址(https://github.com/Oneflow-Inc/one-yolov5/blob/main/models/yolo.py)

文件主要包含 三大部分: Detect类, Model类,和 parse_model 函数

可以通过 python models/yolo.py --cfg yolov5s.yaml 运行该脚本进行观察

parse_model函数解读

newCodeMoreWhite.png

Model 类解读

newCodeMoreWhite.png

Detect类解读

newCodeMoreWhite.png

表2.1  yolov5s.yaml(https://github.com/Oneflow-Inc/one-yolov5/blob/main/models/yolov5s.yaml)解析表

层数formmouduleargumentsinputoutput
0-1Conv[3, 32, 6, 2, 2][3, 640, 640][32, 320, 320]
1-1Conv[32, 64, 3, 2][32, 320, 320][64, 160, 160]
2-1C3[64, 64, 1][64, 160, 160][64, 160, 160]
3-1Conv[64, 128, 3, 2][64, 160, 160][128, 80, 80]
4-1C3[128, 128, 2][128, 80, 80][128, 80, 80]
5-1Conv[128, 256, 3, 2][128, 80, 80][256, 40, 40]
6-1C3[256, 256, 3][256, 40, 40][256, 40, 40]
7-1Conv[256, 512, 3, 2][256, 40, 40][512, 20, 20]
8-1C3[512, 512, 1][512, 20, 20][512, 20, 20]
9-1SPPF[512, 512, 5][512, 20, 20][512, 20, 20]
10-1Conv[512, 256, 1, 1][512, 20, 20][256, 20, 20]
11-1Upsample[None, 2, 'nearest'][256, 20, 20][256, 40, 40]
12[-1, 6]Concat[1][1, 256, 40, 40],[1, 256, 40, 40][512, 40, 40]
13-1C3[512, 256, 1, False][512, 40, 40][256, 40, 40]
14-1Conv[256, 128, 1, 1][256, 40, 40][128, 40, 40]
15-1Upsample[None, 2, 'nearest'][128, 40, 40][128, 80, 80]
16[-1, 4]Concat[1][1, 128, 80, 80],[1, 128, 80, 80][256, 80, 80]
17-1C3[256, 128, 1, False][256, 80, 80][128, 80, 80]
18-1Conv[128, 128, 3, 2][128, 80, 80][128, 40, 40]
19[-1, 14]Concat[1][1, 128, 40, 40],[1, 128, 40, 40][256, 40, 40]
20-1C3[256, 256, 1, False][256, 40, 40][256, 40, 40]
21-1Conv[256, 256, 3, 2][256, 40, 40][256, 20, 20]
22[-1, 10]Concat[1][1, 256, 20, 20],[1, 256, 20, 20][512, 20, 20]
23-1C3[512, 512, 1, False][512, 20, 20][512, 20, 20]
24[17, 20, 23]Detect[80, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [128, 256, 512]][1, 128, 80, 80],[1, 256, 40, 40],[1, 512, 20, 20][1, 3, 80, 80, 85],[1, 3, 40, 40, 85],[1, 3, 20, 20, 85]

参考文章:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK