Ultralytics YOLO27: Запишись в список ожидания.
Начать

Как дообучить 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 переносит веса с учетом формы тензоров:

  1. Веса базовой сети и шеи переносятся полностью — эти слои извлекают общие визуальные признаки, а их формы не зависят от числа классов.
  2. Голова обнаружения инициализируется повторно частично — только финальная свертка каждой ветви классификации (cv3, one2one_cv3) имеет форму, зависящую от количества классов (80 против 5); скрытые слои ветви переносятся, если обе модели имеют один масштаб. Совпадающие классы сопоставляются по названиям, а затем соответствующие строки переносятся до инициализации несопоставленных строк. Слои регрессии рамок (cv2, one2one_cv2) в голове имеют фиксированную форму независимо от количества классов, поэтому переносятся обычным образом.
  3. При изменении количества классов переносится подавляющее большинство весов. Например, при тонкой настройке 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, поможет сохранить предварительно обученные признаки
Автоматический выбор оптимизатора переопределяет lr0

Если задано 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, что сводит риск переобучения к минимуму
Домен сильно отличается от COCOfreeze=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

Задай вопрос, поделись результатами или помоги кому-нибудь.

  1. Yuan YaoYuan 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          0

    mAP一直是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了?

    1. Paula DerrengerPaula DerrengerUltralytics

      不用道歉,这是很合理的问题!不是的:从 .yaml 构建模型是随机初始化,从 yolo11n.pt 开始则利用预训练特征,通常收敛更快、需要的数据更少;YOLO11 官方示例也支持从零训练,并不需要已有 .pt 才能学会检测。你这里不仅 mAP 为 0,三个 loss 也连续为 0,这不能简单解释为“从零训练比较慢”,更应优先排查训练数值异常;仅凭这些日志,还不能确认 DeepSeek 所说的“梯度冲击”。建议保留 YAML,在原来的 model.train(...) 中加入 amp=False,重新启动训练以排查混合精度问题(AMP 检查说明)。如果仍然全为 0,请贴出完整训练代码、启动到首个异常 epoch 的文本日志,以及 GPU 型号、Ultralytics 和 PyTorch 版本。