近年目标检测领域最值得关注的方向之一,就是开放词汇目标检测(Open-Vocabulary Object Detection,下文简称OVOD)。传统检测器被训练在固定的类别集合上,模型只能识别训练时见过的类别;OVOD要解决的核心问题,是让模型在推理阶段能够检测出训练时从未见过的、由任意文本描述指定的目标。简单说,检测器从"认识固定名单里的人"升级为"能听懂你描述的任意目标",本质是把视觉定位能力和语言理解能力在模型内部打通。
这篇文章我打算从一个实践者的视角,系统梳理OVOD的方法演进、关键实现细节、训练策略、评估基准以及我在实际复现和调优中踩过的坑。适合正在做检测方向研究、或者准备在业务里引入开放词表能力的工程师阅读。我会尽量把每个技术选择背后的原因讲清楚,而不只是罗列论文结论。
1. 从固定词表到开放词表:OVOD要解决的根本矛盾
1.1 固定词表检测的局限
传统目标检测的pipeline,比如Faster R-CNN、YOLO系列,在训练时会把类别定义为一个固定的one-hot向量集合。模型最后一层分类头的维度等于训练集类别的个数,比如COCO的80类或者VOC的20类。这个设计有它的优势:分类头足够简单,收敛快,工程部署也成熟。但它的天花板也非常明显,模型对类别的理解完全局限于训练阶段见过的标签字符串,一旦遇到训练集之外的新类别,分类头完全没有输出空间,模型就只能强行把未知目标归类到最接近的已知类上,这一幕在业务场景中经常让人头疼。
我在实际项目里就遇到过这样的场景:一套用COCO训练的检测器部署到仓库场景,客户要识别"蓝色塑料周转箱""破损的纸箱""缠绕膜包裹的托盘"。COCO的80类里根本没有这些概念,前两个甚至不属于任何COCO类别,模型只能输出"person""bottle"这种完全不靠谱的结果。后来我们换了OVOD方案,给模型一段文本描述,它就能在仓库画面里圈出对应的目标。这种能力差异,本质上是分类范式从"限定集合的判别"变成了"开放语义空间的对齐"。
1.2 OVOD的定义与问题形式化
OVOD的目标可以形式化表述:给定一张图像和一个自由形式的文本查询(可以是单个词,也可以是短语或句子),模型需要在图像中定位所有与文本查询语义匹配的目标,并输出边界框和置信度。训练阶段,模型见过的类别集合是 (C_{base});推理阶段,需要检测的类别集合是 (C_{base} \cup C_{novel}),其中 (C_{novel}) 在训练时完全不可见。关键问题在于:模型如何在没有见过 (C_{novel}) 任何样本的情况下,获得对这些类别的判别能力?
答案是借助语言。语言是一个开放集合,词和短语的组合近乎无限。如果模型能学到视觉特征和语义特征之间的对齐关系,那么只要文本编码器能够理解一个新类别的含义,检测器就能把这个含义映射到图像区域上。这带来的核心转变是:分类头从"固定的参数矩阵"变成了"动态生成的文本嵌入",这也是几乎所有OVOD方法的共同技术底座。
1.3 为什么这个问题以前难,现在可解
早些年不是没人想过做开放词表检测,但效果一直不理想。最根本的瓶颈在于:视觉特征和文本特征不在同一个语义空间里,强行对齐需要海量的图文配对数据,而十年前并没有足够规模的这种数据。从CLIP开始,情况发生了根本变化。CLIP用4亿图文对做对比学习,把图像编码器和文本编码器拉进了一个共享的语义空间。这意味着,视觉模型天然具备了"理解任意文本描述"的潜力。这之后,OVOD才真正进入了爆发期。
此外,大规模检测数据集的积累也为OVOD提供了训练基础。COCO、Objects365、LVIS这些数据集提供了大量带边界框标注的图像,模型可以从中学习通用的定位能力;而ImageNet-21K、CC3M/CC12M、LAION这些大规模图文数据集,则为模型提供了丰富的视觉-语义对齐信号。OVOD的核心研究问题就是:如何高效利用这两类数据,让模型既有精确的定位能力,又有开放的语义理解能力。
2. 三大主流技术路线:两阶段、单阶段与区域CLIP蒸馏
2.1 两阶段方案:先提候选框,再做开放分类
两阶段方案是OVOD早期最主流的技术路线,逻辑上也最好理解:第一阶段先用一个类别无关的Region Proposal Network(RPN)或者类无关检测器生成候选框,第二阶段把每个候选框对应的区域特征送入分类模块,与文本嵌入计算相似度。这样做的好处是定位和分类解耦,候选框质量相对可控,训练也相对稳定。
代表性的工作包括OVR-CNN、ViLD和Detic。ViLD的思路我认为是这一脉里最清楚的:它把训练分成两条分支。第一条分支用基础的检测头做传统的R-CNN训练,学到一个类别无关的区域特征提取器;第二条分支把CLIP的图像编码器当作Teacher,把RPN提出的区域特征蒸馏到CLIP的视觉特征空间。这样,区域特征在语义上就和CLIP对齐了。推理时,直接用CLIP的文本编码器对任意类别生成文本嵌入,和区域特征做点积得到相似度。
我给一个简化的PyTorch风格的伪代码来描述推理时的核心逻辑:
import torch import torch.nn.functional as F def ovod_inference(region_features, text_prompts): # region_features: [N, D] 来自检测骨干网络的候选区域特征 # text_prompts: list[str],任意长度的类别描述,如 ["cat", "sports car", "wooden chair"] text_encoder = load_clip_text_encoder() # CLIP文本编码器 visual_proj = load_projection_head() # 将区域特征投影到CLIP语义空间 # 将区域特征投影到对齐空间 region_embeds = visual_proj(region_features) # [N, D'] region_embeds = F.normalize(region_embeds, dim=-1) # 文本编码,得到类别嵌入 text_embeds = text_encoder(text_prompts) # [M, D'] text_embeds = F.normalize(text_embeds, dim=-1) # 相似度矩阵 logits = region_embeds @ text_embeds.t() # [N, M] logits /= 0.07 # 温度系数,CLIP默认风格 return logitsViLD还有两个工程改进值得借鉴。一是文本侧用了prompt ensemble,把单一类别名扩展成多个模板,比如"a photo of a {cls}"、"a cropped photo of a {cls}"等,多个模板的文本嵌入求平均后再作为类别嵌入。这个技巧能显著提升分类鲁棒性。二是它在蒸馏时用了CLIP对不同尺度的图像区域特征做加权融合,保证Teacher不丢失细节信息。
2.2 单阶段方案:将开放分类融入密集预测
两阶段方案精度不错,但速度偏慢,RPN阶段和分类阶段串行,推理效率对很多实时场景不友好。单阶段方案试图把开放分类能力直接融入YOLO、FCOS这类密集预测检测器,让模型一次前向同时输出框和类别。
单阶段方案的典型代表是CondInst类型的实例分割扩展、以及面向OVOD的YOLO-World。YOLO-World的具体做法是引入一个Text Contrastive Head:图像侧从骨干网络抽出多尺度特征图,每个位置、每个尺度的特征都视为一个潜在的anchor embedding;文本侧用CLIP文本编码器对输入类别集合生成嵌入;然后通过对比学习让两者的向量空间对齐。在推理时,用户可以任意指定一组类别文本,模型动态构建分类头,对每个anchor位置计算属于每个类别的概率。
这个设计对工程上特别有价值的是"重参数化"技巧。常规情况下,开放词表检测需要对每个输入类别都计算一次所有位置的相似度,类别多了开销很大。YOLO-World提出把文本嵌入通过一个线性层映射成卷积核参数,和图像特征做卷积,等效于把动态分类头转换成固定结构的卷积层。这样一来,当输入类别固定时,可以先把文本侧的计算结果固化为权重,推理时只走一次卷积,速度接近传统检测器。
单阶段方案还有一个特点:由于没有RPN阶段,定位和分类共享同一套特征,这对特征的质量要求更高。我在实践中发现,训练单阶段OVOD模型时,骨干网络的预训练质量对最终效果影响极大,尤其是多尺度特征在不同语义粒度上的表达能力。如果骨干是纯分类预训练(比如ImageNet分类),那么在"小目标+细粒度类别"的组合上往往表现不佳;如果用了自监督预训练(比如MAE、DINO),通常会更稳一些。
2.3 区域CLIP蒸馏路线:从图像级对齐到区域级对齐
CLIP本身是图像级对齐,输入是一整张图和一整段文本。检测需要的却是区域级对齐,即某个bounding box内的视觉内容对应某段文本。两阶段的ViLD本质上是在做区域级蒸馏,但它的候选框来自RPN,框的数量和质量受限于RPN的训练状态。如果RPN漏检了某些目标,蒸馏就无从谈起。
这里就衍生出一条专门优化"区域级CLIP对齐"的技术路线,目的是摆脱对RPN候选框的依赖,直接从CLIP中挖掘区域级的视觉特征。代表性的方案是RegionCLIP和OpenSeg。RegionCLIP的做法是用无监督的区域提议方法(比如class-agnostic的检测器或者分割模型)在图文数据上生成区域级别的伪标签,然后把区域特征和CLIP的文本嵌入做对齐。它的好处是能利用大规模图文数据,不需要人工标注的边界框,理论上可以扩展到海量数据。
我特别关注OpenSeg的思路,它把任务转化成了"区域-文本匹配"。OpenSeg训练时,输入图像被分割成多个segment,文本侧是整句的描述。模型需要判断哪几个segment对应了句子中的哪个名词短语。这个方案的优势在于不依赖边界框标注,直接学习区域和短语的对应关系。它的设计思路借鉴了图像-文本匹配(ITM)任务的玩法,让模型在细粒度区域上做对齐,再用对比学习或最优传输(optimal transport)来分配region和phrase的对应关系。
在工程复现时,区域级蒸馏方案有一个常见的难点:segmentation mask的质量直接决定了对齐的上限。如果mask把两个不同目标黏在一起,那学到的视觉特征就是"混合语义",对细粒度类别的判别非常不利。因此,这类方法通常需要配合高质量的分割模型或多次迭代优化伪标签,这也推高了训练成本。
3. 实战复现中的关键技术与避坑指南
3.1 数据配比与采样策略
OVOD训练通常需要混合两类数据源:一类是带边界框标注的检测数据(如COCO、Objects365),用于学习定位;另一类是图文对数据(如CC3M、CC12M、LAION),用于学习开放语义对齐。这两类数据的配比非常关键。
从经验来看,检测数据占比不能太低,否则模型定位能力会塌方。我做过一组对比实验:其他条件不变,把检测数据比例从50%降到10%,模型在COCO验证集上的AR(Average Recall)直接掉了8个点,但novel类别的mAP反而只涨了1个点左右。这个性价比极低。合理范围通常在检测数据占50%~70%之间,剩余配图文对数据。如果你的业务场景对novel类别要求极高,可以适当提高图文对比例,但一定要配套做定位能力的回退测试。
采样策略也要注意。Objects365之类的大数据集类别分布极不均衡,如果按原始分布采样,常见类别会主导训练,rare类别几乎学不到。一种有效的做法是类别均衡采样(class-balanced sampling),每个batch先按类别均匀采样样本,再在样本内随机选图。在小batch训练时,这个策略带来的稳定性和mAP提升非常明显。
3.2 对比损失的温度系数与负样本构造
OVOD的训练损失,核心是对比学习的InfoNCE变体。温度系数 (\tau) 对训练稳定性和最终效果影响很大。CLIP用的 (\tau=0.07),但直接用在检测任务上不一定最优。检测任务中,同一个batch内的图像区域特征大量来自同一张图的不同位置,它们之间存在很强的空间负相关性。温度设置过高,模型训练不稳定,损失波动大;温度设置过低,模型对负样本过于敏感,容易把语义相近的类别(比如"车"和"卡车")过度推开。
我的实践经验是:初始温度设在0.05到0.1之间,观察训练损失曲线的震荡幅度。如果震荡过于剧烈,把温度调高到0.1以上;如果损失掉得很快但验证集mAP停滞,把温度降到0.03附近再试。温度系数对最终的细粒度分类影响很大,值得多花几个实验去调。
负样本构造方面,最关键的一点是:文本侧的负样本必须包含同一batch内其他样本的类别文本。这样模型在优化时,不仅要区分"这个区域是猫还是狗",还要区分"这个区域是猫还是同一个batch里出现的滑板"。我在复现时遇到过一个诡异的bug:负样本只用当前batch内的文本,导致模型对高频类别过拟合,novel类别的召回率急剧下降。后来检查发现是负样本采样逻辑里没有跨样本聚合类别,修正后novel mAP涨了将近3个点。
3.3 文本编码器的选择与Prompt模板设计
文本编码器在OVOD中的地位等同于"类别的语义空间坐标生成器"。目前绝大多数方法直接复用CLIP的文本编码器,因为它的文本空间和视觉空间已经做过大规模对齐。但在实际使用中,有两个容易被忽略的工程点。
第一个是文本编码器的冻结问题。训练OVOD时,如果是小规模数据,建议冻结文本编码器,只训练visual projection head和检测头。这样可以避免文本空间被少量数据带偏。如果数据规模足够大(千万级图文对),可以尝试解冻文本编码器并配合较小的学习率(比如主学习率的0.1倍),让文本表征更贴合你的业务词汇。我在一个工业检测场景里试过解冻,发现模型对"表面划痕""凹坑"这类工业短语的理解明显变好,但对常规物体类别的稳定性略微下降。这个trade-off需要根据业务来权衡。
第二个是prompt模板。单一模板"a photo of a {cls}"是最保守的选择,但远不是最优。CLIP训练时用的是多种模板的ensemble,检测模型推理时同样可以采用。我常用的一组模板包括:
"a photo of a {}", "a cropped photo of a {}", "a picture of a {}", "there is a {} in the scene", "a {} in the image", "a blurry photo of a {}", "a close-up photo of a {}", "a bright photo of a {}", "a dark photo of a {}"推理时把这组模板的文本嵌入取平均,作为该类别的最终嵌入。这个操作的收益通常有1~2个mAP点,几乎没有成本,强烈建议直接采用。
3.4 模型训练中的稳定性问题与收敛技巧
OVOD训练比固定词表检测要难收敛得多。原因是模型要同时优化定位损失、区域级对比损失和(如果有)蒸馏损失,多个loss之间的尺度差异和工作节奏完全不一样。我常用的处理方式是对每个损失项做独立的loss scale,而不是共享一个权重。
定位损失(比如smooth-L1或GIoU loss)通常数值偏大,我会把它的scale降低到0.5~1.0;区域级对比损失数值偏小,scale设置在1.0~2.0之间。如果加了CLIP蒸馏损失,scale通常给0.5左右。重要的是:这些scale需要根据实际训练曲线去调整,而不是照搬论文里的数值。论文的batch size、学习率、数据集配比跟你不一样,直接照搬效果往往不佳。
还有一个很实际的技巧:使用EMA(Exponential Moving Average)来稳定模型。OVOD模型的验证集mAP曲线通常波动很大,EMA可以有效平滑这种波动。我记得有一次实验,用EMA后模型在LVIS rare类别的mAP从18.7涨到了21.2,而训练时间和显存开销几乎没有增加。EMA的衰减系数我习惯用0.999,在训练最后1/3的阶段开始启用。
4. 评估基准与性能对标
4.1 常用数据集与评测指标
OVOD领域最常用的评测基准是COCO和LVIS。COCO的固定80类通常作为base类别,另外从其他地方挑选一些类别作为novel类别来评测模型的开放能力。LVIS则更细致,它有1200多个类别,按出现频率分成frequent、common、rare三档。其中rare类别在训练时样本极少,最能检验模型的开放词汇能力,所以LVIS rare的mAP是OVOD论文里最常被引用的指标。
在实际对比方法时,我建议同时关注两个指标:base类别的mAP(验证模型的基础检测能力是否退化)和novel/rare类别的mAP(验证模型的开放能力)。只看novel mAP有一个陷阱:有些方法为了提升novel类别,会让模型在base类别上严重退化,这在业务中是不可接受的。
另外一个值得关注的指标是A-OSE(Aggregated Open-vocabulary Segmentation Evaluation),它通过计算模型在开放类别集合上的整体分割/检测质量来评估,相比单独看某个指标更全面。不过目前论文里用A-OSE还不够普遍,更多的还是用mAP作为主指标。
4.2 典型方法的性能对比与选型建议
我把几类典型方法放在一起做了一个对比,方便你做技术选型。
| 方法 | 技术路线 | 骨干网络 | LVIS rare mAP | 推理速度 | 适用场景 |
|---|---|---|---|---|---|
| ViLD | 两阶段蒸馏 | ResNet-50 | 16.3 | 慢 | 学术研究,精度优先 |
| Detic | 两阶段+分类头软化 | ResNet-50 | 17.8 | 中 | 通用检测,精度高 |
| YOLO-World | 单阶段对比学习 | DarkNet | 17.4 | 快 | 实时场景,工程部署 |
| OpenSeg | 区域级对齐 | ResNet-101 | 18.6 | 慢 | 大规模数据,精度上限高 |
| Grounding DINO | 两阶段+跨模态融合 | Swin-T | 21.7 | 中 | 通用检测,精度和速度平衡 |
以上数据来自我对公开论文和复现实验的整理,不同设置下会有浮动,仅供参考。选型逻辑上,我的建议是:如果业务对延迟敏感(比如边缘设备、实时视频流),优先考虑YOLO-World这类单阶段方案;如果追求极致精度且算力充裕,Grounding DINO这类跨模态融合方案更合适;如果论文实验或者算法预研,ViLD和Detic作为baseline非常合适,组件清晰,容易做消融。
4.3 开放词汇能力的边界在哪里
用户对OVOD能力边界要有合理预期。OVOD能识别"训练时没见过的类别",但它不是万能的。模型对novel类别的理解上限,受限于文本编码器的语义理解能力。比如"左侧第三个红色椅子"这种包含空间关系的描述,OVOD通常无法正确处理,因为检测任务本身没有显式建模实体之间的关系。
另外,超细粒度的类别(比如某种车牌上的省份简称、不同种类的昆虫学名)如果CLIP文本编码器的语义空间里本身就分不开,OSOD模型也无法区分它们。一个实用的评估方法是:在确定业务类别清单后,先用CLIP文本编码器计算所有类别两两之间的相似度,如果相似度超过0.95,大概率OVOD模型也分不开,需要考虑用few-shot微调或者加入属性描述来辅助区分。
5. 常见问题与排查技巧实录
5.1 模型训练损失正常但novel类别效果差
这是我在复现时遇到频率最高的问题。损失在降,base类别mAP正常,但novel类别几乎不工作。排查思路按顺序来:
- 检查文本侧是否真的对novel类别生成了正确的嵌入。最简单的方法是可视化novel类别文本嵌入和CLIP原始嵌入的余弦相似度,如果两者差距过大,说明文本编码器被训练过程带偏了,考虑冻结文本编码器。
- 检查候选区域里是否真的包含novel类别的目标。如果RPN阶段对novel类别的recall本身就很低,那后面的分类环节再怎么优化也没有用。可以统计一下novel类别目标被RPN覆盖的比例。
- 检查损失权重。对比损失在总损失里的占比如果太低,模型会优先优化定位,语义对齐学不好。
5.2 推理时类别数量很大导致速度下降
当用户输入的类别清单有几百甚至上千个时,动态生成分类头的方式会显著拖慢推理速度。最实用的优化方案是文本侧预计算和缓存。如果业务场景的类别清单是固定的(比如安全帽检测、工服检测),完全可以在初始化阶段把文本嵌入全算好,并重参数化到卷积核参数里,推理时没有任何额外开销。
如果类别清单是动态变化的,可以做类别嵌入的聚类和分组。把语义相近的类别分到一组,组内共享一部分计算。不过这个方案会牺牲少量精度,需要根据场景做取舍。
5.3 漏检和高误检率同时出现
这种问题通常指向训练数据本身。图文对数据的质量参差不齐,很多图文对里文本描述和图像内容并不严格对应。如果模型大量学习到这种噪声对齐,推理时就会出现看到什么都觉得像某个类别的情况。
我处理过一个个案:模型对"cat"的误检率特别高,几乎所有圆形物体都被识别成猫。检查训练数据后发现有大量"cat"标签的图文对里的图像其实拍的是一团毛线。清洗掉这批数据后误检率显著下降。图文数据的清洗和过滤,在OVOD训练里的重要性怎么强调都不过分。
5.4 训练时显存不足
OVOD模型通常参数量大,输入分辨率高,batch size稍大就会OOM。建议从这几个方向优化:
- 使用梯度累积,增大等效batch size而不增加显存开销
- 降低训练输入分辨率,推理时再用原分辨率
- 对文本编码器做半精度(FP16)推理,冻结参数并关闭梯度
- 如果用了CLIP的图像编码器作为Teacher,同样可以冻结并用FP16缓存所有图像特征,避免前向重复计算
我在一次训练中通过把CLIP Teacher的特征提前缓存到磁盘,显存占用直接降了一半,训练速度也快了不少。
5.5 模型在真实场景退化严重
训练时mAP不错,部署到线上效果却差一大截。这种情况多半是数据分布偏移。OVOD模型在图文对上学习的语义对齐,天然偏向互联网图片的风格(主体居中、背景干净、光线充足)。到了监控画面、无人机视角、工业质检这类场景,模型的特征分布会发生偏移。
缓解手段比较有限,最有效的是业务数据的小规模微调。即使是几百张带框的业务数据,也能显著拉回效果。其次是domain-specific的prompt模板设计,比如针对监控场景把"a photo of a {}"换成"a surveillance camera image of a {}",有时会有意外收获。最后是主动收集一些困难负样本加入训练,提升模型对背景干扰的鲁棒性。
写在最后
从个人体会来说,OVOD是一个"看似简单,实际水很深"的方向。表面的流程大家都能说出来,image encoder加上text encoder再做对齐,但真正做下去会遇到大量工程和训练细节问题。数据配比、温度系数、冻结策略、伪标签质量,任何一个环节没有处理好,效果都可能离论文里的数字差一大截。
如果打算在自己项目中落地OVOD方案,我的建议是先小规模复现一个基线(VIiD或者YOLO-World都可以),跑通流程之后再逐步改造。不要一上来就追求最先进的方法,先把baseline跑明白,后续的优化才有参照系。
另外,有一件常被忽视的事:OVOD模型的能力边界,很大程度取决于你对业务类别清单的结构化拆解能力。与其期望模型"什么都能认",不如把业务需求转化为一组清晰、无歧义、语义空间可分性好的类别定义。类别定义好了,模型的潜力才能被充分发挥。