ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

开放集识别实战:从特征空间到拒绝阈值的系统化落地指南

开放集识别实战:从特征空间到拒绝阈值的系统化落地指南

1. 从“认得出”到“认得清”:开放集识别到底在解决什么问题

做过图像分类或者异常检测的朋友,大概率都遇到过这样一种尴尬局面:模型在训练集和测试集上表现都很好,指标刷得飞起,可一旦上线,遇到一个从来没见过的类别,它照样会自信满满地给出一个错误答案。比如你训练了一个识别猫和狗的模型,结果线上来了一张兔子的图片,模型不会告诉你“我不认识”,而是会以极高的置信度把它判成猫或者狗。这个问题在学术界有个专门的名字——开放集识别(Open Set Recognition,简称OSR)。

传统分类任务默认一个假设:测试时出现的所有类别,在训练阶段都见过。这个假设叫闭集假设。但现实世界显然不是这样运转的。无论是安防监控、工业质检、医疗影像诊断,还是自动驾驶感知,系统面对的都是一个开放的环境,未知类别、未知模式随时可能出现。开放集识别要解决的核心问题就是:让模型在面对未知类别时,既能正确分类已知类别,又能有效地把未知类别“挑出来”并拒绝掉。

这个方向这几年热度一直在涨,从最早的1-vs-Set Machine、W-SVM,到后来的OpenMax、G-OpenMax,再到基于生成模型、基于原型学习、基于度量学习的一系列方法,整个领域的方法论已经迭代了好几轮。这篇内容我会结合自己在这个方向上的实践和踩坑经验,把开放集识别的核心思路、关键技术路线、实操要点和常见问题系统地梳理一遍。适合正在做异常检测、新类发现、鲁棒分类相关工作的同学参考,也适合刚接触这个方向、想快速建立全局认知的朋友。

2. 开放集识别的核心思路与方案选型

2.1 风险最小化:OSR的理论根基

理解开放集识别,绕不开一个核心概念——开放空间风险(Open Space Risk)。这个概念最早由Scheirer等人在2013年前后系统提出。简单说,闭集分类器在特征空间中划定的决策边界,会把无限大的开放空间也划归到某个已知类别里。而开放集识别要求模型在保证经验风险(已知类分类错误率)可控的同时,把开放空间风险也压到最低。

用生活化的类比来解释:闭集分类器就像一个只学过加减法的小学生,你问他3减5等于多少,他不会说“这个我还没学”,而是会硬凑一个答案给你。开放集识别要训练的,是让这个学生学会说“这道题超出我的知识范围了”。

从数学形式上看,开放集识别的目标可以写成:

在最小化已知类分类损失的同时,最小化未知类被误判为已知类的概率。

这两个目标天然存在张力。你把决策边界收得越紧,已知类的分类精度可能下降;你放得越松,未知类就越容易混进来。所以OSR方法的设计,本质上是在这两者之间找平衡。

2.2 主流技术路线对比

目前开放集识别的方法大致可以分成几条主线,我整理了一个对比表格,方便大家快速定位:

技术路线核心思想代表方法优势局限
基于传统分类器改造在SVM等分类器上引入拒绝机制1-vs-Set、W-SVM、PI-SVM理论清晰,实现简单依赖手工特征,扩展性差
基于深度网络激活利用SoftMax输出或logit分布做拒绝OpenMax、G-OpenMax端到端,易集成对置信度校准敏感
基于生成模型生成伪未知样本辅助训练GAN-based OSR能显式建模未知训练不稳定,成本高
基于原型/度量学习学习紧凑的类原型,用距离做拒绝原型网络变体、CROSR泛化好,可解释原型质量依赖设计
基于自监督/对比学习用对比损失拉开已知与未知对比学习OSR框架表征强,适合大数据需要精心设计正负样本

选哪条路线,取决于你的具体场景。如果你的数据量不大、特征维度不高,传统方法改造可能就够了;如果是图像、语音这类高维数据,深度网络激活或者原型学习路线更合适;如果你有充足的算力且能接受训练的不稳定性,生成模型路线可以尝试。

2.3 为什么深度学习方法成为主流

