YOLOv8模型基础与导出:从网络结构到ONNX

好,咱们正式开始动手前的热身环节。
YOLOv8的结构、训练保存、导出ONNX——这三件事搞明白,后面所有部署工作才能站得住脚。
我见过不少同学,模型训完直接拿PyTorch的.pt文件往生产环境塞,结果推理慢得离谱,还各种报错。
说白了,部署的第一步,就是搞清楚你的模型到底长什么样,以及怎么把它变成通用格式。

YOLOv8网络结构速览

YOLOv8的结构,我习惯把它拆成三块来看:

  • Backbone(主干网络):负责提取特征。YOLOv8用的是CSPDarknet的改进版,加入了C2f模块。
  • Neck(颈部):负责融合多尺度特征。FPN+PAN结构,让不同尺寸的目标都能被照顾到。
  • Head(检测头):负责输出预测结果。YOLOv8换成了解耦头(Decoupled Head),分类和回归分开走。

为什么这么设计?
你想想看,工业场景里目标大小差异很大——一个画面里可能既有大设备,又有小螺丝。
Backbone提取基础特征,Neck把深浅层信息揉在一起,Head再各自干活。分工明确,效率才高。

核心变化:YOLOv8相比v5,最大的改动就是Head部分。v5的耦合头把分类和回归绑在一起,v8解耦后,收敛更快,精度也更高。我在项目中实测过,同样数据下mAP能涨1-2个点。

下面这张图,是我自己画的结构简图,帮你快速建立整体认知:

YOLOv8 网络结构简图 Backbone (CSPDarknet) Neck (FPN+PAN) Head (Decoupled) C2f 模块 跨阶段局部连接 梯度分流更丰富 比v5的C3更轻量 多尺度融合 FPN: 自上而下传递语义 PAN: 自下而上传递位置 适合大小目标混检 解耦头 分类分支: 2个Conv 回归分支: 2个Conv 收敛更快,精度更高 输入: 640×640×3 → 输出: 8400×(4+1+num_classes) 8400个预测框,每个框包含: 类别概率 + 边界框坐标 + 置信度 NMS后处理去除冗余框,保留最终检测结果

PyTorch模型训练与权重保存

训练这块,我不打算讲太多理论——网上教程一抓一大把。
我重点说说权重保存的那些坑,这才是部署环节最容易翻车的地方。

训练流程速览

  1. 准备数据:标注格式转成YOLO格式(txt文件,每行一个目标)。
  2. 配置yaml文件:指定数据路径、类别数、类别名。
  3. 选择预训练权重:yolov8n.pt / yolov8s.pt / yolov8m.pt 等。
  4. 开始训练:yolo train model=yolov8n.pt data=coco128.yaml epochs=100
  5. 保存权重:训练完成后,runs/detect/train/weights/ 下会有 best.pt 和 last.pt。

我的习惯:训练时把 patience 设成 20-30 个epoch,早停机制能帮你省不少时间。另外,batch 大小根据显存来,别贪大——我见过有人把batch设到64,结果显存爆了,白跑半天。

权重文件里到底有什么?

很多人以为 .pt 文件就是个模型结构,其实不是。
PyTorch的 .pt 文件是一个字典,里面包含:

键名 内容 部署时是否需要
model 模型的状态字典(state_dict) ✅ 需要
epoch 当前训练轮数 ❌ 不需要
optimizer 优化器状态 ❌ 不需要
best_score 最佳mAP分数 ❌ 不需要
args 训练参数 ❌ 不需要

看到了吧?
一个 .pt 文件里,真正对部署有用的只有 model 这一项。
其他都是训练过程的“副产品”。

注意:千万不要直接把训练好的 .pt 文件扔到生产环境去推理!
原因有三:1) 文件体积大,加载慢;2) 依赖PyTorch环境;3) 推理速度远不如优化后的格式。
正确的做法是:先导出成ONNX,再转成TensorRT或OpenVINO。

导出为ONNX格式

ONNX(Open Neural Network Exchange)说白了就是模型界的“通用语言”。
不管你是用PyTorch、TensorFlow还是其他框架训的模型,都能转成ONNX。
然后ONNX又可以转成各种推理引擎的格式——TensorRT、OpenVINO、ONNX Runtime都支持。

导出命令

YOLOv8官方已经封装好了导出接口,一行命令搞定:

yolo export model=best.pt format=onnx opset=12

或者用Python代码:

from ultralytics import YOLO

model = YOLO('best.pt')
model.export(format='onnx', opset=12, dynamic=True)

关键参数说明

参数 说明 建议值
opset ONNX算子集版本 12 或 13(兼容性好)
dynamic 是否支持动态batch True(工业场景推荐)
simplify 是否简化模型结构 True(减少冗余算子)
imgsz 输入图像尺寸 640(与训练时一致)

避坑指南:
我曾经在导出时忘了设 dynamic=True,结果模型只能接受固定batch size的输入。
到了生产环境,客户端传来的图片数量不固定,推理服务直接报错。
后来排查了半天才发现是这个问题。所以,工业场景下务必开启动态batch。

导出后的验证

导出完别急着走,先验证一下ONNX模型能不能正常跑:

import onnx
import onnxruntime as ort

# 检查模型结构
onnx_model = onnx.load('best.onnx')
onnx.checker.check_model(onnx_model)

# 用ONNX Runtime跑一次推理
session = ort.InferenceSession('best.onnx')
input_name = session.get_inputs()[0].name
output_name = session.get_outputs()[0].name

import numpy as np
dummy_input = np.random.randn(1, 3, 640, 640).astype(np.float32)
result = session.run([output_name], {input_name: dummy_input})
print('ONNX导出成功,输出shape:', result[0].shape)

如果这一步没报错,恭喜你,模型已经成功从PyTorch的“温室”里搬出来了。
接下来就可以进入下一阶段的优化和部署了。

小技巧:用 onnx-simplifier 工具再跑一遍简化,能去掉很多冗余的Shape和Reshape算子。
安装命令:pip install onnx-simplifier,然后 python -m onnxsim best.onnx best_simplified.onnx。
简化后的模型体积更小,推理速度也能提升5%-10%。

本章小结

咱们这一章把YOLOv8的底牌翻了个底朝天:

  • 网络结构:Backbone提取特征 → Neck融合多尺度 → Head解耦输出
  • 权重保存:.pt文件里只有model是部署需要的,其他都是训练垃圾
  • ONNX导出:一行命令搞定,但别忘了开dynamic和simplify

嗯,到这里,你的模型已经准备好“走出实验室”了。
下一阶段,咱们就要开始真正的手艺活了——模型量化与精度调优。