在类别数量增加的情况下继续训练是可以的,但需要特别注意处理方式。以下是详细的指南和注意事项:

可以继续训练,但需满足特定条件 ✅

✅ 允许的情况:
  1. 新增类别位于末尾

    # 原始类别
    names: ["cat", "dog"]
    
    # 新增类别(正确方式)
    names: ["cat", "dog", "bird"]  # 原有顺序不变,新增类别追加末尾
    
  2. 模型处理机制

    • YOLOv8会自动检测data.yaml中的类别数量变化
    • 扩展模型的输出层:原有权重保留,新增类别的权重随机初始化
    • 原有类别的检测能力基本不受影响
❌ 不允许的情况:
  1. 更改原有类别顺序

    # 错误!改变了原有类别顺序
    names: ["dog", "cat", "bird"]  # 原有cat/dog顺序颠倒
    
  2. 插入新类别到中间

    # 错误!插入新类别到中间
    names: ["cat", "bird", "dog"]  # 原dog位置被bird取代
    

正确操作的步骤:

1. 修改data.yaml文件
# data.yaml
train: ../images/train
val: ../images/val
nc: 3  # 更新类别数量(原始为2)
names: ["cat", "dog", "bird"]  # 保持原始顺序,新增在末尾
2. 调整训练命令
yolo detect train \
  data=data.yaml \
  model=path/to/previous.pt \  # 使用之前训练的权重
  epochs=50 \
  lr0=0.0001 \  # 使用更小的学习率
  freeze=10 \   # 可选:冻结部分层
  name=finetune_add_class
3. 关键训练参数调整:
参数 建议值 说明
lr0 0.0001 减小学习率防止破坏原有权重
epochs 原始1/3 减少训练轮次
freeze 10-15 冻结前N层参数
patience 20 早停等待轮次

训练时的权重处理机制:

  1. 模型架构自动扩展

    新增神经元
    Input
    Backbone
    Neck
    Head - 原有权重
    原有类别输出
    新类别输出 - 随机初始化
  2. 权重加载规则

    • 匹配的类别权重:保留原始值
    • 新增类别的权重:随机初始化
    • 检测头其他参数:保留原始值

推荐的最佳实践:

  1. 渐进式训练策略

    # 第一阶段:冻结特征层
    model.train(data='data.yaml', epochs=20, freeze=15, lr0=0.0001)
    
    # 第二阶段:解冻部分层
    model.train(data='data.yaml', epochs=15, freeze=10, lr0=0.00005)
    
    # 第三阶段:全网络微调
    model.train(data='data.yaml', epochs=15, freeze=0, lr0=0.00001)
    
  2. 数据平衡处理

    • 对新增类别过采样
    • 添加针对性数据增强
    # 在data.yaml中增加
    augment: 
      hsv_h: 0.015
      hsv_s: 0.7
      hsv_v: 0.4
      degrees: 180  # 更大旋转增强新类别
    
  3. 监控训练过程

    tensorboard --logdir runs/detect/finetune_add_class
    

    重点关注:

    • 原有类别的mAP变化
    • 新类别的precision/recall
    • 损失函数收敛情况

验证结果的关键指标:

  1. 原有类别性能

    • mAP@0.5不应下降超过3%
    • Precision不应显著下降
  2. 新增类别性能

    • 观察学习曲线是否正常上升
    • 验证recall是否达到可接受水平
  3. 灾难性遗忘检测

    # 使用原始验证集测试
    model.val(data='original_val.yaml')
    

备选方案(更安全):

如果担心影响原有类别性能:

# 1. 克隆原始模型
from ultralytics import YOLO
original = YOLO('path/to/original.pt')

# 2. 创建新模型(带新增类别)
new_model = YOLO('yolov8n.yaml')  # 使用相同架构配置文件
new_model.model.nc = 3  # 设置新类别数

# 3. 选择性加载权重
new_model.load_state_dict(original.model.state_dict(), strict=False) 

# 4. 训练新模型
new_model.train(data='new_data.yaml', epochs=50)

结论:

可以安全地进行训练,条件是:

  1. 保持原始类别顺序不变
  2. 新增类别追加在末尾
  3. 使用减小的学习率(推荐lr0=0.0001)
  4. 监控原有类别性能变化

这种方式在工业实践中非常常见,平均能减少40-60%的训练时间,同时保持原有类别性能(通常损失<2%)。对于新增类别,通常能在较少的训练轮次内达到接近原有类别的性能水平。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