Как выполнить тонкую настройку YOLO на собственном наборе данных#
Финетюнинг адаптирует предобученную модель для распознавания новых классов, начиная с уже изученных весов, а не со случайной инициализации. Вместо обучения с нуля на протяжении сотен эпох финетунинг использует предобученные признаки COCO и сходится на пользовательских данных за малую часть времени.
В этом руководстве рассматривается финетунинг YOLO26 на пользовательских наборах данных: от базового использования до продвинутых техник, таких как заморозка слоев и двухэтапное обучение.
Тонкая настройка против обучения с нуля#
Предобученная модель уже извлекла общие визуальные признаки — обнаружение границ, распознавание текстур, понимание форм — из миллионов изображений. Трансфертное обучение посредством финетунинга переиспользует эти знания и лишь обучает модель распознавать новые классы, поэтому оно сходится быстрее и требует меньше данных. Обучение с нуля отбрасывает всё это и заставляет модель изучать всё с уровня паттернов пикселей, что требует значительно больше ресурсов.
| Дообучение | Обучение с нуля | |
|---|---|---|
| Начальные веса | Предобучены на 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 классов переносит 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, помогает сохранить предобученные признаки
Когда 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 | Обучается только голова детекции, минимизируя риск переобучения |
| Домен сильно отличается от COCO | freeze=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или выше) и использование более низкой скорости обучения помогут сохранить предобученные знания. Подробнее см. в разделе Ухудшение производительности на исходных классах.