Посмотреть как Markdown

Гиперпараметры

Каждый аргумент обучения — поле датакласса TrainConfig. Базовый класс задаёт само поле и его значение по умолчанию; каждое семейство моделей наследуется от него и переопределяет те значения, которые меняет его опубликованный рецепт.

Задание аргументов

train() принимает именованные аргументы, а CLI — те же имена в форме key=value.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")results = model.train(    data="my-dataset.yaml",    epochs=100,    batch=16,    imgsz=640,    lr0=0.01,) print(results["best_mAP50_95"])
CLI
libreyolo train model=LibreYOLO9s.pt data=my-dataset.yaml \  epochs=100 batch=16 imgsz=640 lr0=0.01

Оба пути ведут в одно и то же место. Аргументы передаются в TrainConfig.from_kwargs(), который собирает датакласс конфигурации семейства.

Опечатка не вызывает ошибку

from_kwargs() отбрасывает любой ключ, которого нет среди полей конфигурации, и выдаёт UserWarning с его именем. Обучение после этого стартует со значением по умолчанию:

python
# UserWarning: Unknown training config keys (ignored): ['learning_rate']model.train(data="my-dataset.yaml", learning_rate=0.001)

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

Значения по умолчанию свои у каждого семейства

TrainConfig задаёт поле и базовое значение по умолчанию. Каждое семейство наследуется от него и переопределяет то, что меняет его опубликованный рецепт, поэтому у вопроса «какая скорость обучения по умолчанию» нет одного правильного ответа.

Базовые значения по умолчанию — optimizer="sgd", lr0=0.01, momentum=0.937, weight_decay=5e-4, scheduler="yoloxwarmcos", epochs=300, batch=16, imgsz=640 и amp=True. Три примера того, как далеко семейство от них уходит:

ПолеБазаYOLOv9D-FINEYOLO-NAS
optimizersgdsgdadamwadamw
lr00.010.012e-45e-4
weight_decay5e-45e-41e-41e-5
scheduleryoloxwarmcoslinearflat_cosinecos
epochs300300132300
ampTrueTrueTrueTrue

D-FINE, DEIM, RT-DETRv4 и детекция YOLO-NAS по умолчанию используют amp=True с amp_dtype="float16". Dome-DETR, PP-YOLOE и YOLO-NAS OBB сохраняют FP32 по умолчанию. Передайте amp=False, когда нужен FP32.

Чтобы прочитать настоящие значения по умолчанию семейства, а не гадать:

Чтение итоговых значений по умолчанию для семейства
from dataclasses import fields from libreyolo import LibreYOLO9from libreyolo.training.config import TrainConfig family_cfg = LibreYOLO9.TRAIN_CONFIG()base_cfg = TrainConfig() for f in fields(family_cfg):    family_value = getattr(family_cfg, f.name)    base_value = getattr(base_cfg, f.name, None)    if not hasattr(base_cfg, f.name) or family_value != base_value:        print(f"{f.name}: {family_value}")
CLI
# Печатает значения по умолчанию для train, val и predict, включая переопределения семейств.libreyolo cfg

Размер батча

batch — это глобальный батч. При обучении на нескольких GPU каждый ранг загружает batch // world_size, поэтому переданное число — это число изображений на шаг оптимизатора независимо от того, сколько GPU задействовано. См. Обучение на нескольких GPU.

batch=-1 включает autobatch. Модель прогоняется в режиме обучения с настоящим обратным проходом на степенях двойки, по кривой потребления памяти строится прямая, и берётся наибольшая степень двойки строго ниже экстраполированного значения, которая укладывается в 60 процентов всей VRAM.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # batch=-1 замеряет память GPU и превращается в конкретную степень двойки.model.train(data="my-dataset.yaml", batch=-1, imgsz=640)
CLI
libreyolo train model=LibreYOLO9s.pt data=my-dataset.yaml batch=-1

Замер именно в режиме обучения и с обратным проходом — это принципиально: замер в режиме инференса не учитывает сохранённые активации и тензоры градиентов, а для глубокой CNN они в несколько раз превышают объём, нужный для инференса. RF-DETR снижает целевую долю до 45 процентов, потому что синтетический обратный проход при замере всё равно недооценивает, во что обходятся его функция потерь и вспомогательные слои декодера.

Autobatch работает только с CUDA. На CPU или MPS он пишет в лог одну строку и оставляет батч по умолчанию.

