Чекпойнты и веса
Чекпойнт LibreYOLO — это словарь torch.save, в котором лежит state dict и метаданные, нужные для того, чтобы его опознать. Эта страница о том, откуда берутся эти файлы, куда они попадают и как загружаются.
- Размещены на
- По одному репозиторию Hugging Face на каждый чекпойнт: huggingface.co/LibreYOLO
- Локальный кэш
weights/ в рабочем каталоге- Схема метаданных
- v1.0
Где ищется чекпойнт
Ссылка на модель без компонента каталога, например LibreYOLO9t.pt,
разрешается относительно weights/ в текущем рабочем каталоге. Если
weights/LibreYOLO9t.pt существует, берётся он; если файл с таким именем лежит
в самом рабочем каталоге, вместо него берётся этот файл; иначе
weights/LibreYOLO9t.pt становится целью скачивания.
Ссылка, в которой каталог всё же есть, — абсолютный или относительный, — понимается буквально. Именно эту форму стоит использовать, когда веса лежат в одном общем месте и скачивать ничего не нужно.
from libreyolo import LibreYOLO, SAMPLE_IMAGE # Имя файла без каталога разрешается в weights/LibreYOLO9t.pt и# скачивается туда, если его там ещё нет.model = LibreYOLO("LibreYOLO9t.pt")print(model(SAMPLE_IMAGE).boxes)from libreyolo import LibreYOLO # Путь с компонентом каталога используется ровно так, как написан,# и никогда не скачивается из сети.model = LibreYOLO("/opt/models/LibreYOLO9t.pt")print(model.family, model.size, model.task)Автоматическое скачивание
Если полученного пути не существует, LibreYOLO разбирает имя файла, восстанавливая семейство, размер и задачу, и запрашивает у соответствующего семейства URL для скачивания. Большинство семейств строят его на основе организации LibreYOLO на Hugging Face, где у каждого чекпойнта свой репозиторий, названный по имени файла:
https://huggingface.co/LibreYOLO/<name>/resolve/main/<name>.ptСуффикс варианта датасета остаётся частью имени репозитория, поэтому чекпойнт, обученный не на датасете семейства по умолчанию, разрешается в собственный репозиторий, а не перезаписывает репозиторий по умолчанию.
Сама передача устроена осторожно, потому что обрезанный файл весов даёт сбой
позже и с непонятным сообщением об ошибке. Данные скачиваются потоком в файл
.part и атомарно переносятся на место только после того, как загрузка
завершится, так что прерванный процесс никогда не оставит недописанный чекпойнт
по конечному пути. Прерванная передача возобновляется со своего байтового
смещения с помощью HTTP-валидатора и начинается заново с нуля, если сервер
сообщает, что объект изменился. При сбое загрузка повторяется три раза с
экспоненциальной задержкой. Параллельные процессы, нацеленные на один путь,
захватывают файл блокировки, поэтому два запуска
обучения, стартовавшие вместе, скачают файл один раз. Там, где семейство
скачивает со стороннего хоста, а не из организации LibreYOLO, оно может
зафиксировать контрольную сумму и отвергнуть файл при несовпадении.
Если задан HF_TOKEN или токен закэширован в ~/.cache/huggingface/token, он
добавляется как bearer-токен. Добавляется он только к URL на
huggingface.co, поэтому семейство, которое скачивает с другого хоста, его
никогда не получает.
Автоматически скачивают не все семейства. Некоторые намеренно не возвращают URL, потому что опубликованные веса нельзя распространять дальше, и тогда ошибка объясняет, что использовать вместо них. Другие перед началом передачи выводят уведомление о лицензии. Это уведомление — сигнал во время выполнения о том, что условия чекпойнта строже условий кода, и его стоит прочитать, а не пролистать.
Организация на Hugging Face
Опубликованные веса лежат на huggingface.co/LibreYOLO, по одному репозиторию на чекпойнт. У каждого репозитория своя лицензия, и внутри семейства она не одинакова: у семейства с кодом под MIT часть весов может быть под другой лицензией. Источник истины — репозиторий. На странице каждой модели перечислены опубликованные чекпойнты этого семейства и их лицензии — в разделах о чекпойнтах и о лицензировании.
Работа без сети
Если файлы уже лежат локально, доступ к сети библиотеке не нужен. Работают два подхода:
Заранее наполнить каталог weights/ рядом с тем местом, откуда запускается
задача. Достаточно один раз скачать чекпойнты на машине с сетью, а потом
скопировать каталог; описанное выше разрешение пути найдёт их и до сети не
дойдёт.
Либо передать абсолютный путь к общему хранилищу. Ссылка с компонентом каталога используется как есть, поэтому смонтированный только на чтение каталог с отобранными весами — рабочая схема. Если процесс не может писать рядом с чекпойнтом, который нужно сконвертировать, конвертация не падает, а переключается на приватный временный каталог.
Для датасетов правило отдельное: они разрешаются относительно ~/datasets или
каталога, указанного в LIBREYOLO_DATASETS_DIR, если эта переменная задана.
Безопасность загрузки
Чекпойнты — это pickle-файлы, а pickle при открытии может выполнить произвольный
код. LibreYOLO считает недоверенным любой файл весов и загружает его по пути
PyTorch с weights_only=True, который ограничивает распаковщик тензорами и
небольшим набором безопасных типов. Это касается и того файла, который передаёте
вы, а не только файлов, скачанных LibreYOLO. На сборке PyTorch, слишком старой
для этого аргумента, загрузка отклоняется, а не выполняется небезопасно.
В некоторых оригинальных обучающих чекпойнтах зашиты объекты, которые ограниченный распаковщик отвергает, — например, объект конфигурации из фреймворка, в котором их обучали. Эти объекты — метаданные, не нужные LibreYOLO, поэтому при конвертации каждый заблокированный класс заменяется инертной заглушкой, которая устраивает распаковщик и ничего не выполняет, а в сконвертированный файл попадают только тензоры. Чувствительные имена модулей отклоняются сразу, а не заменяются заглушкой, и цикл повторов ограничен, поэтому на файле, специально составленном так, чтобы подсовывать бесконечную череду заблокированных классов, загрузка завершается отказом. Остальное об этом пути — в разделе импорт существующих весов.
Метаданные чекпойнта
Чекпойнт LibreYOLO — это словарь, в ключе model которого лежит state dict из
PyTorch. Схема v1.0 требует девять ключей, и вместе они позволяют фабрике
опознать файл, не разбирая его имя и не угадывая по формам тензоров.
| Ключ | Смысл |
|---|---|
model | State dict из PyTorch |
schema_version | Версия контракта метаданных. В v1.0 это строка 1.0 |
libreyolo_version | Версия LibreYOLO, которая создала файл |
model_family | Зарегистрированный идентификатор семейства, например yolo9 |
size | Вариант внутри этого семейства, например t или r18 |
task | Одно каноническое имя задачи |
nc | Положительное количество классов |
names | Отображение индекса класса в метку, покрывающее от 0 до nc - 1 |
imgsz | Положительное входное разрешение |
Задачи с дополнительной структурой записывают её рядом с этими ключами.
Чекпойнты оценки позы добавляют num_keypoints и keypoint_dim, а также могут
добавлять сигмы OKS для каждой ключевой точки. Чекпойнты OCR зашивают полный
набор символов CTC, чтобы файл был самодостаточным. Чекпойнты восстановления
могут записывать тип деградации и коэффициент увеличения. Чекпойнты обучения
добавляют состояние для возобновления — например epoch, состояние оптимизатора
и веса EMA; в опубликованных весах для инференса этого быть не должно.
Файл, в котором есть все девять ключей, загружается по пути с метаданными. Файл, в котором их нет, либо конвертируется, если какое-то семейство узнаёт его структуру, либо загружается по пути совместимости с предупреждением, где названо недостающее.
Просмотр чекпойнта
# Читает метаданные, не создавая модель, и сообщает,# удовлетворяют ли они схеме.libreyolo metadata path=weights/LibreYOLO9t.ptlibreyolo metadata path=weights/LibreYOLO9t.pt --jsonfrom libreyolo.utils.serialization import ( load_untrusted_torch_file, validate_checkpoint_metadata,) loaded = load_untrusted_torch_file("weights/LibreYOLO9t.pt") # Возвращает список проблем. Пустой — файл соответствует v1.0.print(validate_checkpoint_metadata(loaded))print(loaded["model_family"], loaded["size"], loaded["task"], loaded["nc"])libreyolo metadata никогда не создаёт модель, поэтому работает и с файлом,
семейство которого не установлено, и с файлом, в котором вы не уверены.