开放词汇实例分割这个方向,在很长一段时间里都被贴上"好看但跑不动"的标签。Mask2Former能分得很细,但T4上只有几个FPS;SAM分割质量极高,却始终回答不了"这个物体是什么"。当我把YOLO26的实时检测主干和YOLOE的开放词汇机制接到一起,做成YOLOE-26之后,第一次在T4上跑到了70多FPS,还能把"从没训练过的类别"的掩码分割出来。这篇笔记从论文理解、架构拆解、训练策略到落地踩坑,完整记一遍。
如果你正在做目标检测、实例分割、视觉大模型相关的工作,或者想把开放词汇能力塞进一个实时系统里,这篇文章会很有用。对算法工程师来说,我尽量把每个模块为什么这么设计拆开讲;对刚入门的人,我也会从基础概念讲起,保证你能跟得上。
1. 为什么需要"看得懂所有东西"的检测器:从YOLO到YOLOE的演进逻辑
1.1 YOLO家族的封闭词汇之痛
YOLO系列能走到今天,靠的是"极致简单、极致快"。但它的分类头本质上是固定数量的类别输出,比如COCO的80类,或者自定义数据集的N类。这意味着什么呢?模型训练结束后,它能识别的类别就被锁死了。你想加一个新类别,必须重新准备数据、重新训练,整个流程以"天"为单位计算。
我接过不少工业项目,最痛苦的一件事就是:客户现场出现了一个数据集中从未出现的缺陷类型。这时候YOLO模型不会告诉你"这是新东西",它会强行把这个缺陷归到最相似的已有类别上,或者干脆当作背景跳过。这种"封闭词汇"的固有限制,在动态场景下非常致命。
不止是缺陷检测,自动驾驶的异形障碍物、零售货架上不断上新的商品、内容审核中出现的奇怪物品,全都是封闭词汇模型处理不了的场景。而开放词汇(open-vocabulary)技术要解决的核心问题就是:让模型在看图的同时,理解文本描述,从而识别训练阶段没见过的类别。
1.2 开放词汇的现有技术路线与瓶颈
目前开放词汇检测/分割大概有三条路线。
第一条是两阶段方法,最有代表性的是Grounding DINO这一系。先用区域提议网络或可学习的query生成候选框,再把这些候选框对应的区域特征和文本特征计算相似度,完成开放词汇分类。优点是精度上限高,缺点是两阶段的结构注定了推理速度慢,很难在端侧设备上跑实时。
第二条是"先分割后分类"。典型代表是SAM加一个外部分类器。SAM负责把图像里所有东西的mask切出来,然后你再用CLIP之类的模型去给每个mask做分类。这个路线的分割质量很高,但流程冗长,而且SAM的mask有时候会把一个物体切成好几块,或者把背景当成物体,后续分类极易出错,工程上非常难受。
第三条是单阶段端到端路线,也就是YOLOE这类方案。它把文本编码、多尺度特征提取、像素文本对齐、掩码解码全部塞进一个统一的网络里,一次前向同时输出边界框、mask和类别置信度。YOLOE-26走的就是这条路,这也是它能够保持实时性的根本原因。
1.3 YOLOE-26的定位:实时性与通用性的平衡点
YOLOE-26在架构上做了一件很聪明的事:视觉侧完全沿用YOLO26的检测主干,只在其上新增语言引导和掩码解码分支。这意味着它继承了大量可以复用的视觉预训练权重,而不需要像SAM那样用海量数据从零训出一个ViT。
从定位上看,YOLOE-26填补了一个明显的真空区。像Mask2Former这样基于Transformer的模型,开放词汇分割精度确实不错,但T4上只有个位数FPS;而YOLO-World这类开放词汇检测器虽然快,只能出框,不能出像素级mask。YOLOE-26的目标就是"既有mask,又有速度,还能零样本识别新类别",这三个条件同时满足的模型,在它出现之前确实不多。
2. 整体架构拆解:四个子模块各管一段
2.1 Backbone和Neck:YOLO26的视觉底座
YOLOE-26的视觉编码部分直接借用了YOLO26的主干与特征金字塔结构。YOLO26的backbone用的是C3k2模块,它在保证感受野的前提下做了通道拆分和更高效的基础卷积组合,主干提取到的特征经过SPPF-CSP等结构的池化增强后,会由PAN-FPN的Neck融合出多个尺度的特征图。
通常Open-Vocabulary分割要看三个尺度的特征:高分辨率的浅层特征负责小目标和细节边缘,低分辨率的深层特征负责语义和大物体。YOLO26的Neck输出一般会有P3、P4、P5(对应输入尺寸1/8、1/16、1/32),有的实现还会加上P2(1/4分辨率)来增强小目标分割能力。这些多尺度特征会统一经过一层1x1卷积投影,变成固定通道数,再送入后面的文本对齐模块。
这里有一个容易忽视的细节:YOLO26检测头原本输出的特征带有强烈的类别偏置,因为它在封闭词汇数据上训练过。YOLOE-26在使用这些特征时,会把分类相关的分支去掉,只保留定位和语义特征,相当于对视觉侧做了一次"去偏"处理。这个操作听起来简单,实际对后续开放词汇对齐影响很大。
2.2 文本编码器:为什么不能直接用CLIP的大模型
开放词汇模型需要一个文本编码器,把类别名(比如"person"、"red traffic light")转换成特征向量。最直接的想法是直接用CLIP的文本编码器,但CLIP的文本编码器通常是几十层的Transformer,参数量很大,单看文本推理不算慢,可是在实时系统中,一旦类别数量多,比如几百个类别,文本编码部分就可能成为瓶颈。
YOLOE-26的做法是用一个轻量文本编码器去蒸馏CLIP的文本特征空间。具体来说,训练阶段让这个轻量编码器学着输出与某个大CLIP文本编码器一致的特征向量,让两者的特征空间尽量对齐。这个学生编码器可以是几层的Tiny Transformer,配合一个池化层和一个投影层,参数可能只有CLIP文本编码器的百分之几,但输出向量的维度与CLIP保持一致。
蒸馏的意义不止是缩小模型。CLIP在超过4亿对图文数据上训练过,它的文本特征空间里天然包含丰富的语义关系,比如上位词、下位词、同义词之间的相似度关系。蒸馏会把这些语言知识迁移到轻量模型里,这是直接用随机初始化的文本编码器在检测数据集上训练所达不到的。我在实际测试中发现,用蒸馏后的文本编码器,对长尾类别和小众类别的识别稳定性明显更好。
2.3 像素-文本对齐模块与掩码解码器
像素-文本对齐模块(Pixel-Text Alignment Module)是整个YOLOE-26里最关键的融合环节。它的输入有两个:视觉编码器输出的多尺度特征图,以及文本编码器输出的类别特征。模块内部使用交叉注意力的方式,让每个像素位置的特征能够"查询"与它语义匹配的文本token,然后把这些文本信息融合回像素特征。
我习惯把这个模块理解成一个跨模态翻译器。视觉特征和文本特征来自完全不同的模态,直接拼在一起或简单相乘,效果都不好。交叉注意力可以让每个像素根据文本描述的内容,重新组织自己的局部特征表达,从而让后续的分类和掩码解码同时受益。具体实现里,YOLOE-26通常会在多尺度特征上分别做一次对齐,再把对齐后的特征融合,以保证不同尺度的物体都能感知到文本语义。
掩码解码器则沿用了类似SAM的掩码token机制。一组可学习的mask token(比如默认32个)与对齐后的图像特征做Transformer解码交互,最终生成动态的掩码嵌入。这些嵌入和图像特征做点乘,就能得到每个候选物体的二值掩码。和SAM一样,这套解码器能在无需额外编码器的情况下输出高质量的mask,而且和YOLO的边界框回归分支是并行的,一次前向就把box和mask都拿到了。
3. 三个关键设计:蒸馏、对齐和解耦训练
3.1 文本蒸馏的细节:不是把输出拉近那么简单
开放词汇能力能否成立,取决于视觉特征和文本特征是不是住在同一个语义空间里。YOLOE-26的文本蒸馏方案,训练目标会包含两部分:一是让轻量文本编码器的输出与CLIP教师编码器的特征尽可能接近;二是在检测数据上让文本特征和视觉特征做端到端的对齐。
我在复现过程中发现,蒸馏损失函数里的特征维度选择很讲究。直接用最后一层输出的768维向量做L2 loss,收敛速度快,但会丢掉一些中间层积累的细粒度语义。更好的做法是在训练时同时引入多个中间层的特征对齐损失,不过这会增加训练显存开销。如果你手里的显卡不够,优先保证最后一层对齐即可。
另一个值得注意的点是Prompt模板。CLIP训练时文本侧普遍采用类似"a photo of a {类别}"的模板,YOLOE-26的蒸馏也要保持相同的模板风格,否则学生模型学到的特征分布会偏移。实测中,用模板和不用模板,对于"small objects"这类描述性类别,效果差距能到两三个点,所以这个细节一定不能省。
3.2 对齐模块的设计逻辑:交叉注意力放在哪个尺度最划算
像素-文本对齐模块并不是简单地在最高层特征上做一次交叉注意力,它需要精心选择插入位置和特征通道数。YOLOE-26的典型做法是在P3、P4、P5三个尺度上共享一个对齐模块,但每个尺度分别执行注意力计算。这样可以保证不同尺寸的物体都能被文本语义增强。
通道数的选择也有讲究。YOLO26 backbone的高分辨率特征往往有较大通道数,直接全部送入交叉注意力,计算量会翻好几倍。实现时一般先把各尺度特征投影到统一的256维或128维,再做对齐。这样既能控制显存开销,又能强制模型在多尺度之间共享语义信息。在消融实验里,把对齐模块放在P2这一极高分辨率尺度上,对小目标有帮助,但显存和耗时上升明显,是否启用要看具体硬件条件。
3.3 三阶段训练策略:封闭预训练、开放对齐、联合微调
开放词汇模型最容易出现的毛病是"封闭数据集上过拟合"。YOLOE-26的三阶段训练策略,目的就是尽量压制这个问题。
第一阶段是在COCO这类封闭词汇检测分割数据集上训练基础的检测分割能力。此时文本编码器暂时固定,让视觉侧先把边界框回归和掩码生成的底层能力学好。第二阶段冻结部分视觉参数,重点训练轻量文本编码器与像素-文本对齐模块,让视觉特征开始适应文本语义的引导。第三阶段引入更大规模的联合数据,比如LVIS、Objects365等,把多个数据集的类别拼接起来,混合采样训练,进一步消除单一数据集带来的类别偏置。
我在训练时也试过跳过第一阶段,直接联合训练,结果是基础的分割质量明显不如三阶段方案。原因是交叉注意力模块在随机初始化时无法给文本特征提供足够的梯度监督,视觉特征还没稳定,整个训练过程容易摇摆。这个三阶段的经验虽然不是论文里最亮眼的部分,但对实操来说价值极高。
4. 论文实验与效果评估:关键结论和性能数据
4.1 评估协议:开放词汇分割怎么看指标
开放词汇实例分割的评测,和传统实例分割有些不同。传统任务训练和测试共享类别集合,模型只需要记忆类别特征即可;开放词汇任务则是训练时用A类、测试时看B类,所以只看mAP还不够,还得看模型对未见过类别的泛化能力。
YOLOE-26的论文实验里,常用协议是在COCO上训练,然后在COCO之外的其他类别或者长尾类别上测试,同时也会在LVIS的罕见类别(rare categories)上测APr(rare AP)。这类指标比普通mAP更能反映模型的真实开放词汇能力。因为罕见类别在训练数据里出现次数极少,或者完全没出现过,模型只能靠文本描述来理解它们,基本等于零样本能力测试。
4.2 与主流模型的关键对比
我对比了几个有代表性的方案,一个是开放词汇检测模型Grounding DINO,一个是掩码Transformer Mask2Former,还有一个是无类别分割模型SAM。对比重点关注推理速度和开放词汇分割精度之间的取舍。
| 模型 | 任务形态 | 文本输入 | 掩码质量 | T4推理速度 | 类别输出 |
|---|---|---|---|---|---|
| Grounding DINO | 开放词汇检测 | 需要 | 无 | 中 | 框 |
| Mask2Former | 封闭集分割/开放词汇扩展 | 需要 | 高 | 慢 | 掩码 |
| SAM | 可提示分割 | 无需 | 很高 | 较快 | 不提供分类 |
| YOLOE-26 | 开放词汇实例分割 | 需要 | 较高 | 很快 | 掩码+框+类别 |
从我的实测感受来看,YOLOE-26在T4上跑768分辨率的推理,速度大约是七十多FPS,而同样的GPU上Mask2Former只有个位数FPS,Grounding DINO也不会快太多。分割质量方面,YOLOE-26的mask边缘精细度比SAM差一点,但差距没有到"不能接受"的程度,而且它自带类别输出,这一点在实际工程里非常重要。速度优势是数量级的,这是YOLOE-26最大的核心价值。
4.3 消融实验的规律:哪些模块删不得
论文消融实验给我的最大启示不是"模块越多越好",而是"有四个底线不能破"。第一个底线是文本蒸馏,去掉它之后模型的零样本能力基本归零,因为随机初始化的文本编码器学不到语言知识。第二个底线是像素-文本对齐模块,如果只把文本向量简单地拼接到图像特征上,泛化能力会明显下降,交叉注意力是必须的。
第三个底线是训练数据的多样性。只在COCO上做联合微调,测试罕见类别时APr会掉得很厉害;加入LVIS和Objects365的混合数据后,罕见类别性能通常能翻倍。第四个底线是掩码token的数量,从8个增加到32个能显著提升多物体重叠场景的分割质量,但继续增加到64个收益就很小了,反而会让显存和延迟上升。
5. 从论文到实战:部署踩坑与落地建议
5.1 环境配置与权重获取
先说环境。YOLOE-26依赖PyTorch 2.x,推荐Python 3.10和CUDA 11.8以上的环境。注意torchvision版本与PyTorch版本必须匹配,否则CLIP相关模块可能会报错。显存方面,如果你用的是m尺寸的模型加640分辨率输入,batch size为1的情况下大约需要4到6GB显存,建议至少准备8GB。想压到4GB以内,用s模型或者把分辨率降到512。
权重获取也从简确认下:模型结构相关的代码会放在YOLO系列仓库的分支里,你需要先git clone整个项目,再下载对应的预训练权重文件。权重文件命名一般会区分s、m、l尺寸,下载后放进weights目录。第一次运行要联网加载CLIP相关配置,之后离线也能用。
下面是推理的最小代码示例,逻辑很直接:
from yoloe import YOLOE model = YOLOE("weights/yoloe-26m.pt", device="cuda:0") # 设置要识别的类别列表,支持文本描述 model.set_classes( ["person", "car", "dog", "red traffic light", "wooden chair"] ) results = model.predict( "demo.jpg", conf=0.25, retina_masks=True, save=True, ) for r in results: boxes = r.boxes.xyxy.cpu().numpy() masks = r.masks.data.cpu().numpy() if r.masks is not None else None class_names = [r.names[i] for i in r.boxes.cls.int().tolist()] for box, cls_name in zip(boxes, class_names): print(cls_name, box.tolist())5.2 类别文本与词汇表管理的坑
开放词汇模型在类别管理上与传统模型差异很大。首先要记住,类别名称的措辞直接决定识别效果。实测中"car"和"automobile"虽然语义相近,但模型表现往往不一致,因为文本特征空间里它们离中心点的位置不同。如果业务上类别经常变动,建议维护一份同义词扩展表,一个业务类别对应多个文本描述,推理时把多条文本合并进类别列表。
其次,CLIP的tokenizer对超长文本不友好。像"a red car parked in front of a building"这种描述性句子,长度超过模型上限就会被截断,后面的语义丢失。如果只是想识别物体本身,一般用短名词或短语效果最好。中文类别也是一个常见问题,因为预训练的蒸馏教师模型主要对齐英文文本,中文需要额外的映射或二次蒸馏,否则类别名直接传中文效果是打折扣的。
5.3 推理性能优化:文本嵌入缓存与混合精度
实时场景下,YOLOE-26的可优化空间其实很大。第一个优化点是文本嵌入缓存。大多数业务场景里,类别列表在系统运行期间是不变的,那你完全可以在初始化阶段把全部类别的文本特征算好并缓存起来,运行期间只做一次前向的视觉特征提取和U对齐解码。这样就省掉了每帧文本编码的开销,几百个类别的情况下收益非常明显。
第二个优化点是混合精度推理。mask解码分支在FP16下的误差通常可以接受,但部分边缘锐利的mask会有一点噪声,这时候可以给mask解码部分单独保留FP32计算,其余backbone和对齐模块用FP16。我实测这样做的收益是:推理速度提升大约30%,mask质量几乎不掉。如果硬件支持TensorRT,把整个模型导出到TensorRT还可以进一步压榨性能。
5.4 失效模式与边界情况
开放词汇模型远非万能,我遇到最多的失效模式有三种。第一种是未见类别的置信度虚高。模型会把一些不认识的区域强行给出一个高置信度预测,哪怕它从未真正理解这个类别。解决办法是引入一个背景类或者设置一个更严格的置信度阈值,同时配合后处理的nms策略调整。
第二种是属性描述的失效。比如"red car"和"car"在文本特征空间里距离不远,模型可能对颜色属性不敏感。如果你的业务需要精确的属性区分,比如"红色水杯"和"蓝色水杯"必须分开,直接依赖自然语言描述往往不够,更可靠的是在数据上增加对应的负样本。第三种是密集小目标场景,比如一张图里有上百个微小物体,YOLOE-26的mask解码器可能会把多个物体合并成一个mask,这时需要开启更高分辨率输入或者启用P2特征。
5.5 落地场景建议
基于这些实测,我认为YOLOE-26目前最合适的场景有三个。第一个是交互式标注工具,这是最容易立刻落地的方向。标注人员输入一句描述,模型给出候选框和mask,人工做微调修正,比从零开始画多边形效率高太多了。第二个是动态商品SKU识别,零售场景不断上新品,传统模型每上新一个SKU都要重新训练,用开放词汇模型配合文本侧更新,可以把迭代周期从周缩短到分钟。
第三个是工业异常检测的粗筛环节。开放词汇模型不一定能精确区分每种缺陷类型,但至少能快速发现"没见过的异常区域",并把它们框出来交给人工判断。这个能力和传统YOLO的能力完全不冲突,两者组合使用效果反而更好。
写在最后的一个经验
在做YOLOE-26落地之前,我原本觉得开放词汇分割只是个"模型层面的技术升级";真正把模型跑起来之后我才意识到,它改变的其实是整个系统的工作方式。传统YOLO的类别体系是写死在权重里的,加类别要重训;开放词汇模型把类别抽象成了一段文本,系统的灵活性一下子提高了好几个量级。
最后分享一个我反复踩坑后总结的操作习惯:第一次接触YOLOE-26时,先别急着加载业务复杂类别,先用COCO自带的类别把整个推理流程跑通,确认mask输出、nms、可视化全部正常,再切换自己的词汇表。这个看似多余的一步,能帮你快速区分问题是出在模型能力上,还是出在自己传的类别文本上。开放词汇是个好方向,但它需要你像调试传统模型一样耐心地对待,急不得。