【读点论文】Generalized Out-of-Distribution Detection: A Survey

Generalized Out-of-Distribution Detection: A Survey

Abstract

  • Out-of-Distribution 检测对于确保机器学习系统的可靠性和安全性至关重要。例如,在自动驾驶中,我们希望驾驶系统在检测到训练期间从未见过的异常场景或物体,并且无法做出安全决策时,发出警报并将控制权移交给人类。OOD 检测这一术语于2017年首次出现,此后受到了研究界越来越多的关注,导致了大量方法的开发,从基于分类的方法到基于密度的方法,再到基于距离的方法。同时,其他几个问题,包括异常检测(AD)、新奇检测(ND)、开集识别(OSR)和离群点检测(OD),在动机和方法上都与面向对象的检测密切相关。尽管有共同的目标,但这些主题是孤立发展的,它们在定义和问题设置上的细微差异经常会让读者和实践者感到困惑

  • 在这个调查中,我们首先提出了一个统一的框架,称为广义OOD检测,它包含了上述五个问题,即AD,ND,OSR,OOD检测和OD。在我们的框架下,这五个问题可以看作特例或者子任务,更容易区分。尽管对相关领域进行了全面的调查,但对 OOD 检测方法的总结仍不完整,需要进一步的改进。本文特别指出了 OOD 检测领域最新技术发展的差距。它还提供了其他子任务的代表性方法的综合讨论,以及它们如何与 OOD 检测方法的发展相关和启发。调查的结论是确定公开的挑战和潜在的研究方向。

  • 广义 OOD 检测统一了五个相关问题:异常检测(AD)、新奇检测(ND)、开放集识别(OSR)、OOD 检测和离群点检测(OD)。比如 AD 可以工业缺陷检测,ND 可以是检测新物种,OSR 比如图像分类器拒绝未知类别,OOD 检测如自动驾驶识别未知场景,OD 如数据清洗中的离群点。它们的区别在于分布偏移类型(协变量 vs 语义)、ID 数据类型(单类 vs 多类)、是否需要 ID 分类、归纳 vs 转导学习。比如 AD 和 ND 更关注单类,OSR 和 OOD 检测是多类且需要分类,OD 是转导学习,处理所有数据。

    • 任务核心差异典型场景通俗例子是否需已知类别分类
      异常检测(AD)关注 “异常”(偏离预设 “正常”),单类或多类,协变量 / 语义偏移工业缺陷检测、欺诈识别“质检机器人:检测零件表面划痕(协变量异常)或错误型号(语义异常)”否(仅需判断是否正常)
      新奇检测(ND)关注 “新类别”,单类或多类,语义偏移新物种发现、视频监控“生态相机:识别从未记录过的鸟类(新类别)”否(只需检测新类别,不分类已知)
      开放集识别(OSR)多类场景,需同时分类已知类 + 检测未知类,语义偏移图像分类器“垃圾分类模型:正确分类‘苹果 / 香蕉’(已知),拒绝‘塑料玩具’(未知)”是(必须准确分类已知类)
      OOD 检测多类场景,聚焦语义偏移,更广泛(含多标签、目标检测等)自动驾驶、安全关键系统“自动驾驶:识别‘汽车 / 行人’(已知),拒绝‘外星生物’(完全未知语义)”是(需保证已知类分类精度)
      离群点检测(OD)处理全部数据,检测 “少数异常点”,协变量 / 语义偏移数据清洗、异常流量检测“电商交易数据:识别刷单账号(离群点)”否(仅需找出少数异常点)
  • OOD方法划分方面,分为基于分类、基于密度、基于距离、基于重建误差方法。基于分类方法如 Softmax 分数,优点是简单,缺点是过自信;基于密度建模分布,缺点是计算复杂;基于距离计算特征距离,优点是直观,缺点是依赖特征质量;基于重建用自编码器,优点是适用于图像,缺点是重建误差可能不够。

  • 核心目标:让模型不仅能正确分类已知数据(ID, In-Distribution),还能拒绝 / 识别未知数据(OOD, Out-of-Distribution)。

Introduction

  • 值得信赖的视觉识别系统不仅应该对已知的上下文做出准确的预测,还应该检测未知的例子并拒绝它们(或者将它们交给人类用户进行安全处理)。例如,训练有素的 OOD 分类器应该能够检测用户上传的自拍照等非 OOD 图像,并拒绝此类输入,而不是盲目地将它们分类到现有的 OOD 类别中。在自动驾驶等安全关键应用中,当检测到训练中从未见过的异常场景或物体时,驾驶系统必须发出警告,并将控制权移交给驾驶员

  • 大多数现有的机器学习模型都是基于封闭世界假设 进行训练的,其中假设测试数据是从与训练数据相同的分布中提取的,称为非分布(ID)。然而,当模型被部署在一个开放的场景中时,测试样本可能是分布外的(OOD ),因此应该小心处理。分布变化可能是由语义变化(例如,OOD样本来自不同类别)或协变量变化(例如,OOD样本来自不同领域)引起的。

  • 语义分布偏移的检测(例如,由于新类别的出现)是OOD检测任务的焦点,其中标签空间 Y 在 ID 和 OOD 数据之间可以不同,因此模型不应该做出任何预测。除了OOD检测之外,有几个问题采用了“开放世界”的假设,并且具有识别OOD实例的类似目标。这些包括outlier detection (OD) ,anomaly detection (AD),novelty detection (ND) ,以及open set recognition (OSR) 。虽然所有这些问题都因具有相似的动机而相互关联,但就具体定义而言,各子主题之间存在微妙的差异。然而,缺乏对不同子主题之间的关系的全面理解导致研究者和实践者的困惑。更糟糕的是,这些本该互相比较、互相学习的子课题,却在孤立地发展

  • 在本次调查中,我们首次阐明了这些问题之间的相似性和差异,并提出了一个统一的框架称为广义OOD检测。在此框架下,这五个问题(即AD、ND、OSR、OOD检测和OD)可以被视为特殊情况或子主题。虽然其他子课题已被广泛调查,总结的 OOD 检测方法仍然是不够的,需要进一步探索。本文填补了这一空白,具体侧重于 OOD 检测的最新技术发展,分析公平的实验比较的经典方法在共同的基准。我们的调查最后强调了开放的挑战,并概述了未来研究的潜在途径。我们进一步对每个子主题进行文献综述,特别关注OOD检测任务。总而言之,我们对研究界有三个贡献:

    • 统一框架:我们第一次系统地回顾了AD、ND、OSR、OOD检测 和 OD 五个密切相关的主题,并提出了广义OOD检测的统一框架。在这一框架下,可以系统地比较和分析五个子课题的异同。我们希望我们的统一有助于社区更好地理解这些问题,并在文献中正确定位他们的研究。

    • OOD 检测综合调查:注意到近年来存在对AD、ND、OSR和OD方法的综合调查,该调查提供了 OOD 检测方法的综合概述,从而补充了现有的调查。通过与其他子课题的方法学相结合,并简要回顾,以及分享在标准基准上进行公平比较的见解,我们希望为读者提供对每个问题的发展及其相互联系的更全面的理解,特别是对于OOD检测。

    • 未来的研究方向:我们提请读者注意当前广义OOD检测领域中仍然存在的一些问题或局限性。最后,我们讨论了未来研究面临的挑战和机遇。

Generalized OOD Detection

  • 框架概述:在本节中,我们介绍一个统一的框架,称为广义OOD检测,它封装了五个相关的子主题:异常检测(AD),新奇检测(ND),开集识别(OSR),非分布(OOD)检测,和离群点检测(OD)。这些子主题在某种意义上可以是相似的,它们都定义了某种内分布,共同的目标是在开放世界假设下检测外分布样本。然而,在 ID 和 OOD 数据的具体定义和属性方面,子主题之间存在微妙的差异,这常常被研究界所忽视。为此,我们在相应的小节(从第2.1节到第2.5节)中为每个子主题提供了清晰的介绍和描述。每个小节都详细说明了动机、背景、正式定义以及在统一框架中的相对位置。还介绍了应用程序和基准,并提供了便于理解的具体示例。图4示出了每个子主题的设置。最后,我们通过引入邻域主题来阐明通用ood检测框架的范围,从而结束本节。(第2.6节)。

  • Preliminary:

    • 分布转移,在我们的框架中,我们认识到分布转移的复杂性和相互关联性,这是理解各种 OOD 场景的核心。分布转移可以大致分为协变量转移和语义(标签)转移,但澄清它们的相互依赖关系是很重要的。首先,我们定义输入空间为X(感官观察),标签空间为Y(语义类别)。数据分布由空间X ×Y上的联合分布P(X,Y)表示。分布偏移可能发生在边际分布P(X)中,也可能同时发生在P(Y)和P(X)中。请注意,P(Y)的偏移自然会触发P(X)的偏移。

    • 协变量移位:当边际分布P(X)发生变化,影响输入空间,而标签空间Y保持不变时,就会发生这种情况。P(X)上协变量分布移位的例子包括对立例子,域移位和 风格变化。

    • 语义转移:这涉及到P(Y)和间接P(X)的变化。标签空间P(Y)的移动意味着新类别的引入或现有类别的改变。这种变化自然会影响输入空间P(X ),因为现在被观察或收集的数据的性质不同了。

    • 备注:考虑到P(X)和P(Y)之间的相互依赖性,区分不同类型分布变化背后的意图是至关重要的。我们将协变量移位定义为在输入空间(P(X))中有意改变而没有对标签空间(P(Y))进行任何有意改变的场景。另一方面,语义转移特别旨在修改语义内容,直接影响标签空间(P(Y))并因此影响输入空间(P(X))

  • 重要的是,我们注意到协变量移位更常用于评估模型的泛化和鲁棒性能,其中标签空间Y在测试期间保持不变。另一方面,语义分布变化的检测(例如,由于新类别的出现)是在该框架中考虑的许多检测任务的焦点,其中标签空间Y在ID和OOD数据之间可以是不同的,因此该模型不应该做出任何预测

  • 考虑到分布转移的概念,读者可以大致了解图1中各子主题/任务之间的区别和联系。请注意,不同的子任务可以很容易地用以下四个二分法来识别:1)协变量/语义转移二分法;2)单/多类二分法;3) ID分类需要/不需要二分法;4)归纳/直推二分法。接下来,我们继续阐述每个子主题。

    • 在这里插入图片描述

    • 图1:广义OOD检测框架的分类,以分类任务为例。任务分类法有四个依据:1)分布移位检测:任务侧重于检测协变量移位或语义移位;2) ID数据类型:ID数据包含单个类或多个类;3) 任务是否需要ID分类;4) 直推式学习任务需要所有的观察;归纳任务遵循训练-测试方案。请注意,ND通常可以与AD互换,但ND更关注语义异常。对于分类任务,OOD检测通常可与OSR互换。

