想象你是一位新来的美食评委,要在国际美食节上打分,但你每个摊位只允许尝一口。法国菜你只吃过一口蜗牛,日本菜只尝过一片刺身,印度菜只抿过一勺咖喱——然而主办方要求你说出每道新端上来的菜属于哪个国家。这就是小样本分类(Few-shot Classification)的处境:每类只有几张“样本图片”,却要对大量新图片做出准确判断。这听起来像是不可能的任务,但人类其实每天都在做——孩子只看过两三张“熊猫”照片,就能在动物园里认出真熊猫。机器如何做到这件事?答案藏在“元学习”(Meta-Learning)里:不是学会“辨认猫”,而是学会“快速学会辨认任何东西”的技巧。本文将从原型网络、匹配网络、关系网络三大经典模型出发,带你拆解这个“只尝一口也能辨味”的魔法。

岗位关联

小样本分类是 AI 在数据稀缺场景落地的钥匙。掌握它,你将能在医疗影像、工业质检等领域用极少量标注样本构建可用模型,成为解决“数据荒”问题的稀缺人才——这正是众多 AI 团队求贤若渴的核心技能。

目录
  1. 可视化演示
  2. 小样本问题定义
  3. Episode训练策略
  4. 原型网络原理
  5. 匹配网络原理
  6. 关系网络原理
  7. 调参与实战
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

演示Episode采样构建、距离度量与原型计算、度量型方法对比,展示少样本学习如何用极少样本完成分类。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Episode采样构建 N-way K-shot: 每类K个支持样本 查询样本与支持集计算距离 最近原型决定查询分类 总结:Episode模拟小样本测试场景

小样本问题定义

想象你经营着一家“一人食”小餐馆,菜单上有 30 道菜,但每道菜你只吃过一口。这时来了一位顾客,端上一盘你没见过的菜,问你:“这属于哪个菜系?”你慌了——你只记得每道菜的一口味道,怎么判断?这就是小样本分类(Few-shot Classification)的核心处境。形式化地说,它要做的是:每个类别只有 K 张标注图片(K 通常为 1 或 5),面对一张全新的查询图片,判断它属于这 N 个类别中的哪一个。这就是经典的 "N-way K-shot" 任务:N 表示类别数量,K 表示每个类别给出的样本数量。

从技术视角看,小样本分类和常规分类有本质区别。常规分类是“题海战术”——ImageNet 上每类上千张图片,模型背下每一类的“标准答案”。小样本分类则是“突击考试”——每类只有 K 张图,模型必须在考试现场迅速“现学现卖”。它考验的不是“记住了什么”,而是“学得快不快”。这正是元学习(Meta-Learning)的切入点:我们希望模型学会的不是某个固定的分类函数,而是一个“快速适应新类别”的能力。

在元学习的框架下,小样本分类不再是一个单独的分类任务,而是被重构成一个“任务分布”。每个任务(Episode)从数据集中随机采样 N 个类别,每个类别取 K 张作为支持集(Support Set),再取若干张作为查询集(Query Set)。模型在每个任务上学习、预测、更新——如此反复,最终练就“看一眼就会”的本领。

模型训练后面对新的任务时,不再需要重新训练参数,而是利用支持集快速“校准”出一个分类器。这就像品鉴师尝过法国蜗牛、日本刺身、印度咖喱各一口后,就能在新菜上桌时迅速判断它属于哪个菜系——因为 TA 学会的不是某道菜的配方,而是“如何品鉴一道菜”的方法。

Few-shot Task: T={S,Q},S={(xi,yi)}i=1N×K\text{Few-shot Task: } \mathcal{T} = \{ \mathcal{S}, \mathcal{Q} \}, \quad \mathcal{S} = \{(x_i, y_i)\}_{i=1}^{N \times K}
一个少样本任务由支持集和查询集构成,支持集包含 N 个类别各 K 张带标签图片。
  1. 任务定义符用小任务集合 $\mathcal{T}$ 表示一个 Episode,它由支持集 $\mathcal{S}$ 和查询集 $\mathcal{Q}$ 两部分组成。
    T={S,Q}\mathcal{T} = \{ \mathcal{S}, \mathcal{Q} \}
  2. 支持集构成支持集是从 N 个类别中每个类取 K 张图得到的标注样本集合,下标 $i$ 从 1 到 $N \times K$ 遍历所有支持样本。
    S={(xi,yi)}i=1N×K\mathcal{S} = \{(x_i, y_i)\}_{i=1}^{N \times K}
  3. N-way K-shot 的含义N 控制任务难度(类别越多越难区分),K 控制信息量(每类样本越多越容易建模),两者组合出丰富的任务分布。
    N=#classes per episode,K=#samples per classN = \#\text{classes per episode}, \quad K = \#\text{samples per class}

Episode训练策略

如果一个学生只在考前背答案,考试时遇到没见过的题目就抓瞎。少样本训练也是如此——如果你用常规方式训练模型(把所有类别的图片混在一起反复迭代),模型只会记住“见过的猫长什么样”,而遇到一个新的狗品种时照样不认识。为了让模型练出“快速适应新类别”的能力,研究者发明了 Episode 训练策略(也叫元训练)。它的精髓在于:模拟考试——用与最终测试完全一致的方式训练。

假如你现在目标是训练一个人工智能“美食评论家”,你手里有一个包含上百种菜系的大数据集,每个菜系都有几十甚至上百张图片。Episode 训练的做法是这样的:在每一轮迭代中,随机抽取 N 个菜系(比如 5 个),每个菜系随机取 K 张图(比如 5 张)组成支持集,再从这个菜系中另取若干张组成查询集。然后让模型在支持集上“学习”(比如计算原型),在查询集上“考试”(计算分类损失)。下一轮,换 5 个从没抽到一起的菜系,重复这个过程。

