YOLO 模型训练:自定义数据集完整流程

自定义数据集完整训练流程

Ultralytics 统一训练代码

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from ultralytics import YOLO

# 加载模型
# model = YOLO("yolov8n.yaml")  # 从头训练
# model = YOLO("yolo11n.pt")    # 基于预训练权重
model = YOLO("yolo26n.pt")      # 2026推荐,边缘部署首选

# 开始训练
results = model.train(
    # 基础配置
    data="data.yaml",        # 数据集配置
    epochs=100,              # 训练轮数
    imgsz=640,               # 输入尺寸
    batch=16,                # 批次大小
    workers=8,               # 数据加载线程数
    
    # 优化器配置
    optimizer="auto",        # YOLO26自动使用MuSGD
    lr0=0.01,                # 初始学习率
    lrf=0.01,                # 最终学习率因子
    momentum=0.937,          # SGD动量
    weight_decay=0.0005,     # 权重衰减
    
    # 数据增强
    mosaic=1.0,
    mixup=0.1,
    copy_paste=0.1,
    
    # 其他配置
    device=0,                # GPU设备,"cpu"为CPU
    project="runs/train",    # 保存路径
    name="yolo26_exp1",      # 实验名称
    exist_ok=False,          # 是否覆盖
    pretrained=True,         # 使用预训练
    verbose=True,            # 详细日志
    seed=42,                 # 随机种子
)

# 验证模型
metrics = model.val()
print(f"mAP50: {metrics.box.map50:.3f}")
print(f"mAP50-95: {metrics.box.map:.3f}")

各版本训练参数差异

参数YOLOv8YOLO11YOLO26
默认优化器SGDSGDMuSGD
DFL 损失❌ 已移除
NMS 后处理❌ 原生无 NMS
小目标优化一般较好最佳 (STAL)
CPU 推理速度基准+25%+43%

损失函数详解

YOLO 的损失函数由三部分组成,每部分针对不同的学习目标:

yaml
1
2
3
4
5
# 损失权重配置 (ultralytics/cfg/default.yaml)
loss_weights:
  box: 7.5    # 边框回归损失权重
  cls: 0.5    # 分类损失权重
  dfl: 1.5    # DFL 损失权重 (仅 YOLOv8/v11)

边框回归损失 — CIoU

YOLO 使用 CIoU (Complete IoU) 作为边框回归损失。CIoU 在标准 IoU 基础上增加了中心点距离和长宽比一致性惩罚:

$$ L_{CIoU} = 1 - IoU + \frac{\rho^2(b, b_{gt})}{c^2} + \alpha v $$

  • $IoU$:预测框与真实框的交并比
  • $\rho^2(b, b_{gt})$:两个框中心点的欧氏距离
  • $c^2$:最小外接矩形的对角线长度
  • $\alpha v$:长宽比一致性惩罚项

CIoU 相比普通 IoU 损失的核心优势:即使两个框完全不重叠,梯度依然存在,模型可以持续学习。

分类损失 — BCE Loss

分类任务使用 二元交叉熵损失 (Binary Cross-Entropy)

$$ L_{cls} = -\sum_{i=1}^{C} [y_i \cdot \log(\hat{y}_i) + (1 - y_i) \cdot \log(1 - \hat{y}_i)] $$

YOLO 采用多标签分类(Multi-label Classification)而非 Softmax,因为一个锚点可能同时包含多个目标。每个类别独立计算 BCE 损失后求和。

DFL 损失 (Distribution Focal Loss)

YOLOv8/YOLO11 将边界框的四条边距建模为离散概率分布:

$$ DFL(\mathcal{S}i, \mathcal{S}{gt}) = -\sum_{k=0}^{15} \text{Cat}(k; y_{gt}) \cdot \log(\mathcal{S}_i[k]) $$

每条边由 16 个离散值表示,使模型能表达定位的不确定性。首次出现 DFL 损失时 loss 值通常在 3~5 之间,随着训练逐渐降到 1 以下。