Anomaly Detection

  • 背景:“异常”的概念是与预先定义的“正常”相对立的。“正常”的概念应该是明确的,并反映真正的任务。例如,为了创建 “not-hotdog detector”,正常的概念应该被清楚地定义为热狗类,即,OOD 类别,以便违反该定义的对象被识别为异常,其包括牛排、米饭和像猫和狗这样的非 OOD 对象。理想情况下,“热狗” 将被认为是一个同质的概念,不管法国或美国热狗的子类

  • 当前的异常检测设置通常将感兴趣的环境限制在某些特定场景。例如,“非热狗检测器” 只关注真实图像,假设不存在来自其他领域的图像,例如草图。另一个现实的例子是工业缺陷检测,它只基于一套特定产品的装配线。换句话说,“开放世界”假设通常并不完全“开放”。尽管如此,“非热狗”或“缺陷”可以形成一个巨大的未知空间,打破“封闭世界”的假设。综上所述,异常检测的关键是明确定义正常(通常没有子类),在一些特定场景下检测出所有可能的异常样本。

  • 定义:异常检测(AD) 旨在检测测试过程中偏离预定义正常状态的任何异常样本。这种偏离可能是由于协变量转移或语义转移引起的,这导致了两个子任务: sensory AD 和 semantic AD。sensory AD 在假设常态来自相同的协变量分布的情况下,检测具有协变量偏移的测试样本。sensory AD 环境中不会发生语义变化。另一方面, semantic AD 检测具有标签移位的测试样本,假设范式来自相同的语义分布(类别),即范式应该只属于一个类。

  • 从形式上看,在 semantic AD 中,常态来自非分布P(X),而在测试时遇到的异常来自非分布p′(x),其中 p ( x ) ≠ p ′ ( x ) p(x) \neq p′(x) p(x)=p(x) —仅发生协变量移位。感官 AD 的目标是检测来自P′(X)的样本。这种设置不会发生语义转移,即P(Y)= P′(Y)。相反,对于语义AD,仅发生语义转移(即, p ( y ) ≠ p ′ ( y ) p(y)\neq p′(y) p(y)=p(y) ),并且目标是检测属于新类别的样本。

  • 备注:感觉/语义二分法我们对AD子任务定义的感觉/语义二分法来自于[Detecting semantic anomalies]中介绍的低级感觉异常和高级语义异常,以反映深度学习的兴起。请注意,尽管大多数感官和语义 AD 方法由于P(X)上的共同转变而相互包容,但一些方法专门针对其中一个子任务。最近的研究团体也倾向于细分异常类型,以开发有针对性的方法,以便从业者可以为他们自己的实际问题选择最佳解决方案。

  • 在广义的OOD检测框架下,“正常”的定义与“indistribution” 的概念紧密相连,“异常”对应于“out-of-distribution”。重要的是,AD将ID样本视为一个整体,这意味着无论ID数据中的类别(或统计模态)数量有多少,AD都不需要区分ID样本。该特征是AD和其他子主题(例如OSR和OOD检测)之间的重要区别。

  • 应用程序和基准: Sensory AD 只关注语义相同或相似的对象,并确定其表面的观察差异。具有感官差异的样品被认为是感官异常。示例应用包括对抗性辩护,生物特征和艺术品的伪造识别,图像取证,工业检查等。最受欢迎的 academic AD 基准是工业检测的MVTec-AD 。

  • 与 sensory AD 不同,semantic AD 只关注语义的转移。现实世界应用的一个例子是犯罪监控。针对特定类别的主动图像爬虫也需要语义 AD 方法来保证采集到的图像的纯度。 academic benchmarks 的一个例子是在训练期间递归地使用来自MNIST的一个类作为ID,并在测试期间要求模型将它与其余的9个类区分开来

  • 评估:在AD基准测试中,测试样本被标注为正常或异常。部署的异常检测器将为测试样本生成一个置信度得分,表明模型将样本视为正态样本的置信度。低于预定义置信阈值的样本被视为异常。通过将异常视为正,将真正的正常视为负,不同的阈值将产生一系列真正的正率(TPR)和假正率(FPR),由此我们可以计算出受试者工作特征曲线下的面积(AUROC) 。类似地,精确度和召回值可用于计算F值和精确度-召回曲线下的面积(AUPR) 。请注意,AUPR值可以有两种变体:一种将“正常”视为阳性类别,另一种将“异常”视为阳性类别。对于AUROC和AUPR,较高的值表示检测性能较好

  • 备注:异常的替代分类法一些先前的文献认为异常类型有三种:点异常、条件异常或上下文异常,以及组异常或集体异常。在本次调查中,我们主要关注点异常检测,因为它在实际应用中很受欢迎,并且它足以阐明子任务之间的相似性和差异。其他两种异常的细节,即在时序任务中经常出现的上下文异常,以及在数据挖掘领域中常见的集体异常,不包括在本调查中。我们推荐读者阅读最近的 AD 调查论文 [A unifying review of deep and shallow anomaly detection] 以深入讨论它们。

  • 备注:基于监督的分类法我们使用感觉/语义二分法在任务级别细分AD。从方法论的角度来看,一些文献将AD技术分为无监督和(半)监督设置。注意,这两个分类法是正交的,因为它们分别关注任务和方法。

Novelty Detection

  • 背景: “novel” 这个词一般指未知的、新的、有趣的东西。虽然在社区中,新颖性检测(ND)通常可以与AD互换,但严格来说,它们之间的细微差异值得注意。就动机而言,新颖性检测通常不会像AD那样认为“新颖”的测试样本是错误的、欺诈的或恶意的,而是将它们视为学习资源,以积极的学习态度供未来使用。事实上,新颖性检测也被称为“新颖类别检测” ,表明它主要侧重于检测语义转移

  • 定义新颖性检测旨在检测不属于任何训练类别的任何测试样本。检测到的新样本通常是为将来的构建过程准备的,例如更专业的分析,或者模型本身的增量学习。基于训练类的数量,ND包含两种不同的设置:1)单类新奇检测(one class ND):训练集中只存在一个类;2)多类新奇检测(multi-class ND):训练集中存在多个类。值得注意的是,尽管有许多ID类,但多类ND的目标只是区分小说样本和ID。一类和多类 nd 都被公式化为二元分类问题。

  • 框架中的位置:在广义的OOD检测框架下,ND处理OOD样本有语义偏移的设置,即使可能也不需要在ID集中进行分类。所以 ND 和语义 AD 的问题定义是一样的。应用和基准:现实世界的nd应用包括视频监控 ,行星探索和增量学习。对于一类ND,示例学术基准可以与语义AD的基准相同,语义AD将来自MNIST的一个类视为ID,而将其余的视为新颖类别。多类别ND的相应MNIST基准可以在训练期间使用前6个类别,并且在剩余的4个类别上测试作为OOD。评估:对ND 的评估与 AD 相同,AD基于AUROC、AUPR或F分数(详见第2.1节)。

  • 备注:一类/多类二分法尽管ND模型不要求ID分类,即使具有多类注释,但是多类ND上的方法可以不同于一类ND,因为多类ND可以利用多类分类器,而一类ND不能。还要注意,语义 AD 可以进一步分为一类语义 AD 和匹配 ND 的多类语义 AD,因为语义 AD 等同于ND。

  • 备注:AD 和 ND 之间的细微差别除了对语义的特殊兴趣,一些文献[54,55]也指出ND应该是完全无监督的(训练中没有新数据),而AD可能有一些异常的训练样本。需要注意的是,AD和ND都不需要对ID数据进行分类。这是OSR和OOD检测之间的一个关键区别,我们将在随后的章节中讨论。

Open Set Recognition

  • 背景:技术在封闭世界环境中训练的机器学习模型可能会错误地将来自未知类别的测试样本分类为具有高置信度的已知类别之一。一些文献将模型的这种臭名昭著的过度自信行为称为“傲慢”,或“无知恐惧症”。开集识别(OSR)被提出来解决这个问题,用他们自己的术语“已知的已知类”来表示训练中存在的类别,用“未知的未知类”来表示不属于任何训练类别的测试类别。其他一些术语,如开放类别检测和开放集合学习,只是OSR的不同表达

  • 定义:开集识别要求多类分类器同时:1)准确地分类来自“已知已知类”的测试样本,和2)检测来自“未知未知类”的测试样本。框架中的位置:OSR与我们的广义OOD检测框架非常一致,其中“已知的已知类”和“未知的未知类”分别对应于ID和OOD。形式上,OSR处理的是测试过程中OOD样本发生语义转移的情况,即 p ( y ) ≠ p ′ ( y ) p(y)\neq p′(y) p(y)=p(y) 。OSR的目标在很大程度上与多类ND的目标相同,唯一的区别是OSR额外要求对P(Y)中的ID样本进行准确分类。

  • 应用和基准:OSR一般支持真实世界图像分类器的稳健部署,可以拒绝开放世界中的未知样本 。MNIST上的示例学术基准可以等同于多类ND,其将前6类视为ID,将剩余的4类视为OOD。此外,OSR还要求在6个ID类上有一个好的分类器。

  • 评估:与 AD 和 ND 类似,OSR 的指标包括F分数、AUROC 和 AUPR。除此之外,分类性能也通过标准ID准确度来评估。虽然上述指标独立评估新颖性检测和ID分类能力,但一些工作提出了一些联合评估的评估标准,如CCR@FPRx ,当达到某个等于x(如101)的FPR时,该标准计算分类召回率。

Out-of-Distribution Detection

  • 背景:观察到深度学习模型通常不合适,但事实上在图像分类任务和文本分类中对来自不同语义分布的样本进行分类时过于自信,分布外检测领域出现了,要求模型拒绝语义上不同于训练分布的输入,因此不应由模型预测。

  • 定义:分布外检测,或称OOD检测,旨在检测从不同于训练分布的分布中抽取的测试样本,分布的定义将根据目标中的应用明确定义。对于大多数机器学习任务,分布应该指“标签分布”,这意味着OOD样本不应该与训练数据有重叠的标签。在形式上,在OOD检测中,测试样本来自一个分布,其语义从ID转移,即 p ( y ) ≠ p ′ ( y ) p(y)\neq p′(y) p(y)=p(y) 。注意,训练集通常包含多个类,并且OOD检测不应该损害ID分类能力。

  • 框架分布外检测中的位置可以规范到常见机器学习任务中的OSR,如多类分类-保持对来自 ID 类空间 Y 的测试样本的分类性能,并拒绝语义在 Y 支持之外的OOD 测试样本。此外,多类设置和 ID 分类的要求将该任务与 AD 和 ND 区分开来。

  • 应用和基准:OOD检测的应用通常属于安全关键的情况,例如自动驾驶。一个示例学术基准是在训练期间使用CIFAR-10作为ID,并将CIFAR图像与其他数据集(如SVHN等)区分开来。研究人员应该注意,在构建基准时,OOD 数据集不应该有与ID数据集重叠的标签。

  • 评估:除了F-scores、AUROC和AUPR,另一个常用的指标是FPR@TPRx,当TPR为x(例如,0.95)时,它测量FPR。一些作品还使用了另一种度量标准,TNR@TPRx,相当于1-FPR@TPRx。OOD检测还涉及ID分类的性能。

  • 备注:OSR和OOD探测OSR和OOD探测任务之间的差别有三重。

    • 1)不同的基准设置:OSR基准通常将一个多类分类数据集按类拆分为ID和OOD两部分,而OOD检测以一个数据集为ID,在保证ID/OOD数据集之间类别不重叠的情况下,寻找其他几个数据集为OOD。然而,尽管两个子任务的基准传统不同,但它们实际上处理的是相同的语义转换检测问题

    • 2)在OSR没有额外数据:由于理论上的开放风险范围担保的要求,OSR通过设计不鼓励在 训练 期间使用额外数据。这一限制排除了更注重有效性能改进(如离群值暴露)但可能违反OSR约束的方法。

    • 3)OOD检测的广泛性:与OSR相比,OOD检测包含更宽范围的学习任务(例如,多标签分类),更宽的解决方案空间(将在第3节中讨论)。

  • 备注:主流OOD检测侧重于语义,而当前社区中的大多数工作将关键字“超出分布”解释为“超出标签/语义分布”,一些OOD检测工作也考虑检测协变量移位,这些工作声称协变量移位通常会导致模型性能的显著下降,因此需要被识别和拒绝。然而,尽管在下一段将要讨论的一些特定任务(通常是由于高风险或隐私原因)中检测协变量移位是合理的,但关于这个主题的研究仍然是一项有争议的任务。第2.6节和第6.2节)。检测语义转移已经成为面向对象的检测任务的主流

  • 备注:To Generalize, or To Detect? 我们从推广的角度提供了另一个定义:分布外检测,或OOD检测,旨在检测模型不能或不想推广的测试样本。在大多数机器学习任务中,例如图像分类,模型被期望将其预测能力推广到具有协变量偏移的样本,并且它们仅在语义偏移发生时无法推广。然而,对于模型被设计为不可转移到其他领域的应用,例如像游戏 AI 的许多深度强化学习任务,关键术语“分布”应该指“数据/输入分布”,使得模型应该拒绝决定与训练环境不同的环境,即 p ( x ) ≠ p ′ ( x ) p(x)\neq p′(x) p(x)=p(x)。类似的应用是那些高风险的任务,例如医学图像分类或隐私敏感场景,在这些场景中,模型被期望是非常保守的,并且只对完全来自训练分布的样本进行预测,拒绝任何偏离它的样本。最近的研究也强调了一个模型特定的观点:一个稳健的模型应该推广到有协变量转移的例子;弱模型应该拒绝它们

  • 最终,当一项 OOD 检测任务成功地平衡了“检测”和“概括”两个方面时,考虑到诸如任务的意义和固有挑战等因素,它就被认为是有效的。尽管如此,检测语义变化仍然是 OOD 检测任务的主要焦点,也是本次调查的核心。