这样做有三大好处。第一,任务级采样让模型每次面对的都是“新菜系组合”,相当于把它扔进一场场全新的模拟考,逼它学会“如何快速适应”而不是“背下答案”。第二,训练与测试同分布——测试时也是 N-way K-shot,模型在训练时的任务形态和测试完全一致,避免了“训练用 1000 类每类 100 张、测试用 5 类每类 5 张”这种巨大的分布鸿沟。第三,避免类别记忆过拟合——因为每次采样的类别组合都在变,模型不可能记住某个固定类别的固定特征,只能被迫学习“比较样本间关系”的通用策略。

在实际工程中,Episode 的数量通常是几千到几万不等。每个 Episode 内的数据量很小(比如 5 类 × 5 张 + 15 张查询图),因此一次迭代的计算量非常轻,通常几分钟就能跑完一个 epoch。另一个常用技巧是Episode 内批大小选择——查询集图片数不宜太多,一般每类 1~15 张,否则模型会过度拟合当前任务中的支持集细节。

Episode 训练策略就像模拟考制度:每一次模拟考(Episode)都从题库中随机抽题组成新试卷,学生(模型)在不断变化的试卷中练出了“通用的解题能力”。到了真正的考场(测试任务),面对的虽然是从未见过的题目组合,但考试形式一模一样,自然能从容应对。

ET∼p(T)[LT(fθ(ST),  QT)]\mathbb{E}_{\mathcal{T} \sim p(\mathcal{T})} \left[ \mathcal{L}_{\mathcal{T}} \left( f_{\theta}(\mathcal{S}_{\mathcal{T}}), \; \mathcal{Q}_{\mathcal{T}} \right) \right]
Episode 训练的目标是最小化所有随机采样任务上的期望损失,等价于“在各种模拟考中的平均失分最小化”。
  1. 任务期望符号$\mathbb{E}$ 表示期望,下标 $\mathcal{T} \sim p(\mathcal{T})$ 表示对所有从任务分布中采样的小任务求平均损失。
    ET∼p(T)\mathbb{E}_{\mathcal{T} \sim p(\mathcal{T})}
  2. 损失函数$\mathcal{L}$ 是分类损失,输入是模型在支持集上学到的参数(或原型)和查询集样本,输出是预测错误的惩罚。
    LT(fθ(ST),  QT)\mathcal{L}_{\mathcal{T}} \left( f_{\theta}(\mathcal{S}_{\mathcal{T}}), \; \mathcal{Q}_{\mathcal{T}} \right)
  3. 整体目标在每个任务上,先用支持集 $\mathcal{S}_{\mathcal{T}}$ 自适应(如计算原型),再对查询集 $\mathcal{Q}_{\mathcal{T}}$ 预测并计算损失,最终对全部任务平均——这就是“模拟考平均分最小化”。
    min⁡θ  ET∼p(T)[LT(fθ(ST),  QT)]\min_{\theta} \; \mathbb{E}_{\mathcal{T} \sim p(\mathcal{T})} \left[ \mathcal{L}_{\mathcal{T}} \left( f_{\theta}(\mathcal{S}_{\mathcal{T}}), \; \mathcal{Q}_{\mathcal{T}} \right) \right]

原型网络原理

2017 年,Snell 等人提出了原型网络(Prototypical Networks),它的核心思想只有一句话:“每个类别用所有支持样本的平均特征作为代表,查询样本离谁最近就归谁。”听起来像不像美食评委的做法?尝过三道法国菜后,在脑海中形成一个“法式风味的平均印象”;来一道新菜,尝一口,和哪个国家的平均印象最接近,就归类为哪个国家。这就是原型网络——用“平均口味”作为类别的名片。

具体来说,原型网络使用一个嵌入函数 $f_{\phi}$(通常是一个卷积神经网络)将图片映射到特征空间。对于类别 $k$ 的支持集 $\mathcal{S}_k$(包含 K 张图片),类别原型 $c_k$ 就是这些图片特征的均值向量:

得到所有类别的原型后,对于一张查询图片 $x_q$,计算其嵌入 $f_{\phi}(x_q)$ 到每个原型 $c_k$ 的距离 $d\left(f_{\phi}(x_q), c_k\right)$,然后通过 softmax 得到它属于每个类别的概率:

这里距离函数 $d$ 默认采用欧氏距离的平方(squared Euclidean distance)。你可能觉得奇怪:为什么不直接用余弦相似度?论文实验表明,在原型网络中,平方欧氏距离的表现优于余弦相似度,因为平方欧氏距离与“高斯分布假设下的对数似然”天然对应,数学上更自洽。

原型网络的训练方法完全遵循 Episode 策略:每个 Episode 中计算原型、预测查询集、用交叉熵损失更新 $\phi$。由于原型计算简单、可微,整个网络可以端到端训练。在实践中,原型网络是少样本分类中效果最稳健的基线之一,5-way 1-shot 在 miniImageNet 上能达约 49% 准确率,5-way 5-shot 能达约 68%。

原型网络的精妙之处在于它把“记忆”压缩成了“一个点”:不是记住 K 张图,而是记住一个平均向量。这就像美食评委不会刻意背诵每道菜的每个细节,而是提炼出“这个菜系的本质味道”。少即是多——一个精心提炼的原型,胜过一堆冗余的样本。