YOLO26 的 ProgLoss

YOLO26 移除了 DFL,引入 ProgLoss (Progressive Loss Balancing)

python
1
2
3
4
5
6
# YOLO26 损失函数特点
# ❌ DFL 已移除 —— 简化训练,减少超参数
# ✅ ProgLoss:渐进式平衡 box/cls 损失权重
#     - 早期阶段:侧重分类学习 (cls 权重升高)
#     - 后期阶段:侧重边框精调 (box 权重升高)
# ✅ 损失曲线更平滑,调参更直观

ProgLoss 采用课程学习 (Curriculum Learning) 策略:训练初期模型先学会「是什么」(分类),再学会「在哪里」(定位),避免早期定位损失过大干扰分类学习。

1
2
3
4
ProgLoss weight schedule (示意):
Epoch  0-10:  cls=1.0, box=5.0  → 侧重分类
Epoch 10-30:  cls=1.0, box=7.5  → 均衡学习
Epoch 30+:    cls=0.5, box=7.5  → 侧重边框

损失权重调优建议

场景box 权重cls 权重说明
通用检测7.50.5Ultralytics 默认值
小目标为主10.00.3提升边框精度
分类精度优先5.01.0减少误检
高 IoU 要求12.00.3提升定位精度

训练调优最佳实践

学习率调优

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 小数据集:降低学习率
model.train(
    lr0=0.001,    # 从0.01降到0.001
    epochs=200,   # 增加轮数
    cos_lr=True,  # 使用余弦退火
)

# 大数据集:标准配置
model.train(
    lr0=0.01,
    epochs=100,
    warmup_epochs=3,
)

批次大小选择

GPU 显存推荐 batch模型尺寸
4GB8n/s
8GB16n/s/m
12GB32n/s/m/l
24GB64全部

多 GPU 训练

python
1
2
3
4
5
6
# 指定多个 GPU
model.train(
    device=[0, 1, 2, 3],   # 使用 4 张 GPU
    batch=64,               # 总 batch = 单卡 batch × GPU 数
    workers=8,              # 数据加载线程数
)

DDP (Distributed Data Parallel)

Ultralytics 使用 PyTorch 的 DistributedDataParallel 实现多卡训练。DDP 将模型复制到每张 GPU,每个进程独立计算梯度后通过 AllReduce 同步:

python
1
2
3
4
5
# 自动启用 DDP (无需手动配置)
model.train(
    device=[0, 1, 2, 3],
    batch=64,
)

批次大小缩放规则

显卡数单卡 batch总 batch学习率调整
11616lr0=0.01 (基准)
21632lr0=0.02
41664lr0=0.04
816128lr0=0.08

线性缩放法则 (Linear Scaling Rule):多卡训练时,学习率应随总 batch 大小线性增加。起始学习率 = 基准 lr0 × (总 batch / 单卡基准 batch)。建议配合 warmup_epochs 在前几个 epoch 逐步升温到目标学习率,防止初期梯度不稳定。

注意事项

  • Batch Normalization:DDP 默认同步 BN 统计量,多卡训练 BN 估计更准确
  • 梯度累积 (Gradient Accumulation):显存不足时可通过 accumulate 参数模拟大 batch 效果
  • 显存均衡:确保各卡的 batch 和图像尺寸一致,避免 straggler 拖慢整体速度
  • 同步种子:设置 seed=42 确保各卡初始化一致

早停与恢复训练

python
1
2
3
4
5
6
7
8
9
# 启用早停
model.train(
    patience=50,    # 50轮无提升则停止
    ...
)

# 恢复中断的训练
model = YOLO("runs/train/exp/weights/last.pt")
model.train(resume=True)

训练可视化分析

超参数搜索

使用 Ultralytics 自动调参

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from ultralytics import YOLO

model = YOLO("yolo26n.pt")

