Skip to content

输入关键词开始搜索

Omniglot 小样本学习实验:ProtoNet 为什么比直接微调更稳


在很多实际任务里,数据并不总是充足的。

比如医学影像中的罕见病分类、工业质检中的少见缺陷识别、司法文本中的特殊案例判断,这些任务往往很难为每个类别收集大量标注样本。传统监督学习通常依赖较多训练数据,一旦每个类别只有几个样本,模型就很容易过拟合,也很难学到稳定的分类边界。

小样本学习要解决的问题就是:当每个新类别只有极少样本时,模型能不能快速适应?

这次实验选择 Omniglot 数据集,使用 Prototypical Networks 进行 N-way K-shot 分类,并和一个直接微调的 baseline 做对比。实验重点不是追求最强精度,而是理解小样本学习中“度量学习”为什么有效。


本次实验使用的是 Omniglot 手写字符数据集。它包含多个字母系统中的手写字符类别,每个类别样本数量较少,因此很适合用来测试 few-shot learning 方法。

实验中的任务形式是 N-way K-shot:

  • N-way:一次分类任务中包含 N 个类别;
  • K-shot:每个类别只给 K 个 support 样本;
  • query set:模型需要根据 support set 识别 query 样本的类别。

例如 5-way 1-shot 表示:一次任务中有 5 个类别,每个类别只给 1 个已标注样本,然后模型要判断 query 图像属于哪一类。

这次实验评估了四种设置:

设置含义
5-way 1-shot5 个类别,每类 1 个 support 样本
5-way 5-shot5 个类别,每类 5 个 support 样本
20-way 1-shot20 个类别,每类 1 个 support 样本
20-way 5-shot20 个类别,每类 5 个 support 样本

其中 5-way 任务相对简单,20-way 任务更难;1-shot 更考验模型的快速适应能力,5-shot 则能提供更稳定的类别信息。


Prototypical Networks 的核心思想很直观:每个类别可以用一个“原型”表示,query 样本离哪个原型最近,就被分到哪个类别。

具体来说,模型首先用一个卷积神经网络把图像编码成 embedding。对于 support set 中的每个类别,计算该类别所有 support embedding 的平均值,这个平均向量就是类别原型。

如果是 1-shot,那么每个类别只有一个 support 样本,这个样本的 embedding 本身就是原型。

如果是 5-shot,那么每个类别有 5 个 support 样本,模型会取它们 embedding 的均值作为原型。这样可以降低单个样本偶然性的影响。

分类时,模型计算 query embedding 与每个类别原型之间的距离。距离越近,属于该类别的可能性越高。

在代码中,这个过程可以简化成三步:

support_embeddings = encoder(support_x)
query_embeddings = encoder(query_x)
prototypes = compute_prototypes(support_embeddings, support_y, ways)
distances = torch.cdist(query_embeddings, prototypes, p=2) ** 2
logits = -distances
loss = F.cross_entropy(logits, query_y)

这里的 logits = -distances 很关键。距离越小,负距离越大,模型就越倾向于把 query 分到这个类别。


为了验证 ProtoNet 是否真的有优势,我设计了一个 Direct Fine-tuning baseline。

这个 baseline 的做法是:在每个测试 episode 中,新建一个分类头,然后只用 support set 做若干步梯度更新,最后在 query set 上测试准确率。

它更接近一种朴素思路:既然有少量样本,那就直接拿这些样本微调模型。

不过这种方法有一个明显问题:support set 太小。尤其在 1-shot 场景中,每个类别只有一张图片,直接微调很容易被单个样本的细节带偏。它不仅容易过拟合,而且每个 episode 都要重新训练,测试成本也比 ProtoNet 更高。

ProtoNet 则不需要在测试阶段做梯度更新,只要计算类别原型和距离即可。


实验使用一个简单的 Conv4 Encoder 作为特征提取网络。网络结构由 4 个卷积模块组成,每个模块包含:

Conv2d -> BatchNorm2d -> ReLU -> MaxPool2d

输入图像被 resize 到 28×28,经过 4 次池化后得到一个 64 维 embedding。

