社交媒体

YOLO11 训练实战、指标解读与通用模型训练指南

YOLO11 训练实战、指标解读与通用模型训练指南

摘要:本文基于一套可复用的 YOLO11 训练包,完整介绍如何在 GPU 服务器上训练单类别「抛洒物(spill)」检测模型:从环境搭建、目录约定、数据格式、单卡/多卡训练,到验证指标解读与结果复盘;并总结换其他检测任务时的通用打法。
适合读者:具备基础 Linux / Python 能力,希望快速把目标检测落到业务场景的工程师。
技术栈:Ultralytics YOLO11 · PyTorch · CUDA · 可选多卡 DDP


目录

  1. 业务问题与技术选型

  2. 仓库地图:一眼看懂每个目录

  3. 环境搭建:从驱动到 ultralytics

  4. 数据约定:yaml、标签与检查清单

  5. 开始训练:单卡、多卡与常见卡点

  6. 训练结果(1k 实验)与指标解释

  7. 权重怎么选、怎么推理

  8. 换任务的通用方法论

  9. 排错速查与交付清单

  10. 结语


1. 业务问题与技术选型

道路、隧道、城市道路监控里,「抛洒物」是一类高频风险:纸箱、编织袋、轮胎碎片、施工遗留物等,可能引发追尾或二次事故。业务侧通常需要:

  • 有没有抛洒物(检出)

  • 在哪里(定位框)

  • 能不能稳定上线(可训练、可复现、可交付)

从算法看,这就是标准的 单类别目标检测:一张图里找出所有 spill 目标。

我们没有从零造检测器,而是选择 Ultralytics YOLO11:

选择

原因

YOLO11

预训练充分,微调成本低,生态成熟

单类 spill

业务定义清晰,标注与评估都更简单

脚本封装

把 GPU 选卡、多卡 DDP、默认超参收成一条命令

预训练 → 微调

用 COCO 预训练的 yolo11n.pt 作起点,适配垂直场景

整条链路可以概括为:

标注数据 → spill_data.yaml → YOLO11 预训练权重
        → train_yolo11_spill_gpu.sh(单卡/多卡)
        → best.pt → 业务推理 / 部署

2. 仓库地图:一眼看懂每个目录

先建立「空间感」。建议把仓库理解成四块:原料、底模、生产线、成品。

spill_yolo11_gpu_training/
│
├── datasets/                         【原料】模型吃什么
│   ├── spill_data.yaml               ← 数据说明书:路径 / 类数 / 类名
│   ├── train/{images,labels}/        ← 训练图 + 同名 YOLO 标签
│   └── valid/{images,labels}/        ← 验证图 + 标签(选 best、早停靠它)
│
├── models/
│   ├── pretrained/yolo11n.pt         【底模】COCO 预训练起点
│   └── trained/                      【成品】训完后的交付权重与 CSV
│       ├── yolo11n_spill_1k_best.pt
│       └── yolo11n_spill_1k_results.csv
│
├── scripts/                          【生产线】怎么训
│   ├── train_yolo11_spill.py         ← Python:参数 → Ultralytics
│   └── train_yolo11_spill_gpu.sh     ← Shell:环境变量 → 调 Python
│
├── results/charts/                   【复盘】曲线图
│   └── yolo11n_spill_1k_curves.png
│
├── docs/                             【说明】运维细则与本文
├── requirements-gpu.txt              【依赖】ultralytics 等(不含 PyTorch)
├── README.md / README-CN.md
└── runs/                             【实验产物】训练时自动生成

目录用途对照表

路径

一句话

你会不会经常改

datasets/

数据与类别定义

换任务必改

models/pretrained/

起跑用的公开预训练权重

换更大模型时改

models/trained/

交付给业务的权重

训完复制进来

scripts/

启动训练的入口

一般只改参数,不改逻辑

results/charts/

给人看的曲线

复盘时看

runs/

Ultralytics 自动写出的完整实验目录

体积大,按需清理

docs/

文档

阅读即可

记忆口诀:数据在 datasets,起点在 pretrained,命令在 scripts,交付在 trained。


3. 环境搭建:从驱动到 ultralytics

检测训练的「环境坑」往往比算法更耗时。按下面顺序确认即可。

3.1 确认 GPU 驱动

nvidia-smi

能看到 GPU 名称、驱动版本、显存,就说明驱动层正常。同时记下可见卡数,后面多卡要用。

3.2 创建独立 conda 环境

conda create -n spill-yolo11 python=3.11 -y
conda activate spill-yolo11

不要用系统自带 Python 硬装依赖,避免权限与版本污染。

