
根据上述网络结构图进行 YOLOv9 详细讲解。结论:
YOLOv9 的核心不是"又换了一个 backbone",而是把训练期的 PGI(Programmable Gradient Information,可编程梯度信息)和推理期高效的 GELAN(Generalized ELAN)组合起来。 论文要解决的中心问题是:深层网络在前向过程中会逐层丢信息,导致梯度不够可靠;YOLOv9 用 训练期辅助可逆分支 + 多级辅助信息 去补这个问题,而 推理时只保留主分支,所以不会额外增加部署成本。([arXiv][1])
1. YOLOv9 是什么
YOLOv9 对应的论文是 "YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information" 。论文提出两件最重要的事:
一是 PGI ,用来缓解信息瓶颈并生成更可靠的梯度;
二是 GELAN,这是一个基于 ELAN 扩展出来、可适配不同计算块的高效网络结构。论文和官方仓库都把它们作为 YOLOv9 的核心。([arXiv][2])
官方仓库的 COCO 检测结果给出五个主要检测规模:YOLOv9-T/S/M/C/E ,对应 AP 分别约为 38.3 / 46.8 / 51.4 / 53.0 / 55.6 ,参数量约为 2.0M / 7.1M / 20.0M / 25.3M / 57.3M。([GitHub][3])
2. 最容易混淆的地方讲清楚
YOLOv9 在官方仓库里其实有两类你经常会同时看到的配置:
第一类是 paper-faithful 的 YOLOv9 配置 ,例如 yolov9-c.yaml、yolov9-e.yaml。这些配置带有 训练期辅助分支 ,检测头是 DualDDetect 。从作者在官方 issue 里的说明看,训练它们要用 train_dual.py。([GitHub][4])
第二类是 GELAN 配置 ,例如 gelan-c.yaml、gelan-e.yaml。作者说明训练这类模型用普通的 train.py;官方 README 也单独给了 GELAN 的训练入口。([GitHub][5])
另外,官方 README 在推理示例里,YOLOv9 的示例权重写的是 yolov9-c-converted.pt ,而 GELAN 直接用 gelan-c.pt。这说明官方工程里也把"训练态 YOLOv9"和"更适合直接推理的形态"区分开了。([GitHub][3])
3. YOLOv9-C 的网络结构图
如果按官方 models/detect/yolov9-c.yaml 来看,YOLOv9-C 可以画成这张简化图:
text
Input
└─ Backbone
├─ Silence
├─ Conv(64, s=2) -> P1/2
├─ Conv(128, s=2) -> P2/4
├─ RepNCSPELAN4 -> stage 1
├─ ADown(256) -> P3/8
├─ RepNCSPELAN4 -> stage 2
├─ ADown(512) -> P4/16
├─ RepNCSPELAN4 -> stage 3
├─ ADown(512) -> P5/32
└─ RepNCSPELAN4 -> deepest stage
└─ Main Head / Neck
├─ SPPELAN
├─ Upsample + Concat(P4) + RepNCSPELAN4
├─ Upsample + Concat(P3) + RepNCSPELAN4 -> P3
├─ ADown + Concat + RepNCSPELAN4 -> P4
├─ ADown + Concat + RepNCSPELAN4 -> P5
└─ Main predictions at P3 / P4 / P5
└─ Training-only Auxiliary Reversible Branch
├─ CBLinear routing from backbone stages
├─ Extra Conv / ADown / CBFuse / RepNCSPELAN4 blocks
└─ Auxiliary predictions at A3 / A4 / A5
└─ Detect
└─ DualDDetect(A3, A4, A5, P3, P4, P5)
这张图不是概念图,而是直接按 yolov9-c.yaml 摘出来的:Backbone 里主块是 RepNCSPELAN4 和 ADown ,Head 前面有 SPPELAN ,主分支输出三层 P3/P4/P5,同时还有一条 multi-level reversible auxiliary branch ,最后检测头是 DualDDetect(A3, A4, A5, P3, P4, P5)。([GitHub][4])
4. YOLOv9-E 的结构和 C 有什么不同
yolov9-e.yaml 比 C 更大,也更复杂。它的主差异不是只把通道数调大,而是:
- Backbone 更宽更深,很多
RepNCSPELAN4的内部设置从 C 的..., 1变成 E 的..., 2; - 中间加了更重的 CBLinear / CBFuse 路由融合;
- 主分支和辅助分支都更大;
- 最终仍然是
DualDDetect(A3, A4, A5, P3, P4, P5)。([GitHub][6])
可以把 YOLOv9-C 理解为更常用的"精度和代价平衡版",把 YOLOv9-E 理解为更偏高精度的大模型版。官方数据也对应这个趋势:C 大约 25.3M / 102.1G / 53.0 AP ,E 大约 57.3M / 189.0G / 55.6 AP。([GitHub][3])
5. 关键创新点 1:PGI
PGI 是 YOLOv9 最关键的论文创新。论文明确写了,PGI 主要由三部分组成:
- main branch
- auxiliary reversible branch
- multi-level auxiliary information。([arXiv][1])
它解决的问题是:随着网络加深,信息会在前向传播中逐渐丢失,导致 loss 反向给出的梯度越来越不可靠。PGI 的思路不是强行让推理网络变成完全可逆网络,而是在训练时引入一条 辅助可逆分支 来帮主干拿到更可靠的梯度。论文还特别强调:PGI 的推理过程只使用主分支,因此不会增加额外推理成本。 ([arXiv][1])
这个点很重要,因为它决定了 YOLOv9 的提升方式更像是:
"训练期更聪明,推理期不变重。" ([arXiv][1])
6. 关键创新点 2:辅助可逆分支
论文对辅助可逆分支讲得很清楚:作者分析了真正把主干做成可逆结构会明显增加推理代价,甚至可能让推理时间上涨 20% 以上,因此他们没有把"完全可逆"直接塞进主推理路径里,而是把可逆思想放到 辅助监督分支 中。这样,主分支在训练时能接收更可靠的梯度,但部署时又能把辅助分支去掉。([arXiv][1])
这也是 YOLOv9 和很多"单纯改 backbone"模型最不一样的地方:
它把"信息是否丢失""梯度是否可信"当成一等公民来设计。([arXiv][1])
7. 关键创新点 3:多级辅助信息
论文把 multi-level auxiliary information 设计成 PGI 的第三部分。它的目的,是处理多预测分支架构里深监督容易积累误差的问题。对检测任务来说,不同金字塔层负责不同尺度目标,所以多级辅助信息要把"包含全部目标信息的梯度"更有效地汇总回主分支。([arXiv][1])
落到官方 YAML 里,你能直接看到这种设计:
CBLinear 负责从多个主干层做 routing,CBFuse 再把这些多层信息融合进辅助分支。yolov9-c.yaml 里这一套出现在 23--37 层附近,最终形成辅助侧的 A3/A4/A5 三个预测层,再和主分支的 P3/P4/P5 一起进入 DualDDetect。([GitHub][4])
8. 关键创新点 4:GELAN
论文把 GELAN 定义为 Generalized ELAN 。它不是简单"把 ELAN 再堆深一点",而是把 ELAN 泛化成一种 可以支持任意计算块 的层聚合结构。论文原话是:他们模仿 CSPNet,并把 ELAN 扩展成一个能支持任意计算块的 GELAN。([arXiv][1])
论文和官方文档都强调了一点:
GELAN 只用常规卷积,也能拿到非常高的参数利用率,不需要依赖深度可分离卷积来"刷轻量化"。 这是 YOLOv9 很有辨识度的工程取舍。([arXiv][2])
9. 关键创新点 5:GELAN + PGI 的增益是可量化的
论文做了专门消融。以 GELAN 为基线,加 PGI 后:
- GELAN-S:46.7 → 46.8
- GELAN-M:51.1 → 51.4
- GELAN-C:52.5 → 53.0
- GELAN-E:55.0 → 55.6。([arXiv][1])
这说明 PGI 不是"理论上好看",而是确实能给不同规模模型带来稳定增益,尤其在 C/E 这种更强模型上提升更明显。([arXiv][1])
10. 官方仓库里的关键模块怎么理解
从 yolov9-c.yaml 和 yolov9-e.yaml 看,YOLOv9 有几个识别度很高的块:
RepNCSPELAN4:它是 YOLOv9 中最核心的主干/颈部块,本质上把 CSP 与 ELAN 思路结合起来。官方 YAML 大量使用它。([GitHub][4])
ADown:这是 YOLOv9-C/E 里常见的下采样块,官方 YAML 用它替代很多普通 stride=2 下采样。([GitHub][4])
SPPELAN:可以把它理解成 SPP 风格上下文聚合和 ELAN 风格聚合的结合体,在进入金字塔融合前先扩感受野。([GitHub][4])
CBLinear / CBFuse:这是辅助信息 routing 和 fuse 的关键模块,主要服务于 PGI 的多级辅助信息设计。([GitHub][4])
DualDDetect:这是 YOLOv9-C/E 的检测头,接收辅助分支和主分支共 6 个尺度输入。([GitHub][4])
11. YOLOv9 的训练和推理怎么区分理解
部署时最容易踩坑的点。
如果你按论文主线理解,YOLOv9 的增强主要发生在训练期:辅助可逆分支和多级辅助信息都属于训练态设计,论文明确写了推理阶段只用主分支。([arXiv][1])
如果你按官方仓库理解,工程上也确实做了区分:
作者在官方 issue 里明确说 YOLOv9 模型用 train_dual.py 训练,GELAN 模型用 train.py 训练 ;README 的推理示例又特意使用 yolov9-c-converted.pt。这说明官方代码并不是把"训练态"和"推理态"完全混成一个入口。([GitHub][5])
所以做工程时,最稳的理解方式是:
训练:按 paper-faithful 配置走。
部署:优先用官方给出的 converted / export 形态。 ([GitHub][3])
12. YOLOv9 的部署链路
原始 YOLOv9 仓库自带 export.py,支持的导出格式包括:
- TorchScript
- ONNX
- ONNX END2END
- OpenVINO
- TensorRT
- CoreML
- TensorFlow SavedModel / PB / TFLite / EdgeTPU / TF.js
- PaddlePaddle。([GitHub][7])
而且 export.py 的主流程里明确写了:
engine走 TensorRTonnx走 ONNXonnx_end2end会输出num_dets / det_boxes / det_scores / det_classesxml依赖 ONNX 再转 OpenVINO。([GitHub][7])
13. 最常见的部署方式怎么选
做实际项目,可以这样选:
PyTorch / TorchScript :最适合快速验证。原仓库也支持直接 detect.py 推理。([GitHub][3])
ONNX :最通用,适合 ONNX Runtime、OpenCV DNN、跨平台 C++ 服务。官方 export.py 原生支持,并支持动态轴和 simplify。([GitHub][7])
TensorRT :NVIDIA GPU、Jetson、边缘盒子优先。原仓库 export_engine() 明确要求 GPU 环境,并会先导出 ONNX 再生成 .engine。([GitHub][7])
OpenVINO:Intel CPU 优先,原仓库也是通过 ONNX 转过去。([GitHub][7])
14. 原仓库最实用的几个命令
原始仓库 README 里给了推理命令,YOLOv9 的示例是:
bash
python detect.py --source './data/images/horses.jpg' --img 640 --device 0 --weights './yolov9-c-converted.pt'
而 GELAN 的示例是:
bash
python detect.py --source './data/images/horses.jpg' --img 640 --device 0 --weights './gelan-c.pt'
README 还给了 GELAN-C-DET 的训练命令:
bash
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-det --hyp hyp.scratch-high.yaml --min-items 0 --epochs 300 --close-mosaic 10
这些都是官方仓库直接给出的。([GitHub][3])
如果导出 ONNX,原仓库的典型命令就是:
bash
python export.py --weights yolov9-c.pt --include onnx
如果要导出 TensorRT:
bash
python export.py --weights yolov9-c.pt --include engine --device 0
这些命令是 export.py 的参数体系直接支持的。([GitHub][7])
15. 更方便的部署路线:Ultralytics 版 YOLOv9
"好训、好导出、好上线",Ultralytics 也维护了 YOLOv9 系列页面,并明确支持 Inference / Validation / Training / Export 。它给的模型名是 yolov9t/s/m/c/e.pt,分割版是 yolov9c-seg.pt 和 yolov9e-seg.pt。文档还直接给出 Python 和 CLI 的训练/预测入口。([GitHub][8])
例如:
python
from ultralytics import YOLO
model = YOLO("yolov9c.pt")
results = model.train(data="coco8.yaml", epochs=100, imgsz=640)
results = model("path/to/bus.jpg")
或者:
bash
yolo train model=yolov9c.yaml data=coco8.yaml epochs=100 imgsz=640
yolo predict model=yolov9c.yaml source=path/to/bus.jpg
优点是:训练、验证、预测、导出入口统一,工程成本更低。 文档同时提醒,训练 YOLOv9 会比同规模 YOLOv8 更吃资源、耗时更长。([GitHub][8])
16. YOLOv9 和 YOLOv8 的本质差异
最核是:
YOLOv8 更像"改结构与头部的现代化工程模型",YOLOv9 更像"把训练期梯度可靠性作为核心问题来重新设计的模型"。 YOLOv9 的论文重点不是单纯做更轻的 head,而是把 PGI + GELAN 放到一起,用训练态辅助可逆分支来提升主干学习到的信息质量。([arXiv][1])
需求场景:
- 学术上更有新意的训练机制:YOLOv9 更值得看;
- 工业链路更成熟、生态更统一:YOLOv8/Ultralytics 工具链通常更省心
17. 总结
YOLOv9 = GELAN 负责高效前向特征提取,PGI 负责训练期提供更可靠梯度。
真正让它和前几代拉开差距的,不只是某个新模块,而是这套 "训练期变强、推理期不变重" 的整体设计。([arXiv][1])
参考链接:
1\]: https://arxiv.org/html/2402.13616v1 "YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information" \[2\]: https://arxiv.org/abs/2402.13616?utm_source=chatgpt.com "YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information" \[3\]: https://github.com/wongkinyiu/yolov9 "GitHub - WongKinYiu/yolov9: Implementation of paper - YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information · GitHub" \[4\]: https://github.com/WongKinYiu/yolov9/blob/main/models/detect/yolov9-c.yaml "yolov9/models/detect/yolov9-c.yaml at main · WongKinYiu/yolov9 · GitHub" \[5\]: https://github.com/WongKinYiu/yolov9/issues/58 "Please use `train.py` to train gelan models, and use `train_dual.py` to train yolov9 models. · Issue #58 · WongKinYiu/yolov9 · GitHub" \[6\]: https://github.com/WongKinYiu/yolov9/blob/main/models/detect/yolov9-e.yaml "yolov9/models/detect/yolov9-e.yaml at main · WongKinYiu/yolov9 · GitHub" \[7\]: https://github.com/WongKinYiu/yolov9/blob/main/export.py "yolov9/export.py at main · WongKinYiu/yolov9 · GitHub" \[8\]: https://github.com/ultralytics/ultralytics/blob/main/docs/en/models/yolov9.md "ultralytics/docs/en/models/yolov9.md at main · ultralytics/ultralytics · GitHub"