# 启动超参数搜索
result = model.tune(
    data="data.yaml",
    epochs=50,
    iterations=100,         # 搜索迭代次数
    optimizer="AdamW",      # 搜索时建议使用 AdamW
    device=0,
    batch=16,
    plots=True,             # 绘制调参过程
    save=True,              # 保存每次 trial 结果
)

搜索空间配置

Ultralytics 内置的默认搜索空间涵盖 10+ 个超参数:

yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 默认搜索空间 (ultralytics/cfg/tune.yaml)
lr0: [0.0001, 0.01]         # 初始学习率
lrf: [0.0001, 0.1]          # 最终学习率因子
momentum: [0.7, 0.99]       # SGD 动量
weight_decay: [0.0, 0.002]  # 权重衰减
warmup_epochs: [0, 5]       # 预热轮数
warmup_momentum: [0.0, 0.95]
mosaic: [0.0, 1.0]          # Mosaic 增强概率
mixup: [0.0, 0.5]           # MixUp 增强概率
copy_paste: [0.0, 0.5]      # Copy-Paste 增强概率
hsv_h: [0.0, 0.1]           # HSV 色调增强
hsv_s: [0.0, 0.9]           # HSV 饱和度增强
hsv_v: [0.0, 0.9]           # HSV 明度增强
flipud: [0.0, 1.0]          # 上下翻转
fliplr: [0.0, 1.0]          # 左右翻转

与 Ray Tune 集成

对于更大规模的超参数搜索,Ultralytics 支持与 Ray Tune 集成:

bash
1
pip install ray[tune]
python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import ray
from ray import tune
from ultralytics import YOLO

# Ray Tune 搜索空间
search_space = {
    "lr0": tune.loguniform(1e-4, 1e-2),
    "lrf": tune.loguniform(1e-4, 1e-1),
    "momentum": tune.uniform(0.7, 0.99),
    "weight_decay": tune.uniform(0.0, 0.002),
    "mosaic": tune.uniform(0.0, 1.0),
}

# 启动 Ray Tune 搜索
model = YOLO("yolo26n.pt")
result = model.tune(
    data="data.yaml",
    epochs=50,
    iterations=100,
    use_ray=True,                # 启用 Ray Tune
    ray_search_alg="asha",       # Async Successive Halving Algorithm
    device=[0, 1, 2, 3],         # 多卡并行搜索
)

搜索结果解读

runs/tune/ 目录下生成:

1
2
3
4
5
6
runs/tune/
├── exp1/            # 每次 trial 的完整训练结果
├── exp2/
├── ...
├── tune_results.csv # 所有试验的超参数与指标汇总
└── tune_scatter.png # 超参数相关性散点图

解读技巧:

  • 学习率 vs mAP:散点图左上角密集区对应最优学习率范围
  • 增强强度 vs 过拟合:如果高 mosaic/mixup 值对应更高的 val mAP,说明数据增强有效
  • 权重衰减敏感度:小数据集通常对 weight_decay 更敏感,最优值在 0.0003~0.0007

过拟合诊断与正则化

从损失曲线识别过拟合

训练过程出现以下信号时,模型可能正在过拟合:

1
2
3
4
Loss curves:
📈 Train Loss:  持续下降
📉 Val Loss:    先降后升 (拐点 = 过拟合开始)
📊 mAP:         在验证集上停滞或下降

关键判断指标:当训练损失持续下降但验证损失开始上升时,即出现泛化差距 (Generalization Gap),这是过拟合的最明确信号。

正则化技术

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 在训练中应用多种正则化
model.train(
    # 显式正则化
    weight_decay=0.001,       # L2 正则化(权重衰减)
    dropout=0.1,              # Dropout 概率

    # 隐式正则化(数据增强)
    mosaic=1.0,
    mixup=0.2,                # 混合两张图像
    copy_paste=0.2,           # 复制粘贴增强

    # 训练控制
    patience=30,              # 早停
)
  • L2 正则化 (Weight Decay):惩罚大权重,防止模型过于依赖少数特征
  • Dropout:随机丢弃部分神经元,强制模型学习冗余特征
  • 数据增强:Mosaic、MixUp、Copy-Paste 等增强策略隐式地扩充训练分布
  • 标签平滑 (Label Smoothing):通过 label_smoothing 参数控制,防止模型过度自信