Outlier Detection

  • 背景:根据维基百科的定义,离群值是指与其他观察值显著不同的数据点。回想一下,AD、ND、OSR和OOD中的问题设置检测与训练数据分布不同的看不见的测试样本。相比之下,异常值检测直接处理所有观察值,旨在从受污染的数据集中选择异常值 。由于异常值检测不遵循训练测试程序,但可以访问所有观察值,因此解决该问题的方法通常是直推式的,而不是归纳式的。定义:离群点检测旨在检测由于协变量或语义转移而与给定观察集中的其他样本明显不同的样本

  • 框架中的位置:与所有先前的子任务不同,这些子任务的内分布是在训练期间定义的,离群点检测的“内分布”指的是大多数观察值。异常值可能是由于P(Y)上的语义偏移或P(X)上的协变量偏移而存在的。应用和基准虽然主要应用于数据挖掘任务 ,离群点检测也用于现实世界的计算机视觉应用,如视频监控和数据集清洗。对于数据集清洗的应用,离群点检测通常用作主要任务的预处理步骤,例如从开集噪声标签学习、webly监督学习 和开集半监督学习 。为了在MNIST上构建离群点检测基准,应该选择一个类,使得属于该类的所有样本都被视为内联体。来自其他类的一小部分样本被引入作为要检测的异常值

  • 评估:除了F-scores、AUROC和AUPR,异常值检测器的评估也可以通过它支持的主要任务的性能来评估。例如,如果使用异常值检测器来净化带有噪声标签的数据集,则在净化的数据集上训练的分类器的性能可以指示异常值检测器的质量。

  • 备注:关于异常值检测的包含有趣的是,异常值检测任务可以被认为是广义OOD检测框架中的异常值,因为异常值检测器是在给定所有观察值的情况下操作的,而不是遵循训练-测试方案。此外,在最近的深度学习场所中,很少看到关于这一主题的出版物。然而,我们仍然在我们的框架中包括离群点检测,因为直观地说,离群点也属于一种类型的分布外,引入它可以帮助读者更熟悉各种术语(例如,OD,AD,ND,OOD),这些术语已经困惑了社区很长一段时间。

Related Topics

  • 除了我们的广义OOD检测框架(如图1所示)中描述的五个子主题之外,我们还将在下面简要讨论五个相关主题,这有助于澄清本次调查的范围。

    • 拒绝学习(LWR) LWR 可以追溯到早期工作的弃权,其中考虑了简单的模型家族,如支持向量机。首次揭示了神经网络在OOD数据中过度自信的现象。尽管方法不同,随后的工作发展的 OOD 检测和OSR共享与拒绝选项的分类的基本精神。

    • 领域适应/泛化领域适应(DA) 和领域泛化(DG) 也遵循“开放世界”假设。与一般的OOD检测设置不同,DA/DG期望在测试期间存在协变量偏移,而没有任何语义偏移,并要求分类器对同一组类进行准确预测。注意,OOD检测通常涉及检测语义转移,这是对DA/DG的补充。在协变量和语义转移都发生的情况下,模型应该能够检测语义转移,同时对协变量转移具有鲁棒性。关于DA/DG和OOD检测之间关系的更多讨论见第6.2节。DA和DG的区别在于,前者需要来自目标领域的额外但很少的训练样本,而后者不需要。

    • 新颖性发现:新颖性发现要求所有的观察值都像异常值检测一样提前给出。观察值以半监督的方式提供,目标是在未标记的集合中探索和发现新的类别和类。与孤立点稀疏的孤立点检测不同,新奇发现环境中的未标记集可能主要由未知类组成,甚至被未知类淹没。

    • Zero-shot Learning:Zero-shot Learning 有一个相似的目标,即发现新奇事物,但遵循训练-测试方案。测试集是在未知类的“开放世界”假设下,期望仅在已知类上训练的分类器在标签关系等额外信息的帮助下对未知测试样本执行分类。

    • 开放世界识别(Open-world Recognition):开放世界识别旨在建立一个终身学习机器,它可以主动检测新颖的图像,将其标记为新的类别,并进行持续学习。它可以被看作是新颖性检测(或开集识别)和增量学习的结合。更具体地说,开放世界识别扩展了OSR的概念,增加了随时间增量学习新类的能力。在开放世界场景中,系统不仅识别未知实例,还可以更新其模型,以将这些新类作为已知集合的一部分。这种方法更具动态性,更适合环境不是静态的真实世界应用,新的类别可以在初始训练阶段后出现。

    • 共形预测:共形预测(CP)是机器学习中一个强大的统计框架,主要用于为预测提供置信度。与众不同的是,它产生具有特定置信水平的预测区间,超越了单纯点估计的限制。在OOD检测的情况下,保形预测框架变得特别有洞察力:由保形预测方法产生的更宽的预测区间或更低的置信水平可以作为这种OOD数据的指标。虽然CP和OOD检测的交叉研究仍在兴起 ,但在该领域应用保形预测框架的潜力是巨大的,值得进一步探索。

Organization of Remaining Sections

  • 在本文中,我们在第3节集中讨论了OOD检测方法,对文献中提出的不同方法进行了全面概述。我们还在第4节中简要介绍了其他子任务的方法,包括AD、ND、OSR和OD,以使读者对OOD相关问题有更广泛的理解,并启发开发更有效的方法。对于每个子任务,我们将方法分为四组:1)基于分类的方法:主要依赖分类器的方法;2)基于密度的方法:通过对数据密度建模来检测OOD。3)基于距离的方法:使用距离度量(通常在特征空间中)来识别OODs。4)基于重建的方法:以重建技术为特征的方法。为了从经验的角度向读者提供进一步的见解,我们进行了彻底的分析,提供了代表性的 OOD 检测方法和其他子任务的方法之间的公平比较。此外,我们强调了当前广义OOD检测领域中存在的一些剩余问题和限制。最后,我们讨论了未来研究面临的挑战和机遇。值得注意的是,同时进行的调查提供了与面向对象相关的方法的详细解释,这极大地补充了我们的工作。

OOD Detection: Methodology

  • 在本节中,我们将介绍OOD检测的方法。首先,我们在3.1节探索基于分类的模型。这些模型主要利用模型的输出,例如softmax分数,来识别OOD实例。我们进一步研究了基于离群点暴露的方法,这些方法利用了外部数据源和其他类型的方法。后面一节是第3.2节中基于密度的方法。基于距离的方法将在3.3节中介绍。最后将包括一个简短的讨论。

    • 方法类别核心逻辑典型技术优点缺点适用场景
      分类基方法基于分类器输出(如 Softmax 分数),通过阈值拒绝低置信样本Max Softmax、ODIN(温度缩放)、能量分数简单高效,易集成到现有模型对 OOD 样本可能过自信(如 Softmax 误给高置信)实时分类任务(如手机图像分类)
      密度基方法建模 ID 数据分布,OOD 为低密度区域高斯混合模型、流模型(Normalizing Flows)、能量 - based 模型理论严谨,可量化概率计算复杂,高维数据建模难,可能误判高复杂度 OOD 为 ID小数据集、需概率解释场景(如医疗诊断)
      距离基方法计算样本与 ID 数据的特征距离(如马氏距离、余弦相似度)最近邻(KNN)、类中心距离、超球面嵌入直观易懂,不依赖分布假设依赖特征质量(需有效区分 ID 和 OOD 的特征)特征空间可分场景(如图像特征提取较好时)
      重建基方法用自编码器重建样本,OOD 重建误差大自动编码器(AE)、变分自编码器(VAE)、掩码图像建模利用图像重建能力,适合像素级差异检测重建误差可能无法捕捉语义差异(如类别未知但像素相似)图像生成 / 重建任务(如工业图像缺陷检测)