min_samples=0 оставляет длину эпохи неизменной. Положительный минимум выбирает примеры из коротких датасетов детекции с возвращением. class_balanced=False при включении задаёт повторную выборку изображений с коэффициентами повторения; она сочетается с min_samples и DDP. Специализированные загрузчики, обходящие общий семплер, отклоняют включённую балансировку.

Накопление градиентов

nbs задаёт номинальный, он же эффективный, размер батча. На один шаг оптимизатора накапливается round(nbs / batch) микробатчей.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # 4 микробатча по 16 на шаг оптимизатора, эффективный батч 64.model.train(data="my-dataset.yaml", batch=16, nbs=64)

Если оставить None — значение по умолчанию, — накопление выключено и обучение идёт как обычно.

Скорость обучения и расписание

lr0 — начальная скорость обучения, а optimizer принимает sgd, adam и adamw. momentum — это момент SGD или beta1 у Adam, weight_decay — L2-слагаемое, а nesterov относится к SGD.

Форму расписания задают scheduler, warmup_epochs, warmup_lr_start и min_lr_ratio. no_aug_epochs задаёт, сколько последних эпох идёт без сильной аугментации, и несколько расписаний используют его ещё и для формы своего хвоста, так что это не только настройка аугментации. Что каждое семейство делает с аугментационной половиной этого параметра, описано на странице Аугментации.

Некоторые семейства добавляют свои настройки скорости обучения. backbone_lr_mult масштабирует группу бэкбона относительно головы, clip_max_norm задаёт обрезку градиентов, а SegFormer использует head_lr_mult, чтобы его декодирующая голова обучалась со скоростью в десять раз выше, чем у бэкбона. Эти поля живут в подклассе конфигурации семейства, а не в базовом.

clip_max_norm обрезает L2-норму градиента до этого значения перед каждым шагом оптимизатора, а 0 отключает обрезку. У YOLOv9, YOLOv9-E2E и YOLOv9-P2 по умолчанию он равен 10. У D-FINE, Dome-DETR, DEIM, DEIMv2, TinyFormer, RT-DETR, RT-DETRv2, RT-DETRv4, RF-DETR, DINOv2, GTR и EC по умолчанию он равен 0.1. В CLI это clip_max_norm= или --clip-max-norm; семейства, которые принимают его там, перечислены в libreyolo train.

EMA

ema=True держит экспоненциальное скользящее среднее весов рядом с обученными. По умолчанию оно включено везде, кроме FOMO.

ema_decay — целевой коэффициент затухания. Затухание нарастает, а не начинается сразу с целевого значения: фактическая величина на обновлении n равна ema_decay * (1 - exp(-n / tau)), где tau по умолчанию 2000, поэтому ранние обновления точнее следуют за моделью, а поздние её сглаживают. Значения по умолчанию у семейств идут от 0.997 у YOLO-NAS pose через 0.9998 у YOLOX до 0.9999 у YOLOv9 и линейки DETR.

Валидируются именно веса EMA, и они же лежат в best.pt и last.pt. Исходные обученные веса тоже сохраняются, под ключом train_model, поэтому возобновление продолжает обученную траекторию, а не среднее.

Точность вычислений

amp=True выполняет прямой проход под CUDA autocast. amp_dtype выбирает float16 (по умолчанию) или bfloat16; написания fp16 и bf16 тоже принимаются.

Float16 нуждается в динамическом масштабировании функции потерь и получает работающий GradScaler. Bfloat16 с его более широким диапазоном экспоненты в этом не нуждается, поэтому его scaler создаётся, но остаётся выключенным, а путь оптимизатора при этом не меняется. Запрос bfloat16 на устройстве с CUDA без поддержки bfloat16 приводит к ошибке на этапе настройки, а не к тихой деградации.

Вывод, чекпойнты и остановка

Запуски пишутся в project/name. project везде по умолчанию равен runs/train, а вот name — одно из полей, переопределяемых на уровне семейства: базовое значение по умолчанию — exp, тогда как YOLOv9 использует yolo9_exp, а D-FINE — dfine_exp. При exist_ok=False, значении по умолчанию, к существующему каталогу добавляется числовой суффикс, вместо того чтобы перезаписать его.

save_period пишет дополнительный weights/epoch_<N>.pt каждые N эпох — вдобавок к weights/last.pt после каждой эпохи и weights/best.pt всякий раз, когда отслеживаемая метрика улучшается. eval_interval задаёт, как часто запускается валидация, а последняя эпоха проходит валидацию всегда; val=False выключает валидацию, и такой запуск не записывает best.pt. patience останавливает запуск после указанного числа эпох без улучшения; 0 отключает раннюю остановку.

