yolox详细讲解,包括网络结构图、关键创新点、部署

YOLOX 的定位很明确:它是一个 anchor-free 的 YOLO 检测器 ,并把 decoupled headSimOTA 这类当时更先进的检测技巧正式带进了 YOLO 系列。([GitHub][1])

1. YOLOX 是什么

一句话概括:YOLOX = CSPDarknet/PAFPN 主体 + anchor-free 检测头 + decoupled head + SimOTA 标签分配 。论文里作者直接写明,YOLOX 的核心改动是把 YOLO 切到 anchor-free ,再结合 decoupled headSimOTA ,从而在不同模型规模上都拿到更强的精度-速度平衡。论文给出的代表性结果是:YOLOX-L 在 COCO 上达到 50.0% AP、68.9 FPS(Tesla V100) ;官方当前模型库里,YOLOX-S/M/L/X 的测试 mAP 分别约为 40.5 / 47.2 / 50.1 / 51.5。([ar5iv][2])

2. 网络结构图

适合记忆和讲解的简化结构图:

text 复制代码
Input
 └─ Backbone: CSPDarknet
    ├─ Focus stem
    ├─ dark2: Conv + CSPLayer
    ├─ dark3: Conv + CSPLayer   -> 输出 P3 特征
    ├─ dark4: Conv + CSPLayer   -> 输出 P4 特征
    └─ dark5: Conv + SPPBottleneck + CSPLayer -> 输出 P5 特征

 └─ Neck: YOLOPAFPN
    ├─ Top-down:
    │   P5 上采样 + 与 P4 拼接 + CSPLayer
    │   再上采样 + 与 P3 拼接 + CSPLayer
    └─ Bottom-up:
        P3 下采样 + 与中间层拼接 + CSPLayer
        再下采样 + 与高层拼接 + CSPLayer

 └─ Head: YOLOXHead(3 个尺度)
    ├─ 每个尺度先过 1×1 stem
    ├─ 分类分支:两层 3×3 Conv -> cls
    ├─ 回归分支:两层 3×3 Conv -> box
    └─ 目标分支:从回归分支输出 obj

输出尺度:stride = 8 / 16 / 32

这个图不是随便画的,它和官方实现是一一对应的:

官方 YOLOX 模型默认由 YOLOPAFPN()YOLOXHead(80) 组成;Backbone 输出的是 [dark3, dark4, dark5],Neck 再把它们融合后交给 Head。([GitHub][3])

3. Backbone:CSPDarknet

官方代码里,YOLOX 的主干是 CSPDarknet。它的入口不是普通卷积,而是 Focus stem ;随后依次经过 dark2 / dark3 / dark4 / dark5。其中:

  • dark3dark4dark5 是后续特征金字塔的主要输入;
  • dark5 里额外加入了 SPPBottleneck
  • dark2~dark5 都大量使用 CSPLayer。([GitHub][4])

如果你从工程角度理解,Backbone 的作用就是:

  • dark3:分辨率较高,偏小目标;
  • dark4:中尺度目标;
  • dark5:语义最强,偏大目标。

这也是为什么后面 Neck 要把这三层做双向融合。官方实现里 CSPDarknet 默认只把 dark3/dark4/dark5 作为输出特征返回。([GitHub][4])

4. Neck:YOLOPAFPN

YOLOX 的 Neck 类名就叫 YOLOPAFPN 。论文里提到,当它切换到更先进的 YOLOv5 风格架构时,采用了 CSPNet backbone + additional PAN head ;而官方实现中,这一部分具体落地成了 YOLOPAFPN。([ar5iv][2])

从代码看,它的融合流程非常清楚:

  1. 先取出 Backbone 的 [x2, x1, x0] = [dark3, dark4, dark5]

  2. 自顶向下

    • dark5 -> lateral_conv0 -> upsample -> concat(dark4) -> C3_p4
    • reduce_conv1 -> upsample -> concat(dark3) -> C3_p3
  3. 自底向上

    • 小尺度结果下采样后,与中尺度再拼接,过 C3_n3
    • 再下采样,与高尺度拼接,过 C3_n4
  4. 最终输出 3 个尺度 (pan_out2, pan_out1, pan_out0)。([GitHub][5])

这部分你可以把它理解成:
上采样路径把高层语义"送下来",下采样路径再把局部细节"送回去"。所以它既不是只做 FPN,也不是只做 PAN,而是更完整的双向特征融合。([GitHub][5])

5. Head:YOLOXHead

YOLOX 的 Head 是它最重要的改造之一。官方代码里:

  • Head 接 3 个尺度,strides=[8,16,32]

  • 每个尺度先过一个 1×1 的 stem;

  • 然后分成 分类分支回归分支 两路;

  • 分类分支、回归分支各有两层 3×3 Conv

  • 最后输出:

    • reg_preds: 4 通道边框回归
    • obj_preds: 1 通道目标置信度
    • cls_preds: num_classes 通道分类。([GitHub][6])