Classification-based Methods

  • 对OOD检测的研究起源于一个简单的基线,即使用最大softmax概率作为 ID-ness的指标得分。早期的OOD检测方法集中于基于神经网络的输出导出改进的OOD分数。

  • 实现一个分布内和分布外检测系统,如 ODIN、Energy Score 和类中心距离,需要实现 ODIN 的温度缩放和输入扰动,Energy Score 作为另一种置信度度量,以及类中心距离计算。决策融合部分,需要将三个检测的结果加权融合,通过阈值判断是 ID 还是 OOD。这里需要定义一个决策类,处理不同的分数,并输出最终结果。

    • import torch
      import torch.nn as nn
      from torchvision import models, transforms
      from torch.utils.data import Dataset, DataLoader
      import numpy as np
      from PIL import Image
      import time
      # 配置
      NUM_CLASSES = 4  # 分布内类别数
      FEATURE_DIM = 576  # MobileNetV3 Small输出特征维度
      TRAIN_EPOCHS = 5  
      BATCH_SIZE = 8  # CPU内存优化
      DEVICE = torch.device("cpu") 
      class IDClassifier(nn.Module):
          def __init__(self):
              super().__init__()
              # 加载预训练MobileNetV3 Small,冻结特征提取层
              self.backbone = models.mobilenet_v3_small(pretrained=True).features
              for param in self.backbone.parameters():
                  param.requires_grad = False
              # 开放最后两个stage和分类头
              for param in self.backbone[-4:].parameters():
                  param.requires_grad = True
              self.global_pool = nn.AdaptiveAvgPool2d((1, 1))
              self.classifier = nn.Sequential(
                  nn.Dropout(0.2),
                  nn.Linear(FEATURE_DIM, NUM_CLASSES)
              )
          def forward(self, x):
              features = self.backbone(x)  # [B, 576, 7, 7]
              global_feature = self.global_pool(features).squeeze(3).squeeze(2)  # [B, 576]
              logits = self.classifier(global_feature)  # [B, NUM_CLASSES]
              prob = nn.functional.softmax(logits, dim=1)
              return logits, prob, global_feature
      class OODDetector:
          def __init__(self, model):
              self.model = model.to(DEVICE)
              self.model.eval()
          def odin_detect(self, img, temperature=100, epsilon=1e-4):
              """ODIN算法:温度缩放+输入扰动"""
              img = img.to(DEVICE).detach().requires_grad_(True)
              logits, _, _ = self.model(img)
              # 温度缩放
              scaled_logits = logits / temperature
              prob = nn.functional.softmax(scaled_logits, dim=1)
              max_prob, _ = torch.max(prob, dim=1)
              # 生成对抗扰动
              loss = -torch.log(max_prob)
              self.model.zero_grad()
              loss.backward()
              grad = img.grad.data
              sign_grad = grad.sign()
              perturbed_img = img + epsilon * sign_grad
              perturbed_img = torch.clamp(perturbed_img, 0, 1)
              # 二次推理
              with torch.no_grad():
                  perturbed_logits, perturbed_prob, _ = self.model(perturbed_img)
              final_prob = nn.functional.softmax(perturbed_logits / temperature, dim=1)
              return final_prob.max().item()  # 返回最大置信度
          def energy_score(self, logits, temperature=1.0):
              """Energy Score:更敏感的OOD度量"""
              return torch.log(torch.sum(torch.exp(logits / temperature), dim=1) + 1e-8).item()
          def class_center_distance(self, features, class_centers):
              """计算与最近类中心的余弦距离"""
              centers = torch.tensor(class_centers, dtype=torch.float32, device=DEVICE)
              norms = torch.norm(centers, dim=1, keepdim=True) + 1e-8
              dot_product = torch.matmul(features, centers.T)  # [B, NUM_CLASSES]
              cos_sim = dot_product / (torch.norm(features, dim=1, keepdim=True) * norms)
              return (1 - cos_sim.max(dim=1)[0]).item()  # 距离越大越可能是OOD
      class CustomDataset(Dataset):
          def __init__(self, data_dir, labels, transform=None):
              self.images = [f"{data_dir}/{i}.jpg" for i in range(len(labels))]
              self.labels = labels
              self.transform = transform
          def __getitem__(self, idx):
              img = Image.open(self.images[idx]).convert("RGB")
              return self.transform(img), self.labels[idx]
          def __len__(self):
              return len(self.labels)
      def train_model(model, train_loader):
          model.train()
          optimizer = torch.optim.AdamW(
              model.classifier.parameters(), 
              lr=1e-3, weight_decay=0.01
          )
          criterion = nn.CrossEntropyLoss()
          start_time = time.time()
          for epoch in range(TRAIN_EPOCHS):
              for images, labels in train_loader:
                  images = images.to(DEVICE)
                  labels = labels.to(DEVICE)
                  optimizer.zero_grad()
                  logits, _, _ = model(images)
                  loss = criterion(logits, labels)
                  loss.backward()
                  optimizer.step()
          print(f"训练完成,耗时{time.time()-start_time:.2f}秒")
          return model
      def compute_class_centers(model, dataset):
          """计算分布内类别特征中心"""
          model.eval()
          centers = np.zeros((NUM_CLASSES, FEATURE_DIM))
          class_counts = np.zeros(NUM_CLASSES)
          with torch.no_grad():
              for img, label in dataset:
                  img = img.unsqueeze(0).to(DEVICE)
                  _, _, feature = model(img)
                  feature = feature.cpu().numpy()[0]
                  centers[label] += feature
                  class_counts[label] += 1
          # 归一化类中心
          for c in range(NUM_CLASSES):
              centers[c] /= class_counts[c]
          return centers
      class DecisionSystem:
          def __init__(self, id_threshold=0.8, ood_threshold=0.5):
              self.id_threshold = id_threshold  # ID类最小置信度
              self.ood_threshold = ood_threshold  # 融合决策阈值
          def fuse_decision(self, odin_prob, energy_score, center_dist):
              """三部分加权融合(权重通过验证集优化)"""
              fused_score = 0.6*odin_prob - 0.3*energy_score - 0.1*center_dist
              if fused_score > self.ood_threshold and odin_prob > self.id_threshold:
                  return {
                      "decision": "IN-DISTRIBUTION",
                      "class": torch.argmax(model.classifier.out_features).item(),  # 示例占位,需实际推理
                      "confidence": odin_prob
                  }
              else:
                  return {
                      "decision": "OUT-OF-DISTRIBUTION",
                      "confidence": fused_score
                  }
      if __name__ == "__main__":
          # 数据增强配置(小样本增强)
          train_transform = transforms.Compose([
              transforms.Resize((224, 224)),
              transforms.RandomHorizontalFlip(),
              transforms.ColorJitter(brightness=0.2, contrast=0.2),
              transforms.ToTensor(),
              transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
          ])
          # 假设分布内数据:4类,每类5张,标签0-3
          train_labels = np.repeat(np.arange(4), 5)
          train_dataset = CustomDataset("path/to/train_data", train_labels, transform=train_transform)
          train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)
          # 分布外验证数据(示例用随机噪声)
          ood_image = torch.randn(1, 3, 224, 224)  # 模拟OOD样本
          
          model = IDClassifier().to(DEVICE)
          trained_model = train_model(model, train_loader)
          class_centers = compute_class_centers(trained_model, train_dataset)
          detector = OODDetector(trained_model)
      	decision_system = DecisionSystem()
          
          def inference(img):
              # 预处理
              img = transforms.ToTensor()(img).unsqueeze(0).to(DEVICE)
              # 模型输出
              with torch.no_grad():
                  logits, prob, feature = trained_model(img)
              # 三引擎检测
              odin_p = detector.odin_detect(img, temperature=150, epsilon=5e-5)
              energy_s = detector.energy_score(logits, temperature=2.0)
              center_d = detector.class_center_distance(feature, class_centers)
              # 决策融合
              return decision_system.fuse_decision(odin_p, energy_s, center_d)
          # 测试分布内样本
          id_sample = Image.open("path/to/id_sample.jpg").convert("RGB")
          print(inference(id_sample))  # 输出IN-DISTRIBUTION及类别
          # 测试分布外样本
          ood_sample = Image.open("path/to/ood_sample.jpg").convert("RGB")
          print(inference(ood_sample))  # 输出OUT-OF-DISTRIBUTION
      
Output-based Methods
  • a.事后检测:事后方法具有易于使用而无需修改训练过程和目标的优点。这一特性对于在现实生产环境中采用OOD检测方法非常重要,因为在现实生产环境中,再训练的开销可能非常高。早期工作ODIN 是一种事后方法,使用温度缩放和输入扰动来放大 ID/OOD 可分性。该方法的关键是,足够大的温度具有很强的平滑效果,可以将softmax得分转换回logit空间,从而有效区分ID和OOD。注意,这不同于置信度校准,置信度校准采用了更温和测试

    • 虽然校准只关注ID数据的真实正确性可能性,但ODIN分数旨在最大化ID和ood数据之间的差距,从预测置信度的角度来看,可能不再有意义。基于这些见解,最近的工作提出使用能量分数进行 OOD detection,这从可能性的角度得到了理论解释。具有较低能量的测试样品被认为是 ID,反之亦然。然后,联合能量评分 被提议用于执行多标记分类网络的OOD检测。SHE 最近的工作使用代表类别的存储模式来测量用于OOD检测的看不见的数据的差异,与经典的能量方法相比,这是无超参数的和计算有效的。诸如逐层Mahalanobis距离和Gram矩阵的技术被实现用于更好的隐藏特征质量,以执行密度估计。
    • 最近,OOD数据过度自信问题的一个根本原因被揭示出来,使用不匹配的BatchNorm统计数据——根据ID数据估计,但在测试中盲目应用于OOD数据——会触发异常高的单元激活和相应的模型输出。因此,ReAct 提出截断高激活,这建立了强大的事后检测性能,并进一步提升了现有评分函数的性能。类似地,NMD 使用来自BatchNorm层的激活手段用于ID/OOD差异。当ReAct考虑激活空间时,提出了一种称为DICE的基于权重稀疏化的OOD检测框架。DICE基于贡献的度量来排列权重,并选择性地使用最显著的权重来导出用于OOD检测的输出。通过剔除噪声信号,DICE可证明降低了OOD数据的输出方差,从而产生更清晰的输出分布和更强的ID数据可分性。同样,ASH 也以激活空间为目标,但采用了不同的策略。它基于top-K标准从较晚的层中移除输入的特征表示的重要部分(例如,90%),随后通过缩放或分配常数值来调整剩余的激活(例如,10%),从而产生令人惊讶的有效结果
  • b.基于训练的方法:在训练阶段,可以通过设计置信度估计分支【Learning confidence for out-of-distribution detection in neural networks】或类,集成省略策略,对抗性训练,更强的数据扩充,pretext training,更好的不确定性建模,输入水平操纵来发展置信度特别是,为了提高对协变量移位的敏感性,一些方法关注于神经网络中间层的隐藏表示。广义ODIN或G-ODIN 通过使用称为 DeConfC 的专门训练目标和选择超参数(如ID数据上的扰动幅度)扩展了ODIN 。请注意,我们没有将G-ODIN归类为事后方法,因为它需要模型再训练。最近的工作【Mitigating neural network overconfidence with logit normalization】表明,过度自信问题可以通过Logit归一化(LogitNorm)来缓解,Logit norm是一种简单的修复方法,通过在训练中对Logit实施恒定向量规范来修复常见的交叉熵损失。通过LogitNorm训练,神经网络可以在分布内和分布外数据之间产生高度可区分的置信度得分

  • 一些作品重新设计了标签空间,以实现良好的ood检测性能。虽然常用于对分类信息进行编码,但一次性编码忽略了标签之间的内在关系。比如狗和猫vs狗和车的距离统一就不合理。为此,一些工作试图使用标签空间中的信息来进行OOD检测。一些作品将大的语义空间安排成已知类别的层次分类法。在重新设计的标签架构下,自顶向下的分类策略 和 group softmax 训练被证明是有效的。另一组作品使用单词嵌入来自动构建标签空间。稀疏的独热标签被来自不同NLP模型的几个密集单词嵌入替换,形成用于稳健训练的多个回归头。在测试时,具有到来自不同头部的所有嵌入向量的最小距离的标签将被认为是预测。如果最小距离超过阈值,则样本将被分类为“新的”。最近的工作进一步从语言图像预训练模型中提取图像特征,以更好地检测新类别,其中图像编码空间还包含来自语言空间的丰富信息。