训练阶段使用 Omniglot background split,测试阶段使用 evaluation split。这样可以保证测试类别没有在训练阶段出现过,更符合小样本学习中“适应新类别”的设定。

主要配置如下:

项目设置
数据集Omniglot
输入尺寸1 × 28 × 28
EncoderConv4
主训练任务5-way 1-shot
每类 query 数15
训练 episode1000
测试 episode200
优化器Adam
学习率1e-3
baselineDirect Fine-tuning

这次实验没有直接使用 learn2learn,而是手写 episode sampler 和 ProtoNet 训练逻辑。这样虽然代码稍微长一点,但 support set、query set、prototype、distance、episode training 这些概念都能在代码中直接看到,理解起来更清楚。


最终得到的结果如下:

method5-way 1-shot5-way 5-shot20-way 1-shot20-way 5-shot
Direct Fine-tuning0.8562 ± 0.01330.9495 ± 0.00610.6911 ± 0.00780.8212 ± 0.0061
Prototypical Networks0.9172 ± 0.01000.9727 ± 0.00390.7688 ± 0.00740.9162 ± 0.0037

为了更直观地观察两种方法在不同 N-way K-shot 设置下的表现,我把四组结果画成了折线图。

Omniglot 小样本分类中 Prototypical Networks 与 Direct Fine-tuning 的准确率对比

可以看到,Prototypical Networks 在四种设置下都高于 Direct Fine-tuning。5-way 5-shot 是最容易的设置,两种方法都能取得较高准确率;20-way 1-shot 是最困难的设置,准确率明显下降。

两种方法的准确率差距如下:

设置ProtoNet - Direct Fine-tuning
5-way 1-shot+0.0610
5-way 5-shot+0.0232
20-way 1-shot+0.0777
20-way 5-shot+0.0950

除了最终准确率,我也记录了 ProtoNet 在训练过程中的 loss 和 episode accuracy。

Prototypical Networks 在 Omniglot 上训练过程中的 loss 曲线

训练初期 loss 较高,而且波动比较明显。随着 episode 数增加,loss 整体快速下降,并逐渐稳定在较低水平。中后期仍然会出现一些尖峰,这是 few-shot episode training 中很常见的现象,因为每个 episode 都是随机采样出来的小任务,不同任务的难度并不完全一致。

Prototypical Networks 在 Omniglot 上训练过程中的 episode accuracy 曲线

从 episode accuracy 可以看到,模型在训练早期已经快速学到有效的类别区分能力。后期大多数 episode 的准确率接近 1.0,但仍然存在局部下降。这同样来自 episode 之间的难度差异,比如某些字符类别外观更相似,模型更容易混淆。

这两张训练曲线说明,ProtoNet 并不是简单记住固定类别,而是在大量 episode 中学习一种可迁移的度量空间。训练过程中每个 episode 的类别组合都不同,模型需要不断学习“如何比较样本之间的相似性”。


8.1 ProtoNet 在所有设置下都更稳定

Section titled “8.1 ProtoNet 在所有设置下都更稳定”

在 5-way 1-shot 设置中,ProtoNet 的准确率为 91.72%,Direct Fine-tuning 为 85.62%,提升了 6.10 个百分点。

这个结果说明,在每类只有一个样本的情况下,直接微调模型并不是最稳的选择。support set 太小,梯度更新容易受到单个样本影响。ProtoNet 不直接依赖少量样本去更新参数,而是使用已经学到的 embedding 空间来计算类别原型,因此表现更稳定。

无论是 ProtoNet 还是 Direct Fine-tuning,5-shot 的表现都明显好于 1-shot。

以 ProtoNet 为例:

设置Accuracy
5-way 1-shot0.9172
5-way 5-shot0.9727

当每个类别有 5 个 support 样本时,类别原型不再由单个样本决定,而是由多个样本的 embedding 平均得到。这样得到的 prototype 更能代表整个类别,因此分类效果更好。

Direct Fine-tuning 也有类似趋势。更多 support 样本意味着更可靠的梯度更新,过拟合风险相对降低。

类别数增加后,任务难度会显著上升。

ProtoNet 在 5-way 1-shot 中达到 91.72%,而在 20-way 1-shot 中下降到 76.88%。Direct Fine-tuning 也从 85.62% 下降到 69.11%。