官方实现还明确写了:推理时会把三个尺度的输出拼成 [batch, n_anchors_all, 85] 这种形式(COCO 80 类时就是 4 box + 1 obj + 80 cls),并且 decode_in_inference=True,也就是默认在推理阶段做解码;如果做部署导出,代码里提示可以把它设成 False。([GitHub][6])

6. 为什么 YOLOX 的 Head 比老 YOLO 更强

核心原因是:把分类和回归解耦了

论文明确指出,分类和定位本来就是冲突任务,所以很多一阶段/二阶段检测器都已经用 decoupled head,但旧 YOLO Head 还长期是 coupled 的。YOLOX 的实验显示:

  • decoupled head 能明显提升收敛速度;
  • 最终精度也更好;
  • 在 YOLOv3 基线上,单独把 head 改成 decoupled,就从 38.5 AP 提到 39.6 AP
  • 代价是推理延迟从 10.5 ms 增到 11.6 ms。([ar5iv][2])

这也是为什么很多人讲 YOLOX 时,会说它不是"仅仅换成 anchor-free",而是 把 YOLO 系列的头部设计现代化了。([ar5iv][2])

7. YOLOX 的关键创新点

7.1 Anchor-Free

YOLOX 最标志性的改动就是 anchor-free 。论文里写得很直接:传统 anchor 机制有两个主要问题,一是需要聚类找 anchor,泛化性差;二是会增加 Head 复杂度和预测数量,在一些边缘 AI 系统里,预测结果在设备间搬运还会拖慢总延迟。YOLOX 切到 anchor-free 后,把 每个位置的预测从 3 个降到 1 个 ,直接预测 4 个框参数,同时保留多尺度 FPN 分配逻辑。结果是:更简单、更快,而且精度反而更高 ,在它的路线图实验里这一步把 AP 从 42.0 提到 42.9。([ar5iv][2])

7.2 Multi Positives

如果只把目标中心点当正样本,会浪费很多高质量候选。YOLOX 在 anchor-free 基础上又加了 multi positives ,本质上就是类似 FCOS 的 center sampling :把目标中心区域内的一批位置都设为正样本,而不是只留 1 个中心点。这一步又把 AP 从 42.9 拉到 45.0。([ar5iv][2])

7.3 SimOTA

这是 YOLOX 训练端最有名的创新。论文先总结了先进标签分配应满足 4 个特征:loss/quality aware、center prior、dynamic top-k、global view ;原始 OTA 虽然强,但作者发现用 Sinkhorn-Knopp 解 OT 问题会带来 约 25% 的额外训练时间 ,所以他们做了一个近似化版本,叫 SimOTA 。它先算 prediction-gt 的匹配代价,再在固定中心区域内为每个 gt 动态选 top-k 正样本。路线图里这一步把 AP 又从 45.0 提到 47.3。([ar5iv][2])

7.4 强数据增强

YOLOX 明确把 Mosaic + MixUp 当成默认的重要增强,并且在最后 15 个 epoch 关闭 这些强增强。论文还指出,在加入这些强增强后,ImageNet 预训练不再明显有益 ,因此后续模型都直接从头训练。路线图上,"strong augmentation" 这一步带来 +2.4 AP。([ar5iv][2])

7.5 可选的 End-to-End / NMS-Free

YOLOX 论文还尝试了 NMS-free 的 end-to-end 版本,但作者最后把它作为可选模块,而没有放进最终默认模型,因为它会带来一点精度和速度下降。在路线图实验里,+NMS free (optional) 从 47.3 AP 降到 46.5 AP。([ar5iv][2])

8. YOLOX 的训练范式

YOLOX 论文中的默认训练设置是:

  • 总共 300 epochs
  • 5 epochs warm-up
  • 优化器是 SGD
  • 学习率采用 cosine schedule
  • 默认总 batch size 128
  • 输入尺寸做多尺度训练,在 448 到 832 之间按 32 的步长采样。([ar5iv][2])

这说明 YOLOX 并不是只靠一个"新结构"赢的,它实际上是 结构改造 + 标签分配 + 强增强 + 训练策略 一整套组合拳。([ar5iv][2])

9. 标准模型族怎么选

官方模型库分成两类:

  • 标准模型YOLOX-s / m / l / x
  • 轻量模型YOLOX-nano / tiny。([GitHub][7])

