跳转至内容

如何在自定义数据集YOLO 对YOLO 进行微调

微调是通过利用已学习的权重(而非随机初始化)来调整预训练模型,使其能够识别新类别。与从头开始训练数百个 epoch 相比,微调利用了预训练的 COCO 特征,仅需十分之一的时间即可在自定义数据集上收敛。

本指南介绍了如何在自定义数据集上对YOLO26进行微调,内容涵盖从基础用法到图层冻结两阶段训练等高级技术。

微调与从头开始训练

预训练模型已经通过数百万张图像学会了通用的视觉特征——边缘检测、纹理识别、形状理解。通过微调进行的迁移学习会复用这些知识,仅需向模型展示新类别的样貌,因此收敛速度更快且所需数据更少。从头开始训练则会舍弃所有这些知识,迫使模型从像素级模式开始重新学习一切,这需要消耗显著更多的资源。

微调从零开始学习
起始重量COCO 80个类别)上预训练随机初始化
命令YOLO("yolo26n.pt")YOLO("yolo26n.yaml")
融合更快——基础模型已训练完成较慢 - 所有图层从零开始学习
数据要求下层——预训练特征弥补了数据量不足的问题更高级——模型必须仅从数据集学习所有特征
何时使用使用自然图像的自定义类COCO 截然不同的领域COCO 医疗、卫星、雷达)

微调无需额外代码

当一个 .pt 文件已加载 YOLO("yolo26n.pt"),预训练权重存储在模型中。调用 .train(data="custom.yaml") 随后,系统会自动将所有兼容的权重迁移到新的模型架构中,重新初始化任何不匹配的层(例如当类别数量不同时,检测头部分),并开始训练。无需手动加载权重、操作层结构,也不需要编写自定义迁移学习代码。

预训练权重迁移的工作原理

当预训练模型在类别数量不同的数据集上进行微调时(例如,将COCO 80 个类别转换为 5 个自定义类别),Ultralytics 基于形状的权重迁移:

  1. 完全转移脊柱和颈部层——这些层提取的是通用视觉特征,其形状与类别数量无关。
  2. 检测头已部分重新初始化 - 分类输出层(cv3, one2one_cv3) 的形状与类数量相关(80 与 5),因此无法转移,且会随机初始化。盒式回归层(cv2, one2one_cv2) 头部中的结构无论类数量多少都保持固定形态,因此它们能正常传递。
  3. 在改变类数量时,绝大多数权重都会被保留。只有检测头中与分类相关的层会被重新初始化——主干、颈部和边界框回归分支保持不变。

对于与预训练模型类别数相同的数据集(例如,在另一个80类数据集上COCO权重进行微调),包括检测头在内的权重转移率为100%。

基本微调示例

示例

from ultralytics import YOLO

model = YOLO("yolo26n.pt")  # load pretrained model
model.train(data="path/to/data.yaml", epochs=50, imgsz=640)
yolo detect train model=yolo26n.pt data=path/to/data.yaml epochs=50 imgsz=640

选择模型尺寸

更大的模型虽然容量更大,但需要更新的参数也更多,当训练数据有限时,这可能会增加过拟合的风险。从较小的模型(如 YOLO26n 或 YOLO26s)开始,并在验证指标趋于平稳时再进行扩展,是一种切实可行的方法。最佳模型规模取决于任务的复杂度、类别数量、数据集的多样性以及可用于部署的硬件。 有关可用模型尺寸和性能基准,请参阅完整的YOLO26 模型页面

优化器与学习率的选择

默认 optimizer=auto 该设置会根据训练迭代总数来选择优化器和学习率:

  • < 10,000 iterations (small datasets or few epochs): AdamW with a low, auto-calculated learning rate
  • > 10,000 次迭代(大型数据集):MuSGD(一种混合型SGD ),学习率 lr=0.01

对于大多数微调任务,默认设置已能很好地工作,无需任何手动调整。在以下情况下,建议显式设置优化器:

  • 训练不稳定 (损失值骤升或出现背离):尝试 optimizer=AdamW, lr0=0.001 以获得更稳定的收敛
  • 在小型数据集上对大型模型进行微调:较低的学习率,例如 lr0=0.001 有助于保留预训练特征

自动优化器会覆盖手动设置的 lr0

何时 optimizer=autolr0momentum 这些值将被忽略。若要手动控制学习率,请显式设置优化器: optimizer=SGD, lr0=0.005.

冻结图层

冻结功能可防止特定层在训练过程中发生更新。当数据集相对于模型容量较小时,这能加快训练速度并减少过拟合

字段 freeze 该参数接受整数或列表。整数 freeze=10 冻结前10层(0到9,这对应于YOLO26中的骨干网络)。一个列表可以包含如下层索引: freeze=[0, 3, 5] 用于部分主干冻结,或类似于 freeze=["23.cv2"] 以便对层内的特定分支进行精细控制。

示例

model.train(data="custom.yaml", epochs=50, freeze=10)
model.train(data="custom.yaml", epochs=50, freeze=[0, 1, 2, 3, 4])
# Freeze the box regression branch of the detection head
model.train(data="custom.yaml", epochs=50, freeze=["23.cv2"])

合适的冻结深度取决于目标领域与预训练数据的相似程度,以及可用的训练数据量:

场景建议理由
大型数据集,相似领域freeze=None (默认)数据量足够用于调整所有层,且不会出现过拟合
数据集较小,领域相似freeze=10保留核心特征,减少可训练参数
数据集非常小freeze=23仅对检测头进行训练,从而最大限度地降低过拟合的风险
距离COCO很远的域名freeze=NoneBackbone 的功能可能无法很好地迁移,需要重新训练