ck=1K∑(xi,yi)∈Skfϕ(xi)c_k = \frac{1}{K} \sum_{(x_i, y_i) \in \mathcal{S}_k} f_{\phi}(x_i)
pϕ(y=k∣xq)=exp⁡(−d(fϕ(xq),ck))∑k′exp⁡(−d(fϕ(xq),ck′))p_{\phi}(y = k \mid x_q) = \frac{\exp\left(-d\left(f_{\phi}(x_q), c_k\right)\right)}{\sum_{k'} \exp\left(-d\left(f_{\phi}(x_q), c_{k'}\right)\right)}
原型的本质是“支持集的浓缩”——可以用高维空间中的一点代表一整类样本。这就像餐厅为每道菜写了一行浓缩的“口味描述卡”,来新菜时只需要比对描述卡,而不必回忆每一口。
  1. 嵌入函数表示定义特征提取器 $f_{\phi}$,其中 $\phi$ 是网络参数;它把一张图片 $x_i$ 映射为一个特征向量。
    zi=fϕ(xi)∈Rdz_i = f_{\phi}(x_i) \in \mathbb{R}^d
  2. 计算类别原型对类别 $k$ 的 K 张支持集图片的特征向量求平均,得到该类的代表性向量 $c_k$。
    ck=1K∑(xi,yi)∈Skfϕ(xi)c_k = \frac{1}{K} \sum_{(x_i, y_i) \in \mathcal{S}_k} f_{\phi}(x_i)
  3. Softmax 概率公式查询样本到各原型的距离取负然后 softmax,距离越近概率越高。
    pϕ(y=k∣xq)=exp⁡(−d(fϕ(xq),ck))∑k′exp⁡(−d(fϕ(xq),ck′))p_{\phi}(y = k \mid x_q) = \frac{\exp\left(-d\left(f_{\phi}(x_q), c_k\right)\right)}{\sum_{k'} \exp\left(-d\left(f_{\phi}(x_q), c_{k'}\right)\right)}

匹配网络原理

如果说原型网络是“压缩记忆”,那匹配网络(Matching Networks)就是“原样保留,按比匹配”。它由 Vinyals 等人于 2016 年提出,思路像极了一个“人肉比对机”:新菜端上来,我先回忆每一道吃过的菜,看新菜和哪道菜味道最像,再综合所有相似度决定菜系——而不是先把每道菜的平均印象提炼出来再比对。

匹配网络的核心机制是注意力机制(Attention)。给定支持集 $\mathcal{S} = \{(x_i, y_i)\}_{i=1}^{N \times K}$ 和查询图片 $x_q$,预测标签的概率为:

其中 $a(x_q, x_i)$ 是注意力权重,它由余弦相似度经过 softmax 归一化得到:

请注意公式中的两个嵌入函数:$g$ 是查询图片的编码器,$f$ 是支持图片的编码器。匹配网络采用双编码器结构,而且支持集编码不是独立的——$f(x_i)$ 的计算会用到支持集中所有图片的上下文信息(通过 Bi-LSTM 或注意力池化实现),这被称为“全上下文嵌入”(Full Context Embeddings)。这样的设计让支持集样本在编码时互相“参考”,避免孤立地理解每张图。

匹配网络与原型网络的关键差异在于:原型网络先将支持集每个类别聚合成单个原型再比对(先压缩后匹配);匹配网络则保留每一个支持样本,让查询样本与每个样本逐一计算相似度,再加权求和(不压缩直接匹配)。这就像原型网络是“回忆菜系的平均口味”,而匹配网络是“回忆每一口吃过的味道,再综合判断”。

匹配网络在 5-way 1-shot 设置下表现尤为出色(miniImageNet 上约 43%~46%),因为它逐样本匹配的特性在样本极少时能利用“局部细节”——而原型网络在 5-shot 时更有优势,因为均值能平滑噪声。类比来说,原型网络是“抓大放小”的经验型评委,匹配网络是“锱铢必较”的细节控评委。当每类只有一张图时,细节控占优;当每类有多张时,经验型更稳。

p(y^∣xq,S)=∑i=1N×Ka(xq,xi)  yip(\hat{y} \mid x_q, \mathcal{S}) = \sum_{i=1}^{N \times K} a(x_q, x_i) \; y_i
a(xq,xi)=exp⁡(cos(g(xq),f(xi)))∑j=1N×Kexp⁡(cos(g(xq),f(xj)))a(x_q, x_i) = \frac{\exp\left(\text{cos}\left(g(x_q), f(x_i)\right)\right)}{\sum_{j=1}^{N \times K} \exp\left(\text{cos}\left(g(x_q), f(x_j)\right)\right)}
匹配网络的损失函数同样是查询集上的交叉熵。训练时任务(Episode)采样方式和原型网络完全一致,但每次预测要遍历所有支持样本计算注意力,计算量更大但表达更灵活。
a(xq,xi)=exp⁡(cos(g(xq),f(xi)))∑jexp⁡(cos(g(xq),f(xj)))a(x_q, x_i) = \frac{\exp\left(\text{cos}\left(g(x_q), f(x_i)\right)\right)}{\sum_{j} \exp\left(\text{cos}\left(g(x_q), f(x_j)\right)\right)}
匹配注意力:查询图片和支持集中的每张图分别算余弦相似度,再用 softmax 规整为权重,与类别标签加权求和即得预测。
  1. 余弦相似度计算$g(x_q)$ 和 $f(x_i)$ 分别编码查询和支持图片,两者做余弦相似度衡量方向一致性,值域 $[-1, 1]$。
    cos(g(xq),f(xi))=g(xq)⋅f(xi)∥g(xq)∥  ∥f(xi)∥\text{cos}\left(g(x_q), f(x_i)\right) = \frac{g(x_q) \cdot f(x_i)}{\|g(x_q)\| \; \|f(x_i)\|}
  2. Softmax 归一化对所有支持样本的相似度取指数归一化,得到和为 1 的注意力权重向量;相似度越高权重越大。
    a(xq,xi)=exp⁡(cos(g(xq),f(xi)))∑jexp⁡(cos(g(xq),f(xj)))a(x_q, x_i) = \frac{\exp(\text{cos}(g(x_q), f(x_i)))}{\sum_{j} \exp(\text{cos}(g(x_q), f(x_j)))}
  3. 预测为加权和每个支持样本的标签 $y_i$(one-hot 向量)乘以注意力权重后求和,得到各类概率——本质上是“按相似度投票”。
    p(y^∣xq,S)=∑ia(xq,xi)  yip(\hat{y} \mid x_q, \mathcal{S}) = \sum_{i} a(x_q, x_i) \; y_i

