1. Softmax-based方法:从概率分布到温度调节
在OoD检测领域,Softmax-based方法是最早被广泛采用的技术路线之一。它的核心思想非常简单:利用分类模型输出的Softmax概率分布来判断输入样本是否属于已知分布(In-Distribution, ID)。这种方法最大的优势在于无需修改模型结构,直接利用现成的分类模型就能实现OoD检测。
我曾在实际项目中测试过基础版的Softmax方法,发现一个有趣的现象:对于分类正确的ID样本,模型往往会给出接近1.0的最大Softmax概率值;而对于OoD样本,这个概率值通常会明显偏低。SMOOD方法正是基于这个观察,通过设定一个概率阈值来区分ID和OoD样本。比如我们可以设定阈值为0.9,当样本的最大Softmax概率低于这个值时,就判定为OoD。
但这种方法有个明显的缺陷:不同类别的ID样本可能天然具有不同的Softmax概率分布。比如在ImageNet分类任务中,"狗"和"猫"这类常见类别的置信度通常高于一些细分品类。为了解决这个问题,ODIN提出了两项关键改进:
温度缩放(Temperature Scaling):在Softmax计算中引入温度参数T,公式变为:
def tempered_softmax(logits, temperature): exp_logits = np.exp(logits / temperature) return exp_logits / np.sum(exp_logits)通过调节T值(通常设为1000),可以放大ID和OoD样本的概率差异。
输入预处理:对输入图像加入微小扰动,进一步扩大概率差异。实测发现,这种方法能使OoD检测的AUROC指标提升10-15个百分点。
不过要注意的是,温度参数的选择需要根据具体数据集进行调整。我在CIFAR-10上测试时发现,T=1000效果最好,但在某些医疗影像数据集上,T=500反而更合适。
2. 不确定性估计:让模型学会说"我不知道"
传统分类模型有个致命缺陷:即使对完全没见过的OoD样本,也总会给出一个看似"自信"的预测结果。不确定性方法正是为了解决这个问题而生,它的核心是让模型能够量化自己的不确定程度。
这类方法通常需要修改模型结构。我比较喜欢的是"Learning Confidence for OOD Detection"提出的双分支架构:在原有分类分支旁新增一个置信度预测分支。这个分支输出一个0到1之间的置信度值c,用来调整最终的预测概率:
调整后概率 = c * 原始Softmax概率训练时,模型需要同时优化分类准确率和置信度校准。具体来说,对于ID样本,我们期望c接近1(高置信度);对于OoD样本,c应该趋近于0。这种设计有个妙处:即使分类分支出错,只要置信度够低,我们仍然可以将其识别为OoD样本。
另一种有趣的思路是"Multiple Semantic Label Representations",它彻底改变了传统的监督方式。不再使用one-hot标签,而是用词向量作为监督信号。模型需要预测目标类别的语义嵌入,最终用预测向量的L2范数作为OoD分数。这种方法在文本分类场景表现尤其出色,我在一个新闻分类项目中使用它,OoD检测F1值达到了0.89。
不过要注意,不确定性方法需要额外的训练成本。如果你们的模型已经部署上线,可能更适合使用下一节的生成式方法。
3. 生成式模型:重构误差里的秘密
生成式模型为OoD检测提供了全新的视角。这类方法的基本假设是:经过良好训练的VAE或GAN应该能很好地重构ID样本,但对OoD样本会产生较大的重构误差。
我最早尝试的是最基础的VAE重构方法。在MNIST数据集上训练一个VAE后,发现它对数字的重构效果很好,但当输入字母时,重构图像变得模糊不清。通过计算原始图像与重构图像的MSE误差,可以有效地检测出非数字样本。
但这种方法有个明显局限:重构误差受图像质量影响太大。一张稍微模糊的ID数字可能比清晰的OoD字母产生更大的误差。为此,"Improving reconstruction autoencoder..."提出了马氏距离的改进方案:
- 在潜在空间计算ID样本的均值μ和协方差矩阵Σ
- 对于新样本,计算其潜在向量z与μ的马氏距离:
def mahalanobis_distance(z, mu, sigma_inv): delta = z - mu return np.sqrt(delta.T @ sigma_inv @ delta) - 结合重构误差和马氏距离做综合判断
在实际部署中,我发现这种方法对特征空间的维度非常敏感。过高维度会导致马氏距离失效,建议通过PCA将维度降至50-100左右。
更前沿的"Out-of-distribution Detection in Classifiers via Generation"则采用了主动生成策略:训练一个生成模型专门产生"边界样本",这些样本紧贴ID数据流形但又不属于ID分布。然后训练一个二分类器来区分真实ID样本和生成的边界样本。这种方法在医疗异常检测中表现优异,我在皮肤病变识别项目中用它发现了多种罕见病变类型。
4. 专用分类器:简单粗暴的解决方案
如果说前几种方法都带着些"曲线救国"的意味,那么分类器方法就是直击问题本质:直接把OoD检测当作一个分类问题来解决。
最简单的实现方式是修改模型输出层,增加一个额外的"OoD类别"。比如原本10类分类任务变为11类(10个ID类+1个OoD类)。这种方法看似直接,但在实践中遇到两个挑战:
- 需要大量多样的OoD样本进行训练
- OoD样本的多样性可能导致模型偏向将其归类为OoD
"OOD discernment layer"提出了一种更巧妙的方案:在模型不同层插入多个一类SVM分类器。通过分析发现,某些中间层特征对OoD特别敏感。具体实现步骤如下:
- 冻结主模型权重,在各个特征层后添加SVM
- 使用正常ID样本训练这些SVM
- 在验证集上评估各层的OoD检测性能
- 选择表现最好的1-3个层作为最终检测点
我在工业质检系统中采用这种方法,结合了三个不同深度的特征层,使得对新型缺陷的检测率提升了40%。不过要注意,SVM的核函数选择很关键,RBF核通常效果最好但计算量较大。
5. 自监督学习:无监督时代的OoD检测
随着自监督学习的崛起,OoD检测也迎来了新的突破。这类方法最大的优势是完全不需要人工标注,仅通过数据自身的结构就能学习有效的OoD检测能力。
CSI(Contrasting Shifted Instances)是我见过最巧妙的自监督OoD方法之一。它的核心思想是通过对比学习来识别分布偏移。具体来说:
- 对每个样本x,生成其增强版本x'(常规增强)
- 再生成一个"分布偏移"版本x''(使用非常规增强,如极端裁剪)
- 训练模型将x和x'的特征拉近,同时将x与x''的特征推远
- 测试时,使用样本与其增强版本的特征距离作为OoD分数
在CIFAR-100上的实验显示,CSI的性能甚至超过了部分有监督方法。我特别喜欢它的一个特性:对增强策略的选择非常鲁棒。无论是哪种分布偏移,模型都能学到有效的区分能力。
另一个值得关注的是SSD(Self-Supervised Detection)方法。它先用自监督方式预训练特征提取器,然后在特征空间构建马氏距离检测器。这种方法在计算资源有限时特别有用,因为特征提取器可以复用现有模型。
最近我在尝试将CSI思路应用到时序数据中,通过设计特殊的时间序列增强策略(如随机片段交换),在ECG异常检测中取得了不错的效果。自监督方法的潜力还远未被充分挖掘,特别是在多模态场景下。