GCD——Generalized Category Discovery阅读记录

摘要

在本文中,我们考虑一个高度通用的图像识别设置,其中给定一组标记和未标记的图像,任务是对未标记集中的所有图像进行分类。在这里,未标记的图像可能来自标记的类或来自新的类。现有的识别方法无法处理这种情况,因为它们做出了一些限制性的假设,例如未标记的实例仅来自已知或未知类别,以及未知类别的数量是先验已知的。我们解决了更不受约束的设置,将其命名为“广义类别发现”,并挑战了所有这些假设。我们首先通过从新类别发现中获取最先进的算法并使其适应此任务来建立强大的基线。接下来,我们建议在这个开放世界设置中使用具有对比表示学习的视觉变形器。然后,我们引入了一种简单而有效的半监督k-means方法,将未标记的数据自动聚类为可见类和未标记类,大大优于基线。最后,我们还提出了一种新的方法来估计未标记数据中的类数。我们充分利用最近的Semantic Shift Benchmark套件,对通用对象分类的公共数据集和细粒度数据集的方法进行了全面评估。

Introduction

想象一个婴儿坐在车里观察世界。物体实例将通过汽车,对于其中一些,婴儿可能已经被告知它们的类别(“那是一只狗”,“那是一辆车”),并能够识别它们。也会有一些婴儿以前没有见过的例子(猫和自行车),看到了很多这样的例子,我们可能会期望婴儿的视觉识别系统将这些聚类成新的类别。
这是我们在这项工作中考虑的问题:给定一个图像数据集,其中只有一些图像被标记为它们的类别,为其余的每个图像分配一个类别标签,可能使用在标记集合中未观察到的新类别。我们将此问题称为广义类别发现(GCD),并建议这是许多机器视觉应用的现实用例:无论是识别超市中的产品;医学影像病理;或者自动驾驶汽车。在这些和其他现实视觉设置中,通常不可能知道新图像是否来自标记或新类别。
相比之下,考虑现有图像识别设置的局限性。在图像分类这个研究最广泛的问题中,所有的训练图像都带有类标签。此外,测试时的所有图像都来自与训练集相同的类。半监督学习(SSL)[7]引入了从未标记数据中学习的问题,但仍然假设所有未标记的图像与标记的图像来自同一组类。最近,开放集识别(OSR)[38]和小说类别发现(NCD)[19]的任务已经解决了开放世界的设置,其中测试时的图像可能属于新的类别。然而,OSR的目的仅是检测不属于标记集中任何一类的测试时间图像,而不需要在这些检测到的图像之间进行进一步分类。与此同时,在NCD中,方法从标记和未标记的图像中学习,并旨在在未标记的集合中发现新的类。然而,NCD仍然做出限制性假设,即所有未标记的图像都来自新类别,这通常是不现实的
在本文中,我们用许多方法来解决广义类别发现问题。首先,我们通过采用NCD的代表性方法并将其应用于该任务来建立强基线。为了做到这一点,我们调整了它们的训练和推理机制,以适应我们更一般的设置,并使用更健壮的骨干架构重新训练它们。我们表明,现有的NCD方法在这种广义设置下容易过拟合标记类。
接下来,观察NCD方法将其分类头过度拟合到标记类的可能性,我们提出了一种简单但有效的聚类识别方法。我们的关键见解是利用视觉转换器的强大的“最近邻”分类特性以及对比学习。我们提出使用对比训练和半监督k-means聚类算法来识别没有参数分类器的图像。我们表明,无论是在通用对象识别数据集上,还是在更具挑战性的细粒度基准测试上,这些提出的方法都大大优于既定的基线。对于后一项评估,我们利用了最近提出的Semantic Shift Benchmark套件[45],该套件是为识别语义新颖性而设计的。
最后,我们提出了一个具有挑战性的解决方案,图像识别中有待研究的问题:估计未标记数据中的类别数量。几乎所有的方法,包括纯无监督的方法,都假设知道类别的数量,这在现实世界中是一个非常不现实的假设。我们提出了一种利用标记集来解决这个问题的算法。
我们的贡献可以概括如下:(i)广义类别发现(GCD)的形式化,这是图像识别的一个新的和现实的设置;(ii)通过将最先进的标准新类别发现技术应用于这项任务,建立强有力的基线;(iii)一种简单而有效的GCD方法,该方法使用对比表示学习和聚类直接提供类别标签,并且大大优于基线;(iv)一种估算未标记数据中类别数量的新方法,这是一个尚未充分研究的问题;(v)对标准图像识别数据集以及最近的Semantic Shift Benchmark套件进行严格评估[45]。