3.3 安装带 CUDA 的 PyTorch

仓库里的 requirements-gpu.txt 不包含 PyTorch,需按 CUDA 版本单独安装。本训练包验证过的组合接近 torch 2.x + cu128:

python -m pip install --upgrade pip
python -m pip install torch torchvision --index-url https://download.pytorch.org/whl/cu128

若驱动较旧,请到 PyTorch 官网 选择匹配的 CUDA 版本。

3.4 安装训练依赖

在仓库根目录:

python -m pip install -r requirements-gpu.txt

会安装 ultralytics、opencv-python-headless、pyyaml、pandas、tqdm 等。

3.5 环境自检(必做)

python - <<'PY'
import torch, ultralytics
print("torch:", torch.__version__)
print("cuda:", torch.version.cuda)
print("available:", torch.cuda.is_available())
print("gpu count:", torch.cuda.device_count())
print("ultralytics:", ultralytics.__version__)
if torch.cuda.is_available():
    print("gpu0:", torch.cuda.get_device_name(0))
PY

通过标准:available: True,且 gpu count >= 1。
若 CUDA 不可用,先不要开训——优先排查驱动与 PyTorch CUDA 版本是否匹配。


4. 数据约定:yaml、标签与检查清单

4.1 数据说明书 spill_data.yaml

train: train/images
val: valid/images

nc: 1
names:
  0: spill

三件事说清楚:

  1. 训练图在哪、验证图在哪

  2. 一共几类(nc: 1)

  3. 每类叫什么(0 → spill)

路径相对 datasets/ 目录解析。

4.2 YOLO 标签格式

每张 xxx.jpg 对应 xxx.txt,每行一个框:

0 0.512 0.448 0.091 0.056

字段

含义

0

类别 ID(抛洒物任务必须为 0)

0.512

框中心 x(相对图片宽,0~1)

0.448

框中心 y(相对图片高,0~1)

0.091

框宽(相对图片宽)

0.056

框高(相对图片高)

4.3 开训前检查清单

  1. train/images 与 train/labels 基本一一对应

  2. valid/ 非空(否则难以选出可信 best.pt)

  3. 所有标签类别 ID 仅为 0

  4. 在仓库根目录执行脚本,而不是在 scripts/ 里套路径


5. 开始训练:单卡、多卡与常见卡点

5.1 单卡(默认)

conda activate spill-yolo11
cd /path/to/spill_yolo11_gpu_training

bash scripts/train_yolo11_spill_gpu.sh

默认大致为:

项

默认

数据

datasets/spill_data.yaml

底模

models/pretrained/yolo11n.pt

设备

DEVICE=0

Batch

16

输入尺寸

960

Epochs

150

输出

runs/spill_yolo11/yolo11n_spill_gpu/

5.2 多卡(以 8 卡为例)

DEVICE=0,1,2,3,4,5,6,7 \
BATCH=128 \
NAME=yolo11n_spill_8gpu \
bash scripts/train_yolo11_spill_gpu.sh

说明:

  • DEVICE 为本地可见卡号列表,Ultralytics 走 DDP

  • BATCH 建议随卡数近似放大(单卡 16 → 8 卡约 128)

  • 换独立 NAME,避免覆盖旧实验目录

限定物理卡再训练:

CUDA_VISIBLE_DEVICES=4,5 DEVICE=0,1 BATCH=32 \
NAME=yolo11n_spill_gpu45_2gpu \
bash scripts/train_yolo11_spill_gpu.sh

物理 4、5 会被映射成进程内 0、1,因此 DEVICE 只能写 0,1。

5.3 日志读到哪一步算「正式开训」

初始化阶段常见:

Overriding model.yaml nc=80 with nc=1
Transferred ... items from pretrained weights
AMP: running Automatic Mixed Precision (AMP) checks...

含义:检测头已从 COCO 80 类改为 1 类,预训练权重已迁移,正在做混合精度检查。
真正进入训练要看到类似:

Starting training for 150 epochs...
1/150 ...

5.4 AMP 卡在下载?

若停在下载 yolo26n.pt,那是 AMP 自检临时拉小模型,不是任务模型被替换。外网差时:

AMP=False DEVICE=0,1,2,3,4,5,6,7 BATCH=128 \
bash scripts/train_yolo11_spill_gpu.sh

6. 训练结果(1k 实验)与指标解释

本节展示本项目在约 1k 量级、类别干净(仅 class 0) 数据上的一次完整实验结果。对应权重与曲线:

  • 权重:models/trained/yolo11n_spill_1k_best.pt

  • 日志:models/trained/yolo11n_spill_1k_results.csv

  • 曲线:results/charts/yolo11n_spill_1k_curves.png