数据增强调优

不同数据集适合不同的增强策略:

数据集类型推荐增强说明
小数据集 (<1000 张)mosaic=1.0, mixup=0.3强增强扩充多样性
中等数据集mosaic=1.0, mixup=0.1适中的增强
大数据集 (>10K)mosaic=0.5, mixup=0.0弱增强,保留原始分布
密集场景copy_paste=0.3提升遮挡检测能力
航拍/卫星图mosaic=1.0, flipud=0.5利用旋转不变性

早停策略调优

python
1
2
3
4
5
6
7
model.train(
    patience=50,          # 默认 50,小数据集建议 20~30
    save_period=10,       # 每 N 轮保存一次方便回溯
    cos_lr=True,          # 余弦退火配合早停
    lrf=0.001,            # 最终学习率接近零
    warmup_epochs=3,      # 预热防止早停误判
)

过拟合严重时,首选手段是增加数据量降低模型复杂度(选择更小的模型规模如 n→s),正则化只是辅助手段。

结果文件说明

训练完成后 runs/train/exp/ 目录:

1
2
3
4
5
6
7
8
weights/
├── best.pt          # 最佳权重
└── last.pt          # 最后一轮权重
results.csv          # 训练日志CSV
results.png          # 损失曲线
confusion_matrix.png # 混淆矩阵
PR_curve.png         # PR曲线
F1_curve.png         # F1曲线

关键指标解读

  • Box Loss:检测框回归损失 → 持续下降

  • Cls Loss:分类损失 → 持续下降

  • mAP50:IOU=0.5 时的平均精度 → 持续上升

  • mAP50-95:IOU 0.5~0.95 平均精度 → 核心指标

验证指标深度解析

Precision 与 Recall

YOLO 训练输出的指标基于以下定义:

指标公式含义
Precision (精确率)TP / (TP + FP)预测为真的样本中,实际为真的比例
Recall (召回率)TP / (TP + FN)实际为真的样本中,被正确预测的比例
F1-Score2 × P × R / (P + R)Precision 与 Recall 的调和平均

这些指标随 Confidence 阈值变化 —— 高阈值提升 Precision 但降低 Recall,反之亦然。

混淆矩阵 (Confusion Matrix)

confusion_matrix.png 是诊断模型行为的核心工具:

1
2
3
4
5
6
7
            预测类别
          ┌─────────────────┐
  实际    │ TP │ FP (误检)  │
  类别    ├─────┼───────────┤
          │ FN │ background │
          │(漏检)│ (背景误判)  │
          └─────┴───────────┘
  • 对角线:正确分类的样本(越多越好)
  • 非对角线:类别混淆(如将"猫"预测为"狗")→ 需增加类别区分度特征
  • Background FP:模型将背景误检为目标 → 增加负样本或降低置信度阈值
  • 漏检 (FN):目标未被检测到 → 降低置信度阈值或增加小目标检测头

mAP 计算流程

mAP (Mean Average Precision) 是 YOLO 的核心评估指标:

  1. 对所有检测结果按 Confidence 排序
  2. 依次计算每个 Confidence 阈值下的 Precision 和 Recall
  3. 绘制 PR 曲线(Precision-Recall Curve),曲线下面积即为 AP
  4. mAP50:IoU 阈值设为 0.5 时所有类别的 AP 均值
  5. mAP50-95:IoU 从 0.5 到 0.95(步长 0.05)取 10 个阈值的 AP 均值
1
2
mAP50     = 宽松评估 → 目标大致位置正确即可
mAP50-95  = 严格评估 → 框必须精确贴合目标

用指标诊断模型问题

