
第一次跑通一个零样本语义分割模型的时候我盯着可视化结果愣了好几秒。训练数据里根本没有“路灯”这个类别的任何像素标注可模型面对一张夜晚的街道图真的把路灯区域高亮了出来。这种“没教过也能认出来”的能力正是零样本语义分割Zero-shot semantic segmentation这个方向最吸引人的地方。它要解决的是一个反直觉的问题语义分割模型的输出是逐像素标签传统做法里标签集合必须在训练前定死零样本则要求模型在推理时能泛化到从未见过的类别上。这篇文章写给三类人准备入坑这个方向的研究者、需要在业务里处理长尾/动态类别的工程同学以及被“零样本”一词吸引但还没搞清楚它和普通分割有什么区别的初学者。我会把问题定义、技术路线、数据与评估、典型方法、复现经验一次讲透最后聊聊我自己踩过的坑和目前仍然没解决的难点。1. 零样本语义分割的“零”到底指什么1.1 传统语义分割的封闭世界假设语义分割本质上是一个逐像素分类问题。对图像里的每个像素模型都要预测它属于哪个语义类别。经典的模型比如DeepLab、PSPNet、U-Net它们的输出层是一个固定维度的分类器类别数在训练前就锁死了。假设训练集定义了20个类别那网络最后一层就是20个通道跑完softmax再取argmax得到的就是这20类里的一个。这个“封闭世界假设”在真实场景里很别扭。自动驾驶的感知系统需要识别各种罕见交通标识、特殊车型、临时障碍物遥感图像里会出现训练数据里从未标注过的地物类型电商场景要持续上线新商品类别。每次增加类别都要重新采集像素级标注数据重新训练模型。像素级标注有多贵做过分割项目的人都懂一张高分辨率街景图的完整标注可能要花几个小时。零样本语义分割想做的事情就是省掉“为每个新类别重新标注”这个环节。它把知识来源从“像素级标注”换成“类别语义描述”。训练阶段模型见过一部分类别称为可见类或Seen Classes同时每个类别都附带一个语义向量比如词向量、属性向量或者文本描述。测试阶段模型要对一个包含全新类别称为不可见类或Unseen Classes的图像做逐像素分类。模型没见过这些类别的像素样本但见过它们的语义描述它需要靠“视觉特征”和“语义描述”之间的对应关系把新类别“推理”出来。1.2 与开集、少样本、广义零样本的边界这个领域里有一堆很容易混的概念零样本、开集、广义零样本、少样本、幻觉分割、开放世界分割。它们看起来都在讲“模型认不认识新东西”但边界不太一样。零样本语义分割最典型的设置训练和测试是两批类别测试类别在训练时完全不参与评估时也只测测试类别。广义零样本语义分割Generalized Zero-Shot Semantic Segmentation更贴近实际测试图像里同时可能出现训练过的类和没训练过的类模型必须在两者之间做出判断。别小看这个改动它立刻把难度拉高了一个量级因为模型天生偏向训练过的类后面我会详细讲。少样本语义分割是另一个方向它允许在测试时给每个新类别提供少量标注样本比如1到5张图。零样本则一张都不用纯粹靠语义知识。开集分割和开放世界分割更强调“拒绝未知”或“主动发现未知”模型要能判断某个像素属于已知类别还是未知类别甚至把未知类别聚类出来。这几个方向没有高低之分它们在工业界的落地场景不同。我个人的经验是理解零样本分割最适合的起点是先把“类别语义如何承载视觉信息”这个问题想清楚后面所有方法都围绕它展开。2. 三类技术路线的演进从嵌入对齐到CLIP唤醒零样本分割的方法论大致经历了三个阶段我用“间接路线、直接路线、预训练视觉语言模型路线”来归纳方便把握主线。2.1 间接路线先学一个“语义投影”最早期的思路是借鉴零样本图像分类的做法在训练阶段让视觉特征向一个语义向量空间对齐。拍照类比一下这就像让一个只见过中文标签的人通过一本“中英对照词典”学会看英文菜单然后在没见过的新菜品图片上猜测英文名。典型框架如SPNet。它把语义分割网络分成两条流一条是正常的视觉特征提取流负责输出像素级特征另一条是语义嵌入流使用词向量比如word2vec或GloVe的预训练向量作为类别表征。训练时加一个对齐模块让视觉特征和对应的语义向量在共享空间里接近。推理时对未见类只需要把它的词向量放进语义空间用最近邻匹配就能得到类别预测。这套思路的逻辑很清晰但它的瓶颈在“语义向量本身太弱”。word2vec这类词向量是在纯文本语料上训练的它知道“猫”和“狗”语义上相近却不知道“猫”在图像里通常有尖耳朵、圆眼睛这种视觉特征。所以用文本向量做桥梁视觉侧能学到的迁移信号非常有限。我试过用不同词向量切换实验直观感觉是词向量的质量直接决定unseen类性能的天花板。2.2 直接路线视觉特征与语义空间直接对齐既然“间接投影”受限于词向量第二波方法的思路是绕过脆弱的中间表示在训练阶段直接构造一个能从视觉特征映射到类别语义的机制让模型学会“如何对齐”这个动作本身。这里至少有三个子方向值得讲。第一个子方向是特征调制。代表方法如CaGNet它的核心思路是用类别语义向量生成一组调制参数去调整视觉特征的分布。因为不同类别对特征的“偏好”不一样比如车辆类别可能更关注边缘和轮廓天空类别更关注颜色和纹理语义向量可以告诉特征提取器“对这个类该重视什么”。第二个子方向是生成式方法。代表是ZS3Net它用生成模型GAN在训练时直接合成未见类的像素级特征然后把这些合成特征当作训练样本让分割头在特征层面“见过”未见类。听起来很美但生成模型很容易产生模式崩塌合成的特征和真实未见图特征分布有明显差距训练时的收益在推理时会打折扣。第三个子方向是语义关系建模。代表如CSRL它不再把每个类别当独立个体而是显式建模类别之间的语义关系比如“车”和“轮子”是整体与部分“人”和“自行车”有交互关系。训练时利用可见类之间的这些关系把未见类“锚定”在关系网络里。直接路线的总体进步是把注意力从“用什么向量”转移到“怎么用向量”但本质上仍然依赖人工定义的语义空间而且语义空间和视觉空间天然存在“异构鸿沟”语义相近的类别比如“公交车”和“巴士”视觉可能很像语义不相近的类别比如“海豚”和“游泳池”视觉可能也像。这类方法在简单数据集上效果尚可一遇到复杂场景就开始力不从心。2.3 生成式路线用GAN“补”出未见类特征上面提到过生成式的方法这里单独展开一下是因为它在很长一段时间里是零样本分割的主流避坑方向之一。它的逻辑有点像一个没见过“犀牛”的人听说犀牛是“体积大、有角、皮肤厚”于是他在脑子里“脑补”一个犀牛的样子然后用脑补的样本去训练分类器。ZS3Net就是这么做的训练一个特征生成器给它输入未见类的语义向量让它输出对应的视觉特征然后把这些假特征和真实可见类特征混在一起训练像素分类器。我在复现这类方法时遇到的问题很典型合成特征分布太“聚拢”了。真实世界里的同类目标有千变万化的姿态、光照、遮挡生成器很容易把特征都生成在分布的中心区域导致分类器在真实未见类特征上仍然不认。后来一些工作通过加对抗训练、特征重放、正则化来缓解但“脑补样本”始终没有“真实样本”扎实。这也是生成式路线后来逐渐让位于预训练视觉语言模型的原因之一。2.4 预训练视觉语言模型改变了游戏规则2021年以后CLIP这类大规模视觉语言预训练模型改变了零样本分割的玩法。CLIP在数亿图文对上学习了“图像”与“文本”的全局对齐它的文本编码器能给任意英文类别名一个语义向量它的图像编码器能把图像区域映射到同一个语义空间。简单说之前大家费尽心思构造的“类别语义向量”CLIP自己就带着一份很强的之前大家纠结的“视觉语义鸿沟”CLIP用大数据磨平了一部分。直接沿这个思路做的代表方法如ZegFormer。它把语义分割重新定义成“分组识别”两件事先用一个分组模块把图像切成若干候选区域掩码再对每个区域计算视觉特征用CLIP文本特征做分类。这样分割任务被简化成“对一组候选区域做零样本分类”CLIP那套强大的分类能力直接能用上。同时还有MaskCLIP、OpenSeg等一批工作有的通过改造CLIP的注意力图生成密集特征有的引入开放词汇检测的思路做提议生成。它们虽然实现差异很大但有个共同点不再自己从零学“类别语义”而是把预训练模型当成现成的“语义先验”来用。这条路线的优势非常明显我在实际测试里发现CLIP文本特征对未见类的分类能力比word2vec或GloVe高出一个档次。但CLIP也不是万能钥匙。它是图像级/区域级的对齐而分割需要像素级或者至少是掩码级的特征CLIP直接用的特征图分辨率太低细节丢失严重。所以后续工作都在处理“如何把CLIP的高层语义能力下放到密集预测任务”这至今仍是活跃的研究点。3. 数据划分与评估指标里最容易踩的门道很多人开始做零样本分割时第一反应是“先找个数据集跑一下”。但数据划分和评估指标里的坑比模型本身还多。如果没搞清楚评测口径实验结果可能自欺欺人。3.1 常用数据集与零样本Split的细节最常用的两个基准是PASCAL VOC和COCO。PASCAL VOC有20个语义类别常见的零样本划分是15个可见类作为训练集5个不可见类作为测试集。COCO的80个类别里常见划分是65个可见类和15个不可见类。但这里有个大坑不同论文对Split的定义并不完全一致。有的早期工作采用16个可见类加4个不可见类的划分有的会在训练集里保留部分不可见类的验证图像还有的会把背景类算成可见类、或者干脆忽略背景类的评估。所以对比不同论文的精度数字时一定要先确认它们用的是同一份Split文件否则看起来差几个点实际可能是完全不同的任务设置。我看到过不少刚入门的同学拿着论文里的数字和自己的实验一比就说“涨点了”结果连数据划分都不一样。建议的做法是率先确认测试类类别清单、训练图像是否包含未见图、背景类如何参与评估这三个细节再谈性能对比。3.2 为什么必须盯住harmonic mean零样本分割最常用的指标是mIoU但它要分可见类和不可见类分别算。只看不可见类的mIoUunseen IoU很容易被误导有些模型把所有像素都预测成不可见类unseen IoU可能很高但可见类一塌糊涂实际完全不可用。只看可见类的mIoU也一样模型退化成普通分割器也能拿高分但完全没有零样本能力。所以要同时看两个指标并计算它们的调和平均值hm 2 * seen_IoU * unseen_IoU / (seen_IoU unseen_IoU)用调和平均而不是算术平均是因为它惩罚“一类极高、一类极低”的情况。举个例子模型A的seen IoU是40unseen IoU是12算术平均是26调和平均是2 * 40 * 12 / 52 ≈ 18.5模型B如果两边都做到26算术平均同样是26调和平均却是26。一眼就能看出真正“均衡可用”的是模型B。我自己刷实验时的习惯是先记录seen和unseen两个原始值再算hm最后看一眼定性可视化结果。只有hm高但可视化里到处是乱贴标签的多半是评估脚本有问题。3.3 背景类与评估口径的公平性问题背景类在零样本分割里是个特别容易被忽视的角色。语义分割数据集里通常有大量“背景”像素它们不属于任何前景类别。零样本设置里背景怎么处理有些方法把背景当作一个单独的可见类来处理训练时学一个“背景类向量”有些方法在测试时完全忽略背景只在前景掩码上评估有些方法则会额外引入一个“未知阈值”像素和所有类别的相似度都很低时判为背景。这三种做法结果差异非常大。我见过一个实验只改了背景的处理方式unseen IoU跳了将近10个点。所以阅读论文或者评估自己结果时先问清楚背景算不算一类评估时有没有过滤背景像素如果论文里没写建议默认结果存在口径风险。4. 从SPNet到ZegFormer典型方法横向梳理这里给一张我平时用来快速定位方法的对照表把几个关键节点的思路和弱点都写清楚。方法评价带有个人主观判断仅供参考。方法提出的时间大致核心思路弱点SPNet2019年视觉特征与词向量空间对齐词向量语义弱对复杂视觉描述无能为力ZS3Net2019年用GAN生成未见类像素特征合成特征分布偏移训练不稳定CaGNet2020年语义向量调制视觉特征依赖候选区域质量未见类特征难调制CSRL2021年显式建模类别间语义关系关系定义依赖人工复杂场景容易过拟合ZegFormer2022年CLIP文本特征做区域分类区域提议质量决定上限MaskCLIP2022年把CLIP特征图改造为密集预测特征分辨率仍是瓶颈对细节目标不友好OpenSeg2022年开放词汇理念结合掩码分类训练成本高依赖大规模图文数据几个代表方法的演化逻辑值得细看。SPNet的设计其实很朴素分割网络提取特征再通过一个语义投影层把视觉特征映射到词向量空间。它证明了“视觉特征能通过语义空间泛化到未见类”这件事可行但天花板也很明显词向量对视觉差异的刻画太粗。ZS3Net走的生成式路线我在第2章已经讲过。它和SPNet的差异在于SPNet是让视觉特征“主动靠近”语义空间ZS3Net是让语义向量“主动生成”视觉特征一个判别式一个生成式。生成式理论上上限更高因为模型可以显式补全未见类的特征分布但实际训练难度高模式崩塌问题常见。到了CaGNet思路又变了一步。它不再只靠单次投影而是用语义向量生成调制参数去改变特征图每个通道的权重。打个比方SPNet像给每个人发了一副固定度数的眼镜CaGNet则是根据你要看的目标类型自动调节镜片度数。这个“条件化”思想后来在很多方法里都有体现。ZegFormer代表了一个分水岭它把零样本分割重新定义为“分组零样本分类”让CLIP强大的分类能力直接参与决策。我不止一次在实验里观察到同样的候选区域用CLIP文本特征分类的准确率远高于从零训练的语义向量分类器。这也是它在社区里被广泛复现的原因。从方法演化能隐约看出一条主线语义知识的来源不断升级起初来自纯文本词向量后来来自手工关系建模现在来自大规模图文预训练。零样本分割这个领域给了我很深的体会——很多时候方法设计得好不好取决于你给模型喂的“先验知识”够不够强。5. 跑一个零样本分割Demo的完整路径如果你现在想在本地把零样本分割跑起来我的建议是先别急着复现复杂论文。用一个最简单的CLIP-based流程把推理链路打通再逐步增加模块。下面这样的最小流程我亲自跑过稳定且直观。5.1 最小可行的推理流程核心思路只有四步提取类别文本特征、生成候选掩码或者直接用像素特征、把视觉特征投影到共享空间、计算余弦相似度取argmax。这里给出一个简化版的伪代码框架import torch import torch.nn.functional as F # 1. 准备类别名建议配多个提示模板做集成 labels [person, car, streetlight, ...] templates [ a photo of a {}, a photo of the {}, a {} in a scene, ] text_feats [] for label in labels: feats [] for tpl in templates: tokens tokenizer(tpl.format(label)) feats.append(clip.text_encoder(tokens)) text_feats.append(torch.stack(feats).mean(dim0)) text_feat F.normalize(torch.stack(text_feats), dim-1) # (C, D)# 2. 用分割backbone/掩码提议器得到候选区域特征 masks, visual_feats segmentor(image) # visual_feats: (N, D)每个区域取池化后的特征 # 3. 投影到同一空间并归一化 visual_feat F.normalize(proj(visual_feats), dim-1) # (N, D) # 4. 余弦相似度分类 logits visual_feat text_feat.T # (N, C) labels logits.argmax(dim1)为什么用余弦相似度而不是直接内积因为CLIP的文本特征和视觉特征的模长尺度差异很大用余弦相似度相当于把两类特征都归一化到单位球面匹配的是“方向”而不是“长度”这更符合语义对齐的直觉。投影层proj的作用是修正CLIP自带的图级对齐和分割所需的区域级特征之间的小偏差简化场景下甚至可以不加但加上通常会涨点。5.2 训练复现时最容易翻车的细节跑通Demo只是第一步真正训练一个零样本分割模型时我踩过不少坑挑几个最有代表性的说。第一个坑是未见类特征偏移。训练阶段完全没有未见类的像素样本模型学到的特征分布天然偏向可见类。这个问题在广义零样本设置里尤其致命。常见的补救手段包括用熵最小化或伪标签对未见图做二次校准、在损失函数里加入类别均衡项、对文本特征做温度缩放。我试过最简单的办法是推理时给logits除以一个温度系数再softmax能把偏向性压下去一部分但效果有限治标不治本。第二个坑是文本特征到底用哪一层的输出。CLIP文本编码器有多个Transformer层不同层输出的抽象程度不同。早期层更关注词语本身深层更关注整体语义。我的经验是用倒数第二层或者经过池化后的最终特征在多数数据集上表现稳健。只用一个类别的单模板提示和用多个模板取平均之间性能差距常常有3到5个mIoU。第三个坑是掩码提议质量。很多方案依赖预先检测出的候选区域但未见类目标在训练阶段从未被标注过区域提议模型对它们的召回率非常低。这是我在实际项目里感受最深的一点往往模型最后识别错了并不是分类器不行而是候选掩码压根没把目标物体完整圈出来。后来我尝试用通用分割先验比如SAM来补充未见类目标的掩码召回效果立竿见影。这也是目前开放世界/开放词汇分割的一个重要实践方向。第四个坑是颜色可视化。做分割实验时类别到颜色的映射表必须在训练、验证、测试阶段完全一致否则看似精度的结果可视化时一片混乱。我有一段时间怀疑模型学坏了后来发现是颜色映射的索引错位白白浪费了一整天。5.3 做实验时怎么设置消融才有效零样本分割的论文里常见一堆消融但如果你是自己做实验我建议优先把下面这几个变量单独控制而不是一出问题就同时改好几个地方。首先是文本侧的变化用词向量还是CLIP文本特征用单模板还是多模板集成类别描述里要不要加视觉属性比如“长尾巴的猫”这几个问题决定了“语义先验”的上限。其次是特征投影层的设置要不要可学习的投影头投影维度选多少。最后是候选区域质量切换不同的区域提议器对比同一分类头下的性能波动。我做项目时习惯把这三组实验分开跑现象会非常清楚文本侧变化影响大说明瓶颈在语义表达投影头影响大说明视觉和语义空间的异构性还没对齐好区域提议影响大说明分类已经不错分割细节拖累了整体。6. 目前仍然没被解决的三个核心难点到这一步技术路线、数据集、评估方法都清楚了也该说说这个领域“知道但暂时啃不动”的问题。这些问题不是我一个人遇到的整个社区也都在反复撞墙。6.1 类别偏向性模型总是“认熟不认生”零样本分割模型在推理时面对所有类别做统一分类但训练时只见过可见类这导致可见类的分类边界非常清晰而未见类几乎没有决策边界。模型天然会把“不确定”的像素推给可见类。广义零样本设置下这个问题尤其严重模型在unseen类上的召回率常常低到没法看。几类缓解方法都绕不开一个矛盾想要提升unseen类召回就要压低模型对可见类的“过度自信”但这必然伤害seen类的精度。可以用类别均衡重加权、校准损失、逻辑归一化等办法但很难同时保住两边。这本质上是一个不平衡学习问题只不过“缺失类别”直接缺席了训练过程比普通的长尾问题更难办。6.2 掩码提议噪声造成的误差累积很多新方法的pipeline是“先分割候选再分类候选”。这种两段式设计把问题拆解得很干净但也把误差链条拉长了候选掩码错了后面分类再准都白搭。未见类的目标往往形态多样和可见类共享的视觉模式少通用提议器对它们的效果并不稳定。目前我在实验里比较有效的做法是给提议器引入“通用物体性先验”或者用递归掩码细化。但这些手段增加了推理代价而且对原本就十分微小的目标帮助有限。当掩码提议和零样本分类两个环节都没有特别强的保证时整个系统离工业级还有明显距离。6.3 语义知识本身的边界问题CLIP把零样本分割带到了新高度但不能忽略的是CLIP自己也受限于训练数据的覆盖范围。它是在互联网图文对上训练的英文标签占主导某些垂直领域类别比如医疗影像里的病灶类型、工业质检里的瑕疵类别它根本没有对应的视觉概念此时CLIP文本特征和视觉特征对不上方法就会失效。这个边界其实很本质零样本分割假设“类别语义能描述视觉外观”但现实里很多类别的区分信息需要大量领域知识不是一句短语能承载的。我在一个遥感项目上试过细粒度土地覆盖类别文本描述列出好几条CLIP的表现仍然不稳定。可见的知识迁移存在上限这也是为什么这个方向还很值得继续做——谁能在“极少标注、极少语义信息”的情况下再推进一步谁就真的把开放世界的分割向前推了一大步。如果让我给刚接触这个方向的朋友一个实在建议先把我上面那个最小流程跑通用CLIP文本特征 一个现成通用分割器拿自己找的几张图看看可视化效果。你会很快理解“语义对齐”这件事为什么难也会清楚这个方向后续应该往哪里投入精力。我踩了这么多坑最大的心得是别迷信某个指标或某个模型先把数据划分、评估口径、特征来源这三件事夯实再做任何实验都会扎实很多。