文章地址:https://arxiv.org/pdf/2402.13616.pdf
代码地址:https://github.com/WongKinYiu/yolov9
前言
在这篇博客中,我们来聊聊 YOLOv9
。首先,值得注意的一点是,YOLOv9
的变化相对较小,它仍然基于YOLOv5
的代码架构。这就意味着YOLOv5
、YOLOv7
和YOLOv9
实际上是“同一个框架”。如果你已经熟悉其中一个,那么你将能够轻松掌握另外两个。
这也间接回答了大家长期存在的一个疑问:改进YOLOv5
或YOLOv7
是否已经过时了?
YOLOv9
仍然采用 v5
的框架,显然从框架的角度讲,没有“过时”!也不存在"过时"这个说法,即便用 v3
的框架依然可以做出 v10
。
在此,我也想和各位导师们说几句,不要用所谓的版本为难同学们了,特别是当你们可能对当前的YOLO
发展并不完全了解时。虽然以数字命名的 YOLO
版本已经发展到了v9
,但这并不意味着它在所有方面都超越了v5
。并且不只是以数字命名的YOLO
才叫YOLO
,除了这几个以数字命名的版本,还有很多很多优秀的 YOLO
工作,很多数据集的表现上并不比数字版本差!
如果你们不信,可以尝试将YOLOv9
与古老的VGG16
在多个数据集上进行对比实验。我敢肯定,你会发现在某些数据集上,YOLOv9
并不比VGG16
表现得更好。
还有一点,各位同学们,你们做的是新的YOLO
算法,你可以叫 xx-YOLO
或者 YOLO-xx
,不必非得写成基于YOLOv5
的 xx
改进,然后你的对比实验对比一下新的 v8
v9
,这样老师们也没办法“找出问题”。
原理解析
YOLOv9来了! 使用可编程梯度信息学习你想学的内容, v7作者新作!【文献速读】
下面就来带大家跑一下 YOLOv9
, 先简单说下原理,主要就是两点,一个是可编程梯度信息(PGI),另一个是通用高效层聚合网络(GELAN),这里我不过多的解析,简单看下:
- 可编程梯度信息(PGI):假设通过引入
PGI
,可以在深度学习模型中保留更多的输入信息,从而解决信息丢失问题。PGI
允许模型在计算目标函数时使用完整的输入信息,提供可靠的梯度信息用于网络权重的更新,这对于提高模型在复杂任务上的性能至关重要。 - 通用高效层聚合网络(GELAN):
GELAN
这种新型轻量级网络架构可以实现高效的信息流动和优化的参数利用,从而在保持甚至提高检测精度的同时,减少计算资源的需求。GELAN
的设计旨在通过梯度路径规划优化网络结构,使之能够在不同的硬件设备上高效运行,同时提高模型的泛化能力。
图2. 不同网络架构随机初始化权重输出特征图的可视化结果:(a) 输入图像,(b) PlainNet,(.c) ResNet,(d) CSPNet,以及(e) 提出的GELAN。从图中我们可以看出,在不同的架构中,提供给目标函数以计算损失的信息不同程度地丢失了,而我们的架构能够保留最完整的信息,并为计算目标函数提供最可靠的梯度信息。
图3. PGI及相关网络架构和方法。(a) 路径聚合网络(PAN),(b) 可逆列(RevCol),(.c) 传统的深度监督,以及(d) 我们提出的可编程梯度信息(PGI)。PGI主要由三个组成部分构成:(1) 主分支(main branch):用于推断的架构,(2) 辅助可逆分支(auxiliary reversible branch):生成可靠的梯度以供主分支向后传输,以及(3) 多级辅助信息(multi-level auxiliary information):控制主分支学习可计划的多级语义信息。
代码实操
readmd解析
代码Github
地址在这里:https://github.com/WongKinYiu/yolov9
我们先一起看看项目的 readme
,readme
一般都包含了项目最核心的一些信息,一般可以通过这个发掘出一些"有趣的东西" ;
Performance
上看到模型有 5
个版本,但是截止到 2024/3/25
,作者只开源了 YOLOv9-C
和 YOLOv9-E
,YOLOv9-T
YOLOv9-S
YOLOv9-M
还没开放,按照作者的一贯性格,我认为小尺寸的模型不会是简单的尺度缩放
,肯定会有特殊的设计。
Evaluation
这里看到了 6
个 权重链接,并且有的叫做 converted
,这让我首先想到了"结构重参数化",后来看了一眼还真是,v9
还真给"结构重参数化"方法玩明白了,佩服👍,这里的几个权重什么关系我下文说。
下面就是一些 训练和推理的参考了,并且还给了"重参数化"用的脚本!
模型训练
终于来到了关键的点,这几天我也刷到了一些给我推送的文章,大家有些地方可能没注意到,并不是代码写错了,是大家用错了,
这个v9
的训练脚本有三个,和我们之前v5
v7
看的都不一样的,
并且 yaml
结构文件也给了6
个(7的yaml这里忽略
),分别是 v9
的c
和e
,gelan
的c
和e
重点来了!train.py
、tran_dual.py
、train_triple.py
三个都没错,都能用,但是你得对应起来!
train.py
:常规的训练,没有辅助分支的train_dual
:一个辅助分支 + 一个主分支triple_branch
:两个辅助分支 + 一个主分支
所以当我们训练 YOLOv9-c
或者 YOLOv9-e
就用 train_dual
:
python train_dual.py --workers 8 --device 0 --batch 16 --data data/coco.yaml --img 640 --cfg models/detect/yolov9-c.yaml --weights '' --name yolov9-c --hyp hyp.scratch-high.yaml --min-items 0 --epochs 500 --close-mosaic 15
你想训练没有辅助分支的 gelan
结构,你就用 train.py
:
python train.py --workers 8 --device 0 --batch 32 --data data/coco.yaml --img 640 --cfg models/detect/gelan-c.yaml --weights '' --name gelan-c --hyp hyp.scratch-high.yaml --min-items 0 --epochs 500 --close-mosaic 15
这里还涉及到一个问题,辅助分支是干啥的,顾名思义,就是辅助训练的,用"重参数化"思想来解释就是:
训练的时候带着这个辅助分支训练,训练完将这个分支"拿掉",理论上,推理的精度是"几乎不变"的。
这部分怎么做呢?用作者给的重参数化脚本:https://github.com/WongKinYiu/yolov9/blob/main/tools/reparameterization.ipynb
转换后,模型的权重大小基本掉了一半,就和上面Performance
上看到的尺寸对应上了,这就是YOLOv9
最核心的东西!
模型推理
同样的,训练分了多个脚本,推理脚本也是分开的,
如果你想推理你刚才用脚本转换后的权重,你就用这个指令:
python detect.py --source './data/images/horses.jpg' --img 640 --device 0 --weights './yolov9-c-converted.pt' --name yolov9_c_c_640_detect
如果你想推理v9没转换的权重,也就是你刚训练出来的best.pt
,你就用这个指令:
python detect_dual.py --source './data/images/horses.jpg' --img 640 --device 0 --weights './yolov9-c.pt' --name yolov9_c_640_detect
如果你想推理常见的gelan
结构的权重,你就用这个指令:
python detect.py --source './data/images/horses.jpg' --img 640 --device 0 --weights './gelan-c.pt' --name gelan_c_c_640_detect
模型验证
同理,val
也是分开的,
如果你想验证你刚才用脚本转换后的权重,你就用这个指令:
python val.py --data data/coco.yaml --img 640 --batch 32 --conf 0.001 --iou 0.7 --device 0 --weights './yolov9-c-converted.pt' --save-json --name yolov9_c_c_640_val
如果你想验证v9没转换的权重,也就是你刚训练出来的best.pt
,你就用这个指令:
python val_dual.py --data data/coco.yaml --img 640 --batch 32 --conf 0.001 --iou 0.7 --device 0 --weights './yolov9-c.pt' --save-json --name yolov9_c_640_val
如果你想推理常见的gelan
结构的权重,你就用这个指令:
python val.py --data data/coco.yaml --img 640 --batch 32 --conf 0.001 --iou 0.7 --device 0 --weights './gelan-c.pt' --save-json --name gelan_c_640_val
引用
@article{wang2024yolov9,title={{YOLOv9}: Learning What You Want to Learn Using Programmable Gradient Information},author={Wang, Chien-Yao and Liao, Hong-Yuan Mark},booktitle={arXiv preprint arXiv:2402.13616},year={2024}
}
@article{chang2023yolor,title={{YOLOR}-Based Multi-Task Learning},author={Chang, Hung-Shuo and Wang, Chien-Yao and Wang, Richard Robert and Chou, Gene and Liao, Hong-Yuan Mark},journal={arXiv preprint arXiv:2309.16921},year={2023}
}
总结
到这里,YOLOv9
就解析完了,这篇我并没有手把手带大家走训练的全流程,个人觉得和v5
v7
没啥区别,我这样做意义不大,最核心最重要的东西就在我上面的文章里面了;
顺便说一下,YOLOv9
不仅仅支持检测任务,还有实例分割任务和全景分割任务,这个我后面出教程解析,
喜欢我的文章欢迎大家点赞评论交流~