早期OSR研究主要集中在传统机器学习框架下,因为那时候深度网络的拒绝机制还不成熟。但2016年之后,情况发生了明显变化。深度网络天然具备强大的特征提取能力,而OSR的核心难点之一就是在好的特征空间里做拒绝。特征不好,再精巧的拒绝策略也是空中楼阁。

另一个推动因素是**极端值理论(EVT)**在深度模型中的引入。OpenMax就是典型代表,它用Weibull分布对正确分类的激活向量进行拟合,然后估计某个样本属于未知类的概率。这个思路比单纯看SoftMax最大值要靠谱得多,因为SoftMax的输出经过归一化后,已知类的置信度普遍偏高,直接设阈值很容易误杀。

我自己的经验是:如果你的已知类数据量足够,优先考虑深度网络+EVT或者深度网络+原型学习的组合。这两条路线在多个公开数据集上的表现都比较稳,工程落地的可控性也更好。

3. 核心细节解析与实操要点

3.1 特征空间设计:拒绝机制的地基

开放集识别能不能做好,七成看特征空间。特征空间如果本身就把已知类压缩得很紧凑、类间距离拉得很开,那拒绝未知类就是顺水推舟的事。反过来,如果特征空间里已知类都混在一起,那再复杂的拒绝模块也救不回来。

实操中我常用的几个策略:

  • 加性角度间隔损失(AAM-SoftMax):这个在人脸识别领域很成熟,用在OSR上效果也不错。它通过角度间隔把类内紧凑度和类间分离度同时拉大,让特征空间更有“结构感”。
  • 中心损失(Center Loss):给每个类维护一个特征中心,惩罚样本特征到中心的距离。这个损失和SoftMax配合使用,能显著提升类内紧凑度。
  • 对比学习预训练:用SimCLR或者MoCo这类框架先做自监督预训练,再在已知类上微调。这样得到的特征空间泛化性更好,对未知类的容忍度也更高。

注意:特征维度的选择很关键。维度太低,类间区分度不够;维度太高,容易过拟合已知类,导致未知类稍微偏离就被判成已知。我一般从128维起步,根据数据集规模在128到512之间调整。

3.2 拒绝阈值的确定:最容易被忽视的环节

很多论文在报告OSR性能时,默认阈值是调好的。但实际部署时,阈值怎么定是个大问题。定高了,未知类漏检多;定低了,已知类误拒多。

我常用的做法是基于验证集的分位数法。具体步骤:

  1. 在验证集上跑一遍模型,收集所有已知类样本的“已知度分数”(比如OpenMax的激活值、原型距离的负数等)。
  2. 取这些分数的第5百分位或者第10百分位作为初始阈值。
  3. 如果业务对未知类更敏感(比如安防场景),把分位数调低;如果对已知类误拒更敏感(比如推荐场景),把分位数调高。

这个方法的逻辑是:我们假设验证集上的已知类样本分布和线上已知类分布一致,那么低于某个分位数的样本,大概率是异常的。当然,这个假设在分布漂移严重时会失效,所以线上还需要持续监控和动态调整。

3.3 未知类样本的模拟:生成还是挖掘

如果训练时能拿到一些未知类样本,哪怕数量很少,OSR的性能都会有明显提升。但现实中往往拿不到。这时候有两种思路:

第一种是生成伪未知样本。用GAN或者扩散模型在已知类分布的边缘区域采样,把这些样本当作未知类的代理。G-OpenMax就是这条路线的代表。优点是能显式控制未知样本的分布,缺点是生成质量不稳定,而且生成模型本身训练成本高。

第二种是从已知类中挖掘“类未知”样本。具体做法是:把已知类样本做各种强增强(比如大幅旋转、颜色抖动、CutMix),让它们偏离原始分布,然后把这些增强样本当作未知类的近似。这个方法实现简单,而且不需要额外训练生成模型。我在几个工业质检项目里用过,效果比预期好。

实操心得:增强的强度要控制好。太弱了,增强样本和原始样本没区别,起不到模拟未知类的作用;太强了,增强样本完全失去语义信息,模型学到的拒绝边界会过于激进。我一般用AutoAugment或者RandAugment,把强度设在中等偏上。

3.4 评估指标的选择:别只看准确率