关系网络原理

原型网络和匹配网络的距离函数都是固定的(欧氏距离或余弦相似度)——评委的“口味比对规则”是事先定死的。关系网络(Relation Networks)则更进一步:它要学习一个距离函数。Sung 等人 2018 年提出:为什么不训练一个“关系打分器”,让它自己学会评判两道菜有多像?就像新来的美食评委先尝一批菜,观察哪些菜被归为同一菜系,然后自己摸索出“评判相似度”的经验法则,而不是硬套“味道浓的就是川菜”这类先验规则。

关系网络的结构由两个模块组成:嵌入模块(Embedding Module,所有样本共享)和关系模块(Relation Module,一个可学习的打分网络)。给定支持集样本 $x_i$ 和查询样本 $x_j$,先把两者送入嵌入模块得到特征向量,然后将两个特征向量在通道维度上拼接,形成一对样本的组合表示,最后送入关系模块输出一个标量“关系分数”:

其中 $[\cdot, \cdot]$ 表示拼接(concatenation),$f_{\phi}$ 是嵌入函数,$g_{\varphi}$ 是关系函数。训练时,把同一类别的样本对标记为“匹配”(关系分数目标为 1),不同类别的样本对标记为“不匹配”(目标为 0),用均方误差(MSE)回归损失端到端训练。预测时,计算查询样本与每个支持样本的关系分数,取分数最高的类别作为预测结果。

关系网络的设计理念是“端到端度量学习”:它不在嵌入空间中预设某种几何关系,而是让网络在数据驱动下自行发现“什么样的特征距离意味着同类”。这使得关系函数可以表达非线性、非对称的相似度关系——比如“白色羽毛 + 橙色喙”才像天鹅,单独看任何一个特征都不够。这种非线性表达能力远超固定的欧氏距离或余弦相似度。

关系网络在 5-way 5-shot miniImageNet 上可超过 65% 的准确率,说明“学习的度量”确实优于“固定度量”。但代价是训练时间更长——每次预测要计算 $N \times K$ 次关系打分,比原型网络的多一次均值运算慢得多。选择模型时需要权衡:数据噪声大、特征复杂时,关系网络的学习式度量更优;对推理速度要求高时,原型网络的简洁更实用。

ri,j=gφ([fϕ(xi),  fϕ(xj)])r_{i,j} = g_{\varphi} \left( \left[ f_{\phi}(x_i), \; f_{\phi}(x_j) \right] \right)
关系网络是三位评委里最灵活的一位:原型网络靠“平均印象”找共性,匹配网络靠“逐一对号”找细节,而关系网络直接学习“评判规则”本身——它不关心特征长什么样,只关心如何衡量差异才算对。
LMSE=∑i,j(ri,j−1(yi=yj))2\mathcal{L}_{MSE} = \sum_{i,j} \left( r_{i,j} - \mathbb{1}(y_i = y_j) \right)^2
MSE 损失让关系分数向“同类为 1、异类为 0”回归,网络上自动学习出最佳的相似度衡量方式。
  1. 拼接组合表示支持样本和查询样本各自的嵌入特征拼接为一个更长的向量,作为关系模块的输入——相当于把两道菜的味道信息“合在一张品鉴表”上。
    [fϕ(xi),  fϕ(xj)]\left[ f_{\phi}(x_i), \; f_{\phi}(x_j) \right]
  2. 关系函数打分$g_{\varphi}$ 是一个小型神经网络(通常 2~3 层卷积 + 全连接),输入拼接向量,输出标量关系分数。
    ri,j=gφ([fϕ(xi),  fϕ(xj)])r_{i,j} = g_{\varphi} \left( \left[ f_{\phi}(x_i), \; f_{\phi}(x_j) \right] \right)
  3. MSE 回归目标$\mathbb{1}(y_i = y_j)$ 是示性函数,同类为 0,异类为 1;MSE 最小化预测分数与真实标签之间的距离。
    LMSE=(ri,j−1(yi=yj))2\mathcal{L}_{MSE} = \left( r_{i,j} - \mathbb{1}(y_i = y_j) \right)^2

调参与实战

掌握了三种网络结构,真正让模型在任务上“起飞”的关键是实验调参。这就像三位美食评委虽然都懂品鉴原理,但有的擅长清淡菜系,有的偏好重口味——在实际操作中,模型组件选择和超参配置会对最终准确率产生巨大影响。本节总结几条实战中验证过的小样本分类调参经验。

骨干网络选择:在少样本场景下,网络容量并非越大越好。常用骨干是 ResNet-12 或 ConvNet-4(4 层卷积),而不是 ResNet-50 等大网络。原因是每类只有 5 张图,大数据集上表现优异的大模型极易在小样本上过拟合;适度规模的骨干网络配合在 ImageNet 上的预训练权重,往往比从头训练的深网络效果更好。简单来说——评委不是越资深越好,而是“能适应小样本评审节奏”的最佳。

距离度量选型:原型网络标配欧氏距离平方;匹配网络标配余弦相似度;关系网络则不用人工指定度量。实验表明,在原型网络上将欧氏距离替换为余弦相似度会显著掉点(约 3~5%),因为欧氏距离平方隐含了各维度同尺度的假设,恰好与平均化原型形成良性配合。调参时应当“尊重新结构的标配”,不要随意混搭。就像评审蜂蜜时不能用辣椒酱的标准——每个工具都要配它设计时适配的度量。