相关工作

我们的工作与之前在半监督学习、开集识别和新类别发现方面的工作有关,下面我们将简要回顾一下。
半监督学习(Semi-supervised learning) 已经提出了许多方法[7,33,37,40,49]来解决半监督学习(SSL)的问题。SSL假定带标签和未标记的实例来自同一组类。目标是在训练期间利用标记和未标记数据学习一个健壮的分类模型。在现有的方法中,基于一致性的方法似乎是流行和有效的,如LadderNet [36], PI模型[29],Mean-teacher[43]。最近,随着自监督学习的成功,也有人提出了通过增加自监督目标来改进SSL的方法[37,49]。
开集识别(Open-set recognition) 开放集识别(OSR)的问题在[38]中被形式化,其目标是将未标记的实例从与标记数据相同的语义类中分类,同时从未见过的类中检测测试实例。OpenMax[3]是第一个用极值理论解决这个问题的深度学习方法。gan通常用于生成对抗性样本来训练开集分类器,例如[14,25,32]。已经提出了几种方法来训练模型,使具有大重构误差的图像被视为开集样本[34,41,48]。也有一些方法可以学习标记类的原型,并通过与原型的距离从未知类中识别图像[8,9,39]。最近,[8,9]提出学习描述相对于标记类的“他者性”的互易点。[50]联合训练基于流量的密度估计器和基于分类的OSR编码器。最后,Vaze等[45]研究了闭集和开集性能之间的相关性,表明通过提高标准交叉熵基线的闭集精度可以获得最先进的OSR结果。
新类发现(Novel category discovery) 新类别发现(NCD)问题在DTC中被形式化[19]。早期可应用于该问题的方法包括KCL[21]和MCL[22],它们都分别使用标记数据和未标记数据训练两个模型,用于一般任务迁移学习。AutoNovel(又名Rankstats)[17,18]采用三阶段方法解决NCD问题。该模型首先在所有数据上进行自我监督训练,用于低级表示学习。然后,在标记数据的完全监督下对其进行进一步训练,以捕获更高层次的语义信息。最后,进行联合学习阶段,通过排序统计将知识从标记数据转移到未标记数据。Zhao和Han[51]提出了一个具有两个分支的模型,一个用于全局特征学习,另一个用于局部特征学习,通过这两个分支进行双排序统计和相互学习,以更好地进行表征学习和新类发现。OpenMix[53]混合了标记和未标记的数据,以避免模型过度拟合NCD。NCL[52]通过对比学习对未标记数据的成对伪标签进行提取和聚合,并通过在NCD的特征空间中混合标记和未标记的数据来生成硬负( hard negatives)。Jia等[23]提出了一种基于对比学习和赢者通吃哈希的单模态和多模态数据端到端NCD方法。UNO[13]中引入了统一的交叉熵损失,通过交换标记和未标记的分类头中的伪标签,允许模型在标记和未标记的数据上进行联合训练。
最后,我们强调了Girish等人[15]的工作,他们解决了与GCD类似的设置,但用于GAN归因而不是图像识别的任务,以及Cao等人[4]的并行工作,他们在开放世界半监督学习的名称下解决了类似的图像识别设置。与我们的设置不同,它们没有利用大规模的预训练或在语义转移基准上展示性能,这更好地隔离了检测语义新颖性的问题。

Generalized category discovery广义类别发现