OSR的评估和闭集分类很不一样。闭集分类看准确率就够了,OSR必须同时看已知类分类性能和未知类拒绝性能。常用的指标有:

  • AUROC:把已知类和未知类的分数混在一起,看排序质量。这个指标对阈值不敏感,适合比较不同方法。
  • OSCR(Open Set Classification Rate):在不同阈值下,已知类正确分类率和未知类正确拒绝率的综合曲线。
  • F1-OSR:已知类F1和未知类F1的调和平均。
  • 闭集准确率 + 开集拒绝率:最直观的组合,但需要固定阈值。

我一般会同时报告AUROC和固定阈值下的闭集准确率/开集拒绝率。前者用于方法对比,后者用于评估实际部署效果。

4. 实操过程与核心环节实现

4.1 数据准备与划分策略

OSR的数据划分和闭集分类有本质区别。闭集分类是把所有类别按比例分成训练集和测试集,OSR则要把类别分成已知类集合和未知类集合。未知类集合的样本在训练阶段完全不可见,只在测试时出现。

具体操作步骤:

  1. 选定一个多类数据集(比如CIFAR-10、ImageNet子集、或者自己的业务数据)。
  2. 从所有类别中随机选一部分作为已知类(比如10个类里选6个),剩下的作为未知类。
  3. 已知类样本按常规划分成训练集、验证集、测试集。
  4. 未知类样本只放入测试集,且测试集中已知类和未知类的比例要控制好。我一般用1:1或者2:1,具体看业务场景中未知类出现的频率。

注意:未知类的选择不能太随意。如果未知类和已知类在语义上差异极大(比如已知类是猫狗,未知类是飞机),那OSR任务就太简单了。真正有挑战性的是未知类和已知类在视觉上相似的情况,比如已知类有哈士奇,未知类有阿拉斯加。这种设置下才能检验方法的真实能力。

4.2 模型训练流程与关键参数

以深度网络+OpenMax为例,完整训练流程如下:

第一步:基础分类器训练

用已知类训练集训练一个标准分类网络。骨干网络可以用ResNet、EfficientNet或者ViT,看你的数据规模和算力。损失函数用SoftMax交叉熵,优化器用SGD或者AdamW。

关键参数:

  • 初始学习率:0.1(SGD)或1e-3(AdamW)
  • 权重衰减:5e-4
  • 批大小:64或128
  • 训练轮数:100到200,配合余弦退火

第二步:激活向量收集

训练完成后,把训练集(或者验证集)再过一遍网络,收集每个已知类样本在倒数第二层的激活向量。注意,这里要收集的是正确分类的样本的激活向量,分错类的不要。

第三步:Weibull拟合

对每个已知类,取其所有正确分类样本的激活向量,计算每个维度上的均值,然后计算每个样本的激活向量与均值向量的距离。对这些距离用Weibull分布拟合,得到每个类的Weibull参数。

第四步:OpenMax计算

测试时,对每个样本:

  1. 获取倒数第二层激活向量。
  2. 对每个已知类,计算激活向量与该类均值向量的距离。
  3. 用该类的Weibull分布计算这个距离的累积分布函数值,作为“属于该类的概率修正因子”。
  4. 用修正因子调整SoftMax输出,得到修正后的概率分布。
  5. 修正后的概率分布中,已知类的概率之和如果低于某个阈值,就判为未知类。

这个流程听起来复杂,但代码实现并不难。核心就是Weibull拟合和修正因子的计算,网上有现成的开源实现可以参考。

4.3 阈值调优与线上部署

训练和评估完成后,部署环节的阈值调优是最后一公里。我的做法是:

  1. 在验证集上跑一遍,得到所有已知类样本的“已知度分数”。
  2. 画分数分布直方图,观察已知类分数的下尾在哪里。
  3. 取第5百分位作为初始阈值。
  4. 如果线上有少量标注的未知类样本,用这些样本做验证,看漏检率和误拒率是否满足业务要求。
  5. 根据业务反馈微调阈值,一般调整幅度在±2个百分点以内。

线上部署时,我建议加一个分数平滑模块。因为单帧的分数可能有噪声,用滑动窗口平均或者指数移动平均可以降低抖动。窗口大小根据业务帧率定,一般5到10帧比较合适。

5. 常见问题与排查技巧实录

