Обновление до 1.5.0
Из публичного API моделей ничего не удалено: все классы и функции, которые работали в 1.4.0, по-прежнему импортируются. Четыре аргумента изменили форму, а три значения по умолчанию сдвигают числа, с которыми вы, возможно, сравниваете.
- Применимо к
- с 1.4.0 на 1.5.0
- Требуемые изменения в коде
- Четыре, все точечные
- Что сдвигается в результатах
- бэкенд COCO, BN eps в YOLOX, многомасштабность D-FINE
- Удаления из публичного API
- Нет
Эта страница — про обновление самого LibreYOLO. Если вы ищете, как загрузить чекпойнт из оригинального проекта, то это импорт существующих весов — другая тема.
Полная запись о релизе — в списке изменений. Ниже — только та часть, которая что-то требует от вас.
Изменения в коде, которые нужно внести
allow_experimental=True больше не существует
Барьер с подтверждением убран вместе с механизмом
ddp_aware(experimental_key=...), который стоял за ним. Обучение и экспорт EC,
RTMDet, PicoDet и FOMO раньше требовали этого аргумента, поэтому затронут любой
скрипт, который обучает одно из этих семейств.
# 1.4.0
model.train(data="data.yaml", epochs=100, allow_experimental=True)
# 1.5.0: удалите аргумент
model.train(data="data.yaml", epochs=100)Прослойки для обратной совместимости нет. Вызов, который всё ещё его передаёт,
завершается ошибкой TypeError. Вместе с аргументом удалён
BaseModel.EXPERIMENTAL_WEIGHT_FILENAMES. Хук get_download_notice()
сохранился, и его по-прежнему переопределяют MiDaS, SegFormer и YOLO9-P2.
Уровни поддержки по-прежнему публикуются, просто это больше не аргумент: см. уровни стабильности.
Уровня экспорта "experimental" больше не существует
from libreyolo.export.support import Tier
# 1.4.0: Literal["validated", "experimental", "blocked"]
# 1.5.0: Literal["validated", "available", "blocked"]В коде, который ветвится по строке уровня, "experimental" нужно заменить на
"available". BaseExporter больше не выдаёт RuntimeWarning для
этих форматов. Состояние по каждому формату перечислено в
матрице экспорта.
pretrained=False вместе с resume теперь отклоняется
Раньше эта комбинация отрабатывала несогласованно. Теперь она вызывает ошибку:
ValueError: pretrained=False cannot be combined with resume.Выберите что-то одно. pretrained=False начинает с новой инициализации,
задаваемой сидом, — в 1.5.0 это работает для каждого обучаемого семейства, а не
для трёх из них, — а resume продолжает прерванный запуск с его чекпойнта. Оба
варианта описаны в разделе обучение.
CLI-параметр --imgsz — строка, а не int
Изменение уже, чем кажется. Оба этих случая не затронуты:
libreyolo predict --model yolo9-t --source img.jpg --imgsz 640 # по-прежнему работаетmodel.predict("img.jpg", imgsz=640) # по-прежнему работаетМенять нужно только тот код, который вызывает функции команд CLI
напрямую из Python, потому что в predict, train и val тип --imgsz
расширен с int до str, чтобы он принимал прямоугольные размеры:
from libreyolo.cli.commands.predict import predict_cmd
predict_cmd(..., imgsz=640) # 1.4.0
predict_cmd(..., imgsz="640") # 1.5.0, и теперь "480x640" тоже работаетЗначение по умолчанию у train теперь — строка "640". export --imgsz и
раньше принимал строку, а profile не изменился.
Числа, которые меняются
Три изменения сдвигают метрики на настройках по умолчанию. Если вы отслеживаете результаты между версиями, прочитайте их прежде, чем сравнивать запуск на 1.5.0 с запуском на 1.4.0.
faster-coco-eval — бэкенд метрик COCO по умолчанию
val() и валидация по эпохам во время обучения теперь считают метрики COCO на
C++-бэкенде faster-coco-eval, а не на pycocotools.
Решение о переключении принято по измеренному совпадению на всех 100 тестовых сплитах RF100-VL: 1381 из 1400 значений метрик побитово идентичны, максимальное отклонение 2.22e-16, отличия в главных метриках ровно 0, при этом в 15.6 раза быстрее в целом и в 56 раз на датасетах с плотной детекцией. Ваши числа сдвигаться не должны. Но получены они всё же другой реализацией — именно поэтому пункт попал в список.
pycocotools остаётся автоматическим запасным вариантом, когда faster-coco-eval не установлен. Чтобы включить его принудительно:
libreyolo val --model yolo9-t --data coco.yaml --no-faster-coco-evalmodel.val(data="coco.yaml", faster_coco_eval=False)LIBREYOLO_FASTER_COCO_EVAL=0 делает то же самое глобально. Реально
использованный бэкенд пишется в лог на уровне INFO, доступен как
model.last_eval_backend после val() и попадает в JSON-вывод
CLI под ключом eval_backend. Быстрый путь ставится командой
pip install libreyolo[fast-eval].
Чекпойнтам YOLOX, обученным до 1.5.0, нужно переопределение eps
Это ловушка релиза. Прочитайте, если вы дообучали YOLOX.
В YOLOX для BatchNorm заданы eps=1e-3 и momentum=0.03. До 1.5.0 эти
значения применялись постфактум, и такая правка не переживала перестройку под
число классов, которую train() выполняет, когда nc вашего датасета
отличается от nc чекпойнта. Такое дообучение обучалось и считало валидацию во
время обучения при значении torch по умолчанию eps=1e-5, а потом
перезагружалось для инференса с 1e-3: те же тензоры при другой нормализации.
Размеры с обычными свёртками почти не сдвигаются. Depthwise-размер n
сдвигается сильно, потому что его поканальная running_var достаточно мала,
чтобы eps начал доминировать. На RF100-VL ball один и тот же чекпойнт nano
даёт 0.566 mAP50-95 при оценке с тем eps, с которым он обучался, и
0.151 после обычной перезагрузки.
Чекпойнт, обученный до 1.5.0, несёт семантику eps=1e-5. Чтобы получить для него достоверные числа, либо проводите оценку с BN eps, переопределённым на 1e-5:
import torch
from libreyolo import LibreYOLOX
model = LibreYOLOX("my-yolox-finetune.pt")
for module in model.model.modules():
if isinstance(module, torch.nn.BatchNorm2d):
module.eps = 1e-5
model.val(data="data.yaml")либо один раз вложите sqrt((var + 1e-3) / (var + 1e-5)) в веса BN и сохраните
результат. Чекпойнтам, обученным на 1.5.0 и позже, не нужно ни то, ни другое.
Многомасштабное обучение D-FINE использует оригинальный рецепт для каждого размера
base_size_repeat был жёстко зашит в 3 для всех размеров. Теперь он
определяется по размеру так, как задано в оригинале: n обучается на
фиксированном размере с выключенной многомасштабностью, s — 20, m — 6,
l — 4, x — 3. Раньше совпадал только x, поэтому n, s, m и l видят
другое распределение масштабов и сходятся к другим метрикам.
Чтобы вернуть прежнее поведение, задайте значение явно:
from libreyolo.training.config import DFINEConfig
config = DFINEConfig(base_size_repeat=3)DEIM по-прежнему использует жёстко зашитую 3. Подробности о семействе — на странице D-FINE.
Полезно знать, действий не требуется
- Результаты при прямоугольном
imgszизменились, потому что раньше были неверными. Координаты рамок, изменение размера масок в RTMDet, масштабирование в YOLO-NAS и масштабирование эталонной разметки (ground truth) в валидаторе теперь используют высоту и ширину по каждой оси, а не один скаляр. При квадратномimgszрезультаты побитово те же. Прямоугольный инференс или валидация, запущенные на 1.4.0, масштабировались неверно. YOLO-NAS теперь прямо отклоняет прямоугольныйimgsz, а не выдаёт молча неправильный результат. - В словарях метрик появились новые ключи.
max_det,ar_max_detиAR_max_detиз оценщика COCO, а такжеmetrics/lossиmetrics/loss/ceиз FOMO. Значения при настройках по умолчанию не изменились, но всё, что перебирает ключи метрик, включая пользовательские логгеры и заголовки CSV, увидит новые колонки. - Запуски YOLO9 с заданным сидом, которые вызывают перестройку головы, стартуют с другой инициализации, потому что сид теперь применяется до перестройки, а не после. Дообучение с сидом, сделанное на 1.4.0 под другое число классов, не воспроизводится побитово на 1.5.0.
libreyolo[hub-kernels]на CUDA теперь действительно задействует нативное ядро MS-deform-attn. В 1.4.0 оно было закрыто условием, в которое RF-DETR никогда не попадал, поэтому ядро не запускалось. Предсказания могут сдвигаться в пределах точности float для RF-DETR и других семейств с deformable attention. Обычные установки это не затрагивает, аLIBREYOLO_HUB_KERNELS=0отключает ядро.libreyolo predictотбрасывает неподдерживаемые опции вместо ошибки. CLI фильтрует kwargs по сигнатуре__call__модели, поэтому опция, которую семейство не принимает, игнорируется, а не приводит кTypeError. Опечатка в имени флага теперь молча игнорируется.- Источники в реальном времени меняют форму JSON-вывода. Веб-камеры, RTSP-потоки и захват экрана неявно включают стриминг, а он выдаёт по одной записи на кадр, а не одну на вызов. Эти источники появились в 1.5.0, поэтому ни один скрипт для 1.4.0 не затронут.
- Повторный экспорт
rfdetr-poseилиyolonas-poseв ONNX даёт другие имена выходов. В 1.4.0 их многотензорные головы для оценки позы ошибочно определялись как сегментация — по эвристике на число выходов. Уже лежащие на диске файлы.onnxне затронуты. - В установке без torch результаты содержат массивы numpy, а не
torch.Tensor, поэтому.boxes.dataвозвращает другой тип, а разрешение совпадений в NMS может отличаться от torchvision. С установленным torch поведение побайтово прежнее. См. облегчённая установка. - Объекты конфигурации сильнее проверяются при создании. У
TrainConfigпоявился__post_init__, которого раньше не было, поэтому конфигурация, которая и так была некорректной, теперь падает сразу, а не в середине запуска. В сериализациюValidationConfigдобавился ключedge_thresholds, и это ломает строгий обратный разбор дампа 1.4.0 черезValidationConfig(**dump). - Имена файлов весов у семейств с суффиксом задачи определяются иначе.
segformer-b0теперь соответствует файлуLibreSegformerb0-sem.pt. Это устраняет 404 при автоскачивании и ломает любой скрипт, в котором было жёстко прописано старое имя без суффикса. - Маркер pytest
experimental_backendтеперь называетсяextended_backend. Важно, только если вы запускаете набор тестов с-m.
Чекпойнты и датасеты
Чекпойнты, записанные в 1.4.0, загружаются без изменений. В
схему добавились imgsz_h и imgsz_w для
прямоугольных моделей, и она по-прежнему пишет скалярный imgsz = max(h, w)
для кода, который читает её по-старому. Экспорт в
ExecuTorch и MNN теперь требует
сопроводительного файла — <program>.pte.json и
<model>.mnn.json соответственно, — а экспорт HRNet несёт
pose_input: "person_crop". Форматы датасетов не изменились.