Methods with Outlier Exposure
  • a.真实异常值OOD检测方法的另一个分支在训练期间利用一组收集的OOD样本或“异常值”来帮助模型学习ID/OOD差异。从鼓励对给定OOD样本进行平坦/高熵预测 和抑制OOD特征幅度 的并行基线开始,后续工作MCD 使用具有两个分支的网络,对于OOD训练数据,分支之间的熵差异被放大。另一种直接暴露异常值的方法省去了一个额外的弃权(或拒绝类别),并考虑了该类别中所有给定的OOD样本。OECC 在后来的工作中注意到,置信度校准的额外正则化带来了运行经验的额外改善。为了有效地利用给定的、通常是大量的OOD样本,一些工作使用离群点挖掘和对立重采样方法来获得一个紧凑但有代表性的集合。在有意义的“近”OOD图像不可用的情况下,MixOE 建议在ID和“远”OOD图像之间进行插值,以获得有用的异常值,从而实现更好的正则化。

    • 其他工作考虑了更实际的情况,其中给定的OOD样本包含ID样本,因此使用伪标记 或 ID过滤方法以及最佳传输方案 来减少ID数据的干扰。一般来说,异常暴露的OOD检测可以达到更好的性能。然而,研究表明,性能可能在很大程度上受到给定和真实OOD样本之间的相关性的影响。为了解决这个问题,最近的工作提出了一个新的框架,能够有效地利用未标记的野外数据进行 OOD 检测。未标记的野生数据经常可用,因为每当在现实世界系统中部署现有的分类器时,它基本上是免费产生的。该设置可视为在自然环境中训练 OOD 检测器,与离线收集的数据相比,它能更好地匹配真实的测试时间分布。
  • b.Outlier Data Generation 生成离群数据暴露方法对OOD训练数据的可用性强加了强有力的假设,这在实践中是不可行的。当没有OOD样本可用时,一些方法试图合成OOD样本以实现ID/OOD可分性。现有工作利用GANs生成OOD训练样本,并强制模型预测一致,在低密度区域生成边界样本,或者类似地,生成高置信度OOD样本,或者使用元学习更新样本生成。然而,在高维像素空间中合成图像可能难以优化。最近的工作 VOS 提出合成来自特征空间中低似然区域的虚拟离群值,这在给定较低维度的情况下更易处理。虽然VOS 是一种参数方法,将特征空间建模为类条件高斯分布,但NPOS 也生成离群ID数据,但采用的是非参数方法。注意到生成的OOD数据可能不正确或不相关,DOE 合成导致最坏判断的硬OOD数据,以最小-最大学习方案训练OOD检测器,ATOL 使用辅助任务来缓解错误的OOD生成。在对象检测中,提出使用时空未知提取从野外视频中合成未知对象。

Gradient-based Methods
  • 现有的OOD检测方法主要依赖于输出(第3.1节)或特征空间来获得OOD分数,而忽略了来自梯度空间的信息。ODIN 首先探索使用梯度信息进行OOD检测。特别地,ODIN提出通过添加从输入梯度获得的小扰动来使用输入预处理。ODIN扰动的目标是通过加强模型对预测标签的信任来增加任何给定输入的softmax分数。最终,发现扰动会在ID和OOD输入的softmax分数之间产生更大的差距,从而使它们更容易分离,并提高OOD检测的性能。虽然ODIN仅通过输入扰动隐式使用梯度,但最近的工作提出了GradNorm ,它从梯度空间显式导出得分函数。GradNorm采用梯度的向量范数,从softmax输出和均匀概率分布之间的KL散度反向传播。最近的一项研究表明,虽然基于梯度的方法是有效的,但它们的成功不一定取决于梯度,而是取决于学习到的特征嵌入和预测输出分布的大小。
Bayesian Models
  • 贝叶斯模型是一种统计模型,它采用贝叶斯规则来推断模型中的所有不确定性。最具代表性的方法是贝叶斯神经网络,它通过MCMC ,拉普拉斯方法 和变分推断 从模型的后验分布中提取样本,形成模型预测的认知不确定性。然而,它们明显的缺点是预测不准确和计算成本高,这阻碍了它们在实践中的广泛采用。最近的工作尝试了几种不太原则性的近似方法,包括 MC-dropout 和 deep ensembles ,以便更快、更好地估计不确定性。这些方法对OOD不确定性估计的竞争力较弱。进一步的探索采用自然梯度变分推断,并在保留贝叶斯原则的好处的同时,实现实用和负担得起的现代深度学习训练。狄利克雷先验网络(DPN)也用于OOD检测,对三种不同的不确定性来源进行不确定性建模:模型不确定性、数据不确定性和分布不确定性,并形成一系列工作。最近,贝叶斯假设检验已被用于制定 OOD 检测,上加权方法和Hessian近似的可扩展性。
OOD Detection for Foundation Models
  • 基础模型,特别是大规模视觉语言模型,已经在各种下游任务中表现出优异的性能。他们的成功在很大程度上归功于大规模数据集上的大量预训练。几项工作 揭示了经过良好预处理的模型可以显著增强OOD检测,特别是在具有挑战性的场景中。然而,使这些模型适应(调整)训练数据中具有特定语义(标签)空间的下游任务仍然是一个挑战,因为简单的方法如线性探测、即时调整 和适配器式微调方法 在ood检测上没有良好的结果。为了推进这个问题,一个彻底的调查检查如何微调视觉语言模型执行。此外,最近的研究[Can pre-trained networks detect familiar out-of-distribution data?]强调了大规模预训练数据的影响,并对预训练策略对 OOD 检测性能的影响进行了系统研究。在技术方面,LoCoOp 将面向对象的正则化引入到被识别为面向对象的CLIP局部特征的子集,增强即时学习以更好地区分ID和面向对象,LSA 使用双向即时定制机制来增强图像-文本对齐。

  • CLIP 等模型强大的零样本学习能力也为零样本OOD检测开辟了道路。该新设置旨在对已知类别样本进行分类,并检测不属于任何已知类别的样本,其中已知类别仅通过文本描述或类别名称来表示,从而消除了对这些类别进行显式训练的需要。针对这一点,ZOC 基于CLIP的视觉编码器训练了一个解码器,以创建用于OOD检测的候选标签。虽然ZOC是计算密集型和数据要求高的,MCM 选择 softmax 缩放来将视觉特征与用于OOD检测的文本概念对齐。最近的进展,CLIPN ,创新性地将“否”逻辑集成到 OOD 检测中。利用新的提示和文本编码器,以及新的相对损失函数,CLIPN有效地解决了识别难以区分的OOD样本的挑战。这一发展标志着在复杂情况下提高 OOD 检测精度的重大进步。

Density-based Methods

  • OOD检测中基于密度的方法使用一些概率模型显式地对分布进行建模,并将低密度区域中的测试数据标记为 OOD。虽然 OOD 检测可能与 AD 不同,因为在内分布中存在多个类别,但第4.2节中用于AD的密度估计方法可以通过将ID数据统一为一个整体而直接适用于OOD检测。当ID包含多个类别时,类别条件高斯分布可以显式地对入分布进行建模,以便可以基于其可能性来识别OOD样本。基于流量的方法也可用于概率建模。虽然直接估计可能性似乎是一种自然的方法,但一些工作发现,概率模型有时会为ood样本分配更高的可能性。一些工作试图使用似然比来解决这些问题。发现似然性表现出对输入复杂性的强烈偏向,并提出了一种基于似然率的方法来补偿输入复杂性的影响。最近的方法转向新的分数,如 likelihood regret 或多个密度模型的集合。为了直接对语义空间的密度建模,SEM分数与低级别和高级别空间中的密度估计的简单组合一起使用。总的来说,生成模型在训练和优化方面具有极大的挑战性,其性能往往落后于基于分类的方法(第3.1节)。

Distance-based Methods

  • 基于距离的方法的基本思想是,测试OOD样本应该相对远离内分布类的质心或原型。使用到所有类质心的最小 Mahalanobis 距离进行检测。后续工作将图像分为前景和背景,然后计算两个空间之间的Mahalanobis距离比。与参数方法相比,最近的工作[Out-ofdistribution detection with deep nearest neighbors]显示了非参数最近邻距离用于OOD检测的巨大前景。与Mahalanobis不同,非参数方法不强加关于底层特征空间的任何分布假设,因此提供了更强的简单性、灵活性和通用性。

  • 对于距离函数,一些工作使用测试样本特征和类别特征之间的余弦相似性来确定OOD样本。训练特征的第一奇异向量所跨越的一维子空间被示出更适合于基于余弦相似性的检测。此外,其他工作利用输入的嵌入和类质心之间的径向基函数核、欧几里德距离和测地线距离来平衡距离。除了计算样本和类质心之间的距离,主空间的正交补空间中的特征范数在OOD检测中是有效的。最近的工作CIDER 探索了超球面空间中嵌入的可用性,其中可以鼓励类间分散和类内紧密。

Reconstruction-based Methods

  • 基于重建的方法的核心思想是基于ID数据训练的编码器-解码器框架通常为ID和OOD样本产生不同的结果。模型性能的差异可以用作检测异常的指标。例如,仅通过 ID 数据训练的重建模型不能很好地恢复OOD数据,因此可以识别OOD。虽然基于像素级比较的重建模型因其昂贵的训练成本而似乎不是 OOD 检测中的流行解决方案,但利用隐藏特征进行重建被证明是一种有前途的替代方案。最近的工作 MoodCat 不是重建整个图像,而是屏蔽输入图像的随机部分,并使用基于分类的重建结果的质量来识别OOD样本。READ 通过将原始像素的重构误差转换到分类器的潜在空间来组合来自分类器和自动编码器的不一致性。MOOD 表明,与对比训练和经典分类器训练相比,用于预训练的掩蔽图像建模有利于OOD检测任务

Theoretical Analysis

  • 关于面向对象检测的早期理论研究 深入研究了面向对象环境中深度生成模型(dgm)的局限性。这项工作揭示了一个关键的缺陷,即dgm经常分配给OOD数据比训练数据更大的概率,将这个问题主要归因于模型的错误估计,而不是典型的集合假设。这个假设假定相关的外分布可能位于数据分布的高相似性区域。该研究的结论是,任何广义的OOD任务必须限制被认为是分布外的分布集,因为没有任何限制,任务是不可能的。后来的工作【Provable guarantees for understanding out-of-distribution detectio】发展了一个全面的分析框架,旨在加强神经网络中 OOD 检测方法的理论理解和实际性能,从而推进了该领域的发展。他们的创新方法最终形成了一种新的 OOD 检测方法,在理论鲁棒性和经验性能方面都超过了现有技术。

  • 另一系列研究集中在开集学习(OSL)。该领域的开创性工作【Toward open set recognition】将识别未知类别样本的开放空间风险概念化。以下研究将极值理论应用于OSL 。虽然近似正确(PAC)理论可能适用于OSR ,但他们的方法要求在训练过程中使用测试样本。因此,进行了泛化误差界的调查,并证明了在某些假设下低误差OSL算法的存在。尽管如此,根据PAC理论,后来的一项研究为各种情况下的OOD检测的可学性建立了必要和充分的条件,包括ID和OOD数据重叠和不重叠的情况。他们的工作还为现有的OOD检测算法提供了理论支持,并表明在某些实际条件下OOD检测是可能的。

  • 尽管有这些理论上的进步,该领域仍然热切期待进一步的研究,解决 OOD 检测中的泛化、这些模型的可解释性、特定于 OOD 检测的深度学习理论的集成以及与该领域相关的基础模型理论的探索等问题。

Discussion

  • OOD 检测领域自出现以来发展迅速,解决方案空间很大。在多类设置中,问题可以是典型的OSR(4.1节)——在类空间Y内从ID准确地分类测试样本,并且拒绝语义在 Y 的支持之外的测试样本区别往往在于评估协议。OSR将数据集分成两半:一组作为ID,另一组作为OOD。相比之下,OOD通过考虑来自不同数据集或领域的测试样本,允许更通用和灵活的评估。此外,OOD检测包含更广泛的学习任务(例如,多标签分类,对象检测)和解决方案空间。除了方法开发,理论理解也受到了社区的关注,提供了可证明的保证和经验分析,以了解 OOD 检测性能如何根据数据分布变化。