冻结层数也可以视为一个超参数——尝试几个不同的值(0、5、10),并比较验证集的mAP 为特定数据集找到最佳设置的一种实用方法。

微调的关键超参数

与从头开始训练相比,微调通常需要的超参数调整更少。最重要的参数包括:

  • epochs: 微调的收敛速度比从头开始训练更快。建议从一个适中的值开始,并使用 patience 当验证指标趋于平稳时,应及时停止。
  • patience: 默认值 100 是为长时间的训练运行设计的。将其降至 10-20,可避免在已经收敛的运行上浪费时间。
  • warmup_epochs: 默认的预热阶段(3 个 epoch)会将学习率从零开始逐渐增加,这可以防止在早期迭代中因梯度更新过大而破坏预训练特征。即使在微调时,也建议保留默认设置。

有关训练参数的完整列表,请参阅训练配置参考

两阶段微调

两阶段微调将训练分为两个阶段。第一阶段冻结主干网络,仅对颈部和头部进行训练,从而使检测层能够适应新类别,同时不破坏预训练特征。第二阶段解冻所有层,并以较低的学习率对整个模型进行训练,以针对目标领域优化主干网络。

当目标领域COCO 显著差异COCO 医学影像、航拍图像、显微图像)时,这种方法尤为有用——此时虽然可能需要对骨干网络进行调整,但若一次性训练所有内容会导致模型不稳定。关于基于回调函数的自动解冻方法,请参阅《骨干网络的冻结与解冻》。

两阶段微调

from ultralytics import YOLO

# Stage 1: freeze backbone, train head and neck
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=20, freeze=10, name="stage1", exist_ok=True)

# Stage 2: unfreeze all, fine-tune with lower lr
model = YOLO("runs/detect/stage1/weights/best.pt")
model.train(data="custom.yaml", epochs=30, lr0=0.001, name="stage2", exist_ok=True)

常见误区

模型未生成任何预测

  • 训练数据不足:使用极少样本进行训练是最常见的原因——模型无法从过少的数据中学习或进行泛化。在排查其他原因之前,请确保每个类别都有足够且多样化的示例。
  • 检查数据集路径:路径错误 data.yaml 静默生成零个标签。运行 yolo detect val model=yolo26n.pt data=your_data.yaml 在训练前,请确认标签已正确加载。
  • 降低置信阈值: 如果预测结果存在但被过滤掉了,请尝试 conf=0.1 在推理过程中。
  • 验证类数量: 确保 ncdata.yaml 与标签文件中的实际类数相符。

验证mAP 值早期mAP

  • 添加更多数据:微调过程能从额外的训练数据中获益匪浅,尤其是那些角度、光照和背景各异的多样化示例。
  • 检查班级人数:代表性不足的群体AP分数会较低。使用 cls_pw 应用逆频率类权重(从 cls_pw=0.25 对于中度失衡,增加至 1.0 (用于严重失衡的情况)。
  • 减少填充:对于非常小的数据集,过度数据增强可能弊大于利。请尝试 mosaic=0.5mosaic=0.0.
  • 提高分辨率: 对于包含小型物体的数据集,请尝试 imgsz=1280 以保留细节。

微调后,原始类的性能会下降

这被称为“灾难性遗忘”——当模型仅基于新数据进行微调时,会丢失先前学到的知识。如果不将原始数据集的图像与新数据一同纳入训练,这种遗忘现象通常难以避免。为缓解这一问题:

  • 合并数据集:在微调过程中,将原始类别的示例与新类别的示例一并纳入。这是防止模型遗忘的唯一可靠方法。
  • 冻结主干和颈部:将主干和颈部同时冻结,仅让检测头进行训练,这有助于在学习率极低的情况下进行短期的微调。
  • 减少训练轮次:模型仅在新数据上进行训练的时间越长,遗忘现象就越严重。

常见问题

我需要多少张图片才能对YOLO 进行微调?

没有固定的最低要求——结果取决于任务的复杂程度、类别数量,以及该领域与COCO相似程度。图像的多样性(光照、角度、背景各异)比单纯的数量更为重要。请先利用现有数据开始训练,如果验证指标不理想,再逐步增加数据量。

如何在自定义数据集上对 YOLO26 进行微调?

加载一个预训练好的 .pt 提交并调用 .train() 并附上自定义文件的路径 data.yaml.Ultralytics 处理 重心转移、检测头的重新初始化以及优化器的选择。请参阅 基本微调 请参阅该部分以查看完整的代码示例。

为什么我微调过的YOLO 无法检测到任何物体?

最常见的原因是路径设置错误,具体位于 data.yaml (该操作会静默地生成零个标签),以及 nc 在 YAML 文件和实际标签文件中,或者置信度阈值设置过高。参见 常见误区 查看完整的故障排除检查清单。

在微调时,我应该冻结哪些YOLO ?

这取决于数据集的大小和领域相似度。对于与COCO领域相似的小型数据集,冻结骨干网络(freeze=10) 可防止过拟合。对于与COCO差异较大的数据集,若将所有层均设为不冻结(freeze=None) 使骨干网能够适应变化。参见 冻结图层 以获取详细建议。

YOLO 新类别YOLO 进行微调时,如何防止灾难性遗忘?

在训练数据中,除了新类别外,还应包含原始类别的示例。如果无法做到这一点,则冻结更多层(freeze=10 (或更高)并采用较低的学习率,有助于保留预训练知识。参见 原始类的性能下降 了解更多详情。



📅 创建于 0 天前 ✏️ 更新于 0 天前
raimbekovm

评论