YOLO Vision 2026:

Как выполнить тонкую настройку YOLO на собственном наборе данных#

Финетюнинг адаптирует предобученную модель для распознавания новых классов, начиная с уже изученных весов, а не со случайной инициализации. Вместо обучения с нуля на протяжении сотен эпох финетунинг использует предобученные признаки COCO и сходится на пользовательских данных за малую часть времени.

В этом руководстве рассматривается финетунинг YOLO26 на пользовательских наборах данных: от базового использования до продвинутых техник, таких как заморозка слоев и двухэтапное обучение.

Тонкая настройка против обучения с нуля#

Предобученная модель уже извлекла общие визуальные признаки — обнаружение границ, распознавание текстур, понимание форм — из миллионов изображений. Трансфертное обучение посредством финетунинга переиспользует эти знания и лишь обучает модель распознавать новые классы, поэтому оно сходится быстрее и требует меньше данных. Обучение с нуля отбрасывает всё это и заставляет модель изучать всё с уровня паттернов пикселей, что требует значительно больше ресурсов.

ДообучениеОбучение с нуля
Начальные весаПредобучены на 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 классов переносит 606 из 708 тензоров весов: переинициализируются только слои классификации, зависящие от количества классов, в то время как бэкбон, нек и ветви регрессии боксов остаются нетронутыми.

Для наборов данных с тем же количеством классов, что и у предобученной модели (например, тонкая настройка весов, предобученных на COCO, на другом наборе из 80 классов), переносится 100% весов, включая голову детекции.

Перенос классов с помощью псевдонимов имен#

Ultralytics переносит совпадающие строки классификационной головы по имени класса в разных датасетах, игнорируя регистр и пробелы вокруг. Когда эквивалентные классы используют разные имена, переименуй классы исходного чекпоинта в памяти перед загрузкой. Это сохраняет предобученные веса классификации для общих концептов, которые иначе считались бы несовпадающими и инициализировались случайно.

Этот пример перехода с Objects365 v2 на COCO переименовывает исходные классы в загруженном чекпоинте, который train() затем передает дальше в качестве предобученных весов:

from ultralytics import YOLO

# Source Objects365 v2 name -> target COCO name
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")
model.model.names = {i: ALIASES.get(name, name) for i, name in model.model.names.items()}
model.train(data="coco.yaml", epochs=100, imgsz=640)

Пример базовой тонкой настройки#

Пример
from ultralytics import YOLO

model = YOLO("yolo26n.pt")  # load pretrained model
model.train(data="custom.yaml", epochs=50, imgsz=640)

Выбор размера модели#

Более крупные модели обладают большей емкостью, но также содержат больше параметров для обновления, что может увеличить риск переобучения при ограниченности обучающих данных. Начать с меньшей модели (YOLO26n или YOLO26s) и увеличивать масштаб только в случае плато метрик валидации — практичный подход. Оптимальный размер модели зависит от сложности задачи, количества классов, разнообразия датасета и доступного для деплоя железа. Доступные размеры и бенчмарки производительности см. на полной странице модели YOLO26.

Выбор оптимизатора и скорости обучения (Learning Rate)#

Настройка optimizer=auto по умолчанию выбирает оптимизатор и скорость обучения на основе общего числа итераций обучения:

  • < 10 000 итераций (малые наборы данных или мало эпох): AdamW с низкой, автоматически рассчитанной скоростью обучения
  • > 10 000 итераций (большие датасеты): MuSGD (гибридный оптимизатор Muon+SGD) с lr=0.01

Для большинства задач тонкой настройки эта настройка по умолчанию работает хорошо без ручного вмешательства. Рассмотри возможность явного указания оптимизатора, если:

  • Обучение нестабильно (функция потерь скачет или расходится): попробуй optimizer=AdamW, lr0=0.001 для более стабильной сходимости
  • Финетюнинг большой модели на маленьком датасете: более низкая скорость обучения, например lr0=0.001, помогает сохранить предобученные признаки
Автоматический оптимизатор переопределяет ручное значение lr0

Когда optimizer=auto, значения lr0 и momentum игнорируются. Чтобы управлять скоростью обучения вручную, задай оптимизатор явно: optimizer=SGD, lr0=0.005.

Заморозка слоев (Freezing Layers)#

Заморозка предотвращает обновление определенных слоев во время обучения. Это ускоряет обучение и снижает переобучение, когда датасет мал по сравнению с емкостью модели.

Параметр 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"], для точечного контроля над конкретными ветвями внутри слоя (в данном случае — обеими ветвями регрессии боксов головы детектирования).

Пример
model.train(data="custom.yaml", epochs=50, freeze=10)

Правильная глубина заморозки зависит от того, насколько целевой домен похож на предобученные данные и сколько доступно данных для обучения:

СценарийРекомендацияОбоснование
Большой набор данных, похожий доменfreeze=None (по умолчанию)Достаточно данных для адаптации всех слоев без переобучения
Малый набор данных, похожий доменfreeze=10Сохраняет признаки бэкбона, уменьшает количество обучаемых параметров
Очень малый набор данныхfreeze=23Обучается только голова детекции, минимизируя риск переобучения
Домен сильно отличается от COCOfreeze=NoneПризнаки бэкбона могут переноситься плохо и требуют переобучения