cache ускоряет повторные эпохи, держа декодированные изображения в RAM (True или "ram") либо в виде файлов .npy рядом с исходниками ("disk"). Чтение из кэша побайтово совпадает с обычным. Если работают воркеры загрузчика данных, из двух вариантов безопаснее "disk".

average_best=0 отключает усреднение чекпойнтов; положительное N записывает weights/average.pt из не более N лучших снимков. Тензоры с плавающей точкой усредняются равномерно, а целочисленные буферы берутся из лучшего снимка. export_check=False можно включить, чтобы остановить запуск до первой эпохи при ошибке экспорта ONNX. Совпадающие сырые выходы сравниваются с rtol=1e-3, atol=1e-4; для несовместимых структур журнал сообщает о пропуске сравнения.

precise_bn=0 отключает финальную перекалибровку BatchNorm. Положительное значение ограничивает число изображений загрузчика обучения перед финальной валидацией; в DDP лимит применяется к каждому участвующему рангу. Замороженный BatchNorm остаётся замороженным. Собственные колбэки fitness могут управлять выбором лучших чекпойнтов и patience.

Возобновление

resume=True продолжает прерванный запуск с загруженного чекпойнта; resume="path/to/last.pt" вместо этого продолжает с указанного файла.

Python
from libreyolo import LibreYOLO # Загрузить чекпойнт прерванного запуска, затем попросить продолжить.model = LibreYOLO("runs/train/yolo9_exp/weights/last.pt")model.train(data="my-dataset.yaml", resume=True)
CLI
libreyolo train model=runs/train/yolo9_exp/weights/last.pt \  data=my-dataset.yaml resume=true

Возобновление восстанавливает сохранённые аргументы обучения запуска, а явно переданный аргумент переопределяет сохранённый. Оно продолжает писать в каталог запуска чекпойнта. Оно восстанавливает обученные веса, состояние оптимизатора, веса EMA и счётчик обновлений, отслеживание лучшей метрики, масштаб GradScaler, а также состояния генераторов случайных чисел PyTorch, CUDA и NumPy. Оно стартует с эпохи чекпойнта плюс один и прокручивает расписание до этой точки.

Трёх вещей оно не сделает. resume=True нельзя сочетать с pretrained — это приводит к ошибке. В опубликованных весах и в запуске, который уже дошёл до своего epochs, возобновлять нечего, и они вызывают ValueError, который об этом сообщает. И если ключ лучшей метрики в чекпойнте отличается от ключа текущего запуска, отслеживание лучшей метрики сбрасывается в ноль с предупреждением, вместо того чтобы сравнивать величины, которые означают разное.

Рецепты в файле

cfg= загружает YAML-словарь с именами полей TrainConfig и подкладывает его под явные именованные аргументы, так что kwarg всегда побеждает файл.

Python
from libreyolo import LibreYOLO # Ключи в yaml — имена полей TrainConfig. Явные kwargs побеждают.model = LibreYOLO("LibreYOLO9s.pt")model.train(data="my-dataset.yaml", cfg="my-recipe.yaml", epochs=50)

size и num_classes из файла вырезаются, потому что они уже принадлежат экземпляру модели. Флага --cfg в CLI нет; путь к файлу — это аргумент Python.

Выбор классов и взвешивание функции потерь

Для детекции YOLO9, RF-DETR, EdgeCrafter, RT-DETR, D-FINE, DEIM, TinyFormer и YOLO-NAS параметр classes=None сохраняет все классы датасета; список фильтрует разметку, сохраняя исходные ID, nc и names. single_cls=False можно включить, чтобы переназначить сохранённые метки классу 0 с именем object. Возобновление и валидация наследуют сохранённые настройки. Обучение OBB отклоняет single_cls.

ResNet, ConvNeXt, ConvNeXt V2, MobileNetV4, EfficientNetV2 и DINOv2 поддерживают cls_pw=0.0: значения в [0, 1] взвешивают каждый класс обратной частотой в этой степени с нормализацией к среднему 1. class_weights=False при включении выбирает альтернативное взвешивание N / (C * n_c). Оно не сочетается с положительным cls_pw; возобновление требует совпадения настроек взвешивания.

plot_samples=8 задаёт лимит примеров изображений валидации. Используйте 0, чтобы не выводить их, или -1 для всех; это не уменьшает число оцениваемых изображений.

Проверено с LibreYOLO v1.6.0.