论文标题:Entropic Open-set Active Learning
中文标题:熵增开放集主动学习
作者团队:Johns Hopkins University, Baltimore, MD, USA & DEVCOM Army Research Laboratory, Adelphi, MD, USA
期刊会议:AAAI
时间:2024
📚研究背景
传统主动学习的局限
在经典(闭集)主动学习中,通常假设所有未标注数据都来自“已知类别”,模型只需要在已知类别之间区分即可。但在实际应用中,未知类别往往会出现在未标注数据里,使得闭集假设无法满足真实需求。开放集场景下的挑战
当未标注数据同时包含“已知类别样本”和“未知类别样本”时,如果仍使用传统主动学习策略,很可能:- 把未知类别误认为已知:造成错误的训练信号;
- 无法识别真正的新类别:降低整体模型在现实环境中的泛化能力。
因此,开放集场景需要新的方法来同时识别并利用“未知类别”,并将它们纳入后续模型更新中。
🎯主要贡献

提出“开放集主动学习(Open-set AL)”框架
论文在主动学习流程中,显式地考虑了未知类别的存在:- 通过每轮的查询策略,既能标注已知类别样本,也能捕获并识别未知类别样本;
- 对未知类别样本统一视为“开放集类 0”,后续积累更多此类样本有助于提高模型对未知的判别能力。
闭集熵(Closed-set Entropy)与基于距离的熵(Distance-based Entropy)的结合
- 闭集熵 $S_c$:利用每个已知类别对应的二元分类器(Binary Classifier)输出的置信度来衡量已知类别判别的“不确定性”,从而初步区分已知与未知。
- 基于距离的熵 $S_d$:在活跃未知集 $\mathcal{D}_{AU}$ 上聚类,得到若干未知簇中心后,计算样本到这些簇中心的距离分布,并用信息熵来度量不确定性。
两者结合,能更全面地识别并挑选“最具价值、最可能是未知”的样本进行标注。
针对未知样本的专门训练目标
- 额外熵损失 $L_{em}$:鼓励未知样本在二元分类器上输出趋于 0.5 的概率(高熵),避免在已知类别判别器里被误判为已知。
- Tuplet loss:在活跃未知集上,引入度量学习思路,使相同未知簇内的样本彼此靠近,且与其它簇中心尽量拉开距离,增强未知类的可分性。
🍍技术细节
🍓问题设定
已知类别(Known Classes)与未知类别(Unknown Classes)
在开放集环境下,我们关心的分类问题不仅包括已知的 $K$ 个类别(即“known classes”),还要考虑到有一部分“未知类别(unknown classes)”的样本出现在未标注数据集中。- 记已知类别集合为 $K = {1, 2, \dots, K}$。
- 记未知类别集合为 $U$,且 $K \cap U = \emptyset$。
数据集划分
- 小规模有标注数据集: $\mathcal{D}L = \left{\bigl(x_i^L, y_i^L\bigr)\right}{i=1}^{N_L}$,其中样本的标签都来自已知的 KK 个类别。
- 大规模无标注数据集:$\mathcal{D}U = \left{\bigl(x_j^U, y_j^U\bigr)\right}{j=1}^{N_U}$,其中混有已知类别与未知类别的样本。可写作:
- 已知类别样本:属于集合 $K$。
- 未知类别样本:属于集合 $U$。
开放集主动学习循环(AL Cycle)
- 每一轮主动学习会根据一个“查询策略(query strategy)”从 $\mathcal{D}_U$ 中选择一批最值得标注的样本 $X^\text{active}$,并向标注专家(oracle)请求这些样本的真实标签。
- 根据标注结果,可把该批样本分为两类:
- 已知类别样本 $X^k$:标签在 $K$ 中。
- 未知类别样本 $X^u$:标签不在 $K$ 中,而是视为开放集的“类 0”(即未知类别),论文中称这些样本为“active unknowns”。
- 对于标成未知类别的样本($X^u$),会把它们收集到一个“活跃未知集” $\mathcal{D}_{AU}$ 里;对标成已知类别的样本($X^k$)则并入到有标注数据集中,即更新 $\mathcal{D}_L = \mathcal{D}_L \cup X^k$.
- 更新后的 $\mathcal{D}_L$ 会用于进一步训练或提升目标模型 $T(\cdot)$ 的性能。
查询策略
在这篇论文/方法中,核心是利用两种熵度量来区分“已知”与“未知”样本,从而帮助选择最有价值、最有不确定性的样本去标注。因为:
- 如果样本非常像已知类别中的某一类,就无需特别关注,它的标注价值相对较小;
- 如果样本在已知类别分布之外,或者很可能属于未知类别,那么这个样本对模型来说有很大价值,被选中标注后可以帮助模型更好地辨别未知类别。
这两种熵度量分别是:
Closed-set Entropy(闭集熵)
- 假设针对每个已知类别,都各自训练了一个“二元分类器(Binary Classifier)”,共有 K 个这样的分类器。
- 每个样本通过这 K 个二元分类器得到一组输出分数,进而可计算出一个反映“该样本落在已知类别分布中的不确定性”的熵值。
- 对于已知类别样本,该熵值通常会比较低;对于未知类别样本,由于它可能不属于任何已知类别,所以其熵值通常比较高。
Distance-based Entropy(基于距离的熵)
- 这里的想法是:“未知类别的分布”与“已知类别的分布”应该有所区别,特别是当一个样本在特征空间里离已知类别的分布中心比较远时,往往是未知类别的可能性更大。
- 为了进行度量,先对活跃未知集 $\mathcal{D}_{AU}$ 中的样本进行聚类,得到若干个聚类中心(这些中心大致可以代表未知类别的分布)。
- 然后对于任意一个新样本,计算它与这些聚类中心的距离。距离越远,代表它不属于已有的那些未知类别分布,或者说它本身可能是一个“新的未知类别”或是一个非常异常的点。基于这些距离,再计算出一个熵值,用来衡量该样本在“未知分布”角度下的置信度或不确定性。
整体流程
综上,他们的开放集主动学习大致做法是:
- 针对无标注数据里的每个样本,先计算两种熵(Closed-set Entropy 和 Distance-based Entropy)。
- 根据熵值大小,挑选最值得标注的一批样本(即最有价值、最不确定的样本)。
- 询问专家标注这些样本后,得到已知类别与未知类别的划分,把标出的未知样本加入到 $\mathcal{D}_{AU}$,已知类别样本并入到 $\mathcal{D}_L$。
- 利用更新后的数据集来提升分类模型的性能。
- 重复上述流程,直至达到所需的标注规模或模型性能。
🍓Closed-set Entropy(闭集熵)
下面这部分内容主要阐述了“闭集熵(Closed-set Entropy)”的由来、如何训练用于计算闭集熵的二元分类器($G_i(\cdot)$),以及在开放集场景下,为了让未知类别(unknown samples)在这些二元分类器输出中呈现高不确定性,作者又如何在$\mathcal{D}{AU}$(活跃未知样本集)上加入额外的损失项 $L{em}$ 来“拉高”其熵值。结合算法流程,可以整体分为以下几个部分来理解。
1. 什么是闭集熵(Closed-set Entropy)
给定一张样本图片 $x$,在特征提取器 $F(\cdot)$ 的输出特征基础上,每个已知类别 $i\in{1,\dots,K}$ 都对应有一个“二元分类器” $G_i(\cdot)$。它输出一个概率 $p^i\in(0,1)$,表示“$x$ 属于已知类别 $i$ 的置信度”。作者定义了每个二元分类器的熵(Entropy)为:
$$H_i(x) ;=; -,p^i ,\log\bigl(p^i\bigr);-;\bigl(1 - p^i\bigr),\log\bigl(1 - p^i\bigr)$$
这是二项分布下常见的熵公式,数值范围在$[0, \log(2)]$ 之间。当 $p^i=0$ 或 1 时熵为 0(非常确定),当 $p^i=0.5$ 时熵最大为 $\log(2)$(非常不确定)。
接着,为了得到一个更综合的“闭集熵评分” $S_c(x)$,作者取所有二元分类器熵的平均值:
$$S_c(x) ;=; \frac{1}{K\log{2}};\sum_{i=1}^K H_i(x)$$
- 对已知类别的样本而言,期望其中某个 $G_i$ 输出的 $p^i$ 接近 1(其余 $p^j$ 接近 0),导致该样本的总体熵较低;
- 对未知类别的样本而言,理想情况下,这些二元分类器对它都应该“不知道该不该归到第 $i$ 类”,从而让所有 $p^i$ 都接近 0.5,导致熵较高。
因此,$S_c(x)$ 能在一定程度上帮助区分已知与未知样本。
2. 二元分类器的训练(针对已知类别样本)
文中提到,为了拿到每个 $G_i$ 的合理输出,需要把第 $i$ 个已知类别当作“正类”,并把“其余 $K-1$ 个类别”当作“负类”来训练(当然还包含一些未知样本也算“负”)。令
- $\mathcal{D}_L$ 为已知类别数据集,包含 $N_L$ 个带标签的已知类别样本;
- $y_i^L \in {1,\dots,K}$ 是样本所属的真实类别。
对于第 $i$ 个分类器 $G_i$,作者使用一种“改进的二元交叉熵损失”来训练,形式上类似于
$$L_{bce} ;=; \frac{1}{n_l} \sum_{(x,y) \in \mathcal{D}L} \Bigl[-,\log\bigl(p^i\bigr);-;\min{j\neq y_i}!\bigl(\log\bigl(1 - p^j\bigr)\bigr)\Bigr]$$
这里做了特别处理(例如只更新某些负例边界)来减轻负样本数过多导致的偏差。直观来说:
- 若 $(x,y)$ 属于类别 $i$,希望 $p^i\approx 1$,令 $-\log(p^i)$ 这一项尽量小;
- 对于其他类别 $j$ ,若$p^j$接近1,则$log(1-p^j)$很小,此处首先筛选 $p^j$ 最大的 $j$ ,即模型认为最可能的负类。由于加了负号,我们希望这个最小值逐渐增大,即让所有的$log(1-p^j)$不至于太小,尤其是最大的 $p^j$ ,即最终旨在降低 $p^j$ ,鼓励模型在其他类别上具有较低的概率。
- 找到对模型而言“最接近”或最容易混淆成正类的那个负类,以此为突破口进行重点打压和区分这样做的好处是避免模型同时针对大量负类平均分散注意力,反而在训练中提高效率,把重心放在正类和它的“最接近对手”之间的决策边界上,最大程度减小正类与最危险负类之间的混淆。这种策略也能减轻由于负类过多带来的不平衡问题。
这样训练完成后,每个 $G_i$ 就能输出对“是否类别 $i$”的预测概率,从而可以计算出前文介绍的熵 $H_i(x)$。
3. 在未知样本上拉高熵值的损失 $L_{em}$
仅仅用已知数据 $\mathcal{D}L$ 训练完 $G_i$ 后,对于未知类别的样本,$p^i$ 不一定能自然地收敛到 0.5(也就不一定有高熵)。为了在开放集场景下“强制”所有 $G_i$ 对未知样本输出一个近似 $\frac{1}{2}$ 的中间概率,作者又在“活跃未知”数据集 $\mathcal{D}{AU}$ 上引入一个额外损失项 $L_{em}$:
$$L_{em} ;=; \frac{1}{K \cdot n_{au}} \sum_{x ,\in, \mathcal{D}{AU}} \sum{i=1}^K \Bigl(-,\tfrac{1}{2}\log\bigl(p^i\bigr);-;\tfrac{1}{2}\log\bigl(1 - p^i\bigr)\Bigr)$$
其中 $n_{au} = |\mathcal{D}_{AU}|$ 为活跃未知样本数。可以发现,上式正好是在鼓励 $p^i = 0.5$,因为当 $p^i = 0.5$ 时,$(p^i(1-p^i))$ 取到极小值,且那时熵最大。
通过在训练中同时最小化 $\mathcal{D}L\cup\mathcal{D}{AU}$ 上的整体损失(即$L_{bce}$ + $L_{em}$),模型能在已知类别样本保持低熵,同时在未知类别样本上保持高熵。
4. 小结
- 闭集熵($S_c$):由对已知类别的二元分类器得到的平均熵,用于衡量“这个样本对已知类别的归属究竟有多大不确定性”。
- 训练细节:
- 对已知类别样本,用“改进后的二元交叉熵”训练 $G_i$,让已知类别各自对应一个“正/负”判别器;
- 对未知类别样本,用额外的 $L_{em}$ 使模型在未知类别上输出接近 0.5 的概率,形成高熵输出。
这样,既能保证模型对已知类别具有足够的判别能力,也能在遇到未知类别时保持高不确定度,从而更好地进行开放集下的主动学习。
🍓Distance-based Entropy(基于距离的熵)
下面这一段主要描述了基于距离的熵(Distance-based Entropy如何计算,以及它背后希望实现的目标:在特征空间中,能够把“未知类别的样本”与其它类别区分得更明显,从而在主动学习时更准确地区分未知样本。还提出了 Tuplet loss,用来鼓励“样本与其聚类中心靠得近、与其他中心拉得远”,从而使得聚类结构更紧致、类间间隔更大。下面分步骤来解释。
1. 为什么仅用闭集熵 $S_c$ 不够
文中先指出:如果只用闭集熵 $S_c$ 来衡量一个样本是不是未知,可能会被“贴近已知类别分布边缘的未知样本”所欺骗。也就是说,有些未知样本恰好离某个已知类别分布很近,使得对这个样本的预测概率 $p^i$ 并不趋近于 0.5(预期的高熵),导致 $S_c$ 低,进而误判为已知类别。为提高对未知样本的识别能力,需要引入另外一个指标,称为基于距离的熵 $S_d$。
2. 基于距离的熵 $S_d$ 的计算流程
使用 $\mathcal{D}{AU}$ 进行聚类
$\mathcal{D}{AU}$ 包含了已被标为“未知类别”的那些活跃未知样本。虽然它们都属于未知类别,但在特征空间里,可能有不同的分布(例如可能包含多个未知子类)。作者采用了 FINCH 聚类算法(或其它类似算法)来对 $\mathcal{D}{AU}$ 做无监督聚类,指定聚成 $K$ 个聚类(与已知类别数相同,虽然并不一定真的对得上,但这样设定方便后续计算熵)。
令聚类结果为 ${\hat{y}i}{i=1}^{N{AU}}$,其中 $\hat{y}_i \in {1,2,\dots,K}$ 表示第 $i$ 个未知样本所属的聚类标签。计算每个聚类的中心 $c_i$
对第 $i$ 个聚类,其中心向量 $c_i$ 定义为该簇内所有样本在特征空间(由 $F(\cdot)$ 提取)上的平均
$$c_i ;=; \frac{\sum_{(x,\hat{y})\in \mathcal{D}{AU}} \mathbb{I}[\hat{y}=i];F(x)} {\sum{(x,\hat{y})\in \mathcal{D}_{AU}} \mathbb{I}[\hat{y}=i]}$$
其中,$\mathbb{I}[\hat{y}=i]$ 是指示函数,表示样本是否属于第 $i$ 个聚类。计算样本 $x$ 距离各个聚类中心的“概率分布” $q_i(x)$
给定一个未标注样本 $x$ 的特征 $F(x)$,定义
$$q_i(x) ;=; \frac {\exp\Bigl(-|F(x) - c_i|;/;T\Bigr)} {\sum_{j=1}^K \exp\Bigl(-|F(x) - c_j|;/;T\Bigr)}$$
其中 $T$ 是一个温度(temperature)超参数,用来控制距离在指数里的缩放。可以把 $q_i(x$) 理解为“$x$ 在特征空间上属于第 $i$ 个聚类中心的‘软分配概率’”,数值越大表示 $x$ 更贴近 $c_i$。最终的距离熵 $S_d(x)$
一旦我们得到所有 $q_i(x)$,就可以按信息熵的方式计算:
$$S_d(x) ;=; -;\frac{1}{\log(K)};\sum_{i=1}^{K} q_i(x);\log\bigl(q_i(x)\bigr)$$
这里做了一个归一化因子 $\frac{1}{\log(K)}$ 使得 $S_d(x)$ 的取值范围在$[0,1]$ 之间。越接近 1,表示此样本在“离各聚类中心都比较远/不确定到底该归在哪个中心”,从而熵高;而如果 $x$ 明显地贴近第i个聚类中心,$q_i(x)$ 接近 1,$q_j(x),where j \neq i$接近0,则该熵值会更小。解释:
- 对已知类别样本而言,如果它确实跟未知簇分布相差大,那么它与所有未知簇中心的距离都比较大,反而会导致 $q_i(x)$ 比较平均,从而 $S_d(x)$ 较高;
- 对未知类别样本而言,如果它离某一个(或几个)未知簇中心比较近,那它对这些簇的概率会更集中,$S_d(x)$ 就较低。
这样,在主动学习中,就可以根据 $S_c$ 和 $S_d$ 来综合判断某个样本是不是值得“怀疑是未知类别”,从而把它选出来标注。
3. 进一步让聚类中心更具区分性:Tuplet loss
作者还提到,使用交叉熵来训练特征提取器 $F(\cdot)$ 时,一般是针对已知类别;但对未知类别的内部结构,并没有显式约束。为让未知样本在特征空间里能“朝着自己的聚类中心靠拢,同时与其他中心远离”,作者在 $\mathcal{D}_{AU}$ 上引入了一个称为 Tuplet loss (有点类似于对比损失/度量学习的思路)。它的形式为:
$$L_t ;=; \frac{1}{n_{au}} \sum_{x ,\in, \mathcal{D}{AU}} \log\Bigl(,1 + \sum{j\neq \hat{y}} \exp\bigl(D_{\hat{y}} - D_j\bigr)\Bigr) ;+;\beta , D_{\hat{y}}$$
其中
- $D_i = |F(x) - c_i|$ 表示样本 $x$ 与第 $i$ 个聚类中心 $c_i$ 的欧式距离;
- $\hat{y}$ 是样本 $x$ 的聚类标签(即它属于第 $\hat{y}$ 簇);
- 通过 $\exp(D_{\hat{y}} - D_j)$ 这项,把“自己所在簇的距离”与“其他簇的距离”联系起来,鼓励 $D_j > D_{\hat{y}}$,离其他中心远、离自己中心近;
- $\beta ,D_{\hat{y}}$ 这项鼓励自身与所属簇中心保持低距离。
直观含义:
- 让 $x$ 距自己的中心 $c_{\hat{y}}$ 更近,保证类内的紧凑;
- 同时让它与其它中心 $c_j$ 的距离更大,以拉开不同未知子类的间隔。
这样做的结果就是:未知类别在特征空间里可以出现更清晰的聚类结构,也就更有利于后续利用 $S_d$ 来进行熵计算和样本选择。
4. 小结
- Distance-based Entropy ($S_d$):先对活跃未知集 $\mathcal{D}_{AU}$ 做无监督聚类,得到 $K$ 个聚类中心。对于任何样本 $x$,计算它对各个中心的“归属概率” $q_i(x)$,再用信息熵公式得到 $S_d(x)$。
- 如果 $x$ 离某个未知簇中心很近,则 $S_d(x)$ 较低;
- 如果 $x$ 离所有未知簇都远,则 $S_d(x)$ 较高。
- 对于已知类别样本,由于它跟未知簇的中心大多距离较远,就会使它的 $S_d$ 值较高;而对于“自成一派”的未知样本,会降低它的 $S_d$ 值,从而更容易被挑选出来做标注。
- Tuplet loss:进一步强化聚类结构,让“同一个未知簇内的点互相靠近,不同未知簇彼此远离”,提高了 $\mathcal{D}_{AU}$ 中的特征可分性。
🍓算法流程
最后,论文给出了一个开放集主动学习的整体流程(Algorithm 1)。核心步骤简述如下:
初始化
- $\mathcal{D}_L$:已标注的已知类别数据
- $\mathcal{D}_U$:未标注数据(混合已知/未知)
- $\mathcal{D}_{AU} = \varnothing$:活跃未知集最开始为空
- 训练/更新模型 $F, C, {G_i}_{i=1}^K$ 及目标模型 $T$ 等
循环每一轮主动学习(AL cycle)
- 若 $\mathcal{D}_{AU}$ 不空,则使用它来计算距离中心、更新“基于距离的熵”分数 $S_d(x)$。
- 计算所有 $\mathcal{D}_U$ 中未标注样本的闭集熵 $S_c(x)$。
- 为了兼顾多样性(diversity),会先对 $\mathcal{D}_U$ 的特征做聚类,然后在每个聚类里根据 $S_c(x)$ 或者 $(S_c(x) - S_d(x))$ 之类的排序,选出不确定性最高或最有代表性的样本若干个(合计 $b$ 个,$b$ 为标注预算)。
- 将这些样本拿去标注:
- 标注后属于已知类别者 $\to X^k$;
- 标注后属于未知类别者 $\to X^u$。
- 更新数据集:
- $\mathcal{D}_L \leftarrow \mathcal{D}_L \cup X^k$
- $\mathcal{D}{AU} \leftarrow \mathcal{D}{AU} \cup X^u$
- $\mathcal{D}_U \leftarrow \mathcal{D}U \setminus X\text{active}$
- 使用更新后的 $\mathcal{D}L$ 继续训练模型 $T$,并可结合 $\mathcal{D}{AU}$ 上的 $L_{em}$ 重新训练各 $G_i$ 等。
迭代多轮
- 每一轮都会挑选新一批最有价值的样本,不断扩充对已知类别的理解,同时累积“未知类别”样本来帮助模型在判别未知类别时保持高熵、低置信度。
👀复现
可能的报错及解决方案
❌错误1
1 | Traceback (most recent call last): |
😊解决方法:
找到torch.util.data.Dataloader的源码,修改_SingleProcessDataLoaderIter类的_next_data方法的返回值为return index, data
❌错误2
1 | TypeError: unhashable type: 'numpy.ndarray' |
作者的代码关于S_c的计算并没有更新到最终版,目前的代码里并没有进行计算,导致这里输出的并不是熵分数列表,自然地,形状也对不上,所以报错
😊解决方法:
找到query_strategires.py中的eoal_sampling方法,将对应部分修改为:
1 | ####### closed-set entropy score |