Methodologies from Other Sub-tasks

  • 在本节中,我们简要介绍了广义OOD检测框架下的子任务的方法,包括AD、ND、OSR和OD,希望其他子任务的方法可以为OOD检测社区带来更多的想法。

  • 在这里插入图片描述

  • 图2具有视觉任务的广义OOD检测框架下的子任务图示。测试图像上的标签指的是模型的预期预测。(a)在感觉异常检测中,具有协变偏移的测试图像将被视为OOD。在这种情况下,语义不会发生变化。(b)在一类新颖性检测中,正常/ID图像属于一类。具有语义偏移的测试图像将被认为是OOD。©在多类别新颖性检测中,ID图像属于多个类别。具有语义偏移的测试图像将被认为是OOD。注意,( b)和©组成了新颖性检测,这与语义异常检测的主题相同。(d)开集识别在检测任务上与多类新颖性检测相同,唯一的区别是开集识别还需要ID分类。非分布检测解决了与开集识别相同的问题。它的标准目标是在不损失ID分类准确性的情况下检测具有语义变化的测试样本。然而,OOD检测包含了更广泛的学习任务和解决方案空间。(e)异常值检测不遵循训练测试方案。提供了所有观察结果。通过将多数分布定义为ID,它适合于通用的OOD检测框架。离群值可以有任何偏离多数的分布。

Open Set Recognition

  • OSR的概念最早是在中提出的,它表明了 1-class SVM 和 binary SVM 对于解决OSR问题的有效性。特别是,[Toward open set recognition]提出了 1-vs-Set SVM,通过解决一个双平面优化问题来管理开集风险,而不是二元线性分类器的经典半空间。该论文强调,除了限制ID风险之外,开集空间也应该被限制。

  • 基于分类的方法早期的工作集中于使用 紧凑消减概率(CAP) 和 极值理论(EVT) 的逻辑再分配。特别是经典的概率模型缺乏对开集空间的考虑。CAP明确地模拟了 从 ID 点到 OOD 点的类成员减少的概率,而EVT集中于模拟具有极端高/低值的尾部分布。在深度学习的背景下,OpenMax 首先为神经网络实现了EVT。OpenMax 将 softmax 图层替换为 OpenMax 图层,后者使用每个类别的EVT概率模型(如威布尔分布)来校准逻辑值。

  • 为了绕过 open-set 的风险,有些工程在没有EVT的情况下取得了良好的效果。例如,一些工作使用成员损失来鼓励已知类的高激活,并使用大规模外部数据集来学习全局负过滤器,这可以减少新图像的激活。除了明确地强制已知/未知类别之间的差异,其他方法通过变换分类的辅助任务提取更强的特征,或者输入图像及其潜在特征之间的互信息最大化等。

  • 图像生成技术已被用于从已知类别合成未知样本,这有助于区分已知样本与未知样本。虽然这些方法在诸如手写字符的简单图像上是有前途的,但是由于在高维空间中生成高质量图像的困难,它们不能扩展到复杂的自然图像数据集。另一种解决方案是在训练集中连续选择随机类别,并将其视为未知类别,这有助于分类器缩小边界,并获得识别未知类别的能力。此外,将训练数据分成典型和非典型子集,这也有助于学习紧凑的分类边界

  • 基于距离的方法基于距离的 OSR 方法要求原型是类条件的,这允许保持ID分类性能。基于类别的聚类和原型是基于从分类器提取的视觉特征来执行的。OOD样本可以通过计算w.r.t .聚类的距离来检测。一些方法还利用对比学习来学习已知类的更紧凑的聚类,这扩大了ID和OOD之间的距离。CROSR 通过连接来自分类器和重构模型的视觉嵌入来增强特征,用于扩展特征空间中的距离计算。除了使用来自分类器的特征之外,GMVAE 使用重构VAE提取特征,并且将训练集的嵌入建模为具有多个质心的高斯混合,用于随后的基于距离的操作。使用最近邻的分类器也适用于OSR问题。通过存储训练样本,最近邻距离比用于在测试中识别未知样本。

  • 基于重建的方法与第3.4节的动机相似,基于重建的方法期望 ID 与 OOD 样本。可以在重建图像的潜在特征空间或像素空间中捕获差异。通过对已知类别的图像进行稀疏编码,开集样本可以基于它们的密集表示来识别。稀疏集中指数 和 kernel null space 等技术用于稀疏编码。

  • 通过固定从标准多类训练中获得的视觉编码器以保持ID分类性能,C2AE 根据标签向量训练解码器,并使用EVT估计重建图像以区分未知类别。后续工作使用条件高斯分布,通过强制不同的潜在特征来逼近分类高斯模型,这使得能够对已知样本进行分类以及拒绝未知样本。其他方法生成反事实图像,这有助于模型更加关注语义。[Open-set adversarial defense]中还考虑了对抗性防御,以增强模型的稳健性。

  • 讨论:尽管基于密度的方法没有独立的章节,但这些方法可以发挥重要作用,并在一些基于分类的方法(如OpenMax )中被融合为关键步骤。视觉嵌入的密度估计可以有效地检测未知类别而不影响分类性能。混合模型还使用基于流量的密度估计器来检测未知样本。如2.4节中所介绍的,OSR和OOD检测的总体目标是一致的,即从训练数据中检测语义转移。因此,我们鼓励这两个领域的方法应该相互学习。例如,除了新颖的方法,OSR的研究还表明,一个好的分类器在密切集是至关重要的OSR性能,这也应该适用于 OOD 检测任务。

Anomaly Detection & Novelty Detection

  • 本节回顾了感官和语义AD和 one-class ND.的方法。请注意,多类 ND 在前面已经介绍过了。给定同质分布数据,方法包括基于密度、基于重建、基于距离和混合方法。我们也讨论理论著作。

  • 基于密度的方法基于密度的方法模拟正态数据(ID)分布,假设异常测试数据的可能性较低,而正态数据的可能性较高。技术包括经典密度估计、深度生成模型密度估计、基于能量的模型和基于频率的方法。

  • 参数密度估计假设预定义的分布。方法包括多元高斯分布,混合高斯分布 和 泊松分布。非参数密度估计通过直方图 和核密度估计(KDE) 处理更复杂的情况。神经网络生成高质量的特征来增强经典的密度估计。技术包括基于自动编码器(AE) 和变分自动编码器(VAE) 的模型、生成对抗网络(GANs) 、基于流的模型 和表示增强策略。EBM使用标量能量分数来表示概率密度,并为AD提供解决方案。训练EBM在计算上可能是昂贵的,但是分数匹配和随机梯度朗之万动力学实现了有效的训练。AD的频域分析包括CNN核平滑、面向频谱的数据扩充 和 相位频谱定位等方法。这些主要集中在感官 AD。

  • 基于重构的方法这些AD方法利用了特征空间中正常和异常数据的模型性能差异或重构误差。稀疏重建假设正常样本可以使用有限的一组基函数精确重建,而异常具有较大的重建成本和密集表示。技术包括基于L1范数的内核PCA 和低秩嵌入式网络。重构误差方法假设基于正常数据训练的模型对正常测试样本的重构优于异常测试样本。深度模型包括AEs 、VAEs 、GANs 和U-Net 。

  • 基于 AE/VAE 的模型将重建误差与 AE/VAE 模型 相结合,并使用如通过记忆的正态性重建、适应模型架构 和部分/条件重建 的策略。在半监督 AD 中,CoRA 训练了两个关于内点和外点的AEs,使用重构误差进行异常检测。使用 GANs 的重构误差方法利用鉴别器来计算异常检测的重构误差。去噪GANs 、类条件GANs 和集成 等变体进一步提高了性能。基于梯度的方法观察重建任务中正常和异常之间的训练梯度的不同模式,使用基于梯度的表示来表征异常

  • 基于距离的方法这些方法通过计算样本和原型之间的距离来检测异常,需要存储器中的训练数据。方法包括K-最近邻 和 基于原型的方法。基于分类的方法:AD和一类nd通常被公式化为无监督学习问题,但也有一些监督和半监督方法。一类分类(OCC)直接学习对应于正态数据分布的期望密度水平集的决策边界。DeepSVDD 向深度学习社区介绍了经典的OCC。PU学习是针对半监督AD设置提出的,其中除了正常数据之外,还有未标记数据可用。自我监督学习方法使用诸如对比学习、图像变换预测 和未来帧预测 的代理 任务,其中异常更可能在设计的任务上出错。

  • 一类分类学习对应于正态数据分布的期望密度水平集的决策边界,这是DeepSVDD 引入深度学习社区的。PU学习 是半监督 AD 设置的一种流行方法。自我监督学习方法使用诸如对比学习、图像变换预测 和 未来帧预测 的代理任务,其中异常更可能在设计的任务上出错。

  • 讨论:感觉和语义 AD 方法假设正常数据是同质的,尽管其中存在多个类别。虽然语义 AD 方法主要适用于感官 AD 问题,但后者可以受益于专注于较低级特征(例如,基于流和基于隐藏特征)、局部表示和基于频率的方法的技术。虽然当前的OOD检测任务主要集中在语义转移上,但是用于感觉AD的方法可能对远OOD检测特别有帮助,如ImageNet vs Texture数据集

  • 讨论:理论分析除了算法开发,AD 和one-class ND 的理论分析也已经在一些著作中提供。例如,[Open category detection with pac guarantees] 构建了一个干净的 ID 集和一个具有相同样本大小的 ID/OOD 混合集,实现了PAC风格的有限样本保证,以最少的错误警报检测特定部分的异常。这些工作对 OOD 检测的理论研究是有益的。

Outlier Detection

  • 异常值检测(OD)观察所有样本,以识别与多数分布的显著偏差。虽然主要在数据挖掘中进行研究,但基于深度学习的OD方法用于open set noisy data和开集半监督学习中的数据清理。

  • 基于密度的方法包括高斯分布,马氏距离,高斯混合和局部异常因子(LOF) 。RANSAC 估算数学模型的参数。也可以应用经典密度方法和基于神经网络的密度方法。基于距离的方法:离群值可以通过邻居计数、DBSCAN聚类 和基于图的方法来检测。基于分类的方法和方法,如 Isolation Forest 和OC-SVM 可用于OD。深度学习模型可以识别异常值。鲁棒性和特征概化的技术包括集成、协同训练 和 提取。

  • 讨论: OD技术对于开集半监督学习、带有开集噪声标签的学习和新奇发现是有价值的。所有这些解决方案都可以应用,特别是当 OOD 样本在训练阶段暴露时。

Benchmarks and Experiments

  • 在本节中,我们报告了CIFAR 基准测试中不同类别的方法的公平比较。该报告源自OpenOOD基准。我们选择了几种流行的AD方法、OOD检测方法(post-hot、需要训练和需要额外数据)和模型稳健性方法。
    • 在这里插入图片描述

    • 图3代表性OOD检测方法的时间表。不同的颜色表示不同类别的方法。每种方法在右下角都有对应的参考(不显眼的白色)。高引用率和开源代码的方法优先包含在该图中。

