Как дообучить YOLO на собственном наборе данных
Дообучение адаптирует предварительно обученную модель для распознавания новых классов, используя полученные ранее веса, а не случайную инициализацию. Вместо обучения с нуля на протяжении сотен эпох дообучение повторно использует признаки COCO, а затем за гораздо меньшее время адаптирует модель к пользовательским данным.
В этом руководстве рассматривается дообучение YOLO26 на собственных наборах данных: от базового использования до продвинутых методов, таких как заморозка слоев и двухэтапное обучение.
Дообучение и обучение с нуля#
Предварительно обученная модель уже научилась извлекать общие визуальные признаки — обнаруживать границы, распознавать текстуры и понимать формы — на миллионах изображений. Трансферное обучение с помощью дообучения повторно использует эти знания и учит модель только тому, как выглядят новые классы. Поэтому модель сходится быстрее и требует меньше данных. При обучении с нуля все эти знания отбрасываются, и модель вынуждена осваивать все заново, начиная с закономерностей на уровне пикселей, что требует значительно больше ресурсов. В руководстве по настройке YAML-файлов моделей рассказывается, чем файлы .yaml, содержащие только архитектуру, отличаются от чекпойнтов.
| Дообучение | Обучение с нуля | |
|---|---|---|
| Начальные веса | Предварительное обучение на COCO (80 классов) | Случайная инициализация |
| Команда | YOLO("yolo26n.pt") | YOLO("yolo26n.yaml") |
| Сходимость | Быстрее — базовая сеть уже обучена | Медленнее — все слои обучаются с нуля |
| Требования к данным | Ниже — предварительно изученные признаки компенсируют меньший объем данных | Выше — модели нужно изучить все признаки только по набору данных |
| Когда использовать | Собственные классы на обычных изображениях | Домены, принципиально отличающиеся от COCO (медицина, спутниковые снимки, радар) |
Когда файл .pt загружается с помощью YOLO("yolo26n.pt"), предварительно обученные веса сохраняются в модели. Последующий вызов .train(data="custom.yaml") автоматически переносит все совместимые веса в новую архитектуру модели, повторно инициализирует несовпадающие слои (например, последний слой классификации, если число классов различается) и запускает обучение. Загружать веса вручную, изменять слои или писать собственный код для переноса обучения не нужно.
Как работает перенос предварительно обученных весов#
При дообучении предварительно обученной модели на наборе данных с другим числом классов (например, при переходе с 80 классов COCO на 5 собственных классов) Ultralytics переносит веса с учетом формы тензоров:
- Веса базовой сети и шеи переносятся полностью — эти слои извлекают общие визуальные признаки, а их формы не зависят от числа классов.
- Голова обнаружения инициализируется повторно частично — только финальная свертка каждой ветви классификации (
cv3,one2one_cv3) имеет форму, зависящую от количества классов (80 против 5); скрытые слои ветви переносятся, если обе модели имеют один масштаб. Совпадающие классы сопоставляются по названиям, а затем соответствующие строки переносятся до инициализации несопоставленных строк. Слои регрессии рамок (cv2,one2one_cv2) в голове имеют фиксированную форму независимо от количества классов, поэтому переносятся обычным образом. - При изменении количества классов переносится подавляющее большинство весов. Например, при тонкой настройке YOLO26n с COCO (80 классов) на наборе данных с 5 классами переносятся 696 из 708 тензоров весов, а также все совместимые строки классификации, сопоставленные по названию.
Если в наборе данных столько же классов, сколько в предварительно обученной модели (например, если дообучать веса, обученные на COCO, на другом наборе из 80 классов), переносятся 100% весов, включая голову детекции.
Перенос классов с разными названиями#
Ultralytics переносит соответствующие строки классификационной головы между наборами данных, сопоставляя классы по названиям без учета регистра и окружающих пробелов. Если эквивалентные классы называются по-разному, перед загрузкой переименуй классы исходного чекпойнта в памяти. Это позволяет сохранить предварительно обученные веса классификации для общих понятий, которые иначе считались бы несовпадающими и инициализировались случайным образом.
В этом примере перехода с Objects365 v2 на COCO переименовываются исходные классы загруженного чекпойнта, который затем train() передаёт в качестве предварительно обученных весов:
from ultralytics import YOLO
# # Название класса в Objects365 v2 (в нижнем регистре) -> название класса в COCO
ALIASES = {
"wild bird": "bird",
"handbag/satchel": "handbag",
"luggage": "suitcase",
"bowl/basin": "bowl",
"orange/tangerine": "orange",
"monitor/tv": "tv",
"stuffed toy": "teddy bear",
"hair dryer": "hair drier",
}
model = YOLO("path/to/yolo26s-objects365.pt")
# # Названия классов Objects365 записаны с заглавных букв, поэтому сопоставляем по названию в нижнем регистре
model.model.names = {i: ALIASES.get(name.lower(), name) for i, name in model.model.names.items()}
model.train(data="coco.yaml", epochs=100, imgsz=640)По умолчанию настройка cls_remap включает перенос по названиям. Во время обучения выводится сообщение Remapped N/M cls head rows from pretrained weights by class name, когда копируются совместимые строки; задай cls_remap=False, чтобы отключить этот режим.
Пример базового дообучения#
from ultralytics import YOLO
model = YOLO("yolo26n.pt") # загрузить предварительно обученную модель
model.train(data="custom.yaml", epochs=50, imgsz=640)Выбор размера модели#
У более крупных моделей больше возможностей, но и больше параметров для обновления. При ограниченных обучающих данных это может повысить риск переобучения. Практичный подход — начать с небольшой модели (YOLO26n или YOLO26s) и увеличивать ее размер, только если метрики валидации перестают улучшаться. Оптимальный размер модели зависит от сложности задачи, числа классов, разнообразия набора данных и оборудования, доступного для развертывания.
Выбор оптимизатора и скорости обучения#
Настройка optimizer=auto по умолчанию выбирает оптимизатор и скорость обучения в зависимости от общего числа итераций обучения:
- 10 000 итераций или меньше (небольшие наборы данных или малое число эпох): AdamW с низкой скоростью обучения, рассчитанной автоматически
- Более 10 000 итераций (большие наборы данных): MuSGD ( гибридный оптимизатор Muon и SGD) с lr=0.01
Для большинства задач дообучения настройки по умолчанию работают хорошо и не требуют ручной коррекции. Задай оптимизатор явно, если:
- Обучение нестабильно (скачки функции потерь или расходимость): попробуй
optimizer=AdamW, lr0=0.001для более стабильной сходимости - Дообучаешь крупную модель на небольшом наборе данных: явный выбор оптимизатора с более низкой скоростью обучения, например
optimizer=AdamW, lr0=0.001, поможет сохранить предварительно обученные признаки
Если задано optimizer=auto, значение lr0 игнорируется. Чтобы управлять скоростью обучения вручную, задай оптимизатор явно: optimizer=SGD, lr0=0.005.
Заморозка слоев#
Заморозка не позволяет обновлять определенные слои во время обучения. Это ускоряет обучение и снижает риск переобучения, если набор данных мал относительно емкости модели.
Параметр freeze принимает целое число или список. Целое число freeze=10 замораживает первые 10 слоев (индексы 0-9), куда входит большая часть базовой сети YOLO26. Базовая сеть охватывает слои 0-10, поэтому freeze=10 оставляет последний блок C2PSA (слой 10) обучаемым; используй freeze=11, чтобы заморозить базовую сеть целиком. В списке можно указать индексы слоев, например freeze=[0, 3, 5], чтобы заморозить часть базовой сети, или строки с именами модулей, например freeze=["23.cv2", "23.one2one_cv2"], чтобы точечно управлять отдельными ветвями внутри слоя (в этом примере — обеими ветвями регрессии рамок головы детекции).
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=50, freeze=10)Подходящая глубина заморозки зависит от того, насколько целевой домен похож на данные, на которых выполнялось предобучение, и сколько данных для обучения доступно:
| Сценарий | Рекомендация | Обоснование |
|---|---|---|
| Большой набор данных, похожий домен | freeze=None (по умолчанию) | Данных достаточно, чтобы адаптировать все слои без переобучения |
| Небольшой набор данных, похожий домен | freeze=10 | Сохраняет признаки backbone и сокращает число обучаемых параметров |
| Очень маленький набор данных | freeze=23 | Обучается только detection head, что сводит риск переобучения к минимуму |
| Домен сильно отличается от COCO | freeze=None | Признаки backbone могут плохо переноситься, поэтому его нужно дообучить |
Глубину заморозки также можно считать гиперпараметром: попробуй несколько значений (0, 5, 10) и сравни mAP на валидации — это практичный способ подобрать оптимальное значение для конкретного набора данных.
Основные гиперпараметры дообучения#
Для дообучения обычно нужно корректировать меньше гиперпараметров, чем при обучении с нуля. Наибольшее значение имеют:
epochs: дообучение сходится быстрее, чем обучение с нуля. Начни с умеренного значения и используйpatience, чтобы остановить обучение, когда метрики на валидации перестанут улучшаться.patience: значение по умолчанию — 100 — рассчитано на длительное обучение. Уменьши его до 10–20, чтобы не тратить время на запуски, которые уже сошлись.warmup_epochs: разогрев постепенно доводит скорость обучения до запланированного значения в течение первых эпох, поэтому первые батчи с меньшей вероятностью нарушат работу предобученных признаков. При дообучении оставь ненулевое значение, но полные 3 эпохи по умолчанию не обязательны: эволюционный поиск, использованный для официального дообучения YOLO26 на COCO — продолжения обучения на протяжении нескольких эпох с весов Objects365, — подобрал примерно одну эпоху для каждого размера модели.
Полный список параметров обучения см. в справочнике по конфигурации обучения. Если нужно поведение, которое параметры не позволяют настроить, например скорость обучения для каждого слоя, ограничение градиента или пользовательские метрики валидации, создай подкласс тренера.
Двухэтапное дообучение#
Двухэтапное дообучение делит обучение на два этапа. На первом этапе backbone замораживается, и обучаются только neck и head, чтобы слои детекции адаптировались к новым классам, не нарушая работу предобученных признаков. На втором этапе все слои размораживаются, и вся модель обучается с меньшей скоростью обучения, чтобы адаптировать backbone к целевому домену.
Этот подход особенно полезен, когда целевой домен значительно отличается от COCO (медицинские снимки, аэрофотосъёмка, микроскопия): backbone может потребовать адаптации, но одновременное обучение всех слоёв приводит к нестабильности. О том, как автоматически размораживать слои с помощью callback, см. Заморозка и разморозка backbone.
from ultralytics import YOLO
# Этап 1: заморозить backbone, обучать head и neck
model = YOLO("yolo26n.pt")
model.train(data="custom.yaml", epochs=20, freeze=10, name="stage1", exist_ok=True)
# Этап 2: разморозить все слои и дообучать с меньшим lr
model = YOLO("runs/detect/stage1/weights/best.pt")
model.train(data="custom.yaml", epochs=30, optimizer="AdamW", lr0=0.001, name="stage2", exist_ok=True)Распространённые проблемы#
Модель не выдаёт предсказаний#
-
Недостаточно обучающих данных: обучение на очень малом количестве примеров — самая распространённая причина. На слишком малом объёме данных модель не может учиться и обобщать. Прежде чем искать другие причины, убедись, что для каждого класса достаточно разнообразных примеров.
-
Проверь пути к данным: неверные пути к изображениям приводят к ошибке набора данных. Отдельные отсутствующие или пустые файлы меток считаются фоновыми изображениями, о чём сообщается во время сканирования; если в обучающей выборке нет меток, возникает ошибка. Проверь набор данных перед обучением:
yolo detect val model=yolo26n.pt data=custom.yaml -
Уменьши порог уверенности: если предсказания есть, но они отфильтровываются, попробуй
conf=0.1во время инференса. -
Проверь число классов: убедись, что
ncвdata.yamlсоответствует фактическому числу классов в файлах меток.
mAP на валидации перестаёт расти на раннем этапе#
- Добавь больше данных: дополнительный объём обучающих данных значительно повышает эффективность дообучения, особенно если это разнообразные примеры с разными ракурсами, освещением и фоном.
- Проверь баланс классов: у классов с недостаточным числом примеров будет низкий AP. Добавь примеры или настрой
cls_pwна валидационной выборке. - Уменьши аугментацию: для очень маленьких наборов данных сильная аугментация может навредить больше, чем помочь. Попробуй
mosaic=0.5илиmosaic=0.0. - Увеличь разрешение: для наборов данных с маленькими объектами попробуй
imgsz=1280, чтобы сохранить детали.
После дообучения качество на исходных классах ухудшается#
Это явление называют катастрофическим забыванием: при дообучении исключительно на новых данных модель теряет ранее полученные знания. Забывания в основном невозможно избежать, если не добавлять изображения из исходного набора данных вместе с новыми. Чтобы смягчить этот эффект:
- Объедини наборы данных: при дообучении добавь примеры исходных классов вместе с новыми. Это единственный надёжный способ предотвратить забывание.
- Заморозь backbone и neck: заморозка backbone и neck, при которой обучается только detection head, помогает при коротком дообучении с очень низкой скоростью обучения.
- Уменьши число эпох: чем дольше модель обучается только на новых данных, тем сильнее становится забывание.
Часто задаваемые вопросы#
Фиксированного минимума нет: результат зависит от сложности задачи, числа классов и сходства домена с COCO. Разнообразие изображений (разное освещение, ракурсы, фон) важнее их общего количества. Начни с имеющихся данных и увеличивай их объём, если метрики валидации недостаточны.
Загрузи предварительно обученный файл
.ptи вызови.train(), указав путь к собственномуdata.yaml. Ultralytics автоматически выполняет перенос весов, повторную инициализацию слоя классификации и выбор оптимизатора. Полный пример кода см. в разделе Базовая тонкая настройка.Самые распространённые причины — неверные пути к изображениям, отсутствующие или пустые файлы меток, несовпадение
ncв YAML с фактическими файлами меток или слишком высокий порог уверенности. Полный список рекомендаций по устранению неполадок см. в разделе Распространённые проблемы.Это зависит от размера набора данных и сходства доменов. Для небольших наборов данных с доменом, похожим на COCO, заморозка backbone (
freeze=10) предотвращает переобучение. Для доменов, сильно отличающихся от COCO, разморозка всех слоёв (freeze=None) позволяет адаптировать backbone. Подробные рекомендации см. в разделе Заморозка слоёв.Добавь в обучающие данные примеры исходных классов вместе с новыми. Если это невозможно, заморозка большего числа слоёв (
freeze=10или больше) и снижение скорости обучения помогают сохранить предобученные знания. Подробнее см. в разделе После дообучения качество на исходных классах ухудшается.
Комментарии4
Задай вопрос, поделись результатами или помоги кому-нибудь.
Yuan Yao(изменено)这是我在训练时遇到的一个问题,
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 81/1000 6.68G 0 0 0 195 640: 100% ━━━━━━━━━━━━ 121/121 1.2s/it 2:20 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 2.1it/s 11.1s all 1449 8364 0 0 0 0 Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 82/1000 6.68G 0 0 0 184 640: 100% ━━━━━━━━━━━━ 121/121 1.2s/it 2:20 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 2.0it/s 11.3s all 1449 8364 0 0 0 0 Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 83/1000 6.68G 0 0 0 221 640: 100% ━━━━━━━━━━━━ 121/121 1.2s/it 2:19 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 2.1it/s 11.1s all 1449 8364 0 0 0 0 Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 84/1000 6.68G 0 0 0 212 640: 100% ━━━━━━━━━━━━ 121/121 1.2s/it 2:20 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 2.1it/s 11.2s all 1449 8364 0 0 0 0 Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 85/1000 6.68G 0 0 0 221 640: 100% ━━━━━━━━━━━━ 121/121 1.2s/it 2:20 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 2.1it/s 11.2s all 1449 8364 0 0 0 0 Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 86/1000 6.68G 0 0 0 216 640: 100% ━━━━━━━━━━━━ 121/121 1.2s/it 2:20 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 2.1it/s 11.0s all 1449 8364 0 0 0 0 Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 87/1000 6.68G 0 0 0 198 640: 100% ━━━━━━━━━━━━ 121/121 1.2s/it 2:19 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 2.0it/s 11.4s all 1449 8364 0 0 0 0 Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 88/1000 6.68G 0 0 0 229 640: 100% ━━━━━━━━━━━━ 121/121 1.2s/it 2:20 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 2.1it/s 11.2s all 1449 8364 0 0 0 0 Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 89/1000 6.68G 0 0 0 182 640: 100% ━━━━━━━━━━━━ 121/121 1.1s/it 2:18 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 2.1it/s 11.0s all 1449 8364 0 0 0 0 Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 90/1000 6.68G 0 0 0 218 640: 100% ━━━━━━━━━━━━ 121/121 1.2s/it 2:20 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 2.1it/s 11.0s all 1449 8364 0 0 0 0 Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 91/1000 6.68G 0 0 0 181 640: 100% ━━━━━━━━━━━━ 121/121 1.2s/it 2:19 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 2.1it/s 11.1s all 1449 8364 0 0 0 0mAP一直是0。当时我用的是yaml文件用于训练模型,
model_name = r"H:\1_yaoyuan\code\01_yolo26\yolo_Project\ultralytics-main\ultralytics\cfg\models\11\yolo11.yaml"
之后改成了,
model_name = 'yolo11n.pt' # 首次运行会自动下载
然后训练才变的正常,
Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 2/1000 5.47G 2.825 1.856 0.8776 131 640: 100% ━━━━━━━━━━━━ 121/121 1.2s/it 2:20 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 2.0it/s 11.5s all 1449 8364 0.554 0.314 0.32 0.117 Epoch GPU_mem box_loss cls_loss dfl_loss Instances Size 3/1000 5.47G 2.904 1.726 0.8738 206 640: 100% ━━━━━━━━━━━━ 121/121 1.1s/it 2:19 Class Images Instances Box(P R mAP50 mAP50-95): 100% ━━━━━━━━━━━━ 23/23 1.9it/s 11.9s all 1449 8364 0.496 0.29 0.269 0.085这是为什么?微调和从头开始训练差别很大吗? 我问了deepseek,他说:“.yaml 路径迫使模型在毫无知识的情况下承受初始的梯度冲击,导致了数值崩溃;而 .pt 路径让模型从一个稳定的知识基础开始,顺利进入了正常的学习轨道。”
可如果是这样,如果这个世界还没有yolo的pt文件,那么是不是mAP永远都是0了?
Yuan Yao我还是刚学习的阶段,如果我问的问题很幼稚我非常抱歉
Paula DerrengerUltralytics不用道歉,这是很合理的问题!不是的:从
.yaml构建模型是随机初始化,从yolo11n.pt开始则利用预训练特征,通常收敛更快、需要的数据更少;YOLO11 官方示例也支持从零训练,并不需要已有.pt才能学会检测。你这里不仅 mAP 为 0,三个 loss 也连续为 0,这不能简单解释为“从零训练比较慢”,更应优先排查训练数值异常;仅凭这些日志,还不能确认 DeepSeek 所说的“梯度冲击”。建议保留 YAML,在原来的model.train(...)中加入amp=False,重新启动训练以排查混合精度问题(AMP 检查说明)。如果仍然全为 0,请贴出完整训练代码、启动到首个异常 epoch 的文本日志,以及 GPU 型号、Ultralytics 和 PyTorch 版本。
somerongit
Thank You, It's Really a great elaborate guide.