Episode 数量与批大小:训练时 Episode 总数通常在 1 万到 5 万之间,批次大小(每次并行处理的任务数)常见为 2~16。过大的批大小会造成内存瓶颈且收益递减;过小的批大小则梯度噪声大。5-way 5-shot 任务中,每 Episode 每类查询图一般取 5~15 张,查询图太少则训练不充分,太多则单任务过拟合。

数据增强技巧:小样本训练最怕过拟合,随机裁剪、随机翻转、颜色抖动是最常用且有效的增强手段。特别是随机裁剪(random crop)配合缩放,可利用“多尺度局部特征”让模型学到更鲁棒的表示。还可以将支持集每张图做多次增强后扩充到支持集里——比如把 5 张图裁剪成 20 张,相当于增加支持集的信息量,不少论文中这个技巧能带来 2~4% 的提升。这就好比评委在品尝一道菜时,从不同角度闻香、观察色泽,而不是只吃一口了事。

小样本分类的调参没有银弹。MiniImageNet 上表现最好的组合(ResNet-12 + 欧氏距离 + 丰富增强)到了医学影像小样本任务上未必最优。真正的做法是建立一个快速迭代的验证流程:固定一个强大基线(比如原型网络),在基准数据集上先复现论文结果,然后逐项替换组件观察增益。就像美食评委面对陌生菜系时,先按标准流程品鉴,再逐步调整自己的评判侧重点——稳扎稳打,比盲目追求花哨技巧更能带来可靠的效果。

Accuracy5-way 5-shot≈model capacity−overfitting+augmentation bonus\text{Accuracy}_{5\text{-way } 5\text{-shot}} \approx \text{model capacity} - \text{overfitting} + \text{augmentation bonus}
这条“经验公式”想表达:准确率不是模型越强越好,而是要在表示能力与过拟合风险之间取得平衡,数据增强则带来稳定的正向收益。
  1. 模型容量的双向效应$\text{model capacity}$ 越大,嵌入特征越丰富,但相应地过拟合风险 $\text{overfitting}$ 也越高。
    model capacity−overfitting\text{model capacity} - \text{overfitting}
  2. 增强带来的正收益数据增强相当于在极少样本的约束下扩充了有效信息量,$\text{augmentation bonus}$ 为最终准确率做出正向贡献。
    final accuracy≈balance term+augmentation bonus\text{final accuracy} \approx \text{balance term} + \text{augmentation bonus}

AI 应用场景

工业缺陷检测小样本方案

阶段:模型训练阶段与数据准备阶段

解决的问题:在传统工业质检中,每种缺陷类型需要收集成百上千张标注图片才能训练分类模型。但实际流水线上,新型缺陷出现频率极低,往往只能收集到几张到十几张样例。传统 CNN 分类器在数据不足时严重过拟合,漏检率居高不下。采用原型网络,只需每类 5 张缺陷图片构建“缺陷原型”,即可对新增缺陷类型进行有效检测,将标注成本降低 90% 以上。

具体案例:某电子元器件装配厂需要检测焊点上 7 种缺陷(虚焊、桥连、冷焊等),历史数据中“虚焊”仅有 12 张标注图片。工程师用 ResNet-12 做骨干,在历史大数据(含部分正常样本)上预训练嵌入,再用原型网络对 7 类缺陷各自计算原型。上线后对查询图的分类准确率达到 91.3%,比传统迁移学习方案提升了 18 个百分点。

医疗影像罕见病辅助诊断

阶段:模型推理阶段与在线学习阶段

解决的问题:罕见病医学影像数据全球可能只有几百例,每家医院能接触到的只有几张到几十张。传统的监督学习需要大规模标注数据,在罕见病场景几乎不可行。匹配网络的“逐样本对比”特性特别适合此场景——医生可以持续把新确诊的病例图像加入支持集,系统立即获得对新患者影像的分类能力,无需重新训练。类比米其林评委不断品尝新菜、更新自己的味觉记忆库。

具体案例:某三甲医院眼科引入小样本分类系统辅助诊断 3 种罕见眼底病变。系统初始支持集为每类 5 张专家标注的眼底照片。运行 6 个月内,医生陆续补充了 30 张新确诊图像进入支持集,系统分类准确率从 84.2% 提升到 92.6%,且每次更新只需重算原型(分钟级),无需等待数小时的模型重训练。

电商新商品自动归类

阶段:数据准备阶段与推理阶段

解决的问题:电商平台每天上架数万种新品,很多新品类(如“露营灯”、“空气炸锅纸”)历史上没有训练数据。传统分类器只能识别训练集中出现过的固定类目。采用关系网络,运营人员只需为每个新类目提供 3~5 张商品图,关系网络学习“这组图和这个类目标签是否匹配”,即可对新商品进行自动归类。关系网络的可学习度量能捕捉商品间微妙的视觉共性(如“带按钮的圆柱体”可能属于电子烟配件),这是固定距离函数难以做到的。

具体案例:某跨境电商平台使用关系网络处理 200 个新兴类目的自动归类任务。运营团队为每个新类目收集 5 张样本图,系统对新品图片的归类 Top-1 准确率达到 87.5%;相比人工标注成本降低 70%,上新效率提升 3 倍。

Python 演示