Глубину заморозки можно также рассматривать как гиперпараметр — проба нескольких значений (0, 5, 10) и сравнение mAP на валидации — практичный способ найти лучшую настройку для конкретного набора данных.

Ключевые гиперпараметры для тонкой настройки#

Тонкая настройка обычно требует меньше корректировок гиперпараметров, чем обучение с нуля. Наиболее важные параметры:

  • epochs: Финетюнинг сходится быстрее, чем обучение с нуля. Начни с умеренного значения и используй patience, чтобы вовремя остановить обучение, когда метрики валидации выйдут на плато.
  • patience: Значение по умолчанию (100) рассчитано на долгие прогоны обучения. Его уменьшение до 10-20 позволяет не тратить время на прогоны, которые уже сошлись.
  • warmup_epochs: Разогрев по умолчанию (3 эпохи) плавно увеличивает скорость обучения с нуля, что предотвращает повреждение предобученных признаков большими градиентными обновлениями на ранних итерациях. Рекомендуется сохранять значение по умолчанию даже для финетунинга.

Полный список параметров обучения см. в справочнике конфигурации обучения.

Двухэтапная тонкая настройка#

Двухэтапная тонкая настройка разделяет обучение на две фазы. Первый этап замораживает бэкбон и тренирует только нек и голову, позволяя слоям детекции адаптироваться к новым классам, не нарушая работу предобученных признаков. Второй этап размораживает все слои и тренирует полную модель с более низкой скоростью обучения, чтобы адаптировать бэкбон к целевому домену.

Этот подход особенно полезен, когда целевой домен сильно отличается от 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=custom.yaml перед обучением, чтобы убедиться, что разметка загружается корректно.
  • Снизь порог уверенности: если предсказания существуют, но отфильтровываются, попробуй задать conf=0.1 во время инференса.
  • Проверь количество классов: убедись, что параметр nc в data.yaml соответствует реальному количеству классов в файлах разметки.

mAP на валидации слишком рано выходит на плато#

  • Добавь больше данных: тонкая настройка значительно выигрывает от дополнительных данных, особенно разнообразных примеров с измененными углами, освещением и фоном.
  • Проверь баланс классов: недопредставленные классы будут иметь низкий показатель AP. Используй cls_pw, чтобы применить обратную частотную весовку классов (начни с cls_pw=0.25 при умеренном дисбалансе и увеличь до 1.0 при серьезном дисбалансе).
  • Уменьши аугментацию: для очень маленьких датасетов агрессивная аугментация может принести больше вреда, чем пользы. Попробуй mosaic=0.5 или mosaic=0.0.
  • Увеличь разрешение: для датасетов с мелкими объектами попробуй imgsz=1280, чтобы сохранить детали.

Качество предсказаний исходных классов снижается после тонкой настройки#

Это известно как катастрофическое забывание — модель теряет ранее изученные знания при тонкой настройке исключительно на новых данных. Забывания практически невозможно избежать без включения изображений оригинального набора данных вместе с новыми. Чтобы смягчить это:

  • Объедини наборы данных: включи примеры оригинальных классов вместе с новыми во время тонкой настройки. Это единственный надежный способ предотвратить забывание.
  • Заморозь бэкбон и нек: заморозка и того, и другого, чтобы обучалась только голова детекции, помогает при коротких сеансах тонкой настройки с очень низкой скоростью обучения.
  • Тренируй меньше эпох: чем дольше модель тренируется исключительно на новых данных, тем больше возрастает забывание.

FAQ#

  • Фиксированного минимума нет — результаты зависят от сложности задачи, количества классов и того, насколько домен близок к COCO. Более разнообразные изображения (изменчивое освещение, углы, фоны) значат больше, чем просто количество. Начни с того, что есть, и масштабируйся, если метрик валидации недостаточно.

  • Загрузи файл предобученной модели .pt и вызови .train() с путем к кастомному data.yaml. Ultralytics автоматически обрабатывает перенос весов, реинициализацию головы детектирования и выбор оптимизатора. Полный пример кода см. в разделе Базовый финетунинг.

  • Наиболее частые причины — неверные пути в data.yaml (что молча приводит к нулевой разметке), расхождение между nc в YAML и реальными файлами разметки либо слишком высокий порог уверенности. Полный чек-лист для поиска и устранения неисправностей см. в разделе Типичные ошибки.

  • Это зависит от размера датасета и сходства доменов. Для небольших датасетов с доменом, близким к COCO, заморозка бэкбона (freeze=10) предотвращает переобучение. Для доменов, сильно отличающихся от COCO, оставление всех слоев незамороженными (freeze=None) позволяет бэкбону адаптироваться. Подробные рекомендации см. в разделе Заморозка слоев.

  • Включай примеры исходных классов в обучающие данные наряду с новыми классами. Если это невозможно, заморозка большего числа слоев (freeze=10 или выше) и использование более низкой скорости обучения помогут сохранить предобученные знания. Подробнее см. в разделе Ухудшение производительности на исходных классах.

Участники

Комментарии