我们首先形式化了广义类别发现(GCD)任务。简而言之,我们考虑在数据集中对图像进行分类的问题,其中子集具有已知的类标签。任务是为所有剩余的图像分配类标签,使用在标记的图像中可能观察到也可能没有观察到的类(见图1,左)。
在这里插入图片描述
(图1所示。我们提出了一个新的设置:“广义类别发现”和一种解决它的方法。我们的设置可以简洁地描述为:给定一个数据集,其中一个子集具有类标签,对数据集中所有未标记的图像进行分类。未标记的图像可能来自标记或新类。我们的方法利用对比训练的视觉转换器直接通过聚类来分配标签。)
正式地,我们对GCD的定义如下。我们考虑一个包含两部分的数据集D: D L = { ( x i , y i ) } i = 1 N ∈ X × Y L \mathcal{D}_{\mathcal L} = \{(\mathbf{x}_{i},y_{i})\}_{i=1}^{N} \in \mathcal{X} \times \mathcal{Y}_{\mathcal L} DL={(xi,yi)}i=1NX×YL D U = { ( x i , y i ) } i = 1 M ∈ X × Y U , \mathcal{D}_{\mathcal U} = \{(\mathbf{x}_{i},y_{i})\}_{i=1}^{M} \in \mathcal{X} \times \mathcal{Y}_{\mathcal U}, DU={(xi,yi)}i=1MX×YU,其中 y L ⊂ Y U y_{\mathcal{L}}\subset\mathcal{Y}_{\mathcal{U}} yLYU。在训练期间,模型无法访问 D U \mathcal{D}_{\mathcal U}

### Generalized SAM概述 Generalized Sharpness-Aware Minimization (SAM) 是一种优化算法,旨在通过最小化损失函数的锐度来提高模型泛化能力[^1]。传统上,机器学习中的优化目标主要是使训练集上的经验风险最小化。然而,在某些情况下,这种做法可能导致过拟合现象。 为了克服这一挑战,Generalized SAM引入了一个新的视角——不仅关注参数空间中局部极小值的位置,还考虑其形状特性。具体来说,该方法试图找到那些具有较低锐度(即平坦)解附近的最优解路径。研究表明,这样的解决方案往往能够提供更好的测试性能和更强的鲁棒性。 #### 数学表达形式 给定一个神经网络 \( f_\theta(x) \),其中\( \theta \)表示可调参数向量,则原始SAM可以被定义为: \[ \min_{\theta} L(\theta)+\lambda R(\theta+\epsilon),|\epsilon|_p=\delta \] 这里, - \(L\) 表示标准监督任务下的损失; - \(R\) 则衡量扰动后的最大可能增长幅度; - 参数 \(\lambda,\delta>0\) 控制着正则项强度以及允许的最大偏离程度; 对于广义版本而言,上述公式进一步扩展到多维度约束条件,并支持更灵活的距离测度方式,从而适应不同类型的任务需求[^2]。 ```python import torch from torch import nn, optim class GSAMOptimizer(optim.Optimizer): def __init__(self, params, base_optimizer, rho=0.05, adaptive=False): defaults = dict(rho=rho, adaptive=adaptive) super(GSAMOptimizer, self).__init__(params, defaults) self.base_optimizer = base_optimizer(self.param_groups) @torch.no_grad() def step(self, closure=None): if closure is None: raise ValueError('closure should be provided for sharpness-aware update') # Compute perturbed parameters w' grad_norm = 0. for group in self.param_groups: for p in group['params']: if p.grad is not None: param_state = self.state[p] state.setdefault('grad', []).append(p.grad.clone()) grad_norm += torch.norm(p.grad)**2 grad_norm = grad_norm.sqrt().item() for group in self.param_groups: scale = group["rho"] / max(grad_norm, 1e-8) for p in group['params']: if p.grad is not None: e_w = (scale * p.grad).data.sign() p.add_(e_w) loss_at_perturbation = closure().float() # Restore original weights & compute gradient at w' for group in self.param_groups: for i, p in enumerate(group['params']): if 'original_params' not in self.state[p]: self.state[p]['original_params'] = p.data.clone() p.data.copy_(self.state[p]['original_params']) self.zero_grad() loss_at_original = closure().float() final_loss = loss_at_original + ((loss_at_perturbation - loss_at_original)).mean() final_loss.backward(create_graph=True) self.base_optimizer.step(closure=closure) # Example usage with SGD as a base optimizer model = ... # Define your model here base_optim = torch.optim.SGD(model.parameters(), lr=0.01) gsam = GSAMOptimizer(model.parameters(), base_optim, rho=0.05) for input_, target in data_loader: def closure(): output = model(input_) loss = criterion(output, target) gsam.zero_grad() loss.backward() return loss gsam.step(closure) ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值