4. YOLOv8模型训练:配置文件解析、训练参数调优、迁移学习技巧、训练过程监控

好,咱们进入第四章。这一章是实战的硬核部分——把YOLOv8跑起来,并且跑出好效果。

说实话,很多同学在训练阶段容易翻车。要么是参数没调对,模型训飞了;要么是数据不够,过拟合严重。我刚开始做工业质检项目时也踩过不少坑,今天把这些经验都摊开来讲。

4.1 配置文件解析——别小看这个YAML

YOLOv8的训练配置都写在YAML文件里。很多人直接复制粘贴,改个路径就开训。嗯,这样容易出问题。

我们来看一个典型的配置文件结构:

# ultralytics/cfg/models/v8/yolov8n.yaml
# 模型骨架部分
backbone:
  - [-1, 1, Conv, [64, 3, 2]]  # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
  - [-1, 3, C2f, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
  - [-1, 6, C2f, [256, True]]
  - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
  - [-1, 6, C2f, [512, True]]
  - [-1, 1, Conv, [768, 3, 2]] # 7-P5/32
  - [-1, 3, C2f, [768, True]]
  - [-1, 1, SPPF, [768, 5]]    # 9

# 颈部(Neck)部分
head:
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 6], 1, Concat, [1]]  # cat backbone P4
  - [-1, 3, C2f, [512]]        # 12

  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 4], 1, Concat, [1]]  # cat backbone P3
  - [-1, 3, C2f, [256]]        # 15 (P3/8-small)

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 12], 1, Concat, [1]] # cat head P4
  - [-1, 3, C2f, [512]]        # 18 (P4/16-medium)

  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 9], 1, Concat, [1]]  # cat head P5
  - [-1, 3, C2f, [768]]        # 21 (P5/32-large)

  - [[15, 18, 21], 1, Detect, [nc]]  # Detect(P3, P4, P5)

这里每个数字代表什么?我解释一下:

  • 第一个数字:输入来源。-1表示上一层,正数表示第几层
  • 第二个数字:重复次数。比如C2f模块重复3次
  • 第三个参数:模块类型。Conv、C2f、SPPF这些
  • 第四个参数:模块参数。比如[64, 3, 2]表示输出通道64、卷积核3、步长2
我的习惯: 工业场景下,我一般不改backbone结构,只调head部分的检测头数量。比如检测小目标时,我会在head里加一个P2层(160x160的特征图),专门抓小缺陷。

4.2 训练参数调优——别让模型训飞了

训练参数这块,我见过最离谱的是有人把学习率设成0.1,loss直接炸到NaN。咱们一步步来。

核心参数就这几个:

参数名 默认值 工业场景建议 说明
lr0 0.01 0.001 ~ 0.005 初始学习率。数据量小就调低
lrf 0.01 0.01 ~ 0.1 最终学习率 = lr0 * lrf
momentum 0.937 0.9 ~ 0.95 SGD动量,一般不动
weight_decay 0.0005 0.0001 ~ 0.0005 权重衰减,防过拟合
batch 16 看显存,越大越好 batch size,影响BN层效果
epochs 100 200 ~ 500 工业场景数据少,多训几轮
patience 50 30 ~ 50 早停轮数,loss不降就停

实际训练命令长这样:

yolo train \
  model=yolov8n.pt \
  data=custom_dataset.yaml \
  epochs=300 \
  batch=32 \
  lr0=0.002 \
  lrf=0.05 \
  weight_decay=0.0003 \
  patience=40 \
  imgsz=640 \
  device=0,1,2,3 \
  workers=8 \
  project=industrial_qc \
  name=defect_detection_v1
我曾经踩过的坑: 有一次我把batch设成64,但显存只有8G,结果训练到一半OOM了。后来我学乖了——先用batch=8试跑一个epoch,看显存占用,再逐步往上加。另外,workers数别超过CPU核心数,否则数据加载会成为瓶颈。

4.3 迁移学习技巧——站在巨人肩膀上

迁移学习是工业质检的救命稻草。你想想看,工厂里能收集到的缺陷样本可能就几百张,从头训练一个YOLOv8?不现实。

我的做法是这样的:

  1. 选对预训练权重:YOLOv8官方提供了COCO预训练权重。但如果你做的是特定工业场景,比如PCB缺陷检测,我建议先用类似场景的公开数据集做一次预训练
  2. 冻结backbone:前50个epoch冻结backbone,只训练head。这样模型不会忘记通用的特征提取能力
  3. 解冻微调:50个epoch后解冻全部层,用更小的学习率(lr0=0.0001)微调
  4. 数据增强策略:工业场景下,mosaic和mixup很有用。但注意——如果你的缺陷样本很少,mosaic可能会把缺陷切碎,反而不好

冻结训练的代码实现:

from ultralytics import YOLO

# 加载预训练模型
model = YOLO('yolov8n.pt')

# 冻结backbone
for name, param in model.model.named_parameters():
    if 'backbone' in name:
        param.requires_grad = False

# 第一阶段:只训练head
model.train(
    data='custom_dataset.yaml',
    epochs=50,
    lr0=0.001,
    freeze=10  # 冻结前10层
)

# 第二阶段:解冻全部,小学习率微调
for param in model.model.parameters():
    param.requires_grad = True

model.train(
    data='custom_dataset.yaml',
    epochs=100,
    lr0=0.0001,
    resume=True
)

关键经验: 工业场景下,我建议用yolov8m或yolov8l作为基础模型。虽然nano版本快,但小缺陷的召回率不够。我做过对比——在同一个PCB缺陷数据集上,yolov8n的mAP@0.5是0.82,yolov8m能到0.91。推理速度慢了30%,但精度提升明显。

4.4 训练过程监控——别等训完才发现翻车

训练跑起来之后,你不能撒手不管。我习惯用TensorBoard实时监控,YOLOv8原生支持。

启动监控:

# 训练时自动生成日志
yolo train ... project=my_project name=exp1

# 另开终端,启动TensorBoard
tensorboard --logdir my_project/exp1

监控哪些指标?我列个清单:

  • train/loss:训练loss。正常应该稳步下降,如果震荡剧烈,说明学习率太高
  • val/loss:验证loss。如果验证loss先降后升,那就是过拟合了,赶紧加正则化或早停
  • metrics/mAP50:这个最重要。工业场景下,mAP50达到0.9以上才算合格
  • learning_rate:看看学习率变化曲线,确认是不是按余弦退火在衰减
  • 混淆矩阵:每个epoch结束后看一下,哪个类别容易漏检

下面这张图是我在实际项目中总结的训练监控流程:

YOLOv8训练监控流程 开始训练 每个Epoch:前向 + 反向 + 更新 记录 train/loss 验证集推理 + 计算mAP loss上升? 早停 / 调参 继续下一轮 训练结束 关键:每5个epoch保存一次权重,loss连续20轮不降就早停

实际训练时,我还会关注一个容易被忽略的指标——类别分布。工业场景下,正负样本往往极度不平衡。比如一个产品上99.9%的区域都是OK的,只有0.1%是缺陷。这时候看mAP会骗人——模型可能学成了「全部判OK」。

我的做法: 每10个epoch手动跑一次验证集,打印出每个类别的precision和recall。如果某个缺陷类别的recall低于0.5,我就回去检查标注质量,或者给这个类别加权重。YOLOv8支持在数据集的YAML里设置cls_pw参数,给不同类别不同的loss权重。

嗯,训练监控这块就说这么多。记住一句话:不要等训练结束才看结果。中间发现问题,及时止损,重新调参,比跑完一轮再回头省时间得多。