6.1 结果总表

项目

数值

模型

YOLO11n

训练轮数

150

Best Epoch

150

mAP50

0.926

mAP50-95

0.626

Precision(精确率)

0.920

Recall(召回率)

0.892

6.2 训练过程关键节点

Epoch

mAP50

mAP50-95

train/box_loss

train/cls_loss

阶段感受

1

0.000

0.000

3.80

9.91

刚起步,几乎不会检

10

0.005

0.002

1.74

1.58

损失快速下降

20

0.629

0.361

1.38

1.00

验证指标跃升

50

0.817

0.530

1.34

0.79

进入可用区间

100

0.883

0.576

1.12

0.66

持续变稳

150

0.926

0.626

0.83

0.43

本次最优

可以看到:前 20 个 epoch 指标爬升最快,之后是「变稳、变准」的细磨阶段。本次实验中 best 与 last 同为第 150 轮,说明训练结束时验证集仍在受益,没有明显后期崩盘。

6.3 训练曲线

图中通常包含四块:

  1. Validation mAP:看模型「越训越好不好」

  2. Precision / Recall:看「检得准不准、漏不漏」

  3. Train loss:看优化是否在收敛

  4. Val loss:辅助判断是否过拟合

6.4 指标解释(对外评审最常问)

先记住一张关系图:

模型预测框 ──IoU──► 与真值框是否算「配对成功」
        │
        ├─ 算进 TP / FP ──► Precision / Recall
        └─ 在不同 IoU 阈值下平均 ──► mAP50 / mAP50-95

IoU(交并比)是什么?

预测框与标注框的重叠程度:

\mathrm{IoU} = \frac{面积_{交集}}{面积_{并集}}

IoU 越高,框得越准。检测里常用阈值(如 0.50)判断「这个预测算不算检对了」。

Precision(精确率)

\mathrm{Precision} = \frac{TP}{TP + FP}

  • 高:报出来的框里,误报少(「说有抛洒物时更可信」)

  • 低:容易「草木皆兵」,把正常路面也框成抛洒物

本次 0.920:平均而言,模型给出的阳性结果里约九成靠谱。

Recall(召回率)

\mathrm{Recall} = \frac{TP}{TP + FN}

  • 高:真抛洒物漏得少

  • 低:漏检多,安全场景里往往更危险

本次 0.892:大部分真实目标能被找回。业务若更怕漏检,可在推理时适当降低 conf 阈值换更高召回(同时可能增加误报)。

mAP50

在 IoU = 0.50 阈值下的平均精度(Average Precision)。
相对宽松:框得大致对就算检中。适合作为「模型有没有学会这个类」的第一眼指标。

本次 0.926:在 0.5 IoU 标准下表现很强。

mAP50-95

在 IoU 从 0.50 到 0.95、步长 0.05 多个阈值上的平均 mAP。
更严格:不仅要「找得到」,还要「框得准」。工业界常把它看作比 mAP50 更「硬核」的定位质量指标。

本次 0.626:低于 mAP50 是正常现象——阈值变严后分数一定会掉。若业务强依赖精确落框(例如联动测距/告警区域),应更关注 mAP50-95,并考虑加大 IMGSZ 或换更大模型继续抠定位。

和 Loss 的关系

曲线

作用

box_loss

框回归好不好

cls_loss

分类(本任务几乎只有「是不是 spill」)好不好

dfl_loss

边界分布相关的定位辅助损失

Loss 下降 ≠ 业务可用;最终仍以验证集 mAP / P / R 为准。
反过来:若 train loss 一直降、val mAP 却长期接近 0,优先怀疑 验证集标注/类别与 yaml 不一致,而不是盲目加大模型。

6.5 如何理解这组数(业务语言)

一句话给产品/业务同学:

在当前 1k 规模、标注干净的验证集上,模型大约能找回 89% 的抛洒物,报出的结果里约 92% 是对的;在「框得比较准」的宽松标准(IoU=0.5)下综合表现约 0.93,在更严格的定位标准下约 0.63。

上线前仍建议:用真实摄像头回流数据做一次业务抽检,并按场景调 conf / iou 阈值。


7. 权重怎么选、怎么推理

7.1 best.pt vs last.pt

文件

含义

用途

best.pt

验证指标最好的一轮

交付、推理、部署

last.pt

训练结束时最后一轮

断点续训

本次 1k 实验中两者同为第 150 轮,但习惯上对外仍发布 best.pt 命名的交付件。

7.2 归档建议

