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

Схема чекпойнта

Файл .pt в LibreYOLO — плоский словарь, сохранённый через torch.save. Ключ model хранит state dict; остальные ключи верхнего уровня — метаданные, которые опознают чекпойнт без разбора имени файла и без заглядывания в state dict.

Схема v1.0

Каждый официальный чекпойнт .pt в LibreYOLO содержит:

python
{
    "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,
}
КлючТипОписание
modelstate dictВеса модели
schema_versionstrВерсия контракта метаданных; в v1.0 это строка "1.0"
libreyolo_versionstrВерсия, которая создала чекпойнт
model_familystrЗарегистрированное семейство, например yolo9, rfdetr, dfine, ec
sizestrВариант внутри семейства, например t, s, r18, atto
taskstrКаноническое имя задачи
ncintПоложительное число классов
namesdictdict[int, str] с ключами в диапазоне 0..nc-1
imgszintПоложительное квадратное входное разрешение или устаревший скаляр для прямоугольного контракта

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_dim2 для меток 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. Никогда не выводится из формы тензора, поскольку трёхмерный вектор неоднозначен

Заглушки для плотных задач

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

Задачаncnames
depth1{0: "depth"}
edge1{0: "edge"}
restore1{0: "image"}
ocr1{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"). Мастер-веса удаляются, и вместо них каждый квантизованный модуль несёт упакованные веса:

РецептУпакованные тензорыДеквантизация
int8weight_packed int8 с исходной формой весов, _q_w_scale FP32 на каналweight_packed * scale
fp8weight_packed float8_e4m3fn с исходной формой, _q_w_scale FP32 по одному значению на выходной каналweight_packed * scale
w4a16, w4a8weight_packed uint8, два 4-битных кода на байт, младший ниббл первым, код q + 8; _q_w_gscale FP32 [out, ngroups], группа 128 вдоль in_featuresГрупповой масштаб
int2Четыре 2-битных кода на байт, код q + 2, группа 64Групповой масштаб
nvfp4weight_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 на том устройстве, где выполнялась финализация. Эта раскладка — стабильный контракт для внешних экспортёров и сред выполнения.

Чекпойнты обучения

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

python
{
    "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:

python
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) — поддерживаемый способ записать чекпойнт, который соответствует схеме.

Повторяет docs/checkpoint_schema.md из репозитория libreyolo на версии 1.5.0, сверено с libreyolo/utils/serialization.py и BaseModel.save.