news 2026/9/29 3:49:38

【YOLO系列】YOLO v5 网络结构图+代码:从 SPPF 到 ONNX 的配置与验证

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【YOLO系列】YOLO v5 网络结构图+代码:从 SPPF 到 ONNX 的配置与验证

1. 从 SPPF 出发:YOLO v5 网络结构图到底该怎么看

如果你刚把 YOLO v5 的代码 clone 下来,打开models/yolov5s.yaml,大概率会有点懵:backbone、neck、head 三段配置里全是[-1, 1, Conv, [64, 6, 2, 2]]这种列表,光看数字根本对不上论文里的结构图。更别说 SPPF、C3、CSP-PAN 这些模块名,第一次见完全不知道它们在图里的哪个位置。

这篇就聚焦一件事:把 YOLO v5 的网络结构图、yaml 配置和实际代码对应起来,以 SPPF 模块为切入点,梳理 backbone/neck/head 的关键层,然后给你一份可以直接复制的模型配置骨架,最后用 ONNX 导出 + 推理验证走一遍端到端流程。适合已经装好环境、想搞清楚"结构图上的框到底对应哪行代码"的人。

YOLO v5 从 2020 年发布到现在更新了多个版本,第六版之后结构基本定型:backbone 是 New CSP-Darknet53,neck 是 SPPF + New CSP-PAN,head 沿用 YOLO v3 Head 的思路但用 C3 替代了原来的五层卷积。五个尺寸(n/s/m/l/x)结构完全一样,区别只在depth_multiple和width_multiple两个缩放因子。理解这一点,你看任何一张 YOLO v5 结构图都不会再被通道数迷惑。

2. 前置准备:环境、权重与 TaoToken 接入

在动手改配置之前,先把环境和模型文件准备好。我习惯用 conda 隔离:

conda create -n yolov5 python=3.10 -y conda activate yolov5 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt

权重文件放在models/目录下,官方提供 yolov5n/s/m/l/x 五个预训练 pt。如果你只是验证结构,用yolov5s.pt就够了,体积小、导出快。

如果你在调试过程中需要调用大模型来辅助读代码、解释报错,或者想把结构分析结果接到自己的 Agent 流程里,可以用 TaoToken 做统一接入。它的 API 地址是https://taotoken.net/api,兼容 OpenAI 风格的调用方式,模型对话入口在 模型对话,长期做编码或 Agent 任务可以看 Coding Plan。Key 在 API Keys 页面生成,接入细节参考 接入文档。

注意:TaoToken 在这里的角色是辅助你读代码、查报错的工具,不是替代 YOLO v5 本身的推理框架。模型导出和推理还是走 PyTorch/ONNX Runtime。

3. 可复制配置:SPPF 与 backbone/neck/head 骨架

3.1 SPPF 为什么替代了 SPP

先看 SPP 和 SPPF 的区别,这是结构图上最容易混淆的一处。

SPP 的三个最大池化层 kernel size 不一样(比如 5、9、13),但输入都是同一份特征图,最后 concat 起来。SPPF 则是三个 kernel size 相同的最大池化层(都是 5),但后两个的输入是前一个的输出,形成串行结构。效果等价,但 SPPF 运行时间大约快 2 倍,因为串行复用减少了重复计算。

对应到代码,models/common.py里的 SPPF 实现核心是这样:

class SPPF(nn.Module): def __init__(self, c1, c2, k=5): super().__init__() c_ = c1 // 2 self.cv1 = Conv(c1, c_, 1, 1) self.cv2 = Conv(c_ * 4, c2, 1, 1) self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2) def forward(self, x): x = self.cv1(x) y1 = self.m(x) y2 = self.m(y1) y3 = self.m(y2) return self.cv2(torch.cat((x, y1, y2, y3), 1))

结构图上 SPPF 那个框,对应的就是这段:先 1x1 卷积降通道,然后三次串行 maxpool,最后 concat 四个分支再 1x1 卷积升回去。