5.1 已知类准确率下降严重怎么办

这是OSR最常见的副作用。你引入了拒绝机制,已知类的分类精度往往会掉几个点。如果掉得太厉害,可以从这几个方向排查:

  • 检查特征空间是否被过度压缩。如果用了很强的中心损失或者角度间隔损失,已知类特征可能被压得太紧,导致决策边界过于保守。适当降低这些损失的权重。
  • 检查阈值是否设得太高。阈值高,已知类样本容易被误判为未知。把阈值调低试试。
  • 检查未知类模拟样本是否过于激进。如果增强强度太大,模型学到的拒绝边界会过于宽泛,把已知类也拒了。降低增强强度。

5.2 未知类拒绝率上不去怎么办

反过来,如果未知类拒绝率太低,说明模型对未知类太“宽容”。排查方向:

  • 检查特征空间是否区分度不够。如果已知类特征都混在一起,未知类更容易蒙混过关。加强特征判别性训练。
  • 检查是否缺少未知类先验。如果完全没用任何未知类模拟,模型可能根本没学会拒绝。加入伪未知样本或者增强样本。
  • 检查分数计算方式。SoftMax最大值作为已知度分数,在深度网络中往往区分度不够。换成OpenMax或者原型距离试试。

5.3 常见问题速查表

问题现象可能原因排查方法解决思路
已知类准确率大幅下降拒绝边界过激检查阈值和增强强度降低阈值,减弱增强
未知类拒绝率低特征区分度不足可视化特征分布加强判别性损失
训练不稳定生成模型难训练检查损失曲线改用原型或对比学习
线上效果差于离线分布漂移对比线上线下分数分布动态调整阈值
阈值难确定验证集不代表线上检查验证集划分用分位数法+线上监控
推理速度慢拒绝模块计算量大Profile各模块耗时简化拒绝计算,用近似

5.4 几个容易踩的坑

第一个坑:用测试集调阈值。这是学术论文里常见的问题,但在工程中绝对要避免。测试集只能用来做最终评估,调阈值必须用验证集。

第二个坑:忽略类别不平衡。如果已知类之间样本量差异大,Weibull拟合可能会偏向样本多的类。解决办法是对每个类单独拟合,或者对样本少的类做重采样。

第三个坑:把OSR和异常检测混为一谈。两者有重叠,但目标不同。异常检测更关注“偏离正常模式”,OSR更关注“属于已知类还是未知类”。评估指标和方案设计都有差异,不要直接套用。

第四个坑:忽视计算成本。OpenMax的Weibull拟合和修正计算在类别数多的时候会变得很慢。如果已知类有几百个,建议用近似方法或者只对Top-K类做修正。

6. 开放集识别的扩展方向与个人体会

OSR这个方向还在快速演进。最近几年有几个趋势值得关注:一是与自监督学习的结合,用对比学习或者掩码建模预训练的特征,在OSR任务上表现明显更好;二是与元学习的结合,让模型学会“如何拒绝”而不是“拒绝什么”;三是与因果推断的结合,从因果角度理解已知类和未知类的本质差异。

我自己在这个方向摸爬滚打几年,最大的体会是:OSR不是一个单纯的算法问题,而是一个系统问题。特征空间、拒绝机制、阈值策略、线上监控,任何一个环节出问题,整体效果都会打折扣。很多论文只关注拒绝机制的设计,但实际落地时,特征空间的质量和阈值的动态调整往往更关键。

另外,不要迷信单一指标。AUROC高不代表线上效果好,闭集准确率高也不代表未知类拒得好。一定要结合业务场景,定义清楚什么更重要,然后有针对性地优化。工业质检里,漏检一个缺陷可能比误拒一个良品代价高得多,那阈值就要往低里调;推荐场景里,误拒一个正常用户可能比放过一个异常用户影响更大,那阈值就要往高里调。

最后分享一个小技巧:如果你的已知类类别数很多,可以考虑分层拒绝。先用一个粗粒度的拒绝器把明显异常的样本过滤掉,再用细粒度的拒绝器做二次判断。这样既能保证拒绝率,又能控制计算成本。我在一个已知类超过50类的项目里用过这个策略,推理速度提升了将近一倍,拒绝率还略有上升。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进