python118 行
import torchimport torch.nn as nnimport torch.optim as optimimport numpy as np class ConvEmbedder(nn.Module):    """4层卷积嵌入网络,将图片映射到64维特征向量"""    def __init__(self):        super().__init__()        self.encoder = nn.Sequential(            nn.Conv2d(3, 64, 3, padding=1), nn.BatchNorm2d(64), nn.ReLU(),            nn.MaxPool2d(2),            nn.Conv2d(64, 64, 3, padding=1), nn.BatchNorm2d(64), nn.ReLU(),            nn.MaxPool2d(2),            nn.Conv2d(64, 64, 3, padding=1), nn.BatchNorm2d(64), nn.ReLU(),            nn.MaxPool2d(2),            nn.Conv2d(64, 64, 3, padding=1), nn.BatchNorm2d(64), nn.ReLU(),        )        self.fc = nn.Linear(64, 64)     def forward(self, x):        h = self.encoder(x)        h = h.mean(dim=[2, 3])  # 全局平均池化        return self.fc(h)  def euclidean_dist(a, b):    """计算查询特征到原型特征的平方欧氏距离"""    n = a.shape[0]    m = b.shape[0]    a2 = (a ** 2).sum(dim=1, keepdim=True).expand(n, m)    b2 = (b ** 2).sum(dim=1, keepdim=True).expand(m, n).T    dist2 = a2 + b2 - 2 * torch.mm(a, b.T)    return dist2.clamp(min=0)  def create_episode(features, labels, n_way, k_shot, q_query):    """从特征池中采样一个 N-way K-shot Episode"""    classes = torch.unique(labels).tolist()    selected = np.random.choice(classes, n_way, replace=False)    support_x, support_y, query_x, query_y = [], [], [], []    for i, cls in enumerate(selected):        idx = (labels == cls).nonzero().squeeze(1)        perm = torch.randperm(len(idx))        s_idx = idx[perm[:k_shot]]        q_idx = idx[perm[k_shot:k_shot + q_query]]        support_x.append(features[s_idx])        support_y.append(torch.full((k_shot,), i))        query_x.append(features[q_idx])        query_y.append(torch.full((q_query,), i))    return (torch.cat(support_x), torch.cat(support_y),            torch.cat(query_x), torch.cat(query_y))  def train_one_epoch(model, features, labels, optimizer, n_way=5, k_shot=5, q_query=15):    model.train()    total_loss = 0.0    for _ in range(100):  # 100 个 Episode 为一个 epoch        s_x, s_y, q_x, q_y = create_episode(features, labels, n_way, k_shot, q_query)        s_emb = model(s_x)        q_emb = model(q_x)         # 计算每类原型:按标签对支持集特征求均值        prototypes = torch.stack([            s_emb[s_y == c].mean(dim=0) for c in range(n_way)        ])         # 查询样本到各原型的欧氏距离 → softmax 概率        dist = euclidean_dist(q_emb, prototypes)        logits = (-dist).softmax(dim=1)         loss = nn.functional.cross_entropy(logits, q_y)        optimizer.zero_grad()        loss.backward()        optimizer.step()        total_loss += loss.item()    return total_loss / 100  # 模拟运行:随机生成 64 维特征作为"图片嵌入"(真实场景中替换为 CNN 输出的特征)if __name__ == "__main__":    torch.manual_seed(42)    np.random.seed(42)     # 模拟数据集:60 个类,每类 20 个样本,特征维度 64    n_classes = 60    features = torch.randn(n_classes * 20, 3, 32, 32)    labels = torch.repeat_interleave(torch.arange(n_classes), 20)     # 划分训练/验证类别(30 类训练,30 类验证)    train_mask = labels < 30    train_feats, train_labels = features[train_mask], labels[train_mask]    val_feats, val_labels = features[~train_mask], labels[~train_mask]     model = ConvEmbedder()    optimizer = optim.Adam(model.parameters(), lr=1e-3)     # 训练 3 个 epoch    for epoch in range(3):        loss = train_one_epoch(model, train_feats, train_labels, optimizer)        print(f"Epoch {epoch + 1}: avg loss = {loss:.4f}")     # 验证:5-way 1-shot 准确率    model.eval()    correct = total = 0    with torch.no_grad():        for _ in range(200):            s_x, s_y, q_x, q_y = create_episode(val_feats, val_labels, n_way=5, k_shot=1, q_query=5)            s_emb = model(s_x)            q_emb = model(q_x)            prototypes = torch.stack([                s_emb[s_y == c].mean(dim=0) for c in range(5)            ])            dist = euclidean_dist(q_emb, prototypes)            pred = dist.argmin(dim=1)            correct += (pred == q_y).sum().item()            total += q_y.shape[0]    print(f"5-way 1-shot validation accuracy: {correct / total:.2%}")
目的:从零实现原型网络的 Episode 训练与 5-way 1-shot 评估流程,展示“支持集求均值得到原型,查询集以距离最近原则分类”的完整链路。
  1. class ConvEmbedder(nn.Module)4 层卷积网络作为嵌入函数,把 32×32 图片映射为 64 维特征向量;最后一层全连接把特征压缩到可度量空间。
  2. def euclidean_dist(a, b)用展开公式 $\|a-b\|^2 = \|a\|^2 + \|b\|^2 - 2ab^T$ 批量计算平方欧氏距离,避免逐对循环。
  3. def create_episode(...)从特征池中随机采样 N 个类、每类 K 个支持样本和 Q 个查询样本,构造一个完整的 Episode——模拟考出题过程。
  4. support_y.append(torch.full((k_shot,), i))为支持样本构造重整后的类别标签(0~N-1),而不是原始类别编号——让模型每次只关心“本任务内的类别区分”。
  5. prototypes = torch.stack([...])对每类支持样本特征求均值,得到 N 个原型向量——构建每道菜的“口味名片”。
  6. logits = (-dist).softmax(dim=1)欧氏距离取负后做 softmax 得到各类别概率,距离越小概率越高,这就是“离谁近归谁”。
  7. loss = nn.functional.cross_entropy(logits, q_y)用查询集上的交叉熵损失回传更新嵌入网络参数——考试失分后纠正品鉴标准。

常见误区

