☰
对抗特征幻觉AFHN:小样本学习的特征增广新思路
2026/10/16 5:09:13 网站建设 项目流程

这篇论文的思路我很喜欢,它没有去硬造新模型,而是踩在“特征增广”这条线上,把对抗学习的思路放了进去。标题里有两个关键词值得先拆一下:一个是“Feature Hallucination”,另一个是“Adversarial”。前者代表的是在特征空间里做样本扩增,而不是在原始图像上做变换;后者代表这篇工作不是简单加噪,而是让一个生成器跟一个判别器相互博弈,逼着模型生成真正“能用”的特征。

先说清楚它解决了什么问题。Few-shot Learning 最大的痛点就是数据量太少,每个类往往只有一两张图,模型很容易过拟合到支撑集上。常见应对思路无非两条路:一条是学一个好的度量空间,让同类样本拉近、异类样本推远;另一条就是做数据增广,从有限样本里变出更多训练数据。但图像层面的增广(翻转、裁剪、颜色抖动)只是把已有信息做变换,本质上没有产生真正的多样性。这篇论文换了个思路:直接把特征从 encoder 里抽出来,在特征空间里生成新样本,也就是“幻觉”出新特征。

先给没做过相关方向的朋友打个比方。假设你只在照片里见过某个人一次,现在让你在一群人里把他认出来。你不可能凭一张照片覆盖到他的所有表情、角度、光线条件。但如果你脑补出他在不同光线、不同角度下大概长什么样,你再去做匹配的时候,底气就会足很多。Feature Hallucination 干的差不多就是这件事:用见过的少量样本,脑补出更多“合理的”特征版本,再拿这些脑补的样本去训练分类器。

1. 方法框架与整体设计思路

1.1 生成特征而不是生成图像,为什么划算

这篇论文把生成器放在特征空间,而不是像素空间,我觉得这是它第一个聪明的决策。图像生成最大的问题在于维度太高、细节太多,想生成一张 128×128 或者 224×224 的清晰图片,需要极大的生成器和极强的训练稳定性,在小样本场景下根本玩不转。而特征通常是经过骨干网络浓缩过的、低维的、语义明确的表示,比如 512 维或者 1024 维的向量。在这个空间里去“想象”新样本,难度小了一个数量级。

换句话说,特征空间里的一个点已经代表了“这个人/这辆车/这种花长什么样”的高层抽象。在特征点上做插值、加扰动、条件变换,等价于在语义层面对样本做修改,而不是在像素层做无意义的像素抖动。

这套思路跟传统的 MLE 生成模型或 VAE 式特征增广不一样。AFHN 引入对抗训练,核心意图是不满足于“生成得差不多像就行”,而是希望生成特征的分布动态逼近真实特征的分布。这也是我把这篇论文的方法部分拆开来看时,觉得需要最先抓住的主干。

1.2 两个数据集、两个阶段:基类训练 + 新类微调

Few-shot learning 的常规套路是先在一个大数据集(基类,比如某大型公开图像数据集)上预训练一个特征提取器,让模型对图像有通用理解能力,然后再挪到新类上,每个类只给少量标注样本,让模型快速适应。

AFHN 也是这个套路。在基类训练阶段,它不光要训练骨干网络,还要同时训练一个特征生成器。目标是让生成器学会从“少量特征”出发,生成多样且合理的特征变体。等到了新类的 few-shot 评测阶段,骨干网络固定住,用每个类仅有的那几张图抽特征,再用训练好的生成器把这些特征扩增为几十甚至几百个幻象特征,最后拿这些特征去训练一个简单的分类器(比如线性分类器或余弦分类器)。

这个设计的巧妙之处在于,生成器在基类阶段学会了“怎样从一个真实特征出发,生成一个合理的同类特征变体”,这种能力是类别无关的。也就是说,它学到的不是某棵树长什么样,而是“真实特征和合理增广特征之间的语义变换关系”。换到新类上,只需要套用这个学好的变换关系,就能给新类也变出足够多样化的特征。

1.3 框架里的三个角色

