3. YOLO模型训练与部署准备
在FPGA上实现YOLO实时检测加速器之前,必须先在PC端完成一个“可训练、可验证、可导出”的模型准备闭环。这一章的核心目标不是追求最高mAP,而是得到一个结构干净、算子友好、量化可落地的YOLO模型,并把它稳定地导出为ONNX,为后续的定点量化、硬件映射和上板调试提供输入。很多上板失败的问题,根源其实在训练与导出阶段就已经埋下。
一、数据集构建:从采集到划分
YOLO是监督学习模型,数据质量直接决定部署上限。数据集构建通常包含采集、清洗、标注、划分四个步骤。采集时要覆盖真实部署场景的光照、角度、遮挡和运动模糊;清洗时剔除重复帧、严重失焦和错误标注;划分时按场景或时间段切分训练集、验证集和测试集,避免同一视频的相邻帧同时出现在训练和验证中造成“数据泄漏”。
一个典型的数据集目录结构如下:
dataset/
├── images/
│ ├── train/ (约70%)
│ ├── val/ (约20%)
│ └── test/ (约10%)
├── labels/
│ ├── train/
│ ├── val/
│ └── test/
└── data.yaml
其中 data.yaml 描述类别数与路径:
path: ./dataset
train: images/train
val: images/val
test: images/test
nc: 3
names: ['person', 'car', 'bicycle']
二、标注格式:YOLO txt 与坐标归一化
YOLO使用每张图一个 .txt 的标注文件,每行表示一个目标,格式为:
class_id x_center y_center width height
四个坐标均为相对图像宽高的归一化值,范围0~1。例如图像宽640、高480,目标框中心在(320,240)、宽128、高96,则标注为:
0 0.500000 0.500000 0.200000 0.200000
常见误区是把像素坐标直接写入标注文件,导致训练时框全部偏移或缩放异常。若原始数据是VOC XML或COCO JSON,可用脚本批量转换。转换后务必用可视化脚本抽查若干张,确认框与目标对齐。
三、训练环境搭建与模型训练
推荐使用Python 3.9+、PyTorch 2.x、CUDA 11.8/12.x,并安装Ultralytics YOLO框架。环境安装命令示例:
conda create -n yolo python=3.10 -y
conda activate yolo
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
pip install ultralytics onnx onnxruntime opencv-python
以YOLOv8n为例,训练命令如下:
yolo detect train \
model=yolov8n.pt \
data=dataset/data.yaml \
epochs=100 \
imgsz=640 \
batch=16 \
device=0 \
project=runs/train name=yolo_fpga
训练过程中重点关注三类曲线:损失下降是否平稳、mAP@0.5与mAP@0.5:0.95是否持续上升、验证集是否过早饱和或过拟合。若验证损失上升而训练损失继续下降,应减小模型规模或增强数据增广。
四、模型验证与导出ONNX
训练完成后,用验证集评估模型:
yolo detect val model=runs/train/yolo_fpga/weights/best.pt data=dataset/data.yaml imgsz=640
确认mAP与推理速度满足预期后,导出ONNX。FPGA部署通常要求固定输入尺寸、固定batch=1、opset版本与推理引擎匹配:
yolo export model=best.pt format=onnx imgsz=640 opset=12 simplify=True dynamic=False
导出后必须用onnxruntime做一次数值一致性检查,确认ONNX输出与PyTorch输出误差在可接受范围内:
import onnxruntime as ort
import numpy as np
sess = ort.InferenceSession("best.onnx")
x = np.random.randn(1,3,640,640).astype(np.float32)
out = sess.run(None, {sess.get_inputs()[0].name: x})
print(out[0].shape)
五、常见问题与复盘清单
| 问题现象 | 可能原因 | 处理建议 |
|---|---|---|
| 训练loss不下降 | 标注坐标未归一化、类别ID越界 | 检查txt格式与data.yaml类别数 |
| mAP正常但ONNX输出异常 | 导出时dynamic轴或opset不兼容 | 固定输入尺寸,opset设为11/12 |
| ONNX包含大量自定义算子 | 使用了非标准后处理或插件 | 导出时simplify,剥离后处理 |
| 量化后精度骤降 | 激活分布极端、缺少校准集 | 增加校准样本,检查BN融合 |
| 上板后检测框错位 | 预处理归一化方式不一致 | 统一letterbox与归一化参数 |
完成本章后,你应当得到一个经过验证的ONNX模型,并清楚它的输入输出张量形状、算子组成和量化敏感层。这些信息将直接决定后续定点量化策略与FPGA数据通路的位宽设计。