现象可能原因解决方向
Precision 高、Recall 低漏检严重降低置信度阈值、增加小目标数据
Recall 高、Precision 低误检过多提高置信度阈值、增加负样本
mAP50 高、mAP50-95 低框不够精确增加 box 损失权重、细化标注
类别 A 的 AP 远低于其他类类别不平衡增加 A 类样本或使用 Class Weights
PR 曲线突降难例集中Hard Negative Mining、数据增强

F1-Confidence 曲线

F1_curve.png 展示了不同 Confidence 阈值下 F1 得分的曲线。曲线最高点对应的 Confidence 值即为该模型的最优阈值:

python
1
2
3
4
# 自动寻找最优 Confidence 阈值
results = model.val()
best_conf = results.f1_score(threshold=...)
print(f"最优置信度阈值: {best_conf:.3f}")

YOLO26 专属训练方案

MuSGD 优化器

YOLO26 默认使用 MuSGD (Momentum with Scheduled Updates),这是对标准 SGD 的改进:

  • 自适应动量调度:动量值在训练过程中根据梯度方差动态调整
  • 时间感知学习率:集成 cosine annealing 的变体,无需单独设置 cos_lr=True
  • 更快的收敛:在相同 epoch 数下,MuSGD 通常比标准 SGD 提前 10~15% 达到同等精度
python
1
2
3
4
5
6
7
8
# YOLO26 推荐训练配置
model.train(
    optimizer="auto",         # 自动选择 MuSGD
    lr0=0.01,                 # MuSGD 对学习率不敏感,0.005~0.02 均可
    momentum=0.937,
    weight_decay=0.0005,
    cos_lr=False,             # MuSGD 内置调度,无需额外余弦退火
)

ProgLoss 渐进式损失平衡

YOLO26 的 ProgLoss 自动管理 box/cls 损失的权重调度,无需手动调参:

1
2
3
4
5
Training stage          Focus                    Loss behavior
──────────────────────────────────────────────────────────────
Epoch 1-10  (warmup)   分类学习为主              cls loss 快速下降
Epoch 10-30 (explore)  分类+定位均衡             box loss 开始显著下降
Epoch 30+   (refine)   定位精调为主              box loss 缓慢收敛

如果在训练日志中观察到 cls loss 长时间不降,说明 ProgLoss 的默认调度可能不适合当前数据集。此时可回退到手动模式:

python
1
2
3
4
5
6
7
8
# 禁用 ProgLoss 手动设置权重
model.train(
    loss_weights={
        "box": 7.5,
        "cls": 0.5,
    },
    prog_loss=False,
)

STAL 小目标增强训练

YOLO26 的 STAL (Small Target Augmentation Layer) 专门优化小目标检测:

python
1
2
3
4
5
6
# 启用 STAL(YOLO26 默认启用)
model.train(
    stal=True,                     # 小目标增强层
    stal_scale_range=[0.5, 1.0],  # 缩放范围
    stal_epoch_gamma=0.1,         # 增强衰减系数
)

STAL 工作原理:

  1. 检测阶段:识别图像中尺寸小于 32×32 像素的目标
  2. 增强阶段:对这些小目标进行上采样、复制、粘贴到图像其他区域
  3. 衰减策略:随着训练进行,STAL 增强强度逐渐降低,让模型逐步适应原始分布

YOLO26 训练清单

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# ===== YOLO26 推荐完整训练配置 =====
model.train(
    # 数据
    data="data.yaml",
    epochs=200,
    imgsz=640,
    batch=16,

    # 优化器 (MuSGD)
    optimizer="auto",
    lr0=0.01,
    momentum=0.937,
    weight_decay=0.0005,

    # 增强 (STAL 自动启用)
    mosaic=1.0,
    mixup=0.1,
    copy_paste=0.1,

    # 正则化
    dropout=0.1,
    label_smoothing=0.0,

    # 其他
    device=0,
    patience=50,
    seed=42,
    verbose=True,
)

提示:YOLO26 在边缘设备(Jetson、树莓派等)上部署时,建议使用 imgsz=320imgsz=480,推理速度可提升 23 倍,mAP 下降仅 13%。