查看 Markdown

核心概念

四个概念就能描述 LibreYOLO 里的每一个模型:它执行的任务、它所属的家族、它在家族内的尺寸,以及这个家族所处的支持层级。检查点文件名编码了前三个。

文件名格式
Libre<FAMILY><size>[-<task>].pt
标准任务名
17
支持层级
Flagship, Core, Supported, Inference only, Museum, Sibling tier

任务

任务就是模型返回的东西。LibreYOLO 有十七个标准任务名,每一个都对应 Results 对象上承载其输出的那个字段。

任务返回内容
detect带类别和置信度的轴对齐检测框
segment逐实例掩码,每检测到一个目标就有一张掩码
semantic每个像素一个类别标签,不区分实例
panoptic每个像素一个互不重叠的标签,把可数的物体(things)与无定形的背景(stuff)合并在一起
pose逐实例关键点,每行与检测框一一对应
classify整张图片在一个标签集上的概率
obb旋转框,带一个旋转角
point每个检测输出一个图像坐标,而不是一个框
depth一张稠密的相对逆深度图
normal一个稠密的单位向量表面法线场
edge一张稠密的边缘概率图
restore一张复原后的 RGB 图像,用于去模糊、去噪或超分辨率
matte一张从 0 到 1 的软前景图,用于去除背景
ocr带转写文本的文字四边形,按阅读顺序排列
embed一个 L2 归一化向量,它的点积衡量吻合程度
gaze每张检测到的人脸一个视线方向
mesh每个检测到的人一个带姿态的 3D 人体

这些就是出现在检查点(checkpoint)元数据和文件名里的名字。在任何可以传入任务的 地方,也接受大家熟悉的别名,并且在其他一切发生之前先做归一化:detectiondet 变成 detectkeypoints 变成 posecls 变成 classifydeblurdenoisesuper-resolution 都变成 restoreface-recognitionreid 变成 embed。无法识别的名字会直接报错,而不是悄悄退回默认值。

segmentsemanticpanoptic 是三个不同的任务,不是同一件事的三种说法。 实例掩码、逐像素标签和 thing 加 stuff 的合并图有不同的真值(ground truth)、 不同的指标和不同的结果字段。

模型家族

一个家族就是一条架构脉络,有自己的加载、预处理和后处理代码。每个家族都会声明一个 FAMILY 标识符,比如 yolo9rfdetrdfine,声明它支持的任务,以及它发布的 每个尺寸对应的输入分辨率。

LibreYOLO() 是一个工厂,而不是一个类。给它一个路径,它会加载这个文件,从检查点 元数据里识别出家族,识别不出来就从张量的键本身去识别,然后返回该家族模型的一个 实例。这就是为什么换一个检测器只是改一行代码:拿回来的对象暴露同样的 predicttrainvalexport 接口,也返回同样的 Results 类型。

列出家族
# 每个已注册家族的任务、尺寸和输入分辨率libreyolo models
单个模型
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9t.pt") print(model.family, model.size, model.task)print(model.input_size)print(model.nb_classes, model.names[0])
指定任务
from libreyolo import LibreYOLO # 别名在 API 边界处归一化:"keypoints" 解析为# "pose","det" 解析为 "detect","semantic-segmentation" 解析为 "semantic"model = LibreYOLO("LibreYOLO9t.pt", task="det")print(model.task)

支持多个任务的家族通常为每个任务单独发布一个检查点,而且每个任务的尺寸集合往往 还不一样;也有少数家族让两个运行时任务共用同一个文件。无论哪种情况,支持的任务都是 一个固定的列表,请求列表之外的任务会报错,并在消息里给出支持的列表,而不是加载一个 差不多的东西。

完整列表,连同每个家族的基准测试和已发布的权重,见所有模型

尺寸

尺寸是家族内部的一个变体,写成一个小写代号,直接接在家族前缀后面。常见的字母是 n 表示 nano、t 表示 tiny、s 表示 small、m 表示 medium、l 表示 large、x 表示 xlarge,但代号是各家族自己定的,有几个家族用的完全是别的东西:以骨干命名的 代号,比如 r50r101,此时尺寸是 ResNet 的深度;复合缩放的代号,比如 b0b3;或者一个用来标识那唯一一个已发布检查点的名字。YOLOv9 在其他家族用 l 的地方用 c 表示 compact。

尺寸同时也决定了输入分辨率,对于有多个任务的家族,分辨率还可能因任务而异。这两者 都从家族里读取,绝不靠假设;libreyolo models 会把它们打印出来。

检查点文件名

每一个已发布的权重文件都遵循同一套格式:

Libre<FAMILY><size>[-<task>].pt

家族前缀是每个家族固定的字符串,尺寸是小写并且不加分隔符直接接上,任务后缀以 连字符开头。检测不带后缀,沿用 YOLO 检查点一直以来的惯例,所以 LibreYOLO9t.pt 是一个检测器,而 LibreRFDETRn-seg.pt 是同一个家族的分割模型。

任务后缀
detect
segment-seg
semantic-sem
panoptic-panoptic
pose-pose
classify-cls
gaze-gaze
obb-obb
point-point
depth-depth
edge-edge
normal-normal
restore-restore
matte-matte
ocr-ocr
embed-embed
mesh-mesh

如果一个家族没有任何不带后缀的任务,它可以强制要求带上后缀,这样一个不带后缀的 名字就不会被当作它的合法检查点。如果一个家族发布了在默认数据集之外的数据集上训练的 权重,会把数据集名字再作为一个后缀接上去,而这个变体也是文件下载来源的仓库名的 一部分。

有三类家族不在这套格式之内。可提示(promptable)的分割家族、视觉语言家族和开放词汇 检测器没有注册进检查点工厂,也不产出 Libre<FAMILY><size>.pt 文件。它们的前缀指向的 是下载下来的 Hugging Face 快照或者一个可提示的检查点,那里上游的品牌大小写是特意 保留的。

任务是怎么确定的

当有多个信号都可能给出任务名时,它们会按固定顺序依次查询,第一个存在的胜出:你传入的 task 参数,然后是检查点元数据里记录的任务,然后是文件名里的任务后缀,最后是家族的 默认任务。得到的结果在构建模型之前会拿去和家族支持的任务做校验,所以不匹配会在加载 时就失败,而不是之后产出错误的输出。

支持层级

每个家族都只归属于一个层级。层级说的是工程投入,而不是精度:它告诉你一个新功能会 先落在哪里,以及哪些东西的 CI 会一直保持绿色。

层级含义
Flagship功能在这里最先设计,并完整地在 GPU 上验证
Core核心的可训练检测器。功能在同一个发布波次里紧跟 Flagship
Supported起支撑作用的可训练家族。在 CI 里保持绿色,功能视情况落地
Inference only预测、验证和导出。训练相关的功能不适用
Museum一件冻结的展品。只修 bug
Sibling tier一个独立的产品面,有自己的工厂和契约

每个模型页面都在页头标出所属家族的层级。两个 Flagship 家族分别是 CNN 检测器里的 YOLOv9 和 transformer 检测器里的 RF-DETR;除非你有别的理由,否则就从它们开始。

Inference only 说的是缺了什么,缺的是 LibreYOLO 里的训练循环。预测、验证,以及在 家族支持的情况下导出,都是能用的。对这样的家族调用 train() 会抛出 NotImplementedError,并说明原因。

已针对 LibreYOLO v1.5.0 验证。