3.2 yaml 配置骨架

以yolov5s.yaml为例,去掉注释后的骨架如下。你可以直接复制这份,改通道数或 depth/width 因子来生成自己的变体:

# YOLOv5 v6.0 backbone backbone: [[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2 [-1, 1, Conv, [128, 3, 2]], # 1-P2/4 [-1, 3, C3, [128]], [-1, 1, Conv, [256, 3, 2]], # 3-P3/8 [-1, 6, C3, [256]], [-1, 1, Conv, [512, 3, 2]], # 5-P4/16 [-1, 9, C3, [512]], [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32 [-1, 3, C3, [1024]], [-1, 1, SPPF, [1024, 5]], # 9 ] # YOLOv5 v6.0 head head: [[-1, 1, Conv, [512, 1, 1]], [-1, 1, nn.Upsample, [None, 2, 'nearest']], [[-1, 6], 1, Concat, [1]], # cat backbone P4 [-1, 3, C3, [512, False]], # 13 [-1, 1, Conv, [256, 1, 1]], [-1, 1, nn.Upsample, [None, 2, 'nearest']], [[-1, 4], 1, Concat, [1]], # cat backbone P3 [-1, 3, C3, [256, False]], # 17 (P3/8-small) [-1, 1, Conv, [256, 3, 2]], [[-1, 14], 1, Concat, [1]], # cat head P4 [-1, 3, C3, [512, False]], # 20 (P4/16-medium) [-1, 1, Conv, [512, 3, 2]], [[-1, 10], 1, Concat, [1]], # cat head P5 [-1, 3, C3, [1024, False]], # 23 (P5/32-large) [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) ]

几个关键点对照结构图看:

结构图位置yaml 行模块作用
Backbone 末端第 9 行SPPF多尺度池化,扩大感受野
Neck 上采样第 11、15 行Upsample特征金字塔自顶向下
Neck 拼接第 12、16、19、22 行Concat融合不同尺度特征
Head 输出第 24 行Detect三个尺度预测头

depth_multiple控制 C3 的重复次数,width_multiple控制每层通道数。比如 yolov5n 的 depth=0.33、width=0.25,所以 C3 的 3 次会变成 1 次,通道 64 会变成 16。这就是为什么五个模型结构图一样但参数差很多。

3.3 AutoAnchor 与 anchors 配置

yaml 里还有一行anchors: 3,表示每个输出层分配 3 个 anchor。YOLO v5 默认用 AutoAnchor,通过 k-means 在训练集上自动聚类 anchor 尺寸,不用手工选。核心函数在utils/autoanchor.py的kmean_anchors,适应度计算逻辑是:

def metric(k, wh): r = wh[:, None] / k[None] x = torch.min(r, 1 / r).min(2)[0] return x, x.max(1)[0] def anchor_fitness(k): _, best = metric(torch.tensor(k, dtype=torch.float32), wh) return (best * (best > thr).float()).mean()

如果你要自定义 anchor,训练时加--noautoanchor参数即可。

4. 验证请求:ONNX 导出与推理校验

配置看完,必须实际导出一次才能确认结构理解无误。YOLO v5 的export.py支持直接转 ONNX:

python export.py --weights models/yolov5s.pt --device cpu --opset=11 --include onnx

--opset=11是常用设置,默认 17 有些推理后端兼容性不好。导出成功后会生成models/yolov5s.onnx,同时打印每层算子信息。

然后用 ONNX 文件跑一次推理,验证导出正确:

python detect.py --weights models/yolov5s.onnx --device cpu --view-img

正常输出类似:

image 1/2 data/images/bus.jpg: 640x480 4 persons, 1 bus, 1 stop sign, 210.5ms image 2/2 data/images/zidane.jpg: 384x640 2 persons, 1 tie, 180.3ms Speed: 0.6ms pre-process, 195.4ms inference, 8.2ms NMS per image at shape (1, 3, 640, 640)