如果你只想快速选型,可以这么记:

  • YOLOX-S:9.0M 参数,26.8 GFLOPs,640 测试尺寸,约 40.5 mAP,适合普通单卡/边缘 GPU 原型。
  • YOLOX-L:54.2M 参数,155.6 GFLOPs,约 50.1 mAP,适合更高精度场景。
  • YOLOX-X:99.1M 参数,281.9 GFLOPs,约 51.5 mAP,适合追顶精度。
  • Nano/Tiny:更偏移动端和极轻量部署。([GitHub][7])

10. 官方部署支持哪些后端

YOLOX 官方 README 和文档都明确写了,它提供或支持以下部署路线:

  • ONNX
  • TensorRT
  • ncnn
  • OpenVINO
  • MegEngine
  • Android ncnn。([GitHub][1])

从工程上看,你可以这样选:

  • NVIDIA GPU 服务器/边缘盒子:优先 TensorRT
  • 通用 Python/C++ 跨平台:优先 ONNX / ONNX Runtime
  • Intel CPU:优先 OpenVINO
  • 移动端/安卓/NPU 友好链路:优先 ncnn。([YOLOX Documentation][8])

11. ONNX 部署

官方 ONNX 导出命令是:

bash 复制代码
python3 tools/export_onnx.py --output-name yolox_s.onnx -n yolox-s -c yolox_s.pth

自定义实验文件则用 -f

bash 复制代码
python3 tools/export_onnx.py --output-name your_yolox.onnx -f exps/your_dir/your_yolox.py -c your_yolox.pth

官方 ONNXRuntime Demo 也给了直接可跑的命令:

bash 复制代码
cd <YOLOX_HOME>/demo/ONNXRuntime
python3 onnx_inference.py -m <ONNX_MODEL_PATH> -i <IMAGE_PATH> -o <OUTPUT_DIR> -s 0.3 --input_shape 640,640

文档还特别提醒:--input_shape 要和导出时一致。([YOLOX Documentation][9])

12. TensorRT 部署

官方 TensorRT Python 路线是通过 torch2trt 转换,命令大致是:

bash 复制代码
python tools/trt.py -n yolox-s -c your_ckpt.pth

如果是自定义模型,就改用 -f 指定你的 exp 文件。转换后会在实验输出目录生成 TensorRT 模型和序列化的 engine 文件。官方 Python Demo 直接在原来的 demo 命令上加 --trt

bash 复制代码
python tools/demo.py image -n yolox-s --trt --save_result

官方还提供了 TensorRT C++ Demo ,做法是先准备好 model_trt.engine,再 cmake .. && make 编译;跑的时候类似:

bash 复制代码
./yolox ../model_trt.engine -i ../../../../assets/dog.jpg

如果你训的是自定义数据集,还要改 C++ 里的 num_class。([YOLOX Documentation][8])

13. OpenVINO 部署

YOLOX 官方同时给了 OpenVINO PythonOpenVINO C++ 教程。它的典型流程是:

  1. 先导出 ONNX;
  2. 再把 ONNX 转 OpenVINO IR。([YOLOX Documentation][10])

这里有一个很容易忽略的点:

官方文档明确说,如果你后续要转 OpenVINO,导出 ONNX 时要把 opset 设成 10,否则下一步会失败。([YOLOX Documentation][9])

OpenVINO 的转换命令在文档里也给了:

bash 复制代码
python3 mo.py --input_model <ONNX_MODEL> --input_shape <INPUT_SHAPE> [--data_type FP16]

Linux 环境下还需要先 source /opt/intel/openvino_2021/bin/setupvars.sh。([YOLOX Documentation][11])

14. ncnn 与 Android 部署

YOLOX 官方给了 C++ ncnnAndroid ncnn 两条路。C++ ncnn 的基本流程是:

  1. 先导出 ONNX:
bash 复制代码
python3 tools/export_onnx.py -n yolox-s
  1. 再用 onnx2ncnn 转成 param/bin
bash 复制代码
./onnx2ncnn yolox.onnx model.param model.bin

([YOLOX Documentation][12])

这里有个很重要的工程细节:

官方文档明确写了,ncnn 不支持 Focus 模块 ,所以转换时会出现 Unsupported slice step! 之类警告;不过 YOLOX 的 yolox.cpp 已经实现了 C++ 版 Focus 层,因此文档要求你进一步手动修改 model.param。这点说明 YOLOX 的 ncnn 部署不是"导出即跑",而是要处理 Focus 兼容问题。([YOLOX Documentation][12])

Android ncnn 的流程更简单一些:官方教程是下载 ncnn-android-vulkan.zip,放到 app/src/main/jni 或修改 ncnn_DIR,再把示例 param/bin 放进 app/src/main/assets,最后用 Android Studio 打开项目构建。([YOLOX Documentation][13])

15. 实际部署时你最该注意什么