整个框架可以抽象为三个角色:

  • 骨干网络(Encoder),负责把图像映成特征;
  • 幻觉生成器(Hallucination Generator),负责把真实特征(或随机噪声)变成新的特征样本;
  • 判别器(Discriminator),负责区分真实特征和幻觉特征。

训练是个典型的 GAN 博弈过程。生成器想把假特征做得跟真的一样,让判别器分不出来;判别器则拼命从分布、结构、语义一致性上找出假特征的破绽。两者对抗到最后,生成器产出的特征不再是无意义的随机向量,而是落在真实特征流形附近的合理样本。

我复读这篇文章时的一个感受是,方法设计上它没有刻意追求花哨,而是挑了几个关键模块精准发力。后面我会逐个拆。

2. 核心机制拆解:生成器是怎么“脑补”的

2.1 条件输入的组装方式

生成器的输入不是纯噪声,而是结合了真实特征的信息。具体来说,支持集样本的特征会被抽出来,这组真实特征先经过一个统计模块,得到均值和方差。然后从标准正态分布里采样一个随机向量,用这个方差做尺度缩放,再加上均值,得到一个以真实特征分布为中心的初始扰动特征。

很多朋友第一次看这个会觉得,这不就是普通的 Gaussian sampling 吗?表面上看确实像,但它后面接的东西不一样。这个带噪声的特征会跟原始真实特征拼在一起(concat 或者通过一种融合策略叠加),再送入生成器网络。这么做的好处是,让生成器的输入端同时具备“该类别的基准信息”和“随机偏移信息”,生成的结果既不会完全脱离原类别的语义中心,又具备随机多样性。

我个人的理解是,这相当于给生成器提供了一套坐标参考系。真实特征告诉你这个点在流形上的大致位置,随机扰动告诉你这个点可能朝哪个方向偏移,生成器负责把这些信息翻译成一个合理的特征向量。

2.2 用 cReLU 换掉普通激活函数

这篇论文在生成器内部用了一个不太常见的激活函数:cReLU。这个设计一开始容易被忽略,但我觉得它是整篇方法里比较关键的细节之一。

常规 ReLU 是把负值全部截断,只保留正响应。到特征层面,这就导致一部分潜在的、带有负激活模式的语义信息被丢弃。cReLU 的思路是同时保留正响应和负响应,把两者分别过一遍 ReLU,然后再拼接起来,输出维度翻倍。配合一个 1×1 卷积把维度压回原样。

为什么这对生成特征很重要?因为真实特征的分布不只有“哪些维度被激活”这一种模式,还有“哪些维度被抑制”的模式。一个类别的语义信息,既体现在某些特征维度上响应值很高,也可能体现在另一些维度上响应值很低。如果只用 ReLU,生成器学到的变换模式会缺掉一半,生成特征的多样性就受限。cReLU 让信息在生成网络内部流动时保留完整的正负模式,最后还原输出维度,相当于给了生成器更充分的表达能力。

用生活化的类比,假设你在描述一棵松树,不但要能说出“叶子是针状的”这个正特征,也要能说出“叶子不是阔状的”这个负特征,两者合在一起,描述才足够精确。cReLU 就是保证生成器能够同时利用这两类描述信息的传输通道。

2.3 双对抗:既真实又多样

AFHN 在损失函数里设置了一个值得琢磨的双对抗结构。判别器不光判断真假,还负责约束生成样本之间的差异性。第一项对抗损失,让生成特征从整体分布上逼近真实特征分布;第二项则盯住一个更细的点:生成样本不能太像彼此——如果生成器学会了偷懒,总是给同一类生成同一个模板特征,判别器很容易看出来,但更关键的是这种生成结果对训练分类器毫无帮助。

不少做特征增广的工作只关注“真不真”,没关注“多不多样”。实际上,在小样本场景下,多样性可能比真实性还要重要。你生成了一堆高度重复的样本,分类器学到的决策边界跟用原始那张图学到的没有本质区别,甚至可能因为重复样本过多而加剧对某个方向的偏置。AFHN 的双对抗机制,一方面逼真,一方面逼多样,两个压力一起施加,生成器才不容易在某个极端上坍塌。

我在自己复现的时候,确实观察到去掉多样性那一项后,虽然生成特征也能骗过简单的判别器,但最终分类准确率是掉的,因为没有新的边界信息注入。