mkdir -p models/trained
cp runs/spill_yolo11/<NAME>/weights/best.pt \
   models/trained/yolo11n_spill_1k_best.pt

7.3 最小推理代码

from ultralytics import YOLO

model = YOLO("models/trained/yolo11n_spill_1k_best.pt")
results = model.predict(
    "path/to/image.jpg",
    imgsz=960,   # 尽量与训练接近
    conf=0.25,   # 阈值可按业务调
)
results[0].show()
# results[0].save()  # 如需落盘可视化结果

8. 换任务的通用方法论

抛洒物只是「单类/少类检测」的一个实例。换成安全帽、烟火、行人、裂纹,流水线几乎不变,变的是数据与命名。

8.1 永远不变的五步

1. 准备 YOLO 格式数据(images + labels)
2. 编写 data.yaml(路径 + nc + names)
3. 选择预训练权重(yolo11n / s / m ...)
4. 启动训练(单卡或 DEVICE=0,1,...)
5. 使用 best.pt 做验证与业务接入

8.2 一定要改的

项

做法

类别定义

改 nc、names,并保证标签 ID 一致

数据路径

新的 train/、valid/

yaml 文件

新建,如 datasets/helmet_data.yaml

实验名

新的 NAME / PROJECT,避免覆盖

三类别示例:

train: train/images
val: valid/images

nc: 3
names:
  0: helmet
  1: no_helmet
  2: person

8.3 常常要拧的旋钮

参数

何时调整

IMGSZ

小目标多:960 → 1280(显存上升)

BATCH

显存有余量就加大;OOM 就减小

MODEL

先 n 跑通,再尝试 s/m

EPOCHS / PATIENCE

数据更大或收敛慢时加长

AMP

外网差、检查卡死时关闭

8.4 推荐的「换皮」顺序

  1. 保持目录结构,只换数据内容

  2. 新建 yaml,不覆盖旧任务配置

  3. 人工抽查 20 张:框准不准、ID 对不对

  4. 小规模短训,确认链路与指标方向

  5. 全量训练,独立 NAME

  6. 按规范归档:yolo11n_<task>_best.pt

即使不改脚本文件名,也可以纯靠环境变量切换任务:

DATA=datasets/helmet_data.yaml \
PROJECT=runs/helmet_yolo11 \
NAME=yolo11n_helmet_8gpu \
DEVICE=0,1,2,3,4,5,6,7 \
BATCH=128 \
bash scripts/train_yolo11_spill_gpu.sh

脚本叫什么不重要,DATA 和数据内容才决定任务。


9. 排错速查与交付清单

9.1 排错速查

现象

优先怀疑

No module named 'ultralytics'

环境未激活,或未安装依赖

cuda available: False

PyTorch CUDA 与驱动不匹配

Invalid CUDA device

设置可见卡后仍写物理编号

停在 AMP Downloading

外网慢 → AMP=False

显存只用四成左右

n 模型常见;可加大 BATCH/IMGSZ

loss ↓ 但 mAP≈0

验证集类别/标注与 yaml 不一致

找不到脚本

未在仓库根目录执行

9.2 对外交付清单

开训前

  • nvidia-smi 正常

  • import torch, ultralytics 成功且 CUDA 可用

  • yaml 与标签类别一致

  • train/valid 非空、类别干净

交付时

  • 发布 best.pt

  • 记录:NAME、MODEL、IMGSZ、数据版本、关键指标

  • 附上 results.csv 与曲线图

  • 业务侧确认推理 imgsz/conf 与训练同量级,并做实景抽检


10. 结语

抛洒物检测并不需要神秘配方。把它拆开,就是:

干净的单类 YOLO 数据 + 一份 yaml + YOLO11 预训练权重 + 可配置的 GPU 训练入口。

本训练包已经帮你收好了目录约定、默认超参、单卡/多卡启动方式。你只要:

  1. 看懂 datasets / models / scripts 各自负责什么;

  2. 把环境验到 CUDA 可用;

  3. 跑通训练,拿走 best.pt;

  4. 换任务时优先换数据与 yaml,用环境变量切换实验名。

在约 1k、标注干净的实验中,模型达到 mAP50 ≈ 0.926、mAP50-95 ≈ 0.626、Precision ≈ 0.920、Recall ≈ 0.892,说明这条流水线足以支撑垂直场景的第一版可用模型;后续优化重点通常在 更多真实回流数据、更干净的验证集、以及按业务权衡召回与误报。


本文为对外技术分享整理,基于 YOLO11 Spill Detection 训练包的真实 1k 实验与工程实践。