这很好理解。5-way 任务只需要在 5 个候选类别中做判断,而 20-way 任务需要在 20 个类别中选择。候选类别越多,query 样本被错误原型吸引的概率也越高。

8.4 ProtoNet 在复杂任务中优势更明显

Section titled “8.4 ProtoNet 在复杂任务中优势更明显”

最值得注意的是 20-way 5-shot 结果。

ProtoNet 达到 91.62%,Direct Fine-tuning 只有 82.12%,差距达到 9.50 个百分点。

这说明当类别数变多时,ProtoNet 学到的 embedding 空间依然具有较好的泛化能力。相比直接在少量 support 样本上微调,基于距离的原型分类更适合这种类别快速切换的场景。


9. 为什么 ProtoNet 更适合小样本分类

Section titled “9. 为什么 ProtoNet 更适合小样本分类”

这次实验让我更直观地理解了 ProtoNet 的优势。

第一,ProtoNet 把分类问题转化成距离度量问题。模型不需要为每次新任务重新训练一个复杂分类器,只要判断 query 样本和各类原型之间的距离即可。

第二,类别原型具有很强的解释性。每个 prototype 都可以理解为某一类在 embedding 空间中的中心点。query 离哪个中心点近,就被归到哪个类别。

第三,ProtoNet 测试阶段不需要梯度更新。Direct Fine-tuning 每个 episode 都要重新微调,计算成本更高,也更容易被 support set 中的噪声影响。

第四,K-shot 增加时,ProtoNet 可以自然地利用更多样本。多张 support 图像的 embedding 平均后,原型会更稳定,这也是 5-shot 结果明显好于 1-shot 的原因。


小样本学习中还有一类典型方法是 MAML。MAML 的核心目标是学到一个好的初始化参数,让模型在面对新任务时,只需要少量梯度更新就能快速适应。

ProtoNet 的思路不太一样。它不是强调“如何快速更新参数”,而是强调“如何学到一个适合比较样本相似性的特征空间”。

可以简单理解为:

方法直觉
MAML学一个好初始化,让模型能快速微调
ProtoNet学一个好 embedding 空间,让同类样本靠近、异类样本远离
Direct Fine-tuning直接在少量 support 样本上更新模型

这次实验中的 Direct Fine-tuning baseline 更接近朴素微调方式。结果显示,在 support set 很小的情况下,直接微调不如 ProtoNet 稳定。


这次实验中遇到的主要问题不在模型本身,而在环境和数据准备。

一开始我尝试使用 learn2learn,但安装过程容易卡住。后来改为手写 episode sampler,这样不仅减少了依赖问题,也更容易看清小样本学习的完整流程。

Omniglot 数据集下载时也可能因为 GitHub 访问问题卡住。最后采用了本地 zip 检查、代理下载、有效 zip 校验和手动解压的方式,保证数据加载过程更稳定。

从实验实现角度看,最关键的是 episode 的组织方式。普通监督学习通常是按 batch 随机取样,而 few-shot learning 的训练 batch 本身就是一个小任务。每个 episode 都包含 support set 和 query set,模型需要在这种任务结构中学习如何快速完成分类。


这次 Omniglot 小样本分类实验验证了一个很清晰的结论:在样本极少的分类任务中,Prototypical Networks 比直接微调更稳定。

在 5-way 1-shot、5-way 5-shot、20-way 1-shot 和 20-way 5-shot 四种设置下,ProtoNet 都取得了更高的准确率。尤其在 20-way 5-shot 中,ProtoNet 比 Direct Fine-tuning 高出 9.50 个百分点,说明当类别数变多时,基于原型的度量分类仍然能保持较好的泛化能力。

这也说明,小样本学习并不是简单地“拿少量样本继续训练模型”。更重要的是让模型在训练阶段学到一种可迁移的比较能力,使它在面对新类别时,可以用很少样本快速建立类别表示。

如果把这类方法放到实际任务中,它更适合那些标注成本高、类别变化快、每个新类别样本很少的场景,比如医学图像、工业缺陷识别、罕见类别检测和个性化分类任务。