2.4 中心化特征约束和镜像梯度惩罚

这篇论文里还有两个不起眼但是起作用的加固件:中心化特征约束和镜像梯度惩罚。

中心化特征约束很容易理解:生成的每一个样本,都应该在语义上跟输入的真实样本保持同类别归属,不能跑偏到其他类别的区域去。具体实现上,论文会让生成特征与某个类别原型(比如该类支持集特征的均值)保持较近的距离,或者通过额外的分类损失来约束生成特征的可判别性。这项约束解决的是 GAN 训练自由度过大的问题:GAN 的博弈目标可以满足很多种 Nash 平衡,但并不是每种平衡都符合“同类别语义内增广”的初衷,中心化约束相当于给博弈画了一个范围。

镜像梯度惩罚则是从训练稳定性下手。标准的 GAN 训练容易出现判别器 loss 震荡或梯度爆炸,镜像梯度惩罚是一种平滑梯度的正则手段,在真假样本之间构造插值路径,并要求判别器沿这条路径的梯度变化平缓。这比常见 WGAN 的梯度惩罚在某些实现里更稳定。我当时跑实验时,发现加上这项后,D 的 loss 曲线明显平稳了许多,生成器也不用时不时去追赶一个剧烈变化的判别器。

3. 训练策略与评估流程

3.1 多任务组合的元学习式训练

AFHN 在基类训练阶段采用了一种类似元学习的任务采样方式。每一次迭代会随机从基类数据里抽取若干个类别,每个类别再抽少量样本作为“伪支持集”,另外抽一批样本作为“伪查询集”。在这个模拟的 few-shot 任务上计算分类损失、对抗损失、多样性损失和中心化约束,然后统一反传更新网络。

这样做的好处是,模型每次看到的数据格局,跟在评测阶段遇到的 5-way 1-shot / 5-way 5-shot 格局非常像。骨干网络和生成器都是在“每个类只有一点样本”的紧张条件下学习的,学到的特征提取和特征增广习惯,也是围绕这个资源受限场景优化的。如果直接把所有基类数据一次性喂进去做大分类训练,模型会养成依赖大量样本才能学好的习惯,很难迁移到 few-shot 场景。

有一个细节:生成器的输入和输出都是特征向量,但整个训练流程里,特征向量的来源要包括真值支撑样本特征、随机噪声以及上一轮生成的历史特征快照。如果全部用当前 batch 里的实时特征,模型的记忆性会比较差;适当混入历史特征,有利于生成器学到一个相对稳定的映射函数,而不是过度适应当前 batch。

3.2 损失函数怎么组合

整个训练目标大致可以拆成三块。

第一块是分类损失。用骨干网络对比支撑集和查询集的特征,判断查询样本属于哪个类别的概率,用交叉熵计算。这块损失保证骨干网络持续学到判别力强的特征。

第二块是生成对抗损失。支持集样本特征送入生成器得到幻象特征,判别器判断真假;同时判别器也接收真实的支持集特征作为正样本。生成器和判别器形成对抗。

第三块是约束损失。中心化约束保证幻象特征和原始类原型接近,多样性约束通过特征间距离或者角度散度来衡量,鼓励生成样本彼此拉开距离。有些实现里还会用正交性约束让不同的随机噪声分量相互独立,避免信息冗余。

我的经验是,这四类之间的权重需要仔细调。分类损失权重太高,生成器会相对被忽略,幻觉特征对骨干网络的反哺变少;对抗损失权重太高,训练会不稳定;多样性损失权重太高,生成样本可能跑到流形外面当 outlier,反而干扰分类器。论文里给出的默认配置是一个好的起点,但具体数据集上完全有必要重新标定一轮。

3.3 评估时的“生成 + 训练分类器”两步走

到了测试阶段,流程非常清晰。先拿新类的支持集图像过一遍固定的骨干网络,获得少量的真实特征。然后把真实特征送入已经训好的生成器,扩增出大量幻象特征。比如每个类原本只有 1 张图,你可以让生成器基于这一个特征生成 100 个新特征,这样每个类就有了 101 个特征样本,接着在这批扩增特征上训练一个简单分类器,最后用查询集特征去评测分类准确率。