第一,YOLOX 是 anchor-free,但不是"零后处理"。默认模型仍然是常规检测流程,输出 box/obj/cls,再做阈值过滤和 NMS;只有论文里的 optional end-to-end 版本才是往 NMS-free 方向走。([ar5iv][2])

第二,部署时一定统一输入尺寸、预处理和输出解码方式 。官方 ONNX 文档已经明确提醒 input_shape 要和导出一致;而 Head 代码也说明了推理端默认会做 decode。你如果自己改导出逻辑,往往就是在这一步最容易出错。([YOLOX Documentation][9])

第三,Focus 是一个典型兼容点。在 PyTorch 里它没问题,但到 ncnn 这类后端时就可能需要额外处理,这也是很多人第一次部署 YOLOX 会踩的坑。([YOLOX Documentation][12])

16. 总结

YOLOX 的本质,不只是"把 YOLO 改成 anchor-free",而是用 CSPDarknet + PAFPN 作为主体,再用 decoupled head、multi positives、SimOTA 和强增强,把 YOLO 系列整体推进到一个更现代的一阶段检测框架。 这也是它在学术和工业部署里都很有影响力的原因。([ar5iv][2])

参考链接:

1\]: https://github.com/Megvii-BaseDetection/YOLOX/blob/main/README.md?utm_source=chatgpt.com "README.md - Megvii-BaseDetection/YOLOX" \[2\]: https://ar5iv.labs.arxiv.org/html/2107.08430 "\[2107.08430\] YOLOX: Exceeding YOLO Series in 2021" \[3\]: https://github.com/Megvii-BaseDetection/YOLOX/blob/main/yolox/models/yolox.py "YOLOX/yolox/models/yolox.py at main · Megvii-BaseDetection/YOLOX · GitHub" \[4\]: https://github.com/Megvii-BaseDetection/YOLOX/blob/main/yolox/models/darknet.py "YOLOX/yolox/models/darknet.py at main · Megvii-BaseDetection/YOLOX · GitHub" \[5\]: https://github.com/Megvii-BaseDetection/YOLOX/blob/main/yolox/models/yolo_pafpn.py "YOLOX/yolox/models/yolo_pafpn.py at main · Megvii-BaseDetection/YOLOX · GitHub" \[6\]: https://github.com/Megvii-BaseDetection/YOLOX/blob/main/yolox/models/yolo_head.py "YOLOX/yolox/models/yolo_head.py at main · Megvii-BaseDetection/YOLOX · GitHub" \[7\]: https://github.com/Megvii-BaseDetection/YOLOX/blob/main/README.md "YOLOX/README.md at main · Megvii-BaseDetection/YOLOX · GitHub" \[8\]: https://yolox.readthedocs.io/en/latest/demo/trt_py_readme.html?utm_source=chatgpt.com "YOLOX-TensorRT in Python" \[9\]: https://yolox.readthedocs.io/en/latest/demo/onnx_readme.html "YOLOX-ONNXRuntime in Python --- YOLOX 0.2.0 documentation" \[10\]: https://yolox.readthedocs.io/en/latest/demo/openvino_py_readme.html "YOLOX-OpenVINO in Python --- YOLOX 0.2.0 documentation" \[11\]: https://yolox.readthedocs.io/en/latest/demo/openvino_cpp_readme.html "YOLOX-OpenVINO in C++ --- YOLOX 0.2.0 documentation" \[12\]: https://yolox.readthedocs.io/en/latest/demo/ncnn_cpp_readme.html?utm_source=chatgpt.com "YOLOX-CPP-ncnn" \[13\]: https://yolox.readthedocs.io/en/latest/demo/ncnn_android_readme.html?utm_source=chatgpt.com "YOLOX-Android-ncnn"

相关推荐
组合缺一1 小时前
Solon AI Harness 首次发版
java·人工智能·ai·llm·agent·solon
星幻元宇VR1 小时前
VR环保学习机|开启沉浸式环保教育新时代
大数据·人工智能·科技·安全·vr·虚拟现实
海兰2 小时前
【实战】HiMarket本地化部署指南
人工智能·ubuntu·架构·银行系统
zhangshuang-peta2 小时前
MCP:把不确定性变成工程能力
人工智能·ai agent·mcp·peta
哥布林学者2 小时前
深度学习进阶(三)Transformer Block
机器学习·ai
UXbot2 小时前
UXbot 是什么?一句指令生成完整应用的 AI 工具
前端·ai·交互·个人开发·ai编程·原型模式·ux
m0_564876842 小时前
提示词工程手册学习
人工智能·python·深度学习·学习
发光小北2 小时前
SG-UHF110 系列远距离超高频 RFID 读写器如何应用?
服务器·网络
Blurpath住宅代理2 小时前
社交媒体数据采集技术指南:从合规获取到营销洞察
网络·爬虫·动态代理·数据抓取·住宅ip·住宅代理