Схема чекпойнта
Файл .pt в LibreYOLO — плоский словарь, сохранённый через torch.save. Ключ model хранит state dict; остальные ключи верхнего уровня — метаданные, которые опознают чекпойнт без разбора имени файла и без заглядывания в state dict.
Схема v1.0
Каждый официальный чекпойнт .pt в LibreYOLO содержит:
{
"model": state_dict,
"schema_version": "1.0",
"libreyolo_version": "0.x.y",
"model_family": "yolo9",
"size": "t",
"task": "detect",
"nc": 80,
"names": {0: "cat", 1: "dog"},
"imgsz": 640,
}| Ключ | Тип | Описание |
|---|---|---|
model | state dict | Веса модели |
schema_version | str | Версия контракта метаданных; в v1.0 это строка "1.0" |
libreyolo_version | str | Версия, которая создала чекпойнт |
model_family | str | Зарегистрированное семейство, например yolo9, rfdetr, dfine, ec |
size | str | Вариант внутри семейства, например t, s, r18, atto |
task | str | Каноническое имя задачи |
nc | int | Положительное число классов |
names | dict | dict[int, str] с ключами в диапазоне 0..nc-1 |
imgsz | int | Положительное квадратное входное разрешение или устаревший скаляр для прямоугольного контракта |
task принимает одно из значений: detect, segment, semantic, panoptic,
pose, classify, gaze, obb, point, depth, edge, normal,
restore, matte, ocr, embed или mesh.
Официальные чекпойнты пишут все ключи names. Читающий код может дополнять
недостающие ключи метками class_i для устаревших разреженных отображений,
но ключи вне диапазона недопустимы.
Прямоугольные чекпойнты сохраняют скалярный imgsz для устаревшего читающего
кода, равный max(imgsz_h, imgsz_w), и дополнительно пишут imgsz_h и
imgsz_w с реальными размерами. Читающий код, который понимает прямоугольные
поля, обязан предпочитать их скаляру. Семейства с фиксированным прямоугольным
контрактом, например поза HRNet, отклоняют несовместимые размеры во время
выполнения.
Схема намеренно плоская, а model — намеренно state dict.
from libreyolo import LibreYOLOfrom libreyolo.utils.serialization import unwrap_libreyolo_checkpointimport torch # Скачать чекпойнт и пересохранить его, чтобы появился локальный путь.LibreYOLO("LibreYOLO9t.pt").save("roundtrip.pt") loaded = torch.load("roundtrip.pt", map_location="cpu", weights_only=False)state_dict, metadata = unwrap_libreyolo_checkpoint(loaded) print(metadata["schema_version"], metadata["model_family"])print(metadata["size"], metadata["task"], metadata["nc"], metadata["imgsz"])print(len(state_dict), "tensors")Дополнения для позы
Поза обычно одноклассовая — nc: 1 и person, — но голова позы YOLO-NAS
поддерживает и многоклассовую позу с одним общим скелетом ключевых точек, и
тогда nc и names описывают классы так же, как в детекции. Экспорт позы для
среды выполнения выдаёт scores с формой [batch, anchors, nc].
| Ключ | Описание |
|---|---|
num_keypoints | Положительное число ключевых точек, которое использует голова позы |
keypoint_dim | 2 для меток x,y или 3 для меток x,y,visibility; выходы модели всегда содержат x,y,visibility |
oks_sigmas | Необязательные OKS-сигмы для каждой ключевой точки; если ключа нет, берётся значение по умолчанию для задачи, соответствующее num_keypoints |
num_keypoints_per_class | Необязательное число ключевых точек по классам для голов в стиле GroupPose, у которых тензор ключевых точек дополнен по классам; 0 для классов без ключевых точек |
Дополнения для задачи mesh
Чекпойнты mesh используют task: "mesh", nc: 1 и names: {0: "person"}.
Раскладка параметров различается между моделями тела, поэтому размерности
записываются, а не предполагаются.
| Ключ | Описание |
|---|---|
body_model | Параметризация, например mhr; обязателен и определяет, как трактовать все поля ниже |
num_betas | Число коэффициентов идентичности и формы; 45 для MHR |
num_body_pose | Ширина блока параметров позы тела; 130 для MHR. Плоский вектор, а не по тройке на сустав, потому что суставы рига имеют разное число степеней свободы |
num_vertices | Число вершин, которое выдаёт декодер; 18439 для MHR |
num_joints | Число суставов, которое выдаёт декодер; 127 для MHR |
rotation_format | Как закодированы повороты, например euler_zyx для MHR или axis_angle. Никогда не выводится из формы тензора, поскольку трёхмерный вектор неоднозначен |
Заглушки для плотных задач
Некоторые задачи предсказывают плотные карты, а не классы, поэтому поля, похожие на классовые, существуют только ради совместимости со схемой.
| Задача | nc | names |
|---|---|---|
depth | 1 | {0: "depth"} |
edge | 1 | {0: "edge"} |
restore | 1 | {0: "image"} |
ocr | 1 | {0: "text"} |
Предсказания задачи edge — плотные карты вероятностей float32 в диапазоне
[0, 1].
Чекпойнты restore могут добавлять degradation — короткую метку искажения,
например deblur, denoise или super-resolution; dataset — метку
происхождения, например GoPro или SIDD; и scale — положительный целый
коэффициент увеличения выхода относительно входа, например 4 для модели
сверхразрешения x4. Отсутствие ключа или значение 1 означает, что
восстановленное изображение сохраняет входное разрешение. Среда выполнения
также выводит этот коэффициент из семейства и размера, поэтому scale —
метаданные о происхождении, а не требование на этапе загрузки.
Дополнения для OCR
Семейство ppocr поставляет по одному составному чекпойнту на уровень; его
state dict в model хранит две подмодели в пространствах ключей det.* и
rec.*.
| Ключ | Описание |
|---|---|
charset | Полный алфавит CTC в порядке выходных индексов: индекс 0 — пустой символ CTC, затем словарь распознавания, затем символ пробела. Загрузчики обязаны читать его из чекпойнта, а не из отдельного файла |
pipeline | Значения по умолчанию для пайплайна, зафиксированные при конвертации: det_limit_side_len, det_db_thresh, det_db_box_thresh, det_db_unclip_ratio, rec_image_shape. Аргументы времени выполнения могут переопределять их при каждом вызове |
components | Зарезервировано под необязательные стадии пайплайна: определение ориентации документа, распрямление и поворот текстовых строк. В v1 пусто |
Метаданные среды выполнения при экспорте
Экспортированные артефакты используют то же соглашение о двойной записи для
прямоугольного случая: imgsz_h и imgsz_w пишутся рядом с устаревшим
скаляром imgsz, а читающий код, который не понимает прямоугольные поля, не
должен молча считать скаляр квадратным контрактом.
Поддержка прямоугольного входа в среде выполнения ограничена конкретными
семействами и форматами. Экспорт семейства YOLO9, HRNet, NAFNet и Real-ESRGAN
может использовать неквадратные imgsz_h и imgsz_w в поддерживаемых
форматах; семейства или форматы без явной поддержки прямоугольного входа
отклоняют такие метаданные, а не обрабатывают эти артефакты как квадратные.
Экспорт HRNet даёт фиксированные головы по вырезу человека с батчем 1 и
точностью FP32, где W32 принимает 256x192, а W48 — 384x288, и детектор
человека в граф не встроен.
Экспорт со встроенным NMS может добавлять такие плоские ключи:
| Ключ | Описание |
|---|---|
nms | Строковое булево значение; "true" означает, что граф содержит встроенный выход постобработки |
nms_conf | Порог уверенности, зафиксированный во встроенном выходе |
nms_iou | Порог IoU, зафиксированный во встроенном выходе |
max_det | Максимальное число строк детекций после NMS, которое выдаёт встроенный выход |
nms_raw_output | Строковое булево значение; "true" означает, что граф также предоставляет вспомогательный сырой выход детектора |
Для экспорта детекции YOLO9 в ONNX с nms=true выход 0 (с именем output)
— самостоятельный тензор после NMS с порогами, заданными при экспорте. При
nms_raw_output=true выход 1 (с именем raw) зарезервирован для бэкендов
LibreYOLO, чтобы они применяли собственное отсечение по исходному холсту и
семантику predict(conf=..., iou=..., max_det=...) во время выполнения.
Сторонним потребителям следует использовать первый выход.
Экспорт позы может добавлять num_keypoints; keypoint_dim, где сырой
экспорт в стиле GroupPose может использовать более крупные значения, например
8, когда тензор включает поля точности или логитов классов;
num_keypoints_per_class как список в кодировке JSON, где слоты классов с
нулём ключевых точек обязаны сохраняться, потому что они задают схему; и
pose_input, где "person_crop" означает, что граф принимает один уже
вырезанный фрагмент и не содержит детектора. Экспорт HRNet для среды
выполнения требует именно этого значения.
Экспорт классификации может добавлять crop_pct — вещественную долю
центрального выреза, для которой целевой размер предварительного
масштабирования равен round(imgsz / crop_pct) и которая при отсутствии
ключа равна 0.875, — и interpolation со значением "bilinear" или
"bicubic" и значением по умолчанию "bilinear".
Экспорт в ExecuTorch пишет плоские метаданные в обязательный файл-спутник
<program>.pte.json. Контракт v1 — CPU, FP32, батч 1 и фиксированный входной
холст; дополнительно он требует executorch_version, executorch_delegate
со значением "xnnpack" и положительный executorch_delegate_partitions.
Загрузчик отклоняет файл-спутник, который заявляет другой делегат,
динамические формы или точность не FP32.
Экспорт в MNN пишет плоские метаданные в обязательный файл-спутник
<model>.mnn.json. Контракт v1 — CPU, FP32, только детекция и фиксированная
входная форма NCHW; дополнительно он требует mnn_version, mnn_backend со
значением "cpu", упорядоченные непустые mnn_input_names и
mnn_output_names, mnn_input_shape из четырёх положительных целых в
порядке [batch, channels, height, width] и mnn_batch, равный
mnn_input_shape[0]. Загрузчик отклоняет метаданные с динамическими формами,
с точностью не FP32, с задачей не детекции, с неподдерживаемым семейством
или с несогласованными формами.
.pte и .mnn — артефакты под конкретный бэкенд, а не чекпойнты PyTorch.
Квантизованные чекпойнты
Квантизованная модель добавляет один необязательный плоский ключ quant со
словарём-манифестом, где лежат schema, recipe, keep_high_precision,
execution, происхождение калибровки, module_count и state. Манифесты
FP8 могут дополнительно нести fp8_tensorwise_weights — точный список имён
модулей QuantLinear, у которых масштаб весов задан на весь тензор, а не на
каждый выходной канал. Загрузчик, который видит quant, восстанавливает
структуру квантизованных модулей и политику масштабирования до
load_state_dict.
state различает две формы артефакта.
"prepared" — значение по умолчанию: хранит мастер-веса FP32 и буферы
масштабов _q_*, и такую модель можно обучать. Читающий код без поддержки
квантизации может игнорировать ключ quant и загрузить мастер-веса как
обычную вещественную модель.
"finalized" — форма для развёртывания, которую пишет export(format="pt").
Мастер-веса удаляются, и вместо них каждый квантизованный модуль несёт
упакованные веса:
| Рецепт | Упакованные тензоры | Деквантизация |
|---|---|---|
| int8 | weight_packed int8 с исходной формой весов, _q_w_scale FP32 на канал | weight_packed * scale |
| fp8 | weight_packed float8_e4m3fn с исходной формой, _q_w_scale FP32 по одному значению на выходной канал | weight_packed * scale |
| w4a16, w4a8 | weight_packed uint8, два 4-битных кода на байт, младший ниббл первым, код q + 8; _q_w_gscale FP32 [out, ngroups], группа 128 вдоль in_features | Групповой масштаб |
| int2 | Четыре 2-битных кода на байт, код q + 2, группа 64 | Групповой масштаб |
| nvfp4 | weight_packed uint8 [out, ceil(in/16)*8], код sign<<3 | E2M1 level; weight_block_scale float8_e4m3fn [out, ceil(in/16)]; _q_w_amax FP32 на тензор | block_scale * amax / (448 * 6) |
| mxfp4 | Как nvfp4, но блоками по 32 элемента, плюс weight_block_exp int8 [out, ceil(in/32)] | 2 ** exponent |
Буферы диапазона активаций _q_act_lo, _q_act_hi и _q_calibrated
сохраняются для int8. Для неквантизованных тензоров манифест записывает
remainder со значением "fp16" или "fp32". Распаковка воспроизводит
симуляцию бит в бит, поэтому инференс в форме finalized в точности совпадает
с инференсом в форме prepared на том устройстве, где выполнялась финализация.
Эта раскладка — стабильный контракт для внешних экспортёров и сред
выполнения.
Чекпойнты обучения
Чекпойнты тренера используют то же обязательное ядро метаданных и могут добавлять плоские поля обучения и возобновления:
{
"model": state_dict,
"epoch": 42,
"optimizer": optimizer_state_dict,
"config": {},
"loss": 1.23,
"best_metric_key": "metrics/mAP50-95",
"best_metric_value": 0.51,
"best_epoch": 39,
"is_ema_weights": True,
"train_model": raw_state_dict,
"ema": ema_state_dict,
"ema_updates": 12345,
}is_ema_weights объявляет, сглажен ли model верхнего уровня с помощью EMA.
Когда EMA включена, train_model, ema и ema_updates сохраняют состояние
для возобновления. Публикуемые веса для инференса должны быть компактными и не
должны включать состояние оптимизатора, эпоху, конфиг, значение функции потерь
и состояние EMA для возобновления, если только их намеренно не распространяют
как чекпойнты обучения.
Ради совместимости между релизами читающий код принимает устаревшие псевдонимы
лучшей метрики: best_mAP50_95, best_mAP50, best_metric и
best_metric_name.
Внешние снапшоты
Схема распространяется на файлы .pt, созданные в LibreYOLO. Она не
переименовывает и не оборачивает многофайловые снапшоты upstream, которые
используются отдельными уровнями моделей.
Размер 14b-a7b у LibreMODUS — явное исключение: псевдоним разрешается через
LibreVLM(...) в каталог зафиксированных upstream-файлов, и
LibreYOLO не добавляет к нему метаданные v1.0 и не перевыкладывает его как
.pt.
Устаревшие и чужие веса
Новый пишущий код проверяет данные строго и обязан писать метаданные v1.0. Когда метаданных нет или они неполны, устаревшие чекпойнты, похожие на LibreYOLO, загружаются по пути совместимости с предупреждением и инструкцией по конвертации, а чужие upstream-чекпойнты уходят на автоконвертацию. См. upstream-чекпойнты.
Вспомогательные функции
Вспомогательные функции схемы лежат в libreyolo.utils.serialization:
wrap_libreyolo_checkpoint(
state_dict,
*,
model_family,
size,
task,
nc,
names=None,
imgsz=None,
libreyolo_version=None,
schema_version="1.0",
**extra_metadata,
) -> dict
validate_checkpoint_metadata(checkpoint, *, strict=False) -> list[str]
unwrap_libreyolo_checkpoint(loaded, *, strict=False) -> tuple[dict, dict]validate_checkpoint_metadata ничего не изменяет и возвращает список ошибок;
с strict=True вместо этого выбрасывает CheckpointMetadataError.
model.save(path) — поддерживаемый способ записать чекпойнт, который
соответствует схеме.