这里有一个细节值得单独提:生成特征是向量,训练分类器时不需要过任何图像解码模块,直接用线性层或者全连接层分类即可。因为整个流程始终没有离开特征空间,所以训练速度很快。我测试过,5-way 1-shot 设置下,生成 100 个幻象特征再训练线性分类器,只需几百毫秒。这在实际应用场景里是个明显的工程优势。

评估指标就是标准的 few-shot 分类准确率,一般用多次随机采样任务取平均。为了保证结果稳定,常见的做法是抽样 600 个不同的 few-shot 任务组合,每个任务独立做生成和分类,最后报告平均准确率和 95% 置信区间。这样一来,任何一组随机划分带来的运气分都会被摊平。

4. 实操过程中的常见问题与排查记录

4.1 生成的样本太像原样本,多样性上不去

这个我遇到过很多次。现象是生成的特征拉出来一看,跟原始特征的余弦相似度都在 0.95 以上,扩增 100 个跟只扩增 10 个没有本质区别。这种问题通常出在条件输入的构造方式上。如果随机噪声的方差系数设得太小,或者融合模块里真实特征的权重占得太大,生成器就会学成“输入啥输出啥”的恒等映射。cReLU 在这里也起作用:如果激活函数没有保留足够的负向信息,噪声信息在中间层被抑制,输出自然会退化成输入的近似拷贝。

另一个可能的原因是噪声采样太早被丢弃。有的复现版本在生成器第一个卷积层之后就把噪声分量混在一起了,后续几层没有额外的随机注入,导致噪声贡献越来越弱。合理的做法是在多个尺度上叠噪声,或者对噪声分量做显式的通道级调节,让它有更直接的路径影响到最终输出。

排查方向:先打印生成样本和原始样本之间的平均距离,距离太近说明多样性约束失效;然后单独把噪声方差调大两个量级,观察生成样本距离是否变化,如果变化极小,问题多半出在网络结构的信息传播路径上。

4.2 训练发散或震荡:判别器过强

GAN 类模型训练不稳定是家常便饭。AFHN 虽然加了镜像梯度惩罚,但判别器依然可能过强,导致生成器的梯度信号没有意义。我调试的时候发现一个规律:如果把判别器的参数量或者层数堆得比生成器明显高出很多,前几百轮生成器的 loss 忽上忽下,损失曲线像锯齿一样。

这种时候优先做的不是调生成器,而是把判别器瘦身或者降低判别器的学习率。一个常用的比率是生成器学习率保持不变,判别器学习率降到它的三分之一或五分之一。这个小改动往往能肉眼可见地稳定训练曲线。此外,判别器输入端的特征也要做适当的标准化或者 grad clipping,防止极端的特征值把判别器权重带偏。

4.3 生成特征在新类上效果退步

有时同一个生成器,在基类上测试效果不错,但换到新类评测时,扩增特征对分类准确率的提升很小甚至为负。这个问题的本质是分布漂移。基类和新类的特征分布不可能完全一样,生成器在基类上学到的“变换模式”包含了一些基类特有的偏置,应用在新类上就不一定准确。

缓解手段有几个。一是在评测时把生成器的输入特征和生成特征都做一遍类内归一化,削弱绝对尺度差异,保留相对结构差异。二是把生成特征的规模控制在适中范围,不要一次性生成太多,比如每类 100 个左右通常比每类 500 个更能保持稳定,因为生成的样本多了,离群点出现的概率也会增加。三是可以在支持集特征上先做一个简单的非线性变换,让特征分布更紧凑,再交给生成器。

4.4 训练耗时长,骨干网络和生成器谁该先固定

这个问题在复现时很现实。训练的总体时间主要消耗在骨干网络上,因为它要处理完整的图像数据。生成器输入输出都是特征向量,训练成本相对低很多。我在实际实验里习惯分两阶段:先用基类数据把骨干网络训练到基本收敛,让特征具备足够的判别力,然后再联合训练生成器,此时骨干网络只做前向推理、不参与反传,会省下大量的时间。