误区我以为小样本分类就是把常规分类器的训练数据减少到每类 5 张,其余流程(batch 采样、损失函数)都不变。结果模型严重过拟合,准确率只有 30%,我一度怀疑小样本方法都是骗人的。

正解小样本分类的核心不是“数据变少”,而是“训练范式改变”。Episode 训练(每次随机采样 N 类 K 张模拟测试场景)才是关键。普通分类器训练时所有类别一起迭代,学到的是“类别专属特征”;Episode 训练让模型每轮面对不同类别组合,被迫学会“比较样本关系”的通用能力。就像模拟考制度——普通训练是反复做同一套卷子,Episode 训练是每次做新卷子。

为何常见:大多数人接触深度学习都是从常规监督学习入门的,“数据集 → 模型 → 损失 → 更新”的思维定式根深蒂固,容易忽略小样本方法独特的任务采样范式。

误区反正支持集是给模型参考的,那每类多放几张图(比如 50 张)不就更准吗?我在实验里确实看到准确率提升了,但有人说这不叫小样本分类了。

正解支持集大小由任务定义决定。小样本分类的任务设定就是每类 1~5 张图,如果把 K 扩大到 50,问题退化为常规少数据分类,不再属于小样本范畴。更重要的是,小样本方法在 K 很小时表现出的“快速适应”能力,在 K 变大后不一定最优——原型网络在 K=50 时反而不如微调一个预训练分类器。每种方法有它的舒适区。

为何常见:直觉上“更多信息 = 更好结果”在机器学习中根深蒂固;小样本分类反直觉的地方在于,它的价值恰恰是在信息极度受限的条件下依然保持可用。

误区原型网络把每类 K 张图的特征求个平均,这个“平均脸”一定是最佳类别代表。如果均值效果不好,那肯定是嵌入网络不够好。

正解均值原型假设类别在特征空间中是“单峰分布”(一个中心点就能代表)。但真实数据往往是多模态的——比如“鸟类”类别中既有白鹭又有孔雀,平均后的原型可能落在两者之间空空如也的区域,既不接近任何真实样本。这时匹配网络的逐样本注意力或关系网络的可学习度量更能捕捉复杂的类内结构。

为何常见:均值是入门统计学的第一课,人们习惯于用均值代表整体。但高维特征空间中的均值可能毫无意义——它可能落在数据流形之外,就像“鸟的平均照片”从不存在于自然界。

误区关系网络可以学习距离度量,原型网络只能用固定的欧氏距离,所以关系网络“理论上”应该全面碾压原型网络。我在小数据集上测试后发现关系网络确实高 2%,但训练速度慢 3 倍。

正解没有绝对最优的模型,只有最适合任务的模型。关系网络的“可学习度量”优势在有足够训练数据时才能发挥;在训练 Episode 数量很少时,它容易过拟合到训练任务分布,反而不如原型网络的简洁归纳偏置稳健。论文原实验中,关系网络在 5-shot 设置下和原型网络持平甚至稍低。

为何常见:人们潜意识里认为“更复杂 = 更强大”。但在小样本学习中,更强的模型容量往往带来更高的过拟合风险,简单方法在数据受限时反而是最优选择——这就是“少即是多”的机器版本。

误区我在做图像检索时一直用余弦相似度,效果不错。所以小样本分类的距离度量我也先用余弦相似度,结果原型网络的准确率只有 42%,而论文里用欧氏距离是 68%。我以为是代码写错了。

正解度量函数的选择必须和模型结构、特征分布配合。原型网络把多个样本特征平均后作为原型,此时欧氏距离平方与“高斯分布均值”的似然估计天然对应,数学上自洽;而余弦相似度只考虑方向、不考虑模长,会丢失原型向量的长度信息(这个长度反映了类内样本的紧凑程度)。匹配网络用余弦相似度是因为它不聚合均值,逐样本比对时方向一致性更稳定。度量选型要和“特征如何聚合”一起考虑。

为何常见:很多人在图像检索/人脸验证中习惯了余弦相似度,产生了路径依赖。但小样本分类的度量选择本质上是“嵌入空间的几何设计问题”,不同空间结构需要不同的度量工具。

面试题

Q1. 关于 N-way K-shot 任务定义,下列说法正确的是?

单选题 · easy

  • A.N 是每类样本数,K 是类别数
  • B.N 是类别数,K 是每类支持样本数← 正确答案
  • C.N 和 K 分别表示训练和测试图片数
  • D.N 表示网络层数,K 表示卷积核大小

答案:B。N-way K-shot 中 N 表示每轮任务(Episode)中抽取的类别数量,K 表示每个类别提供的带标签支持样本数量。比如 5-way 5-shot 就是 5 个类别、每类 5 张支持图,查询图再从这些类别中抽取。选项 A 把 N 和 K 的含义搞反了。

Q2. 小样本分类中“支持集”(Support Set)的作用是什么?

单选题 · easy

  • A.用于预训练嵌入网络的大规模数据集
  • B.用于测试时提供每类的 K 张带标签参考样本← 正确答案
  • C.用于验证模型泛化能力的无标签图片集
  • D.用于存储模型参数的额外存储空间

答案:B。支持集是小样本任务中每个类别给出的 K 张带标注图片,模型仅在测试时“看一眼”这些图片就做出分类决策。选项 A 是预训练数据集的角色,选项 C 描述的是查询集或者无监督集的角色,选项 D 与存储有关但与分类任务无关。

Q3. Episode 训练策略的核心思想是什么?

单选题 · mid

  • A.每次迭代从数据集中随机抽取大量图片组成大批次训练
  • B.每次迭代构造一个 N-way K-shot 的模拟任务,在支持集上学习、查询集上验证← 正确答案
  • C.每次迭代用全部类别以降低采样偏差
  • D.每次迭代只用一个类别来避免类别间干扰