Benchmarks and Metrics

  • 构建OOD检测基准的常见做法是将整个数据集视为 indistribution (ID ),然后收集几个与任何ID类别无关的数据集作为OOD数据集。在这一部分中,我们展示了来自两个流行的OOD基准测试的结果,分别是来自 OpenOOD (c.f图4),每个基准设计近OOD和远OOD数据集,以便于对OOD检测器进行详细分析。Near-OOD数据集与ID数据集相比只有语义上的移位,而far-OOD则进一步包含了明显的协变量(域)移位。

    • 在这里插入图片描述

    • 图4第5节中使用的CIFAR-10基准的图示。CIFAR-100基准测试只是交换了CIFAR-10和CIFAR-100在图中的位置。

  • CIFAR-10 是一个用于通用对象分类的10类数据集,包含50k训练图像和10k测试图像。对于OOD数据集,我们用CIFAR-100 和 TinyImageNet 构造了 near-OOD。请注意,TinyImageNet中删除了1,207个图像,因为它们实际上属于CIFAR-10类。Far-OOD由MNIST 建立,SVHN ,Texture ,Places365 有1305个图像由于语义重叠而被删除。

  • 另一个OOD检测基准使用CIFAR-100 作为in-distribution,它包含50k训练图像和10k测试图像,有100个类。对于OOD数据集,near-OOD包括CIFAR10 和TinyImageNet 。与CIFAR10基准测试类似,由于与CIFAR100类的语义重叠,TinyImageNet中删除了2,502个图像。Far-OOD由MNIST 、SVHN 、Texture 和 Places365 组成,移除了1,305个图像。我们只报告AUROC分数,它测量受试者工作特征(ROC)曲线下的面积。

Experimental Setup

  • 为了确保来自不同领域并具有不同实现的方法之间的公平比较,实现了具有公共超参数和架构选择的统一设置。ResNet18 用作主干网络。如果实现的方法需要训练,则使用SGD optimizer的广泛接受的设置,学习率为0.1,动量为0.9,100个时期的权重衰减为0.0005。有关进一步的详细信息,请参考OpenOOD 。

Experimental Results and Findings

  • 数据扩充方法是最有效的:我们根据方法类型将图5分成几个部分。一般来说,最有效的方法是那些使用模型不确定性和数据扩充技术的方法。该组主要包括简单有效的方法,如预处理方法,如PixMix 和CutMix 。PixMix在CIFAR-10中获得了93.1%的Near-OOD,是该基准测试中所有方法中的最佳性能。这些方法在大多数其他基准测试中也表现良好。类似地,增强模型不确定性估计的其他简单有效的方法,如 Ensemble 和 Mixup 也表现出优异的性能。

    • 在这里插入图片描述

    • 图5在CIFAR-10/100基准测试中,不同方法在广义OOD检测框架下的比较。结果来自OpenOOD 。不同的颜色表示方法类别。每种方法都报告近OOD(左栏)和远OOD(右栏)AUROC分数,如第5.1节所述。黑色的方法名称源于OOD检测,而红色的是AD方法,蓝色的是OSR方法,粉色的是模型不确定性工程的模型。

  • 额外的数据似乎没有必要?比较UDG (来自额外数据部分的最佳值)和KNN (来自无额外数据部分的最佳值),我们发现UDG的优势仅在CIFAR-10 near-OOD,这是不令人满意的,因为需要大量的真实异常值数据。在基准测试中,我们使用整个TinyImageNet训练集作为额外数据,训练离群点的选择会极大地影响OOD检测器的性能,因此需要进一步探索

  • Post-Hoc Methods 总体上优于训练 : 令人惊讶的是,需要训练的方法并不一定表现得更好。一般来说,仅推理方法优于训练方法。然而,经过训练的模型通常可以与事后方法结合使用,这可能会进一步提高它们的性能。

  • Post-Hoc Methods 正在取得进展:总的来说,2021年以来,最近的 Post-Hoc Methods 比以前的方法有更好的性能,表明仅推理方法的方向是有前途的,并正在取得进展。最近的方法在更真实的数据集上的性能比以前的方法有所提高,以前的方法集中在玩具数据集上。例如,经典的 MDS 在 MNIST 上表现良好,但在CIFAR-10 和 CIFAR-100 上表现不佳,而最近的 KNN 在 MNIST、CIFAR-10、CIFAR-100 上保持良好的表现,在ImageNet上也表现突出。

  • 虽然异常检测(AD)方法最初被设计用于检测MVTec-AD数据集上的像素级外观差异,但是它们在Far-OOD检测中显示出潜力,例如使用DRAEM和CutPaste。这两种方法都获得了高性能的far-OOD检测,特别是当使用CIFAR-100作为分布数据集时。

  • 探索OpenOOD在我们的调查中,我们领导了OpenOOD 的开发,这是一个开源代码库,为各种模型架构和OOD检测方法的公平比较提供了一个统一的框架和基准平台。OpenOOD 不断更新,包括两份全面的实验报告[Openood: Benchmarking generalized outof-distribution detection,Openood v1.5: Enhanced benchmark for out-of-distribution detection],深入研究广泛的分析和发现【OpenOOD: Out-of-Distribution benchmark】。我们鼓励读者探索OpenOOD的资源,以更深入地了解关键方面,如选择模型架构、利用预先训练的模型、实际应用和详细的实现见解。

Exclusion of Covariate-Shift Detection

  • 虽然 OpenOOD 不包括纯协变量转换的设置,但这是一个经过深思熟虑的选择。主要焦点是语义转移,这是OOD检测的基础。通过不单独分析协变量移位,我们旨在避免潜在的误解,并防止过分强调协变量移位检测。[Full-spectrum out-of-distribution detection] 中的实验强调了一个关键发现:大多数当前的OOD检测器对协变量移位比语义移位更敏感,并导致了“全谱OOD检测”的概念,倡导有效概括的模型,以处理协变量移位,同时检测具有语义移位的样本。更多实验评估可以在OpenOOD v1.5 中找到。

Challenges and Future Directions

  • 在本节中,我们将讨论广义OOD检测的挑战和未来方向。

Challenges

  • a.适当的评估和基准:我们希望这项调查能够澄清各种子任务的区别和联系,并帮助未来的工作适当地确定框架内的目标问题和基准。主流的 OOD 检测工作主要集中在检测语义变化上。诚然,由于分布变化的多样性,OOD 检测的领域可能非常广泛。如此宽泛的面向对象定义也带来了一些挑战和担忧,这些挑战和担忧提倡对考虑中的面向对象类型进行明确的规范(例如,语义面向对象、对抗性面向对象等)。)以便所提出的解决方案可以更加专业化。此外,检测某种分布变化的动机也需要澄清。虽然拒绝用语义转移对样本进行分类是显而易见的,但检测感官 OOD 应具体到一些有意义的场景,以将任务的必要性和实际相关性联系起来。

  • 我们还敦促机构群体仔细构建基准和评估。值得注意的是,早期的工作[A baseline for detecting misclassified and out-of-distribution examples in neural networks]忽略了这样一个事实,即一些OOD数据集可能包含具有ID类别的图像,从而导致不准确的性能评估。幸运的是,最近的 OOD 检测工作[Semantically coherent out-of-distribution detection]已经意识到这一缺陷,并特别注意从 OOD 样本中去除ID类别,以确保正确评估。

  • b.无异常值的OOD检测异常值暴露方法 对 OOD训练数据的可用性进行了强有力的假设,这在实践中可能很难获得。此外,需要执行仔细的去重复,以确保异常值训练数据不包含ID数据。这些限制可能导致不灵活的解决方案,并阻止方法在现实世界中的采用。展望未来,该领域的一个主要挑战是设计不依赖于辅助离群数据集的无离群学习目标

  • c.分类和OOD检测之间的权衡:在OSR和OOD检测中,重要的是同时实现双重目标:一个用于ID任务(例如,图像分类),另一个用于OOD检测任务。对于共享网络,这两个任务之间可能存在固有的折衷。有希望的解决方案应该两者兼顾。这两项任务可能相互矛盾,也可能不矛盾,这取决于方法论。例如,[Large-scale long-tailed recognition in an open world] 主张将图像分类和开集识别结合起来,使模型同时具备对已知类别的鉴别识别能力和对新类别的敏感性。检测新类别的能力与其在闭集类别上的准确性高度相关。证明了针对 ID 类的聚类紧密度进行优化可能有助于改善分类和基于距离的OOD检测性能。这种解决方案可能比 ND 更可取,ND与分类模型分开开发二进制 OOD 检测器,并且需要部署两个模型

  • d.真实世界的基准和评估目前的 OOD 检测方法主要是在CIFAR等较小的数据集上进行评估。然而,据观察,在CIFAR上有效的策略可能在像 ImageNet 这样的大型数据集上表现不佳,ImageNet 具有更广泛的语义空间。这种差异强调了在大规模真实环境中进行 OOD 检测评估的重要性。因此,我们建议未来的研究重点关注基于 ImageNet 的 OOD 检测基准,并探索大规模开放集识别(OSR)基准,以充分测试这些方法的有效性。此外,最近的研究强调了ImageNet OOD基准中错误样本的存在,并引入了修正的NINCO数据集以进行更准确的评估。此外,扩展基准的范围以涵盖现实场景,如更真实的数据集 和对象级OOD检测,可以提供有价值的见解,特别是在自动驾驶等安全关键应用中。

Future Directions

  • a.跨子任务的方法由于不同子任务之间的内在联系,它们的解空间可以共享并相互启发。例如,最近出现的基于密度的 OOD 检测研究(参见第3.2节)可以从基于密度的 AD 方法(参见4.2节)已经存在很长时间了。

  • b.OOD 检测和泛化一个open world分类器应该考虑两个任务,即,对协变量移位具有鲁棒性,同时意识到语义移位。现有作品独立追求这两个目标。最近的工作提出了一个语义一致的OOD检测框架,该框架鼓励检测语义OOD样本,同时对可忽略的协变量偏移具有鲁棒性。鉴于OOD的模糊定义,通过明确考虑不变特征(语义相关)和环境特征(非语义)之间的分离,提出了OOD检测的形式化。这项工作强调了训练集中的虚假环境特征会显著影响OOD检测,特别是当语义OOD数据包含虚假特征时。此外,全谱OOD检测 强调了“协变量移位内分布”的影响,并表明大多数先前的OOD检测器不幸地对协变量移位而不是语义移位敏感。这种设置明显提高了OOD检测器的泛化能力。最近关于开放长尾识别、开放复合域自适应、开集域自适应和开集域泛化的工作考虑了开放类样本的潜在存在。展望未来,在算法设计和综合性能评估方面,我们预见了OOD检测和OOD推广如何更好地相互促进的巨大研究机会

  • c.OOD检测和开集噪声标签现有的从开集噪声标签学习的方法集中于抑制噪声的负面影响。然而,开集噪声样本对于离群点暴露可能是有用的(参见第3.1.2节)并可能有益于 OOD 检测。利用类似的想法,开集半监督学习的设置可以有希望用于OOD检测。我们相信OOD检测和前两个领域的结合可以提供更多的见解和可能性。

  • d.OOD检测用于更广泛的学习任务如3.6节所述,OOD检测包含更广泛的学习任务,包括多标签分类、对象检测、图像分割、时间序列预测 和 基于激光雷达的3D对象检测。对于分类任务本身,研究人员还扩展了OOD检测技术,以提高零样本预训练模型的可靠性(如CLIP)。此外,一些研究侧重于应用 OOD 检测方法,以产生可靠的图像字幕。最近的进展将OOD检测扩展到持续自适应或在线学习环境[368]。此外,OOD检测显示了在更广泛的应用中解决模型可靠性问题的前景,如减轻大型语言模型中的幻觉问题。OOD 检测方法的整合有望提高各领域模型的可靠性和实用性,而来自这些领域的见解反过来可以进一步完善 OOD 检测技术。

  • e.利用世界模型的OOD检测:利用基础模型的现有工作,特别是多模态模型,如CLIP ,已经显著增强了OOD检测性能,如第3.1.5节所述。从这一点出发,最近的进展进一步集中于利用大型语言模型中封装的广泛的世界知识。这种方法与多模态世界模型的快速发展相一致,为OOD检测社区的进一步创新提供了蓬勃发展的机会。