联合阶段再跑大概几十个 epoch 就能看到生成特征质量的明显提升。如果一开始就让骨干网络和生成器完全同步训练,两者相互影响,整个训练过程会很慢,而且梯度来源混杂,骨干网络的特征质量未必能得到保证。分阶段训练还有一个好处:生成器的输入特征质量是稳定的,训练信号的方差会更小。

4.5 评估任务里分类器的选择

生成特征扩增好了,最后接的分类器选择也很关键。很多人习惯用线性分类器,因为它简单、不容易过拟合,但小样本场景下线性分类器往往不是上限最高的。我对比过几种设置在 5-way 5-shot 下的表现:一个简单的全连接分类器 + Softmax 交叉熵,一个基于余弦相似度的分类器,一个加上 Dropout 的全连接分类器。余弦相似度分类器配合生成特征,整体稳定性更好一些,尤其是在特征经过 L2 归一化之后,收敛速度快且不容易被个别极端特征带偏。

但我不会建议一上来就把分类器做得很复杂。先用一个简单的线性层,跑通整条流程、拿到基线结果,再逐步微调。如果一上来就上 MLP 多层分类器,最后效果不错,你很难判断是生成器起作用还是分类器本身的拟合能力在起作用,排查起来会很头疼。

5. 后续扩展思路与个人体会

5.1 与度量学习的融合方向

AFHN 的生成特征质量跟骨干网络特征的判别力高度绑定。如果骨干网络本身学到的特征空间不理想,生成器再强也难为无米之炊。一个自然的改进方向是,在骨干网络的训练目标中显式引入度量学习损失(比如 Triplet Loss 或者 原型损失),让相同类别的特征更聚拢、不同类别的特征更分散。度量空间的改善会直接传导给生成器,让它在更干净的空间里做增广,生成特征的语义保真度也会有明显提升。

5.2 引入类别语义信息的可能性

目前生成器的条件信息主要来自支持集特征的统计量和随机噪声。如果能把类别的语义描述也注入进来,比如某种类级别嵌入、文字描述向量,或者基类学习出来的类别原型矩阵,生成器在做特征增广时会有更强的诱导信号,不至于在完全隐含的语义空间里乱走。这个方向特别适合做跨领域迁移,因为语义描述可以充当不同类别之间共享的桥。

5.3 与 Transformer 或注意力机制的衔接

这篇论文的生成器主体是卷积结构。换成 Transformer 或注意力模块,效果也许不同。特征增广本质上是在特征空间里建模条件分布,自注意力机制可以在不同特征维度之间建立显式的依赖关系,有助于捕捉维度之间的协同变化模式。生成的特征也许能比 CNN 式生成器更贴近真实特征的高阶相关结构。不过代价是计算量上升,而且小数据场景下 Transformer 式生成器很容易过拟合,需要配合强正则化。

5.4 我个人的实验体会

我反复读这篇论文,也在自己的数据集上试过两轮实验。给我的总体感觉是,这套框架的价值不在某个模块多惊艳,而在于它把三件事拧在了一起:特征空间增广的高效率、对抗训练的分布逼真性、多样性和中心化约束带来的可用性。三者缺一都会出问题。光有对抗没有多样性约束,生成的样本再真实也帮不上分类器什么忙;光有多样性没有对抗约束,生成样本很可能跑偏到流形外部;两者都有但不用中心化约束,模型偶尔会产出跨类别的诡异样本。

如果你准备在某个具体项目里复现 AFHN,我最想提醒的是:不要拘泥于论文默认的超参数,一定要在自己的数据上重新调一次三类损失的权重和随机噪声的方差系数。这比改动网络结构带来的收益更大。另外,评估阶段不要只在一个任务划分上跑结果,先跑 600 个随机任务的均值再说,小样本场景单次任务的波动幅度远超你想象。

对于刚接触 few-shot learning 的朋友,这篇文章是一份很好的进阶材料:它把“生成模型怎么服务于判别任务”这件事讲得很清楚,而且每个技术点都能对应实际的工程意义。读的时候建议重点看生成器输入怎么构造、双对抗损失怎么配合、生成特征怎么反哺分类器,这三块拿下一篇文章就吃透了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询