Towards Open Set Deep Networks

Abstract

  • 深度网络在解决各种视觉识别问题方面取得了显著成果,并在学术和商业应用领域产生了巨大影响。最近在深度网络方面的研究突出表明,很容易生成人类永远不会将其归类为特定对象类别的图像,但网络却能以很高的置信度将这些图像归类为给定类别–深度网络很容易被人类认为没有意义的图像所欺骗。深度网络的封闭集特性迫使它们从已知类别中进行选择,从而导致了此类伪像。现实世界中的识别是开放集,即识别系统应在测试时拒绝未知/未见类别。
  • 我们提出了一种方法,通过引入新的模型层 OpenMax 来估计输入来自未知类别的概率,从而调整深度网络,使其适用于开放集识别。估计未知概率的一个关键因素是根据网络倒数第二层的激活模式调整元识别概念。OpenMax 允许拒绝 “愚弄 ”和不相关的开放集图像;OpenMax 大大减少了深度网络所犯的明显错误的数量。我们证明,OpenMax 概念提供了有界的开放空间风险,从而正式提供了开放集识别解决方案。我们使用来自 Caffe Model-zoo 的预训练网络,在 ImageNet 2012 验证数据以及数千张愚弄和开放集图像上评估了由此产生的开放集深度网络。所提出的 OpenMax 模型的开放集识别准确率明显优于基本深度网络以及对 SoftMax 概率进行阈值化处理的深度网络
  • 论文地址:[1511.06233] Towards Open Set Deep Networks
  • 参考项目:GitHub - takumayagi/openmax-cifar10: A simple training/evaluation code of open set recognition using OpenMax (https://arxiv.org/abs/1511.06233)
  • 开放集识别的核心问题是传统深度学习模型在封闭集下工作,无法处理未知类。论文提出的 OpenMax 方法通过引入新的层来估计未知类的概率。利用倒数第二层的激活向量(AV),结合元识别(Meta-Recognition)和极值理论(EVT)来估计未知概率。OpenMax 修改了 SoftMax 层,允许未知类的存在。数学原理部分可能涉及 Weibull 分布的拟合,用于计算输入属于已知类的概率,从而估计未知类的概率。涉及特征空间中的距离度量,而非像素空间,因为对抗样本在像素空间接近但特征空间可能远离。
  • OpenMAX(Open Maximum)算法是对传统softmax函数的一种改进。传统的softmax函数在多分类问题中广泛应用,但它假设所有类别都是已知的,这在开放环境下(存在未知类别)可能导致模型性能下降。OpenMAX算法通过引入一个“未知类别”,使得模型能够识别并处理未见过的数据。OpenMAX算法的核心思想是在softmax层的输出中增加一个额外的维度,用于表示“未知类别”。具体来说,它通过以下步骤实现:
    • 计算softmax分数:与传统softmax函数相同,计算每个已知类别的概率分数。
    • 引入未知类别:将softmax分数进行变换,增加一个表示未知类别的概率分数。
    • 重新归一化:对包含未知类别的概率分数进行归一化,得到最终的分类结果。

Introduction

  • 得益于视觉和学习领域的研究进展,计算机视觉数据集已从几百幅图像发展到数百万幅图像,从几个类别发展到数千个类别。最近的深度网络研究极大地改进了视觉识别的许多方面。丰富的表征、可扩展的分类方法和大型数据集的共同进化,带来了许多商业应用。然而,在动态和不断变化的现实世界中部署识别系统时,会遇到各种各样的操作挑战。绝大多数识别系统都是为静态的封闭世界设计的,其主要假设是所有类别都是先验已知的。深度网络与许多经典的机器学习工具一样,旨在执行封闭集识别

  • 最近关于开放集识别 和开放世界识别 的研究,正式确定了在需要在测试过程中剔除未知对象的情况下进行识别的流程。虽然我们总是可以用 “其他 ”类来训练无趣类(已知未知对象),但不可能用所有可能的未知对象实例来训练。因此,设计视觉识别工具时需要正式考虑 “未知未知”。尽管已经开发出了一系列算法来解决这一问题,但利用深度网络进行开放集识别仍是一个悬而未决的问题。

  • 在大多数深度网络中,最后一个全连接层的输出被馈送到 SoftMax 函数,该函数会产生 N 个已知类别标签的概率分布。虽然深度网络总是会有一个最有可能的类别,但人们可能希望,对于未知输入,所有类别的概率都很低,而对不确定性的阈值处理将剔除未知类别。最近有论文展示了如何生成 “fooling” or “rubbish” 图像,这些图像在视觉上与所需类别相去甚远,但却能生成高概率/置信度分数。这有力地表明,对不确定性进行阈值处理不足以确定未知的内容。在第 3 节中,我们展示了将深度网络扩展到 SoftMax 概率阈值在一定程度上提高了开放集识别率,但并没有解决欺骗图像的问题。在深度网络的理论/实践中,即使使用阈值概率,也无法满足 中对开放集识别的正式定义。这就引出了本文要解决的第一个问题:“how to adapt deep networks support to open set recognition?”

  • SoftMax 层是问题的重要组成部分,因为它具有封闭性。我们提出了一种替代方案 OpenMax,它扩展了 SoftMax 层,使其能够预测未知类别。OpenMax 包含识别系统失效的可能性。这种可能性用于估算给定输入属于未知类别的概率。为了进行估算,我们将元识别(Meta-Recognition) 的概念应用于深度网络。我们使用深度网络倒数第二层(SoftMax 之前的全连接层,如 FC8)的分数来估计输入是否与已知训练数据 “相去甚远”。我们将该层的分数称为激活向量(AV)。这一信息被纳入我们的 OpenMax 模型,用于描述识别系统的失败。通过放弃已知类别概率总和为 1 的限制,并拒绝远离已知输入的输入,OpenMax 可以在运行过程中正式处理未知/未见类别。我们的实验证明,OpenMax 与元识别思想的结合可以轻松解决深度网络的开放集识别问题,并拒绝高置信度的傻瓜图像

  • 对于人类观察者来说,愚弄/垃圾图像显然不属于感兴趣的类别,而对抗图像 则提出了更高难度的挑战。这些对抗图像在视觉上与训练样本没有区别,但其设计却能让深度网络产生高置信度但不正确的答案。这与标准的开放空间风险不同,因为对于任何给定的输出类别,对抗图像在输入空间中都 “接近 ”训练样本。

  • 我们在开放式深度网络中提出的一个重要观点是,“开放空间风险 ”应在特征空间而非像素空间中衡量。在之前的研究中,大多数问题的开阔空间风险都不是在像素空间中测量的 。因此,我们会问:"是否存在一个特征空间,理想情况下是深度网络中的一个层,在这个层中,这些对抗图像远离训练示例,也就是说,在开放集识别问题中,未知图像、欺骗图像和对抗图像成为离群值?我们研究了深度网络中用于测量开放空间风险的特征空间/层的选择。我们表明,对倒数第二层网络的整体激活模式进行极值元识别启发的距离归一化处理,可为未知图像、愚弄图像甚至许多对抗图像的 OpenMax 归一化提供拒绝概率。图 1 显示了我们的模型、输入图像、欺骗图像、对抗图像(系统可以拒绝)和开放集图像的激活模式示例。

    • 在这里插入图片描述

    • 图 1:举例说明激活向量模型如何为我们的元识别和 OpenMax 深度网络扩展提供足够的信息,以支持开放集识别。OpenMax 算法测量输入的激活向量(AV)与前几类的模型向量之间的距离,调整分数并提供未知概率的估计值。左侧显示的是不同图像的激活向量(AV),不同的激活向量之间用黑线隔开。每张输入图像都成为一个激活向量,以 10x450 彩色像素显示,纵向是 10 个深度网络通道激活能量的每个像素,横向显示前 450 个 ImageNet 类别的响应。图像底部标识了各种类别指数(鲨鱼、鲸鱼、狗、鱼等)的范围。对于四个类别(棒球、双髻鲨、大白鲨和潜水员)中的每一类,我们都显示了四种类型图像的 AV:模型、真实图像、愚弄图像和开放集图像。视听图像显示了激活模式,其中,对于真实图像,相关类别的反应往往是一起的,例如,鲨鱼与其他鲨鱼、鲸鱼、大型鱼类有许多共同的视觉特征,因此有相关的反应,但与狗或棒球则没有。对 AV 的目测显示,与真实图像或模型 AV 相比,愚弄图像和开放集图像的响应模式存在显著差异。例如,请注意许多 “愚弄 ”图像中更深(深蓝色)的线条,以及许多 “开放集 ”图像中不同的绿色图案。底部的 AV 图像来自 “对抗 ”图像,通过添加几乎不可见的像素变化,将锤头图像转换为潜水员图像。右侧的两列显示了两个类别的相关图像。每个示例都显示了真实图像的 SoftMax (SM) 分数和 OpenMax (OM) 分数,以及产生左侧所示 AV 的傻瓜图像和开放集图像的分数。红色的 OM 分数意味着 OM 算法将图像分类为未知图像,但为了完整起见,我们显示了原本存在混淆的棒球/锤头类别的 OM 概率。右下角显示的是对抗图像及其相关分数–尽管网络将其归类为潜水员,但其与锤头的视觉相似度显然更高。OpenMax 将这幅对抗图像作为潜水员类别中的异常值予以剔除。作为从失败中恢复的示例,我们注意到,如果图像是高斯模糊图像,OpenMax 将其分类为双髻鲨的概率为 0.79 OM。

  • 总之,本文的贡献在于

    • 利用激活向量估算深度网络故障概率的多类元识别技术。
    • 使用 MetaRecognition 和 OpenMax 对开放集深度网络进行形式化,并证明所提出的方法可管理深度网络的开放空间风险
    • 通过实验分析开放集深度网络在剔除未知类别、欺骗图像和来自对抗图像的明显错误方面的有效性,同时保持其在测试图像上的准确性
  • 传统深度学习模型(如 SoftMax)属于封闭集识别系统,强制将所有输入归为已知类别,导致对未知类(Open Set)或对抗样本(Fooling Images)产生高置信度错误分类。开放集识别的本质矛盾在于:测试时可能出现训练中未见过的类别,系统需具备 “拒绝未知” 的能力。 OpenMax 方法通过以下核心思路解决问题:

    • 从像素空间到特征空间的转换:将开放空间风险的度量从像素级转向深度网络的特征空间(倒数第二层激活向量,AV),因为对抗样本在特征空间中可能与已知类差异显著。
    • 元识别(Meta-Recognition)与概率建模:利用极值理论(EVT)对激活向量的分布进行建模,估计输入属于未知类的概率,从而允许模型拒绝 “离群” 样本。
  • OpenMax 通过修改 SoftMax 层,引入对未知类的概率估计,其核心步骤包括:

    • 激活向量(AV)的利用:使用倒数第二层 的激活向量作为特征表示,每个类别的激活向量均值(MAV)用于刻画已知类的特征分布。
    • EVT 拟合与距离度量:对每个已知类,用 Weibull 分布拟合激活向量与 MAV 的距离尾部,计算输入属于该类的 “离群概率”。
    • 激活向量修正与未知类概率计算:根据离群概率调整 top-α 类的激活值,并引入未知类的伪激活,重新归一化概率分布。

Open Set Deep Networks

  • 打开深度网络的一种自然方法是对输出概率应用阈值。我们认为这是拒绝不确定的预测,而不是拒绝未知类别。我们预计来自未知类别的图像都将具有较低的概率,即非常不确定。这只适用于一小部分未知输入。我们在第 3 章中的实验表明,对不确定输入进行阈值化处理会有所帮助,但对于开放集识别来说,这仍然是一个相对较弱的工具。Scheirer 等人 将开放空间风险定义为与标注 “远离 ”已知训练样本的数据相关的风险。这项工作只提供了一个一般性定义,并未规定如何测量距离,也未说明测量这种距离的空间。为了使深度网络能够处理开放集识别,我们必须确保它们能够管理/最小化开放空间风险,并有能力拒绝未知输入
  • 我们试图选择一个层(特征空间),在这个层中我们可以建立一个紧凑的消减概率模型,该模型可以设置阈值来限制空地风险。我们将该模型开发为基于与已学模型距离的衰减概率模型。在下一节中,我们将详细介绍从已知训练数据中估算距离的空间和元识别方法,然后介绍将这种距离纳入深度网络决策函数的方法。我们称这种方法为 OpenMax,它是作为网络最后一层的 SoftMax 函数的替代方案。最后,我们证明了整个模型是一个紧凑的消减概率模型,因此符合开放集识别的定义
  • SoftMax 的局限性与 OpenMax 的改进:传统 SoftMax 强制概率和为 1: P ( y = j ∣ x ) = e v j ( x ) ∑ i = 1 N e v i ( x ) P(y=j|x) = \frac{e^{v_j(x)}}{\sum_{i=1}^N e^{v_i(x)}} P(y=jx)=i=1Nevi(x)evj(x),无法处理未知类。OpenMax 通过引入权重 ω j ( x ) \omega_j(x) ωj(x) 修正激活向量: v ^ j ( x ) = v j ( x ) ⋅ ω j ( x ) \hat{v}_j(x) = v_j(x) \cdot \omega_j(x) v^j(x)=vj(x)ωj(x),并定义未知类激活 v ^ 0 ( x ) = ∑ i v i ( x ) ( 1 − ω i ( x ) ) \hat{v}_0(x) = \sum_i v_i(x)(1-\omega_i(x)) v^0(x)=ivi(x)(1ωi(x)),最终概率为: P ^ ( y = j ∣ x ) = e v ^ j ( x ) ∑ i = 0 N e v ^ i ( x ) \hat{P}(y=j|x) = \frac{e^{\hat{v}_j(x)}}{\sum_{i=0}^N e^{\hat{v}_i(x)}} P^(y=jx)=i=0Nev^i(x)ev^j(x) 其中 ω j ( x ) = 1 − α − i α e − ( ∥ x − τ j ∥ λ j ) κ j \omega_j(x) = 1 - \frac{\alpha-i}{\alpha} e^{-\left(\frac{\|x-\tau_j\|}{\lambda_j}\right)^{\kappa_j}} ωj(x)=1ααie(λjxτj)κj,基于 Weibull 分布的累积分布函数(CDF)计算离群概率。
  • 极值理论(EVT)与 Weibull 分布:对每个已知类 j,计算正确分类样本的激活向量与 MAV 的距离,用 Weibull 分布拟合距离的尾部(最大的 η \eta η 个距离),参数 ( τ j , κ j , λ j ) (\tau_j, \kappa_j, \lambda_j) (τj,κj,λj) 刻画该类的 “开放空间风险”。Weibull 分布的单调性保证了离群概率的合理估计,从而满足 “紧凑衰减概率模型” 的数学定义。
  • OpenMax 的底层逻辑建立在两个关键假设上:
    • 特征空间的判别性:深度网络的倒数第二层激活向量(AV)能捕捉类别间的语义关联(如鲨鱼与鲸鱼的激活模式相似,与棒球差异大),未知类或对抗样本的 AV 在特征空间中与已知类 MAV 的距离较远。
    • 开放空间风险的可度量性:通过 EVT 拟合 AV 距离的尾部分布,可量化输入属于已知类的 “合理性”,从而将未知类的概率估计转化为 “离群概率” 的补集。
  • 激活向量 AV即训练(测试)样本通过神经网络的倒数第二层(全连接层)得到各类样本的激活向量 AV;均值激活向量 MAV即各类训练样本的 AV 的均值,如 N 分类,就得到 N 个 MAV;Weibull分布 由于正态分布与真实的极值分部情况不符合(极值的部分就是正态分布的两端),故引出极值理论,常用的极值分部有:Weibull分布、Gumbel分布、以及Frechet分布. 注:OpenMax使用的是Weibull分布。
  • 闭集N分类网络通过网络模型输出得到N维激活向量,将激活向量输入到SoftMax层,经过SoftMax层,会得到一个N维的得分向量,也就是我们所看到的各类测试样本的分类得分,Socre。而OpenMax在SoftMax之前加入了一系列处理,为了方便描述,以第 i 类为例,即:计算出第 i 类所有训练样本的 MAV,并让第 i 类中所有分类正确的 AV 依次与 MAV 计算欧式距离,得到第 i 类的距离集,而这个距离集,将用于Weibull分布拟合,通过拟合得到第 i 类的累积分布函数 CDF.
  • 现在,就到了测试样本的阶段:输入一个测试样本,得到其激活向量 AV,计算该激活向量到各类 MAV 的距离,于是得到 N 个距离,将这 N 个距离分别带入各类拟合好的 CDF 函数中,得到 N 个概率,这N个概率分别代表此测试样本 AV 到 MAV 的距离出现在各类距离集中的概率,通俗理解就是将距离带入 CDF 函数,就得到此测试样本是各类的N个概率
  • 矫正得分:利用这N个概率,对应矫正此测试样本的的得分向量Score,矫正方法:CDFi(AV到MAV的距离) = 此样本属于 i 类的概率,反正 1 - CDFi(AV到MAV的距离) = 此样本不属于 i 类的概率, 将此概率作为修正权值. 其中 CDFi 为第 i 类的累积分布函数. 将这 N 个修正权值对应乘到此测试样本AV经过SoftMax后得到的得分向量上
  • 经过对测试样本的得分矫正,无非是对得分向量中的 N 个得分值进行一定的消减,将每类预测概率上消减的值加在一起就是 此类为未知类的概率,此时就可以得到一个 N+1 维的得分向量

Multi-class Meta-Recognition

  • 我们的第一步是确定输入何时可能不属于已知类别,也就是说,我们希望添加一种元识别算法来分析分数,并识别深度网络何时可能评估错误。之前的元识别工作使用最终系统得分,并根据极值理论(EVT)分析其分布,发现这些分布遵循 Weibull 分布。虽然我们可以独立使用每类分数,并使用 EVT 考虑它们的分布,但这不会产生紧凑的消减概率,因为傻瓜图像显示分数本身并非来自接近已知输入训练数据的紧凑空间。此外,对于深度网络来说,直接对类别后识别分数集(SoftMax 层)进行 EVT 拟合是没有意义的,因为最后的 SoftMax 层有意进行了重归一化,以遵循对数分布。因此,我们对倒数第二层进行分析,该层通常被视为按类估算。这种按类估算由 SoftMax 函数转换为最终输出概率。

  • 我们采用的方法是,来自倒数第二层的网络数值(以下简称激活向量(AV))并不是独立的每类得分估计值,而是提供了 “相关 ”类别的分布情况。在第 2.2 节中,我们将讨论一个基于图 1 的示例。

  • 我们的整个 EVT 元识别算法总结如 Alg 1 所示。为了使用异常值识别离群值,我们采用了最近类平均值 或最近非离群值 的概念,并将它们作为第一近似值应用于激活向量中的每个类。虽然更复杂的模型,如最近类多中心(NCMC) 或 NCM 森林,可以提供更精确的建模,但为了简单起见,本文只关注使用单一平均值。每个类别用一个点来表示,即平均激活向量(MAV),其平均值仅根据正确分类的训练实例计算得出(图 1 第 2 行)。

    • 在这里插入图片描述
  • 给定 MAV 和输入图像,我们测量它们之间的距离。我们可以直接设定距离阈值,例如使用 [Towards open world recognition] 的跨类验证方法来确定总体最大距离阈值。在[Towards open world recognition]中,我们对特征进行了度量学习,对其进行了归一化处理,这使得单一的共享阈值成为可能。然而,不同类别的视听图像缺乏统一性,这给我们带来了更大的挑战,因此,我们寻求一种按类别划分的元认知模型。特别是在 Alg1 ,我们使用 libMR 的 FitHigh 函数对所有正确的正向训练实例与相关 µi 之间的最大距离进行 Weibull 拟合。这将产生一个参数 ρi,用于估算输入是第 i 类异常值的概率。

  • 给定 ρi 后,一个简单的剔除模型是由用户定义一个阈值来决定是否剔除输入,例如,确保 90% 的训练数据被剔除为离群值的概率接近于零。虽然实现起来很简单,但要校准一个绝对的元识别阈值却很困难,因为它取决于未知的未知数。因此,我们选择在第 2 章所述的 OpenMax 算法中使用这一方法,该算法具有连续调整功能。

  • 我们注意到,我们的校准过程只使用正确分类的数据,对这些数据来说,类 j 是秩 1。在测试时,对于输入 x,假设类别 j 的概率最大,那么 ρj (x) 就提供了 MR 估计的概率,即 x 是离群值,应予以剔除。我们对高等级(如前 10 名)使用一个校准,但作为扩展,也可以对不同等级进行单独校准。请注意,当每个示例有多个通道时,我们会计算每个通道每个类别的均值向量 µ j ; c µ_{j;c} µj;c 和 Weibull 参数 ρ j ; c ρ_{j;c} ρj;c。值得注意的是,我们的目标并不是确定输入的训练类别,相反,这是一个元识别过程,用于确定给定输入是否来自未知类别,因此应予以拒绝。

Interpretation of Activation Vectors

  • 本节将以图 1 为例,介绍激活向量和元识别的概念。

  • 封闭集: 假设输入为有效输入,例如双髻鲨,即图 1 中的第二组激活记录。激活向量显示了与大白鲨相关的视听维度的高分。所有鲨鱼都与其他鲨鱼、鲸鱼和大型鱼类共享许多直接视觉特征和许多上下文视觉特征,这就是为什么图 1 显示了这些组中许多 ImageNet 类别的多个较高激活(亮黄绿色)。我们假设,对于大多数类别而言,相关激活存在相对一致的模式。MAV 以单点的形式捕捉了这种分布。如果输入图像是大白鲨,我们还期望虎鲨、双髻鲨和鲸鱼的激活度较高,但鸟类或棒球的激活度很弱或没有激活度。凭直觉,这似乎是在训练过程中测量距离的正确空间。

  • 开放集: 首先让我们考虑开放集图像,即来自未知类别的真实图像。这些图像总是会被深度网络映射到 SoftMax 提供最大响应的类别中,例如,图 1 中的岩石图像被映射到棒球,右边的鱼被映射到锤头鱼。有时,开放集图像的置信度较低,但最大得分会产生相应的类别。将输入的激活向量与输入产生最大响应的类别的 MAV 进行比较,我们会发现输入的激活向量往往与平均值相去甚远。然而,对于某些开放集图像,所提供的响应虽然接近平均值,但整体激活水平仍然较低。如果输入是一个与已知类别密切相关的 “未知 ”类别,或者如果对象小到无法很好地区分,就会出现这种情况。例如,如果输入的是不同类型的鲨鱼或大鱼,可能会产生较低的激活度,但 AV 的差异可能还不足以被剔除。因此,在开放集识别中,除了直接估算类别是否未知外,仍有必要对不确定性进行阈值化处理。

  • Fooling Set: 考虑一个 “愚弄 ”输入图像,它是人为构建的,目的是使某一特定类别(如棒球或锤头)具有较高的激活得分,从而以较高的置信度被检测到。虽然人为构造增加了感兴趣类别的概率,但图像生成过程并没有同时调整所有相关类别的得分,导致 AV 与模型 AV “相去甚远”。图 1 中每个类别组的第 3 个元素显示了来自愚弄图像的激活。许多愚弄图像在视觉上差异很大,其激活向量也是如此。许多激活度非常低的区域(深蓝色/紫色)可能是因为人们可以通过降低其他类别的激活度来增加特定类别的 SoftMax 输出,这反过来又会降低 SoftMax 计算的分母

  • 对抗集: 最后,考虑一下对抗输入图像 ,它被构建为接近于一个类别,但却被错误地标记为另一个类别。图 1 右下方显示了一个例子。如果对抗图像是按照附近的类别构建的,例如从双髻鲨到大白鲨,那么本文提出的方法将无法将其检测为问题–MAV 无法捕捉到细粒度的类别差异。不过,可以在任何一对图像类别之间构建对抗图像。当目标类别足够远时,例如这里的锤头鱼和潜水的例子,或者更远,例如锤头鱼和棒球,对抗图像的激活得分就会有显著差异,因此可以被剔除。我们在实验中不考虑对抗图像,因为实验结果更多取决于我们选择生成的对抗图像–我们不知道有什么有意义的分布。举例来说,如果我们随机选择类别对(a; b)并生成从 a 到 b 的对抗图像,那么其中大部分图像的层次距离都会很大,很可能会被剔除。如果我们选择最接近的对抗图像,很可能来自附近的类别,那么激活度就会很接近,也就不会被拒绝。

  • 我们的 OpenMax 流程的结果是,开放集以及愚弄或对抗图像一般都会被剔除。制作不被拒绝的欺骗性或对抗性图像,不仅意味着为感兴趣的类别获得高分,还意味着保持其他 999 个类别的相对分数。通过这些约束条件,至少可以大大缩小对抗/欺骗图像的空间。我们希望,任何满足所有限制条件的输入图像都能获得人类对类别标签的支持,就像图 3 中的一些欺骗图像一样,我们也能在对抗图像对中看到细粒度分离的类别,如公牛鲨和大白鲨

  • 有人可能会问,单个 MAV 是否足以表示具有不同方面/视角的复杂物体。未来的工作应该研究能捕捉不同视图/示例的更复杂模型,例如 NCMC 或 NCM 森林 。如果深度网络确实实现了独立于视图的识别目标,那么倒数第二个激活点的分布就应该几乎独立于视图。虽然鲨鱼的开颌视图和侧视图在视觉上有很大不同,而且多示例模型可能更有效地捕捉不同视图中的不同特征,但不同鲨鱼的开颌视图和侧视图仍然非常相似。因此,每个视角都可能呈现出相对一致的视像,从而允许单个 MAV 同时捕捉这两种视像。直观地说,虽然图像特征可能会因视图的不同而有很大的差异,但反向视图所代表的 “相关类别 ”的相对强度应与视图无关得多

OpenMax

  • 标准 SoftMax 函数是分类概率分布的梯度对数归一化器,这也是它通常被用作网络最后一个全连接层的主要原因。传统定义在计算中使用了每个节点的权重。基于 Caffe 的深度网络倒数第二网络层中的分数,也就是我们所说的激活向量,在产生它的卷积过程中进行了加权。让 $v(x) = v_1(x),…,v_N (x) $ 成为每个类别的激活级别, y = 1 , . . . , N y = 1,...,N y=1,...,N在深度网络训练后,输入图像 x 会产生激活向量 v(x),SoftMax 层会对其进行计算

    • P ( y = j ∣ x ) = e v j ( x ) ∑ i = 1 N e v i ( x ) , ( 1 ) P(y = j|x) =\frac{e^{v_j(x)}} {\sum^N_{i=1} e ^{v_i(x)}} ,(1) P(y=jx)=i=1Nevi(x)evj(x),(1)

    • 然而,在开放集识别中,测试时会出现未知的类别,因此要求概率之和为 1 并不合适。

  • 为使 SoftMax 适应开放集,让 ρ 成为由 Alg. 1. 在 Alg. 2 中,我们总结了 OpenMax 的计算步骤。为方便起见,我们将未知的未知类定义为索引 0。我们使用 x 与 µi 之间距离的 Weibull CDF 概率(图 2 第 3 行)作为拒绝估计的核心。模型 µi 是通过与类别 i 相关的图像计算得出的,这些图像在训练过程中被正确分类(top-1)。我们希望距离的 EVT 函数只为少数排名靠前的图像提供有意义的概率。因此,在算法 2 的第 3 行,我们计算了最大的 α 个激活类别的权重,并用它来缩放 Weibull CDF 概率。然后,我们计算修改后的激活向量,并修改最高分。我们计算未知未知类的伪激活,保持总激活水平不变。包括未知的未知类别在内,新修订的激活计算 OpenMax 概率,如公式 2 所示。

  • OpenMax 提供的概率支持在未知未知类(y = 0)概率最大时明确拒绝。这种元识别方法是确定未知未知类别的第一步,我们的实验表明,单个 MAV 在检测愚弄图像方面的效果相当不错,而且比仅对不确定性进行阈值处理更好。然而,在任何产生确定性估计的系统中,不确定性阈值法仍然是一种有效的元识别方法,不应被忽视。因此,在 Alg.2 的第 9 行中,最终的 OpenMax 方法也会拒绝未知和不确定的输入。

  • 为了选择超参数 ϵ \epsilon ϵ;η;和 α,我们可以使用一组训练图像加上一组开放集图像采样来执行网格搜索校准程序,在这组图像上优化 Fmeasure。这里的目标是对整体比例/灵敏度选择进行基本校准,而不是在未知的未知空间中优化阈值,这在实验中是无法实现的。

  • 请注意,未知未知类概率的计算会在本质上改变所有估计概率。对于固定阈值和未知概率很小的输入,OpenMax 会比 SoftMax 拒绝更多的输入。图 2 显示了 100 幅示例图像、50 幅训练图像和 50 幅开放集图像以及傻瓜图像的 OpenMax 和 SoftMax 概率。离对角线越远,OpenMax 对概率的改变越大。基于不确定性剔除的阈值选择 ϵ \epsilon ϵ ,将在保留训练示例和剔除开放集示例之间找到平衡。傻瓜图像不用于阈值选择。

    • 在这里插入图片描述

    • 图 2:2012 年 ImageNet 中 100 个类别的愚弄(三角形)、开放集(方形)和验证(圆形)的 OpenMax 概率与 SoftMax 概率对比图。点越偏离对角线,OpenMax 对概率的改变就越大。低于对角线意味着 OpenMax 估算降低了输入在类别中的概率。对于某些输入,OpenMax 增加了该类别的概率,这是当主要类别被部分剔除,从而降低了其概率并增加了第二或更高等级类别时出现的情况。基于不确定性的剔除阈值( ϵ \epsilon ϵ)选择可以在正确分类训练示例和剔除开放集示例之间优化 F-measure。(对角线以下三角形和正方形的数量表示,OpenMax 阈值(垂直方向)的不确定性阈值比 SoftMax 阈值(水平方向)更好。)

  • 尽管 OpenMax 并不属于我们的实验评估范围,但请注意,OpenMax 还可通过其估计概率提供有意义的等级排序。因此,OpenMax 可直接支持剔除前 5 个类别的输出。同样需要注意的是,由于对激活分数 $\hat v_i(x) $ 进行了重新校准,OpenMax 通常不会产生相同的分数排序。

OpenMax Compact Abating Property

  • 虽然阈值不确定性确实提供了剔除某些输入的能力,但尚未证明它能正式限制深度网络的开放空间风险。我们不难发现,就激活向量而言,SoftMax 的正向标注空间并不局限于训练空间附近,因为最大类得分的任何增加都会提高其概率,同时降低其他类的概率。只要最大方向有足够的增加,即使其他维度有较大的变化,也会为主导类提供较大的激活。虽然理论上可以说深度网络激活是有边界的,但傻瓜图像却令人信服地证明,SoftMax 无法管理开放空间风险

    • 在这里插入图片描述
  • 定理 1(开放集深度网络): 如 Alg. 2 所示,使用元识别对激活向量进行扩展的深度网络,随后将 SoftMax 调整为 OpenMax(如公式 2 所示),可提供开放集识别功能。

  • 证明 元认知概率(Weibull 的 CDF)是 ∣ ∣ µ i − x ∣ ∣ ||µ_i - x|| ∣∣µix∣∣ 的单调递增函数,因此 1 − w i ( x ) 1 - w_i(x) 1wi(x) 是单调递减的。因此,它们构成了 定义的紧凑消减概率的基础。由于 OpenMax 变换是 MetaRecognition 概率的加权单调变换,应用[Towards open world recognition]中的定理 1 和 2 可以得出,对未知的 OpenMax 概率进行阈值化处理,可以管理在视听特征空间中测量的开放空间风险。因此,这是一个开放集识别函数。

Experimental Analysis

  • 在本节中,我们将介绍为评估 OpenMax 方法在使用深度神经网络执行开放集识别任务时的有效性而进行的实验。我们的评估基于包含 1K 个视觉类别的 ImageNet Large Scale Visual Recognition Competition (ILSVRC) 2012 数据集。该数据集包含约 130 万张用于训练的图像(每个类别约有 1K 至 1.3K 张图像)、50K 张用于验证的图像和 150K 张用于测试的图像。由于 2012 年 ILSVRC 的测试标签尚未公开,因此我们像其他人一样,报告了验证集的性能。我们使用 Caffe 软件包 提供的预训练 AlexNet(BVLC AlexNet)深度神经网络。据报道,BVLC AlexNet 在 ILSVRC 2012 验证集上获得了约 57.1% 的最高准确率。选择预训练的 BVLC AlexNet 是经过深思熟虑的,因为它是开源的,也是深度学习中使用最广泛的软件包之一。

  • 为确保正确评估开放集,我们采用了与 中类似的测试协议。在测试阶段,我们使用 ILSVRC 2012 验证集的全部 1000 个类别、傻瓜类别和以前未见过的类别对系统进行测试。之前未见过的类别选自 ILSVRC 2010。Ruskovsky 等人指出,ILSVRC 2010 中大约有 360 个类别被丢弃,没有用于 ILSVRC 2012。这 360 个类别中的图像作为开放集图像,即未见或未知类别。

  • 欺骗图像通常完全无法被人类识别为属于给定类别,但深度网络却能近乎肯定地报告它们属于指定类别。我们使用 Nguyen 等人提供的傻瓜图像,这些图像是通过进化算法或像素空间梯度上升法生成的。最终测试集包括来自 ILSVRC 2012 的 50K 张封闭集图像、15K 张开放集图像(来自 ILSVRC 2010 的 360 个不同类别)和 15K 张傻瓜图像(每个 ILSVRC 2012 类别各 15 张图像)。

  • 训练阶段: 如前所述(图 1),我们考虑倒数第二层(全连接层 8,即 FC8)来计算平均激活向量(MAV)。MAV 向量是通过考虑深度网络训练对相应类别正确分类的训练实例来计算的。MAV 分别针对每种作物/通道进行计算。计算每个正确分类的训练示例与特定类别的 MAV 之间的距离,以获得特定类别的距离分布。在这些实验中,我们使用的距离是归一化欧氏距离和余弦距离的加权组合。补充材料显示了纯欧氏距离和其他测量方法的结果,总体表现类似。根据这些距离估算 Weibull 分布的参数。在 ILSVRC 2012 中,对 1000 个类别中的每个类别都重复了这一过程。在参数估计阶段,通过一小部分保留数据集获得用于估计威布尔分布参数的尾部尺寸的确切长度。此过程重复多次,以获得 20 的总体尾部大小。

  • 测试阶段: 在测试过程中,每张测试图像都要经过 OpenMax 分数校准过程,这在图 2 中已经讨论过。激活向量是测试图像 FC8 层的值,该层由 1000x10 维值组成,分别对应每个类别和每个通道。对于每个类别中的每个通道,使用每个类别的 MAV 和每个类别的 Weibull 参数对输入进行比较。在测试过程中,计算与 MAV 的距离,并获得修正的 OpenMax 激活,包括新的未知类别(见图 2 第 5 和第 6 行)。使用修订后的激活值(公式 2)计算每个通道的 OpenMax 概率,输出结果为 1001x10 个概率。对每个类别而言,10 个通道的平均值即为整体 OpenMax 概率。最后,1001 个概率中最大的类别就是预测类别。这个最大概率会受到不确定性阈值的影响(第 9 行)。在这项工作中,我们重点关注严格的 top-1 预测。

  • 评估: ILSVRC 2012 是一个大规模的多类分类问题,top-1 或 top-5 准确率用于衡量分类算法的有效性 。封闭集系统的多类分类误差可通过跟踪错误分类来计算。对于开放集测试,评估必须跟踪由于对已知类别进行标准多类分类而产生的误差,以及已知类别和未知类别之间的误差。我们使用 F-measure 来评估开放集的性能。对于开放集识别测试,F-measure 比准确率更好,因为它不会被真否定所夸大。

  • 对于 OpenMax/SoftMax 概率值的给定阈值,我们计算整个数据集的真阳性、假阳性和假阴性。例如,当使用验证集、傻瓜集和开放集的图像测试系统时(见图 3),真阳性定义为验证集上的正确分类,假阳性定义为验证集上的错误分类,假阴性定义为系统错误地将傻瓜集和开放集类别中的图像分类为已知示例。图 3 显示了 OpenMax 和 SoftMax 在不同阈值下的性能。我们的实验表明,OpenMax 的建议方法在开放集测试中始终获得较高的 F-measure。

    • 在这里插入图片描述

    • 图 3:OpenMax 和 SoftMax-w/threshold 的性能以 F-measure 表示,是阈值对输出概率的函数。测试使用了 80,000 张图像,其中 50,000 张验证图像来自 ILSVRC 2012,15,000 张愚弄图像和 15,000 张 “未知 ”图像来自 ILSVRC 2010 类别,2012 年未使用。基础深度网络性能与 SoftMax-w/threshold 的阈值 0 相同。OpenMax 的性能收益比采用最佳阈值的 SoftMax 提高了近 4.3% 的准确率,比基础深度网络提高了 12.3%。从上下文来看,在测试集中,OpenMax 比 SoftMax 多正确分类了 3450 张图像,比基础深度网络多正确分类了 9847 张图像。

    • 在这里插入图片描述

    • 图 4:上图显示了 OpenMax 和 SoftMax 作为傻瓜图像和开放集测试图像检测器的性能。根据 OpenMax 和 SoftMax 概率值的不同阈值计算 F 值。所提出的 OpenMax 方法在预测阶段拒绝愚弄图像方面表现非常出色。

Discussion

  • 我们看到,利用 OpenMax 架构,我们可以自动剔除许多未知的开放集和傻瓜图像,并剔除一些对抗图像,而对真实分类率的影响却不大。在使用元识别时,一个显而易见的问题是 "我们该如何处理被剔除的输入?这个问题最好由操作系统设计师来解决,但也有多种可能性。OpenMax 可以作为开放世界识别 场景中的新颖性检测器,然后由人类对数据进行标注,系统再逐步学习新的类别。或者将检测作为引入其他模式的标志 。

  • 第二种方法是尝试去除可能导致分类失误的微小噪声,这种方法尤其适用于对抗性图像或噪声图像。例如,图 1 的右下方显示了一张对抗图像,其中带有噪声的双髻鲨图像被基础深度网络错误地分类为潜水员。OpenMax 拒绝接受该输入,但通过少量简单的高斯模糊处理,该图像可以重新处理,并以 0.79 的概率被接受为双髻鲨

  • 我们使用非测试数据进行参数调整,为简洁起见,只显示了带阈值的 SoftMax 和 OpenMax 共享的不确定性阈值的性能变化。补充材料显示了 OpenMax 参数在更大范围内的变化,例如,我们可以提高开放集和傻瓜剔除能力,但代价是剔除更多的真实类。在未来的工作中,这种真实类别剔除率的增加可能会通过提高 AV 模型的表现力来缓解,例如,每个类别采用多个 MAV。例如,放在桌子上的棒球与投手投出的棒球有着不同的背景,因此在视听模型中可能有不同的 “相关 ”类别。

  • 有趣的是,我们观察到 OpenMax 的剔除过程经常会识别/剔除深度网络错误分类的 ImageNet 图像,尤其是包含多个物体的图像。同样,许多远离训练数据的样本在场景中也有多个物体。因此,OpenMax 剔除的其他用途还包括改进训练过程和帮助开发更好的定位技术。示例见图 5。

    • 在这里插入图片描述

    • 图 5:在本例中,OpenMax 也会在训练过程中预测失败。正式类别是 agama,但在此输入中,agama 的 MAV 被拒绝,得分最高的类别是吉普车,概率为 0.26。然而,通过裁剪图像区域,可以找到检测到 agama 的窗口和检测到吉普车的窗口。作物 1 是吉普车区域,作物 2 是 agama,作物 AV 与适当的模型明显匹配,分别以 0.32 和 0.21 的概率被接受。

Towards Open Set Deep Networks: Supplemental

  • 在本补编中,我们提供了更多材料,以加深读者对开放集深度网络、平均激活向量、开放集识别和 OpenMax 算法的理解。我们在 ILSVRC 2012 数据集上进行了更多实验。首先,我们通过实验说明了 OpenMax 在 EVT 校准的各种参数下的性能(本文算法 1),然后介绍了 OpenMax 对 “顶级类 ”总数(即本文算法 2 中的α)的敏感性,以便在重新校准 SoftMax 分数时加以考虑。然后,我们介绍了用于 EVT 校准的不同距离度量,即欧氏距离和余弦距离。然后,我们用测试阶段进行的开放集评估的定性示例来说明 OpenMax 的工作原理。最后,我们通过类混淆图来说明平均激活向量的分布情况。

Parameters for OpenMax Calibration

Tail Sizes for EVT Calibration

  • 在本节中,我们将扩展分析主论文中 Alg 1 用于 EVT 拟合的尾部大小对 OpenMax 算法性能的影响。我们尝试了多种尾部尺寸来估计 Weibull 分布的参数(主论文 Alg 1 第 3 行)。我们发现,随着尾部尺寸的增大,OpenMax 算法在从开放集和傻瓜集中剔除图像方面变得非常稳健。在这种情况下,OpenMax 的表现仍然比 SoftMax 好得多。实验结果如图 6 所示。然而,当尾部大小超过 20 时,我们发现在验证集上的性能有所下降。从图 7 中可以看出这一现象,因为当尾数超过 20 时,OpenMax 的 F-Measure 开始下降。因此,在剔除开放集和愚弄集的图像,同时保持 ILSVRC 2012 验证集的正确分类率之间,需要保持一个最佳平衡。
    • 在这里插入图片描述

    • 图 6:该图显示了 EVT 拟合尾部大小不同时的傻瓜检测精度和开集检测精度。图中绘制了精度与不同不确定性阈值的对比,每个图中的尾部都不同。我们发现,在尾部大小不同的情况下,OpenMax 的性能始终优于 SoftMax。不过,虽然增加尾部大小会增加 OpenMax 对开放集和欺骗的拒绝率,但同时也会增加对真实图像的拒绝率,从而降低验证集的准确率,见图 7。这种类型的准确率图通常会给开放集测试带来问题,这就是为什么我们在图 7 中使用 F 测量来更好地平衡拒绝率和真实接受率。在主要论文中,所有实验都使用了 20 的尾数。

    • 在这里插入图片描述

    • 图 7:该图显示了 OpenMax 和 Softmax 在开放集测试中的 F-测量性能(使用验证、傻瓜和开放集图像进行测试)。每幅图都显示了 F 值与不同的不确定性阈值之间的关系。不同图中的尾部大小各不相同。OpenMax 在尾部大小为 20 时达到最佳性能。当尾部尺寸大于 20 时,虽然 OpenMax 能很好地拒绝愚弄集和开放集中的图像(图 6),但也会拒绝真实图像,从而降低验证集的准确性。因此,我们在本文的实验中选择了尾部大小为 20 的图像。

Top Classes to be considered for revision α

  • 在主论文的 Alg 2 中,我们介绍了通过 OpenMax 校准 FC8 分数的方法。在此过程中,我们还加入了一个调整类别概率以及估计未知未知类别概率的过程。为此,在 Alg 2(主论文)中,我们考虑了需要修改的 “顶级 ”类别(主论文,Alg 2,第 2 行),它由参数 α 控制。我们称该参数为 α rank,其中 α 的值表示需要修改的 “顶级 ”类别的总数。在我们的实验中,我们发现当 α = 10 时性能最佳。当 α 值越小,F-Measure 的性能就越低。如果我们继续增加 α 值,使其超过 10,我们会发现 F-Measure 性能或傻瓜/开集检测准确率几乎没有提高。α = 10 以上的性能变化不大,最可能的原因是排名较低的类别的 FC8 激活非常小,对 OpenMax 概率的影响不大。图 8 和图 9 显示了不同 α 值的结果。
    • 在这里插入图片描述

    • 图 8:上图显示了 OpenMax 和 Softmax 在重新校准时考虑的顶级类别数量发生变化时的性能。在我们的实验中,我们发现当考虑对前 10 个类别(即 α = 10)进行重新校准时,性能最佳。

    • 在这里插入图片描述

    • 图 9:该图显示了不同字母大小的傻瓜检测和开放集检测准确率。在我们的实验中,α 值为 10 的结果最好。将 alpha 值提高到 10 以上并不会带来任何性能提升。

Distance Measures

  • 我们尝试了不同的距离测量方法来计算平均激活矢量和输入测试图像的激活矢量之间的距离。我们尝试了余弦距离、欧几里得距离和欧几里得-余弦距离。与欧几里得-余弦距离相比,余弦距离和欧几里得距离稍差。余弦距离不提供紧凑的消减特性,因此可能无法限制那些在角度上相距较小,但在欧氏距离上仍然较远的点的开放空间。欧氏余弦距离能在超锥中找到最近的点,从而限制开放空间并找到与平均激活矢量最近的点。欧氏距离和欧氏余弦距离的性能非常相似。图 10 显示了不同距离对总体性能的影响。我们可以看到,OpenMax 的性能仍然优于 SoftMax,而欧氏余弦距离在所有测试中表现最佳。
    • 在这里插入图片描述

    • 图 10:上图显示了 OpenMax 和 Softmax 在使用不同类型的距离度量时的性能。我们发现两者的性能趋势相似,欧氏余弦距离的性能最佳。

Qualitative Examples

  • 查看成功和失败的定性示例通常非常有用。图 11 - 图 12 显示了 OpenMax 未能检测到开放集示例的例子。其中一些来自 ILSVRC 2010 中的类,与 ILSVRC 2012 中的类接近但不完全相同。其他例子则是来自 ILSVRC 2010 中不同类别的对象,与 ILSVRC 2012 中的特定对象类别在视觉上非常相似。最后,我们展示了一个示例,OpenMax 处理了 ILSVRC 2012 验证图像,但降低了其概率,因此带有 SoftMax 的 Caffe 提供了正确答案,但 OpenMax 却弄错了这个示例。
    • 在这里插入图片描述

    • 图 11:左图是 2010 年 ILSVRC 的图像,“地铁列车”,n04349306。OpenMax 和 Softmax 都将其归类为 n04335435。而不是 “未知”。OpenMax 预测左侧图像属于 ILSVRC 2012 中的 “n04335435:streetcar, tram, tramcar, trolley, trolley car ”类别,输出概率为 0.6391(caffe 概率为 0.5225)。右图是 ILSVRC 2012 中的一个图像示例,“streetcar, tram, tramcar, trolley, trolley car”,n04335435 不难看出,ILSVRC 2010 中的开放集类别可能有许多名称不同但语义或视觉上非常相似的相关类别,因此这种错误是必然会发生的。这就是为什么傻瓜剔除比开放集剔除更强的原因。

    • 在这里插入图片描述

    • 图 12:上图显示了 OpenMax 算法对验证图像进行错误分类的示例。

Confusion Map of Mean Activation Vectors

  • 因为未知类别的检测/剔除取决于得分最高的 FC8 类别的平均激活向量(MAV)的距离。请注意,这不同于寻找从输入到最高分平均激活向量的距离。不过,我们仍然发现,对于仅是已知类别细粒度变体的未知类别,系统不太可能拒绝它们。同样,对于对抗性图像,如果图像被对抗性地修改为 “近似”,OpenMax 就不太可能拒绝/检测到它。因此,考虑现有类别之间的混淆是非常有用的。
    • 在这里插入图片描述

    • 图 13:上图显示了 ILSVRC 2012 中每个类别的平均激活向量(MAV)与其他类别的平均激活向量之间的距离混淆矩阵。距离值越小,表示各个类别的平均激活向量非常接近,距离值越大,表示类别之间的距离越远。OpenMax 的大部分错误分类都发生在细粒度分类中,这是意料之中的。

Comparison with the 1-vs-set algorithm.

  • 主要论文侧重于深度网络内的直接扩展。虽然我们认为这是切题,但审稿人可能会担心,将其他模型(例如基于线性的 1-vs-set 开放集算法[Toward open set recognition] )应用于 FC8 数据会提供更好的结果。为了完整起见,我们确实进行了这些实验。我们使用 liblinear 对来自 1000 个类别的训练样本进行线性 SVM 训练。我们还使用 [Towards open world recognition] 中引用的 liblinear 扩展训练了一个 1-Vs-set 机器,并在 1000 个类别的训练数据上对其进行了改进。1-Vs-Set 算法的总体 F 值仅为 0.407,远低于 OpenMax 方法的 0.595。

  • OpenMax 是开放集识别的经典方法,目标是让模型能够区分已知类别(训练过的类别)**和**未知类别(未训练过的类别)。传统 Softmax 在封闭集(测试类别全在训练集中)表现良好,但遇到未知类别时会错误地将其分类到已知类别。OpenMax 通过以下步骤调整 Softmax 分数:

    • 计算均值激活向量(MAV):每个已知类别的训练样本在最后一层全连接层的激活值的均值(代表该类的 “典型特征”)。
    • 建模类内距离分布:计算训练样本激活值到 MAV 的距离(如欧氏距离、余弦距离或 Eucos 混合距离),并使用 Weibull 分布拟合这些距离的尾部(表示 “异常” 程度)。
    • 调整 Softmax 分数:对于测试样本,计算其到各已知类别 MAV 的距离,通过 Weibull 模型估计 “异常概率”,将原始 Softmax 分数的一部分分配给 “未知类别”,生成 OpenMax 分数。
  • OpenMax 核心实现(utils/openmax.py)。fit_weibull:使用训练集的类内距离分布拟合 Weibull 模型(每个类别每个通道独立拟合)。openmax:对测试样本的 Softmax 分数进行调整:

    • 计算样本到各已知类别 MAV 的距离(如 Eucos)。

    • 通过 Weibull 模型估计 “异常概率”,调整原始分数(将部分分数分配给未知类)。

    • 生成 OpenMax 分数(包含未知类)和原始 Softmax 分数。

    • def openmax(weibull_model, categories, input_score, eu_weight, alpha=10, distance_type='eucos'):
          """Re-calibrate scores via OpenMax layer
          Output:openmax probability and softmax probability
          """
          nb_classes = len(categories)
          ranked_list = input_score.argsort().ravel()[::-1][:alpha]
          alpha_weights = [((alpha + 1) - i) / float(alpha) for i in range(1, alpha + 1)]
          omega = np.zeros(nb_classes)
          omega[ranked_list] = alpha_weights
          scores, scores_u = [], []
          for channel, input_score_channel in enumerate(input_score):
              score_channel, score_channel_u = [], []
              for c, category_name in enumerate(categories):
                  mav, dist, model = query_weibull(category_name, weibull_model, distance_type)
                  channel_dist = calc_distance(input_score_channel, mav[channel], eu_weight, distance_type)
                  wscore = model[channel].w_score(channel_dist)
                  modified_score = input_score_channel[c] * (1 - wscore * omega[c])
                  score_channel.append(modified_score)
                  score_channel_u.append(input_score_channel[c] - modified_score)
              scores.append(score_channel)
              scores_u.append(score_channel_u)
          scores = np.asarray(scores)
          scores_u = np.asarray(scores_u)
          openmax_prob = np.array(compute_openmax_prob(scores, scores_u))
          softmax_prob = softmax(np.array(input_score.ravel()))
          return openmax_prob, softmax_prob
      def compute_openmax_prob(scores, scores_u):
          prob_scores, prob_unknowns = [], []
          for s, su in zip(scores, scores_u):
              channel_scores = np.exp(s)
              channel_unknown = np.exp(np.sum(su))
              total_denom = np.sum(channel_scores) + channel_unknown
              prob_scores.append(channel_scores / total_denom)
              prob_unknowns.append(channel_unknown / total_denom)
          # Take channel mean
          scores = np.mean(prob_scores, axis=0)
          unknowns = np.mean(prob_unknowns, axis=0)
          modified_scores = scores.tolist() + [unknowns]
          return modified_scores
      
  • 数据混合(BC 学习,dataset.py),在训练阶段(self.mix=True),随机选择两个不同类别的样本,按比例混合图像和标签:

    • 图像混合:通过 r(0-1 随机数)加权平均两个图像(BC+ 方法会进一步标准化)。
    • 标签混合:生成软标签(如类别 A 的标签为 r,类别 B 为 1-r)。
    • 这种混合迫使模型学习类间边界,提升对未知类的区分能力。
  • 在 PyTorch 中,可以通过修改模型的 forward 方法,返回倒数第二层的输出。例如,对于一个分类模型,通常最后一层是全连接层(fc),输出类别数。倒数第二层可能是另一个全连接层(fc_prev),输出维度为隐藏层大小。

    • import torch
      import torch.nn as nn
      class OpenMaxNet(nn.Module):
          def __init__(self, num_classes=10, hidden_dim=512):
              super(OpenMaxNet, self).__init__()
              self.features = nn.Sequential(
                  nn.Conv2d(3, 64, kernel_size=3, padding=1),
                  nn.ReLU(inplace=True),
                  nn.MaxPool2d(kernel_size=2, stride=2),
                  nn.Conv2d(64, 128, kernel_size=3, padding=1),
                  nn.ReLU(inplace=True),
                  nn.MaxPool2d(kernel_size=2, stride=2),
                  nn.Conv2d(128, 256, kernel_size=3, padding=1),
                  nn.ReLU(inplace=True),
                  nn.MaxPool2d(kernel_size=2, stride=2),
              )
              self.avgpool = nn.AdaptiveAvgPool2d((4, 4))
              self.fc1 = nn.Linear(256 * 4 * 4, hidden_dim)  # 倒数第二层(激活向量 AV)
              self.fc2 = nn.Linear(hidden_dim, num_classes)  # 输出层(分类 logits)
          def forward(self, x):
              x = self.features(x)
              x = self.avgpool(x)
              x = torch.flatten(x, 1)
              av = self.fc1(x)  # 激活向量 AV(形状:[batch_size, hidden_dim])
              logits = self.fc2(av)  # 分类 logits(形状:[batch_size, num_classes])
              return logits, av
      
  • MAV 是每个类别的训练样本中分类正确的 AV 的均值。需要遍历训练集,收集每个类别的正确样本的 AV,然后计算均值。这里需要注意,训练时可能需要在验证集上筛选正确分类的样本,或者在训练集上使用模型预测正确的样本。收集训练集中分类正确样本的激活向量,按类别计算均值:

    • def compute_mav(model, train_loader, num_classes, device):
          model.eval()
          class_wise_avs = [[] for _ in range(num_classes)]  # 按类别存储激活向量
          with torch.no_grad():
              for images, labels in train_loader:
                  images, labels = images.to(device), labels.to(device)
                  logits, avs = model(images)
                  preds = logits.argmax(dim=1)
                  # 仅保留分类正确样本的 AV
                  correct_mask = (preds == labels)
                  for av, label in zip(avs[correct_mask], labels[correct_mask]):
                      class_wise_avs[label.item()].append(av.cpu().numpy())
          # 计算每类的 MAV(均值)
          mavs = []
          for av_list in class_wise_avs:
              if len(av_list) == 0:
                  raise ValueError(f"类 {i} 无正确分类样本,无法计算 MAV")
              mav = np.mean(av_list, axis=0)
              mavs.append(mav)
          return np.array(mavs)  # 形状:[num_classes, hidden_dim]
      
  • 计算距离集 D (i)。对于每个类别 i,计算该类别所有正确样本的 AV 到其 MAV 的距离(如欧式距离、余弦距离或 eucos 距离)。原始代码中使用了 eucos(欧式距离加权加上余弦距离),这一步需要实现这些距离计算函数。计算每个类别训练样本 AV 到其 MAV 的距离(支持欧式、余弦、Eucos 距离):

    • import numpy as np
      import scipy.spatial.distance as spd
      def compute_distances(avs, mav, distance_type="eucos", eu_weight=0.5):
          """
          计算一组 AV 到 MAV 的距离
          avs: 形状 [N, hidden_dim](N 个样本的激活向量)
          mav: 形状 [hidden_dim](当前类别的均值激活向量)
          """
          distances = []
          for av in avs:
              if distance_type == "euclidean":
                  dist = spd.euclidean(av, mav)
              elif distance_type == "cosine":
                  dist = spd.cosine(av, mav)
              elif distance_type == "eucos":  # Eucos 距离(欧式加权 + 余弦)
                  eu_dist = spd.euclidean(av, mav)
                  cos_dist = spd.cosine(av, mav)
                  dist = eu_weight * eu_dist + cos_dist
              else:
                  raise ValueError(f"未知距离类型: {distance_type}")
              distances.append(dist)
          return np.array(distances)
      # 生成所有类别的距离集
      def generate_distance_sets(model, train_loader, mavs, num_classes, device, distance_type="eucos"):
          model.eval()
          distance_sets = [[] for _ in range(num_classes)]  # 每类的距离集
          with torch.no_grad():
              for images, labels in train_loader:
                  images, labels = images.to(device), labels.to(device)
                  logits, avs = model(images)
                  preds = logits.argmax(dim=1)
                  correct_mask = (preds == labels)
                  for av, label in zip(avs[correct_mask], labels[correct_mask]):
                      av_np = av.cpu().numpy()
                      mav = mavs[label.item()]
                      dist = compute_distances([av_np], mav, distance_type=distance_type)[0]
                      distance_sets[label.item()].append(dist)
          return [np.array(ds) for ds in distance_sets]  # 形状:[num_classes, N_i](N_i 为类 i 正确样本数)
      
  • 拟合 Weibull 分布。使用每个类别的距离集 D (i),拟合 Weibull 分布,得到每个类别的 Weibull 模型参数。这里需要使用 libmr 库(原始代码中使用了 libmr.MR ()),但 PyTorch 中可能需要找到替代方法,或者确保 libmr 可用。使用 libmr 库(需提前安装:pip install libmr)对每个距离集拟合 Weibull 分布:

    • import libmr
      def fit_weibull(distance_sets, tailsize=20):
          """
          对每个类别的距离集拟合 Weibull 分布
          distance_sets: [num_classes, N_i] 每类的距离集合
          tailsize: 取距离最大的前 tailsize 个样本拟合极值分布
          """
          weibull_models = []
          for distances in distance_sets:
              mr = libmr.MR()
              sorted_distances = np.sort(distances)
              tail = sorted_distances[-tailsize:]  # 取最大的 tailsize 个距离(极值部分)
              mr.fit_high(tail, len(tail))  # 拟合 Weibull 分布
              weibull_models.append(mr)
          return weibull_models  # 形状:[num_classes](每个元素是一个 Weibull 模型)
      
  • 测试阶段的 OpenMax 处理。对于测试样本,首先获取其 AV,计算到每个 MAV 的距离,然后使用 Weibull 模型计算每个距离的 CDF 值,得到修正权值。根据修正权值调整原始得分(SoftMax 前的 logits 或 SoftMax 后的概率),生成新的 N+1 维得分(N 个已知类 + 1 个未知类)。对测试样本的激活向量进行处理,生成修正后的 OpenMax 概率(N+1 维,新增未知类):

    • def openmax(av, logits, mavs, weibull_models, alpha=5, threshold=0.5, distance_type="eucos", eu_weight=0.5):
          """
          av: 测试样本的激活向量(形状:[hidden_dim])
          logits: 原始分类 logits(形状:[num_classes])
          mavs: 所有类别的 MAV(形状:[num_classes, hidden_dim])
          weibull_models: 所有类别的 Weibull 模型(形状:[num_classes])
          """
          num_classes = len(mavs)
          softmax_prob = torch.softmax(logits, dim=0).numpy()  # 原始 SoftMax 概率
          # 步骤 1: 计算到所有 MAV 的距离
          distances = []
          for i in range(num_classes):
              dist = compute_distances([av], mavs[i], distance_type=distance_type, eu_weight=eu_weight)[0]
              distances.append(dist)
          # 步骤 2: 用 Weibull 模型计算 CDF(1 - 概率质量函数)
          # CDF(d) 表示距离 <= d 的概率,这里需要 1 - CDF(d) 表示距离超过 d 的概率(即“异常”程度)
          weibull_scores = []
          for i in range(num_classes):
              mr = weibull_models[i]
              weibull_score = mr.w_score(distances[i])  # 1 - CDF(d)
              weibull_scores.append(weibull_score)
          # 步骤 3: 选择前 alpha 个最可能的类别进行修正(alpha 剪枝)
          sorted_indices = np.argsort(softmax_prob)[::-1]  # 按概率降序排列
          alpha_weights = [((alpha + 1) - i) / alpha for i in range(1, alpha + 1)]  # alpha 权重
          omega = np.zeros(num_classes)
          for i in range(alpha):
              if i < len(sorted_indices):
                  omega[sorted_indices[i]] = alpha_weights[i]
          # 步骤 4: 修正得分
          modified_prob = []
          unknown_prob = 0.0
          for i in range(num_classes):
              # 修正系数:1 - omega[i] * weibull_scores[i]
              correction = 1 - omega[i] * weibull_scores[i]
              modified_p = softmax_prob[i] * correction
              modified_prob.append(modified_p)
              unknown_prob += softmax_prob[i] * (1 - correction)  # 被扣除的概率累加到未知类
          # 步骤 5: 生成 OpenMax 概率(N+1 维)
          openmax_prob = np.array(modified_prob + [unknown_prob])
          return openmax_prob, softmax_prob
      
  • 完整使用流程示例

    • # 超参数设置
      num_classes = 10
      hidden_dim = 512
      distance_type = "eucos"
      eu_weight = 0.5
      tailsize = 20
      alpha = 5
      threshold = 0.5
      device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
      # 步骤 1: 加载数据集(以 CIFAR-10 为例)
      from torchvision import datasets, transforms
      train_transform = transforms.Compose([
          transforms.RandomCrop(32, padding=4),
          transforms.RandomHorizontalFlip(),
          transforms.ToTensor(),
          transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
      ])
      train_dataset = datasets.CIFAR10(root="./data", train=True, download=True, transform=train_transform)
      train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True)
      # 步骤 2: 训练特征提取模型(假设已训练好)
      model = OpenMaxNet(num_classes=num_classes, hidden_dim=hidden_dim).to(device)
      # 此处省略模型训练代码(需用标准交叉熵损失训练分类任务)
      # 步骤 3: 计算 MAV
      mavs = compute_mav(model, train_loader, num_classes, device)
      # 步骤 4: 生成距离集并拟合 Weibull 分布
      distance_sets = generate_distance_sets(model, train_loader, mavs, num_classes, device, distance_type=distance_type)
      weibull_models = fit_weibull(distance_sets, tailsize=tailsize)
      # 步骤 5: 测试阶段(示例)
      test_image = ...  # 加载测试图像(形状:[1, 3, 32, 32])
      model.eval()
      with torch.no_grad():
          logits, av = model(test_image.to(device))
      logits = logits.squeeze(0)  # 形状:[num_classes]
      av = av.squeeze(0).cpu().numpy()  # 形状:[hidden_dim]
      # 计算 OpenMax 概率
      openmax_prob, softmax_prob = openmax(
          av=av,
          logits=logits,
          mavs=mavs,
          weibull_models=weibull_models,
          alpha=alpha,
          threshold=threshold,
          distance_type=distance_type,
          eu_weight=eu_weight
      )
      print("SoftMax 概率(10类):", softmax_prob)
      print("OpenMax 概率(11类,最后一维为未知类):", openmax_prob)
      
  • 在 OpenMax 算法的实现中,训练阶段需要持久化存储的内容主要包括模型参数均值激活向量(MAV)Weibull 分布模型参数,以及关键超参数(如距离类型、tailsize 等)。这些内容在推理阶段需被加载,用于完成开放集识别的核心逻辑。

    • 训练好的神经网络模型的权重参数(如 OpenMaxNetstate_dict)。PyTorch 的 .pth 文件(如 model_weights.pth)。推理阶段需要通过该模型提取测试样本的激活向量(AV)。激活向量是 OpenMax 算法的输入基础,其质量直接影响后续 MAV 距离计算和 Weibull 概率估计的准确性。

    • 每个已知类别的均值激活向量(形状为 [num_classes, hidden_dim] 的 numpy 数组)。.npy.npz 文件(如 mavs.npy)。MAV 是已知类别在特征空间中的 “中心”,用于衡量测试样本激活向量(AV)与已知类别的 “相似程度”。推理时,需计算测试样本 AV 到所有 MAV 的距离(如欧氏、余弦距离),这些距离是后续 Weibull 概率计算的核心输入

    • 每个类别拟合的 Weibull 分布的参数(形状、尺度、位置参数)。libmr 库支持的序列化格式(如通过 pickle 保存模型对象,或手动存储参数为 .json 文件)。Weibull 模型用于量化测试样本 AV 到 MAV 的距离是否属于 “异常”(即是否可能来自未知类)。推理时,需将测试样本的距离输入 Weibull 模型,得到 “离群概率”(1 - CDF),该概率用于修正 SoftMax 得分

    • import torch
      import numpy as np
      import pickle
      import json
      from libmr import MR
      # 步骤 1: 加载模型参数
      model = OpenMaxNet(num_classes=10, hidden_dim=512).to(device)
      model.load_state_dict(torch.load("openmax_model.pth"))
      model.eval()
      # 步骤 2: 加载 MAV
      mavs = np.load("mavs.npy")  # 形状 [num_classes, hidden_dim]
      # 步骤 3: 加载 Weibull 模型
      with open("weibull_models.pkl", "rb") as f:
          weibull_models = pickle.load(f)  # 长度为 num_classes 的列表,每个元素是 libmr.MR 对象
      # 步骤 4: 加载超参数
      with open("config.json", "r") as f:
          config = json.load(f)
      distance_type = config["distance_type"]
      tailsize = config["tailsize"]
      alpha = config["alpha"]
      eu_weight = config["eu_weight"]
      # 步骤 5: 推理示例(测试样本)
      test_image = ...  # 加载测试图像
      with torch.no_grad():
          logits, av = model(test_image.to(device))  # 提取激活向量 AV
      av_np = av.squeeze().cpu().numpy()  # 转换为 numpy 数组
      # 计算 OpenMax 概率(使用加载的参数)
      openmax_prob, _ = openmax(
          av=av_np,
          logits=logits.squeeze(),
          mavs=mavs,
          weibull_models=weibull_models,
          alpha=alpha,
          distance_type=distance_type,
          eu_weight=eu_weight
      )
      
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