查看 Markdown

检查点与权重

LibreYOLO 检查点是一个 torch.save 字典,里面装着一份 state dict,外加识别它所需的元数据。本页讲这些文件从哪里来、落到哪里,以及它们是怎么被加载的。

托管位置
每个检查点一个 Hugging Face 仓库: huggingface.co/LibreYOLO
本地缓存
工作目录下的 weights/
元数据 schema
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。多数家族基于 Hugging Face 上的 LibreYOLO 组织构建这个 URL, 那里每个检查点都有自己的仓库,仓库名就是文件名:

https://huggingface.co/LibreYOLO/<name>/resolve/main/<name>.pt

数据集变体后缀仍然是仓库名的一部分,因此在家族默认数据集之外训练出的检查点会解析到 它自己的仓库,而不是覆盖掉默认的那个。

传输过程本身是防御性的,因为一个被截断的权重文件会在之后以一条毫无帮助的报错失败。 下载会流式写入一个 .part 文件,只有在完成时才原子地移动到位,因此被中断的进程绝不 会在最终路径上留下一个写了一半的检查点。中断的传输会借助 HTTP 验证器从它的字节偏移 处续传,如果服务器表明对象已经变了,就从零重新开始。失败会以指数退避重试三次。指向 同一路径的并发进程会占用一个锁文件,因此同时启动的两次训练只下载一次。当某个家族是 从第三方主机而不是 LibreYOLO 组织获取文件时,它可以固定一个校验和,并在不匹配时拒绝 该文件。

如果设置了 HF_TOKEN,或者 ~/.cache/huggingface/token 下缓存了 token,它会作为 bearer token 附加上去。它只会附加到 huggingface.co 的 URL 上,因此从别的主机下载的 家族永远拿不到它。

并不是每个家族都会自动下载。有些故意不返回 URL,因为发布的权重不允许再分发,此时报错 会说明该改用什么。另一些会在传输开始前打印一条许可提示。那条提示就是运行时的信号,说明 这个检查点的条款比代码的更窄,值得读一读,而不是划过去。

Hugging Face 组织

发布的权重放在 huggingface.co/LibreYOLO,每个 检查点一个仓库。每个仓库都带有一份许可证,而且许可证在一个家族内部并不统一:代码采用 MIT 许可的家族,也可能有一些权重不是。以仓库为准。每个模型页都会在 Checkpoints 和 Licensing 小节列出该家族已发布的检查点及其许可证。

离线使用

一旦文件都在本地,这个库就没有任何地方需要网络访问。有两种做法可行:

在任务运行的位置旁边预先准备一个 weights/ 目录。在一台联网的机器上把检查点取一次, 然后把这个目录复制过去就够了;上面那步解析会找到它们,永远不会访问网络。

或者传一个指向共享位置的绝对路径。带目录部分的引用会照原样使用,因此把整理好的权重以 只读方式挂载也是一种有效的配置。如果进程无法在它需要转换的检查点旁边写入,转换会退回 到一个私有临时目录,而不是直接失败。

数据集遵循另一套规则:它们解析到 ~/datasets 下,或者在设置了 LIBREYOLO_DATASETS_DIR 变量时解析到该变量指定的目录下。

加载安全

检查点是 pickle,而 pickle 在被打开时可以执行任意代码。LibreYOLO 把每个权重文件都当作 不可信的,用 PyTorch 的 weights_only=True 路径加载它,这条路径把 unpickler 限制在 张量和一小组安全类型上。这对你传入的文件同样适用,而不只是对 LibreYOLO 下载的文件。 如果 PyTorch 的版本老到不支持这个参数,加载会被拒绝,而不是以不安全的方式执行。

有些上游训练检查点内嵌了受限 unpickler 会拒绝的对象,比如来自它们训练所用框架的一个 配置对象。这些对象是 LibreYOLO 并不需要的元数据,因此在转换过程中,每个被拦下的类都会 被替换成一个惰性替身,它能满足 unpickler 而不运行任何东西,最终只有张量保留进转换后的 文件。敏感的模块名会被直接拒绝,而不是替换成桩,重试循环也有上限,因此一个刻意构造出 无穷多被拦类的文件会以失败告终。这条路径的其余部分见导入已有权重

检查点元数据

LibreYOLO 检查点是一个字典,它的 model 键放着 PyTorch 的 state dict。schema v1.0 要求九个键,它们合在一起,让工厂不必解析文件名、也不必从张量形状去猜,就能识别一个 文件。

含义
modelPyTorch 的 state dict
schema_version元数据契约的版本。v1.0 用字符串 1.0
libreyolo_version生成该文件的 LibreYOLO 版本
model_family一个已注册的家族标识符,比如 yolo9
size该家族内的变体,比如 tr18
task一个规范任务名
nc一个正的类别数
names类别索引到标签的映射,覆盖 0nc - 1
imgsz一个正的输入分辨率

带有额外结构的任务会把这部分信息记在上述键旁边。姿态检查点会加上 num_keypointskeypoint_dim,还可能加上逐关键点的 OKS sigma。OCR 检查点内嵌完整的 CTC 字符集, 这样文件是自包含的。Restore 检查点可能记录退化类型和一个放大倍数。训练器检查点会加上 断点续训所需的状态,比如 epoch、优化器状态和 EMA 权重;发布出来的推理权重不应该带 这些。

满足全部九个键的文件走元数据路径加载。不满足的文件要么被转换——前提是有某个家族认得 它的结构——要么走兼容路径加载,并给出一条指明缺了什么的警告。

查看一个检查点

CLI
# 读取元数据而不构建模型,# 并报告它是否满足 schemalibreyolo metadata path=weights/LibreYOLO9t.pt
JSON
libreyolo metadata path=weights/LibreYOLO9t.pt --json
Python
from libreyolo.utils.serialization import (    load_untrusted_torch_file,    validate_checkpoint_metadata,) loaded = load_untrusted_torch_file("weights/LibreYOLO9t.pt") # 返回问题列表,为空表示文件满足 v1.0print(validate_checkpoint_metadata(loaded))print(loaded["model_family"], loaded["size"], loaded["task"], loaded["nc"])

libreyolo metadata 从不构建模型,因此它对家族没有安装的文件、以及你拿不准的文件都 能用。

已针对 LibreYOLO v1.5.0 验证。