YOLO训练保持原有识别能力
在 YOLOv8 训练新数据集时,默认会覆盖模型的原有识别能力(即"灾难性遗忘"问题)。以下是解决方案和最佳实践:
1. 问题原因
- 单任务训练:YOLO默认训练模式会重置模型权重,只学习当前数据集的特征
- 类别冲突:如果新旧数据集的类别定义不同(如原"person"和新"hardhat"),模型会遗忘旧类别
2. 解决方案
方案一:联合训练(推荐)
将新旧数据集合并训练:
# combined.yaml
train: - path/to/old_dataset/train/images- path/to/new_dataset/train/images
val:- path/to/old_dataset/val/images- path/to/new_dataset/val/images
nc: 20 # 新旧类别的总数
names: [旧类别1, 旧类别2, ..., 新类别1, 新类别2...]
方案二:迁移学习(保留部分能力)
冻结部分层,只训练检测头:
from ultralytics import YOLOmodel = YOLO('yolov8n.pt') # 加载预训练模型
model.train(data='new_data.yaml',epochs=100,freeze=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # 冻结前10层(具体层数需实验)
)
方案三:模型集成(独立保存)
分别训练新旧模型,推理时合并结果:
# 同时加载两个模型
model_old = YOLO('old_model.pt')
model_new = YOLO('new_model.pt')# 合并检测结果
results_old = model_old.predict(source)
results_new = model_new.predict(source)
combined_results = merge_detections(results_old, results_new)
3. 关键参数控制
参数 | 作用 | 推荐值 |
---|---|---|
pretrained=True | 加载COCO预训练权重 | 必须开启 |
freeze | 冻结层数 | 10-15层 |
lr0 | 初始学习率 | 0.001(比正常小10倍) |
cos_lr=True | 余弦退火学习率 | 推荐开启 |
4. 最佳实践
-
数据准备:
- 保留10%的旧数据集图片添加到新训练集
- 确保新旧数据集的标注格式一致
-
训练技巧:
model.train(data='combined.yaml',epochs=300, # 更长的训练周期batch=8, # 较小的batch sizeimgsz=640,optimizer='AdamW', # 使用更稳定的优化器lr0=0.001 * 0.1, # 降低学习率weight_decay=0.0005 )
-
验证评估:
# 验证时同时检查新旧类别 metrics = model.val(data='combined.yaml',split='val', # 确保验证集包含新旧数据conf=0.25 ) print(metrics.box.map50) # 查看mAP50
5. 恢复已遗忘的模型
如果已经训练了新模型但需要恢复旧能力:
-
从备份加载原始模型:
old_model = YOLO('backup/yolov8n_original.pt')
-
使用方案一的联合训练重新训练
6. 注意事项
- 类别ID冲突:确保新旧数据集的类别ID没有重叠
- 数据平衡:新旧数据集每个类别的样本量尽量均衡
- 性能监控:训练时使用TensorBoard监控各类别AP变化
通过以上方法,可以最大程度保留模型的通用识别能力。如果新旧任务差异过大(如"人脸识别"→"车辆检测"),建议分开训练两个专用模型。