Conclusion

  • 在本调查中,我们全面回顾了五个主题:AD、ND、OSR、OOD检测和OD,并将它们统一为广义OOD检测的框架。通过阐明每个子任务的动机和定义,我们鼓励后续工作准确定位其目标问题,并找到最合适的基准。通过对每个子任务的方法论进行整理,我们希望读者能够容易地掌握主流方法,确定合适的基线,并根据现有的方法贡献未来的解决方案。通过提供见解、挑战和未来方向,我们希望未来的工作将更多地关注现有的问题,并探索广义OOD检测范围内甚至范围外的其他任务之间的更多交互。

  • 结合广义 OOD 检测的核心研究成果,我们可以从分类强化OOD 检测两个维度构建高效方案

    • 轻量骨干网络选择(CPU 优化):

    • import torch
      import torch.nn as nn
      from torchvision.models import mobilenet_v3_small
      class IDClassifier(nn.Module):
          def __init__(self, num_classes=4, feature_dim=576):
              super().__init__()
              self.backbone = mobilenet_v3_small(pretrained=True).features  # 冻结特征提取层
              self.global_pool = nn.AdaptiveAvgPool2d((1, 1))
              self.classifier = nn.Sequential(
                  nn.Dropout(0.2),  # 防过拟合
                  nn.Linear(feature_dim, num_classes)
              )
              # 冻结骨干网络参数
              for param in self.backbone.parameters():
                  param.requires_grad = False
              # 仅开放最后两个stage和分类头
              for param in self.backbone[-4:].parameters():
                  param.requires_grad = True
          def forward(self, x):
              features = self.backbone(x)  # [B, 576, 7, 7]
              global_feature = self.global_pool(features).squeeze(-1).squeeze(-1)  # [B, 576]
              logits = self.classifier(global_feature)  # [B, num_classes]
              prob = nn.functional.softmax(logits, dim=1)
              return logits, prob, global_feature
      
    • 小样本训练策略,冻结骨干网络前 3/4 层,仅微调最后 1/4 层 + 分类头

    • # 数据增强与加载
      from torchvision import transforms
      from torch.utils.data import DataLoader, Dataset
      class CustomDataset(Dataset):
          def __init__(self, images, labels, transform=None):
              self.images = images
              self.labels = labels
              self.transform = transform
          def __getitem__(self, idx):
              return self.transform(self.images[idx]), self.labels[idx]
          def __len__(self):
              return len(self.labels)
      transform = transforms.Compose([
          transforms.Resize((224, 224)),
          transforms.RandomHorizontalFlip(),
          transforms.ColorJitter(brightness=0.2, contrast=0.2),
          transforms.ToTensor(),
          transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
      ])
      # 优化器配置(仅微调最后几层)
      model = IDClassifier(num_classes=4)
      optimizer = torch.optim.AdamW(
          model.classifier.parameters(), 
          lr=1e-3, weight_decay=0.01
      )
      criterion = nn.CrossEntropyLoss()
      # 快速训练循环(5 epoch,batch_size=8)
      import time
      start_time = time.time()
      for epoch in range(5):
          model.train()
          for images, labels in DataLoader(dataset, batch_size=8, shuffle=True):
              optimizer.zero_grad()
              logits, _, _ = model(images)
              loss = criterion(logits, labels)
              loss.backward()
              optimizer.step()
      print(f"训练完成,耗时{time.time()-start_time:.2f}秒")
      
  • OOD 检测模块实现(三引擎协同)

    • ODIN(成熟方案,提升拒识能力)

    • def odin_detect(model, img, temperature=100, epsilon=1e-4):
          model.eval()
          img = img.clone().detach().requires_grad_(True)
          # 第一次前向传播
          with torch.no_grad():
              logits, _, _ = model(img)
          scaled_logits = logits / temperature
          prob = nn.functional.softmax(scaled_logits, dim=1)
          max_prob, _ = torch.max(prob, dim=1)
          # 计算对抗扰动
          loss = -torch.log(max_prob)
          loss.backward()
          grad = img.grad.data
          sign_grad = grad.sign()
          perturbed_img = img + epsilon * sign_grad
          perturbed_img = torch.clamp(perturbed_img, 0, 1)
          # 二次推理
          with torch.no_grad():
              perturbed_logits, perturbed_prob, _ = model(perturbed_img)
          final_prob = nn.functional.softmax(perturbed_logits / temperature, dim=1)
          return final_prob.max().item()  # 返回最大置信度
      
    • Energy Score(前沿度量,替代 Softmax)

    • def energy_score(logits, temperature=1.0):
          """基于Logit的能量分数,值越小越可能是ID类"""
          return torch.log(torch.sum(torch.exp(logits / temperature), dim=1) + 1e-8).item()
      
    • 类中心距离(可解释性方案)

    • class ClassCenterManager:
          def __init__(self, feature_dim=576, num_classes=4):
              self.centers = torch.zeros(num_classes, feature_dim).cuda()  # 存储类中心特征
          def update_centers(self, features, labels):
              """根据训练集特征更新类中心"""
              with torch.no_grad():
                  for c in range(self.centers.shape[0]):
                      mask = (labels == c)
                      if mask.any():
                          self.centers[c] = features[mask].mean(dim=0)
          def calculate_distance(self, features):
              """计算样本特征与最近类中心的余弦距离"""
              norms = torch.norm(self.centers, dim=1, keepdim=True) + 1e-8
              dot_product = torch.matmul(features, self.centers.T)  # [B, num_classes]
              cos_sim = dot_product / (torch.norm(features, dim=1, keepdim=True) * norms)
              return (1 - cos_sim.max(dim=1)[0]).item()  # 距离越大越可能是OOD
      
  • 决策融合与阈值校准(提升鲁棒性)

    • class DecisionFuser:
          def __init__(self, id_threshold=0.8, ood_threshold=0.5):
              self.id_threshold = id_threshold  # ID类置信度下限
              self.ood_threshold = ood_threshold  # 融合分数阈值
          def fuse_scores(self, odin_prob, energy_score, cos_dist):
              """加权融合三引擎分数,通过验证集调参确定权重"""
              score = 0.6 * odin_prob - 0.3 * energy_score - 0.1 * cos_dist
              if score > self.ood_threshold:
                  pred_class = torch.argmax(model.classifier.out_features).item()
                  return {
                      "class": pred_class,
                      "confidence": odin_prob,
                      "is_id": True,
                      "scores": {
                          "odin": odin_prob,
                          "energy": energy_score,
                          "cos_dist": cos_dist
                      }
                  }
              else:
                  return {
                      "class": None,
                      "confidence": score,
                      "is_id": False,
                      "scores": {
                          "odin": odin_prob,
                          "energy": energy_score,
                          "cos_dist": cos_dist
                      }
                  }
      
  • 完整推理流程(含 CPU 优化)

    • def inference_pipeline(img_path, model, class_centers, fuser):
          # 1. 图像预处理
          img = Image.open(img_path).convert("RGB")
          tensor = transform(img).unsqueeze(0).to("cpu")  # CPU推理
          # 2. 前向传播
          with torch.no_grad():
              logits, prob, features = model(tensor)
          # 3. 三引擎检测
          odin_p = odin_detect(model, tensor, temperature=150, epsilon=5e-5)
          energy_s = energy_score(logits, temperature=2.0)
          cos_d = class_centers.calculate_distance(features)
          # 4. 决策融合
          result = fuser.fuse_scores(odin_p, energy_s, cos_d)
          # 5. 结果解析
          if result["is_id"]:
              return f"识别为{result['class']}类,置信度{odin_p:.4f}"
          else:
              return "检测为未知类别,建议拒识"
      
  • 对比学习增强特征(提升类间可分性)

    • # 在训练阶段加入对比损失
      class ContrastiveLoss(nn.Module):
          def __init__(self, temperature=0.1):
              super().__init__()
              self.temperature = temperature
          def forward(self, features, labels):
              sim_matrix = torch.cosine_similarity(features.unsqueeze(1), features.unsqueeze(0), dim=2)
              labels = (labels.unsqueeze(1) == labels.unsqueeze(0)).float()
              sim_matrix = sim_matrix - 1e8 * (1 - labels)  # 屏蔽非同类样本
              pos_sim = sim_matrix[labels.bool()].view(labels.shape[0], -1)
              return -torch.log(pos_sim / torch.sum(torch.exp(sim_matrix / self.temperature), dim=1, keepdim=True)).mean()
      # 联合训练损失
      total_loss = criterion(logits, labels) + 0.2 * contrastive_loss(global_feature, labels)
      
  • 元学习小样本适应(3 样本快速学习)

    • # 使用MAML元学习框架
      from torchmeta.modules import MetaModule, MetaLinear
      class MetaClassifier(MetaModule):
          def __init__(self, num_classes=4):
              super().__init__()
              self.backbone = mobilenet_v3_small(pretrained=True).features
              self.classifier = MetaLinear(576, num_classes)
          def forward(self, x, params=None):
              features = self.backbone(x)
              global_feature = nn.AdaptiveAvgPool2d((1, 1))(features).squeeze(-1).squeeze(-1)
              logits = self.classifier(global_feature, params=params.get('classifier', None))
              return logits
      
  • 模型量化:

    • # FP32转INT8量化
      from torch.quantization import quantize_dynamic
      
      quantized_model = quantize_dynamic(
          model, {nn.Linear}, dtype=torch.qint8
      )
      quantized_model.eval()
      
  • TorchScript 优化:

    • # 转换为TorchScript
      script_model = torch.jit.script(model)
      script_model.save("ood_detector.pt")
      # 加载推理
      loaded_model = torch.jit.load("ood_detector.pt")
      
首先需要了解得物网站的数据结构和爬取方式,得物网站比较复杂,需要使用Selenium+BeautifulSoup进行爬取。 以下是一个简单的得物爬虫Python代码实现(注:仅供学习参考,请勿用于商业用途): ```python import time from selenium import webdriver from selenium.webdriver.chrome.options import Options from bs4 import BeautifulSoup options = Options() options.add_argument('--no-sandbox') # 解决DevToolsActivePort文件不存在报错的问题 options.add_argument('window-size=1920x3000') # 指定浏览器分辨率 options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面 options.add_argument('blink-settings=imagesEnabled=false') # 不加载图片, 提升速度 options.add_argument('--headless') # 无界面 driver = webdriver.Chrome(options=options) url = 'https://www.dewu.com/' driver.get(url) # 等待页面加载完成 time.sleep(3) # 模拟鼠标击,展开商品列表 driver.find_element_by_xpath('//div[text()="全部商品"]').click() # 等待页面加载完成 time.sleep(3) # 获取页面源代码 html = driver.page_source # 解析页面 soup = BeautifulSoup(html, 'html.parser') # 获取商品列表 items = soup.find_all('div', {'class': 'item-card'}) for item in items: # 获取商品标题 title = item.find('div', {'class': 'title'}).text.strip() # 获取商品价格 price = item.find('div', {'class': 'price'}).text.strip() # 获取商品链接 link = item.find('a', {'class': 'item-link'})['href'] print(title, price, link) # 关闭浏览器 driver.quit() ``` 这里的代码仅仅是一个简单的爬虫示例,如果想要更加深入地了解得物网站的数据结构和爬取方式,需要结合具体的需求进行更加详细的分析和实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羞儿

写作是兴趣,打赏看心情

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值