答案:B。Episode 训练(元训练)模仿测试环境的任务结构,每轮从数据集中随机采样 N 个类别、每个类别 K 张支持图和若干查询图组成一个小任务,模型在支持集上快速适应、在查询集上计算损失并更新。这就像模拟考——每次考试都是新的题目组合,训练出来的是“快速适应能力”而非“记住固定类别”。

Q4. 原型网络中,类别原型(Prototype)是如何计算的?

单选题 · mid

  • A.对支持集中所有样本的特征做加权平均,权重来自注意力机制
  • B.对支持集中该类所有样本的特征向量取平均← 正确答案
  • C.对查询集中该类样本的预测概率取最大值
  • D.对支持集中所有类别的样本特征做全局平均

答案:B。原型的计算公式为 $c_k = \frac{1}{K}\sum f_{\phi}(x_i)$,即对类别 k 的 K 张支持集图片特征求数学平均。A 选项是匹配网络的做法(注意力加权),不是原型网络;C 选项用查询集预测值反推原型是本末倒置;D 选项把类别间的特征混在一起,会完全破坏类别区分度。

Q5. 匹配网络与原型网络最核心的区别是什么?

单选题 · mid

  • A.匹配网络使用卷积网络,原型网络使用 Transformer
  • B.匹配网络保留每个支持样本做逐样本注意力匹配,原型网络聚合为类原型后再匹配← 正确答案
  • C.匹配网络不支持 Episode 训练,原型网络支持
  • D.原型网络不需要嵌入函数,匹配网络需要

答案:B。匹配网络将查询样本与每个支持样本逐一计算余弦相似度并加权求和,不进行类别级聚合;原型网络先将每类支持样本特征平均成一个原型向量,再计算查询样本到各原型的距离。这就是“逐一对号”和“先浓缩再比对”的根本差异。

Q6. 在原型网络中使用余弦相似度替代平方欧氏距离,通常会导致:

单选题 · hard

  • A.准确率大幅提升,因为余弦相似度对尺度不敏感
  • B.准确率下降,因为平方欧氏距离与原型的高斯均值假设更匹配← 正确答案
  • C.准确率不变,因为两种度量在 softmax 下等价
  • D.训练无法收敛,因为余弦相似度不可导

答案:B。原型网络的原型是均值向量,平方欧氏距离对应高斯分布的对数似然,数学上自洽;余弦相似度忽略向量模长,丢失了类内样本紧凑度信息,实际实验中原型网络的余弦相似度版本准确率明显逊于欧氏距离版本。C 选项不正确——softmax 的单调变换不改变 argmax,但改变概率分布和梯度行为,效果并不等价。

Q7. 关系网络的关系模块输出的是什么?

单选题 · easy

  • A.查询样本属于每个类别的概率分布
  • B.支持样本与查询样本之间的“关系分数”实数值← 正确答案
  • C.支持样本经过嵌入后的特征向量
  • D.嵌入网络的梯度更新方向

答案:B。关系网络将支持样本特征与查询样本特征拼接后送入关系模块,输出一个标量关系分数(0~1),表示两者的相似程度。训练时用 MSE 让同类对的分数趋近 1、异类对趋近 0,最终取关系分数最高的类别作为预测。它的不同于 softmax 概率分布,而是一个回归输出。

Q8. 关于 Episode 训练策略的优势,下列说法正确的有?

多选题 · mid

  • A.让模型学会快速适应新任务而非记忆固定类别← 正确答案
  • B.训练时的任务结构与测试时完全一致← 正确答案
  • C.可以显著减少训练所需的总图片数量
  • D.避免模型对特定类别组合产生过拟合← 正确答案

答案:ABD。Episode 训练通过随机采样类别组合构造大量模拟任务,使模型学会“如何学习”(选项 A);训练任务与测试任务同为 N-way K-shot 结构,分布一致(选项 B);不断变化的类别组合使模型无法依赖记忆固定组合,从而避免过拟合(选项 D)。选项 C 错误——Episode 训练只是改变采样方式,并不会减少数据的总需求量。

Q9. 以下哪些做法可以有效缓解小样本分类中的过拟合?

多选题 · hard

  • A.使用更大容量的骨干网络(如 ResNet-152)
  • B.训练时对支持集图片做随机裁剪、翻转等数据增强← 正确答案
  • C.在 ImageNet 上预训练后微调嵌入网络← 正确答案
  • D.增加支持集每类的样本数量到 100 张

答案:BC。数据增强(B)能增加支持集的有效样本多样性,是小样本场景最常用的抗过拟合手段;预训练(C)给模型提供了良好的特征初始化,大幅降低从头训练时的过拟合风险。A 错误——更大容量的网络在数据匮乏时过拟合更严重;D 错误——把 K 从 5 增加到 100 改变了任务定义,已不再是标准小样本分类。

Q10. 关于原型网络、匹配网络和关系网络的比较,正确的有?

多选题 · hard

  • A.原型网络在 5-shot 时往往优于 1-shot,因为均值能平滑噪声← 正确答案
  • B.匹配网络在 1-shot 时更有优势,因为逐样本匹配保留了细节信息← 正确答案
  • C.关系网络无需人工设计距离函数,表达能力最强,训练也最快
  • D.三种网络都可以使用 Episode 训练策略端到端学习← 正确答案

答案:ABD。原型网络的均值聚合在 K 增大时噪声被平滑、原型更稳定(A 正确);匹配网络逐样本对比不丢失细节,在仅有一个样本时优势明显(B 正确);三种网络都基于 Episode 元学习范式,可以端到端训练(D 正确)。C 错误——关系网络虽然不需要人工指定度量,但关系模块增加了参数量和计算量,训练速度反而最慢。