如果你在 CPU 上跑 yolov5x,推理时间可能在 1.5s~2.0s 之间,这是正常的,官方标称的 766ms 是理想条件。关键是检测结果和 pt 模型一致,说明 ONNX 导出没有丢算子。

想进一步确认 SPPF 在 ONNX 图里的位置,可以用 netron 打开 onnx 文件,搜索MaxPool节点,你会看到三个连续的 MaxPool 串在一起,那就是 SPPF 的串行池化结构。

5. 本篇常见错排查

报错一:Unsupported ONNX opset version

导出时 opset 设太高,某些推理后端不支持。解决:--opset=11或--opset=12。

报错二:RuntimeError: Input type (torch.FloatTensor) and weight type (torch.HalfTensor) should be the same

用了 FP16 权重但设备不支持。解决:导出时加--device cpu,或推理时指定--half只在 GPU 上用。

报错三:ONNX 推理结果和 pt 不一致

常见原因是预处理没对齐。检查detect.py里的letterbox是否一致,以及--img-size是否和导出时相同。导出时默认 640,推理也要 640。

报错四:ModuleNotFoundError: No module named 'onnx'

requirements.txt里 onnx 不是必装项。解决:pip install onnx onnxruntime。

报错五:SPPF 相关KeyError: 'SPPF'

用了旧版代码但 yaml 是新版。解决:确认models/common.py里有 SPPF 类,旧版只有 SPP。升级到 v6.0 之后的代码即可。

报错六:AutoAnchor 聚类报switching strategies from kmeans to random init

数据集太小或标注框太少,k-means 无法收敛。解决:这是警告不是错误,会自动 fallback 到随机初始化。数据量够大时不会出现。

6. 结构理解之后:把调试链路接起来

走到这里,你应该能对着任意一张 YOLO v5 结构图,指出 SPPF 在哪、C3 在哪、三个 Detect 头分别对应哪几行 yaml。这套"结构图 → yaml → 代码 → ONNX 验证"的链路,是我自己反复用过最稳的确认方式。

如果你在改结构、加模块的过程中需要快速查 API 用法或让模型帮你解释某段 forward 逻辑,可以用 TaoToken 的 模型对话 做辅助;要把它接进自己的编码工作流,看 Coding Plan;Key 和接入方式分别在 API Keys 和 接入文档。API 地址统一用https://taotoken.net/api。

最后一个实用技巧:改完 yaml 后,先跑python models/yolo.py --cfg models/your_model.yaml,它会打印每层的输入输出 shape 和参数量,比直接训练快得多,能在几秒内发现通道对不上的问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 3:49:08

校园网安全巡检实战:日志留存、弱口令排查与终端抽查指南

简介:这份文档面向中小学、幼儿园、职校及其他教育单位的信息安全负责人与网络管理员,围绕教育系统网络与信息安全巡检的实际工作展开,帮助读者理清巡检流程、检查要点与整改方向。内容涵盖巡检计划安排、重要设备日志备份、数据备份方式核查…

作者头像 李华
网站建设 2026/9/29 3:47:39

GPT-5+Codex登陆Azure AI:TaoToken统一Key接入配置与验证指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 3:46:34

C++状态模式实战:从std::variant到状态持久化

做了十几年C,状态模式是我在项目里用得最多、也见过最多花式跑偏的设计模式。很多人一提到状态模式,脑子里就是抽象类State、两个子类、Context里放个SetState,然后就没有然后了。这不叫高级应用,这只是把教材里的例题换了种语言抄…

作者头像 李华
网站建设 2026/9/29 3:46:28

Windows 搭建 ESP-IDF:cmd 与 VSCode 插件共用工具链

在 Windows 上折腾 ESP-IDF 开发环境,我前前后后重复装过七八次,从最早的手动 git clone 再一条条配环境变量,到后来的官方安装器,再到 VSCode 里 esp-idf 插件的一键配置,每条路都踩过坑。现在新机器到手,…

作者头像 李华