YOLOv5 全面解析教程①:网络结构逐行代码解读
撰文 | Fengwen, BBuf
本教程涉及的代码在:
https://github.com/Oneflow-Inc/one-yolov5
教程也同样适用于 Ultralytics/YOLOv5,因为 One-YOLOv5 仅仅是换了一个运行时后端而已,计算逻辑和代码相比 Ultralytics/YOLOv5 没有做任何改变,欢迎 star 。详细信息请看:一个更快的YOLOv5问世,附送全面中文解析教程
1、引言
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)
源码进行解读。
2、yolov5s.yaml 文件内容
3、anchors 解读
YOLOv5 初始化了 9 个 anchors,分别在三个特征图 (feature map)中使用,每个 feature map 的每个 grid cell 都有三个 anchor 进行预测。分配规则:
尺度越大的 feature map 越靠前,相对原图的下采样率越小,感受野越小, 所以相对可以预测一些尺度比较小的物体(小目标),分配到的 anchors 越小。
尺度越小的 feature map 越靠后,相对原图的下采样率越大,感受野越大, 所以可以预测一些尺度比较大的物体(大目标),所以分配到的 anchors 越大。
即在小特征图(feature map)上检测大目标,中等大小的特征图上检测中等目标, 在大特征图上检测小目标。
4、backbone & head 解读
[from, number, module, args] 参数
四个参数的意义分别是:
第一个参数 from :从哪一层获得输入,-1 表示从上一层获得,[-1, 6]表示从上层和第 6 层两层获得。
第二个参数 number:表示有几个相同的模块,如果为 9 则表示有 9 个相同的模块。
第三个参数 module:模块的名称,这些模块写在 common.py 中。
第四个参数 args:类的初始化参数,用于解析作为 moudle 的传入参数。
下面以第一个模块 Conv 为例介绍下 common.py 中的模块
Conv 模块定义如下:
比如上面把 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 等参数读取,具体代码如下:
"width_multiple"参数的作用前面介绍 args 参数中已经介绍过了,那么"depth_multiple"又是什么作用呢?
在 yolo.py (https://github.com/Oneflow-Inc/one-yolov5/blob/main/models/yolo.py) 的 257 行有对参数的具体定义:
其中 gd 就是 depth_multiple 的值,n 的值就是 backbone 中列表的第二个参数:
根据公式(1)很容易看出 gd 影响 n 的大小,从而影响网络的结构大小。
后面各层之间的模块数量、卷积核大小和数量等也都产生了变化,YOLOv5l 与 YOLOv5s 相比较起来训练参数的大小成倍数增长,
其模型的深度和宽度也会大很多,这就使得 YOLOv5l 的精度值要比 YOLOv5s 好很多,因此在最终推理时的检测精度高,但是模型的推理速度更慢。
所以 YOLOv5 提供了不同的选择,如果想要追求推理速度可选用较小一些的模型如 YOLOv5s、YOLOv5m,如果想要追求精度更高对推理速度要求不高的可以选择其他两个稍大的模型。
如下面这张图:
yolov5 模型复杂度比较图
5、Conv 模块解读
网络结构预览
下面是根据 yolov5s.yaml
(https://github.com/Oneflow-Inc/one-yolov5/blob/main/models/yolov5s.yaml) 绘制的网络整体结构简化版。
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。
6、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 运行该脚本进行观察
7、parse_model 函数解读
8、Model 类解读
9、Detect 类解读
10、附件
表 2.1 yolov5s.yaml 解析表
(https://github.com/Oneflow-Inc/one-yolov5/blob/main/models/yolov5s.yaml)
11、参考文章
https://zhuanlan.zhihu.com/p/436891962?ivk_sa=1025922q
https://zhuanlan.zhihu.com/p/110204563
https://www.it610.com/article/1550621248474648576.htm
其他人都在看
欢迎 Star、试用 OneFlow 最新版本:https://github.com/Oneflow-Inc/oneflow/
评论