想象你第一次来到郊外观星,夜空中散落着三片隐约可见的星群:一片呈勺状,一片呈十字,一片呈弯弧。你只认识其中几颗最亮的星,却要判断一颗新出现的星星属于哪一片星群。直觉做法是:先找到每片星群的大致中心——那些亮星围绕的“共同重心”,再看新星离哪个中心最近。这就是 Prototypical Networks(原型网络)的核心思想:用极少量的样本来计算每个类别的“星光重心”(即原型向量),然后按距离把新样本归入最近的星座。这篇教程没有复杂的数学推导,而是从星空直觉出发,带你一步步认识原型网络如何完成小样本分类,并理解它的公式、代码与实战价值。

岗位关联

掌握原型网络,你便打通了小样本分类的经典基线,也为后续理解 MAML、CNAPS 等更复杂的元学习算法铺好了跳板。它是 AI 工程师进阶元学习领域的必经一站。

目录
  1. 可视化演示
  2. 核心思想:每个类别都有“重心”
  3. 模型结构:观星者的三件套
  4. 原型向量:支撑集求均值
  5. 距离度量:直线还是方向?
  6. 训练策略:用“情景”练就观星术
  7. Matching 对比:一对一与一对多
  8. 代码实践:从星空到 PyTorch
  9. 局限展望:星空亦有边界
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

展示时域信号波形与其频域频谱的对应关系,通过调节频率和噪声观察信号分解过程。

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

时域与频域分析 青色曲线为时域信号波形 橙色柱为频域频谱分量 X(k) = Σ x(n)·e^(-j2πkn/N) FFT将信号从时域转换到频域。

核心思想:每个类别都有“重心”

回到观星的场景。你之所以能判断新星星属于哪片星群,不是因为记住了每一颗已知星的位置,而是因为每片星群都有一个“视觉中心”——所有星星环绕着它聚拢。只要这片星群没有被完全打散,中心就具有代表性,新星的归属也就有了依据。这个“视觉中心”,就是类别的原型(prototype)。

在原型网络中,每个类别的原型不是凭空给出的,而是通过对该类别所有已知样本(称为支撑集,support set)的特征向量取平均得到的。为了让“平均”有意义,我们需要先把原始样本送进一个神经网络,将其映射到一个嵌入空间(embedding space)。在这个空间里,属于同一类别的样本彼此靠近,就像同一个星座的星星天然聚在一起。支撑集的平均位置就构成了类别原型。

形式化地说,假设支撑集里类别 $k$ 的样本集合为 $S_k$,经过嵌入函数 $f_\phi$ 后,该类的原型向量定义为:

一句话总结:原型网络之所以“能打”,是因为它把复杂的分类任务化简为“找重心 + 比远近”,就像观星者只需记住每片星群的大致中心,而不是每一颗星的精确位置。

ck=1∣Sk∣∑(xi,yi)∈Skfϕ(xi)c_k = \frac{1}{|S_k|} \sum_{(x_i, y_i) \in S_k} f_\phi(x_i)
这个公式可以理解为:把类内所有已知样本的“坐标”求一个平均坐标,这个平均坐标就是该类在嵌入空间中的“星座重心”。
  1. 文本中的符号约定$x_i$ 是第 $i$ 个原始样本,$y_i$ 是其类别标签;$S_k$ 表示所有属于类别 $k$ 的支撑样本组成的集合。
    (xi,yi)∈Sk(x_i, y_i) \in S_k
  2. 嵌入函数是什么$f_\phi$ 是一个带参数 $\phi$ 的神经网络,把原始样本 $x_i$ 变成向量 $f_\phi(x_i)$,同一类样本做相同映射后更接近。
    xi↦fϕ(xi)x_i \mapsto f_\phi(x_i)
  3. 求和是在做什么把所有支撑样本的嵌入向量逐位相加,等价于把所有“星星坐标”按维度累加。
    ∑(xi,yi)∈Skfϕ(xi)\sum_{(x_i, y_i) \in S_k} f_\phi(x_i)
  4. 平均的意义用集合大小 $|S_k|$ 求平均,得到类别 $k$ 的中心 $c_k$,即原型向量。
    ck=1∣Sk∣∑(xi,yi)∈Skfϕ(xi)c_k = \frac{1}{|S_k|} \sum_{(x_i, y_i) \in S_k} f_\phi(x_i)

模型结构:观星者的三件套

观星者通常随身携带三样东西:望远镜、星图和量角器。望远镜负责看清星星(提取特征),星图负责标记已知星群(保存支撑集),量角器负责测量角度和距离(判断远近)。原型网络的结构恰好对应这三个组件。

第一个组件是特征提取网络,即嵌入函数 $f_\phi$。它扮演望远镜,把原始图像或特征向量映射到嵌入空间。第二个组件是原型计算模块,它不训练参数,而是做一次简单的算术:把同一类的支撑样本嵌入取平均,得出每个类的原型。第三个组件是距离分类头,它对查询样本与各个原型求距离,再将负距离转换为类别置信度。

整个推理流程可以表示为一个概率公式:给定查询样本 $x$,它属于类别 $k$ 的概率由查询嵌入 $f_\phi(x)$ 与原型 $c_k$ 的距离决定:

这套结构和观星工具一一对应:望远镜负责看清特征,星图负责存样本,量角器负责算距离。三件套缺一不可。

pϕ(y=k∣x)=exp⁡(−d(fϕ(x),ck))∑k′=1Kexp⁡(−d(fϕ(x),ck′))p_\phi(y = k \mid x) = \frac{\exp\left(-d(f_\phi(x), c_k)\right)}{\sum_{k'=1}^{K} \exp\left(-d(f_\phi(x), c_{k'})\right)}
距离 $d$ 越小,指数部分越大,概率越高。这就像新星离哪个星群重心更近,就越可能属于那片星群。
  1. 负距离的作用距离 $d$ 越大说明越不相似,加负号变成越大越相似的得分。
    −d(fϕ(x),ck)-d(f_\phi(x), c_k)
  2. 指数核化对得分取指数,把“差距”放大成非负权重,同时保证计算稳定。
    exp⁡(−d(fϕ(x),ck))\exp\left(-d(f_\phi(x), c_k)\right)
  3. 分母归一化对全部 $K$ 个类别的指数求和,把所有类的分数压缩成总和为 1 的概率分布。
    ∑k′=1Kexp⁡(−d(fϕ(x),ck′))\sum_{k'=1}^{K} \exp\left(-d(f_\phi(x), c_{k'})\right)

原型向量:支撑集求均值

你可能会问:为什么要用“平均”来代表一个类别?难道一个类别内部没有差异吗?当然有,但小样本场景下我们没有太多信息,平均是一种最稳的估计——就像做饭时不知道每个人口味,最安全的做法是取“大众口味”的平均值。原型向量就是类别信息在嵌入空间中的“大众口味”。

从数学上看,原型向量是对支撑集嵌入的类内平均。这个操作有两个好处:第一,它不引入额外可学习参数,完全由支撑集直接计算,因此面对新类别时无需微调模型;第二,它天然支持任意数量的类别,只需要对每个类分别求均值即可。值得注意的是,虽然“平均”听起来简单,但真正重要的是嵌入函数 $f_\phi$。如果嵌入函数训练得好,同类样本的嵌入自然聚拢,平均值就极具代表性;如果嵌入函数混乱,平均值也会失去意义。所以原型网络的全部学习压力都集中在嵌入网络上——这就像观星者不仅要有一张好星图,更关键的是有一台能把星星“看清”的好望远镜。

在实际训练中,支撑集通常由 $N$ 个类别、每类 $K$ 个样本组成,即所谓的 $N\text{-way } K\text{-shot}$ 设定。$K$ 越小,计算出的原型噪声越大,但原型网络的价值恰恰是在 $K=1$ 或 $K=5$ 时依然保持可用。原型向量的计算完全透明、可解释,这是它优于许多黑箱模型的重要特质。

距离度量:直线还是方向?

有了原型之后,剩下的问题就是“怎么算距离”。现实中,判断两颗星星是否属于同一片星群,既可以用它们之间的直线距离(欧氏距离),也可以用它们之间的方向夹角(余弦距离)。两种度量方式对应两种不同的几何直觉。

欧氏距离关注的是绝对位置差:

它计算查询样本嵌入与原型向量在嵌入空间中的直线长度。余弦距离关注的是方向一致性:

它先算两个向量夹角的余弦值(角度越小,余弦越接近 1),再用 1 减去它得到“距离”。

在实践中,原论文作者发现欧氏距离在小样本分类任务上普遍优于余弦距离。原因是欧氏距离对向量长度更敏感,与“类别中心”的几何结构更匹配:如果把嵌入网络看作一个线性判别模型,欧氏距离下的原型分类恰好等价于高斯判别分析,具有更扎实的理论支持。而余弦距离强行忽略了模长信息,反而丢失了一部分判别能力。当然,在某些语义场景下,余弦距离仍可作为备选。

deuclid(x,ck)=∥fϕ(x)−ck∥2d_{\text{euclid}}(x, c_k) = \left\| f_\phi(x) - c_k \right\|_2
dcos(x,ck)=1−fϕ(x)⋅ck∥fϕ(x)∥2∥ck∥2d_{\text{cos}}(x, c_k) = 1 - \frac{f_\phi(x) \cdot c_k}{\| f_\phi(x) \|_2 \| c_k \|_2}
欧氏距离回答“离得有多远”,余弦距离回答“方向有多像”。如果嵌入向量的长度本身包含重要信息,欧氏距离更合适;如果只关心语义方向,余弦距离更合适。
  1. 欧氏距离的计算对两个向量逐位相减后取平方和,再开根号,得到实际直线长度。
    ∥fϕ(x)−ck∥2=∑j=1d(fϕ(x)j−ck,j)2\| f_\phi(x) - c_k \|_2 = \sqrt{\sum_{j=1}^{d} (f_\phi(x)_j - c_{k,j})^2}
  2. 余弦相似度两向量的内积除以各自的模长乘积,结果落在 $[-1, 1]$,越大表示方向越一致。
    cos⁡(fϕ(x),ck)=fϕ(x)⋅ck∥fϕ(x)∥2∥ck∥2\cos(f_\phi(x), c_k) = \frac{f_\phi(x) \cdot c_k}{\| f_\phi(x) \|_2 \| c_k \|_2}
  3. 转成距离用 1 减去余弦相似度,相似度越高,距离越接近 0。
    dcos=1−cos⁡(fϕ(x),ck)d_{\text{cos}} = 1 - \cos(f_\phi(x), c_k)

训练策略:用“情景”练就观星术

原型网络不是在普通数据集上一次性训练,而是采用Episode 元训练策略。观星者不是靠死记硬背某一片夜空来学习,而是反复在随机挑选的若干片星域中练习“找重心”的能力;每次练习都面对一组全新的星群组合。这就逼迫他学会通用的方法,而不是记住特定星空。

每个 episode 的具体流程是:先从全部类别中随机抽取 $N$ 个类别,再从这 $N$ 个类中各自抽取支撑集($K$ 个样本)和查询集($Q$ 个样本)。原型网络用支撑集计算原型,再对查询集样本进行分类,最后用分类误差更新嵌入网络的参数。这样一个 episode 就是一个完整的“小规模多分类任务”,模型的每一次更新都发生在任务层面,而不是样本层面。

训练所用的损失函数是查询集上的负对数似然:

通过大量随机组合的 episode 训练,模型学会了在不同类别组合下都能快速找到“重心”并正确分类。这种“见多识广”恰如观星者阅遍无数星域,最终形成了通用的星群识别能力。

L=−1∣Q∣∑(xi,yi)∈Qlog⁡pϕ(yi∣xi)\mathcal{L} = -\frac{1}{|Q|} \sum_{(x_i, y_i) \in Q} \log p_\phi(y_i \mid x_i)
这个损失衡量的是:模型对查询样本真实类别给出的概率,平均起来离 1 有多远。概率越接近 1,损失越小。
  1. 单样本对数项对查询样本 $x_i$ 的真实类别概率取对数,概率越大,$\log$ 值越接近 0。
    log⁡pϕ(yi∣xi)\log p_\phi(y_i \mid x_i)
  2. 负号与平均取负号使损失为正,再对全部 $|Q|$ 个查询样本求平均,得到该 episode 的整体损失。
    −1∣Q∣∑(xi,yi)∈Qlog⁡pϕ(yi∣xi)-\frac{1}{|Q|} \sum_{(x_i, y_i) \in Q} \log p_\phi(y_i \mid x_i)

Matching 对比:一对一与一对多

在元学习的星空中,原型网络并不孤独。它的近亲 Matching Networks(匹配网络) 同样支持小样本分类,但两者的机制有微妙差异。打个比方:Matching Networks 像是观星者对星空图中的每一颗已知星都单独比对,新星与每颗星分别测距离,再按加权投票决定归属;原型网络则是先把同类星星汇总成一个“代表星星”,再只与代表比远近。

Matching 网络通过注意力机制计算查询样本与所有支撑样本的加权求和,相当于保留每个支撑样本的独立影响。而原型网络先做一次均值聚合,把支撑集压缩成类别原型,再去算距离。这意味着原型网络的计算量更小——查询样本只需和 $N$ 个原型比较,而 Matching 网络需要和全部支撑样本逐个比较。当支撑集很大时,原型网络的推理速度优势非常明显。

但两者并非谁绝对更好。在分布较为复杂、同类样本内部呈多峰分布时,Matching 网络保留逐样本信息的做法可能更有弹性;而在支撑集规模有限、类别边界清晰时,原型网络的均值归纳更稳健。实际选型时,通常把原型网络作为首选基线,因为它是当之无愧的“最简可行方案”,而且解释性更强——原型本身就是一种可解释的类别表征。

代码实践:从星空到 PyTorch

理论落地向来是新手最关心的环节。原型网络的代码并不复杂,核心步骤只有数据组织、模型定义、训练循环和评估。我们先在合成高斯点云数据上模拟“观星”任务:4 片星群(4 个类),每片星群取 5 个已知点(5-shot),其余点作为查询集。嵌入网络用简单的多层感知机即可。

训练阶段的核心是 sample_episode 函数:它从数据集中随机挑类、随机挑支撑集和查询集。模型先用支撑集算出原型,再用欧氏距离分类查询集,最后用交叉熵损失反向传播更新嵌入网络。评估阶段与训练几乎一致,只需在未见过的类别组合上计算准确率即可。整套逻辑与前面讲的“观星术”完全吻合——随机星域 + 找重心 + 比远近。

Python 代码部分将在第 5 节给出完整实现。你可以在本地运行,观察不同 N-way K-shot 配置对准确率的影响,这能帮助你建立起对小样本分类任务最直观的体感。

局限展望:星空亦有边界

原型网络虽然优雅,但并不是万能的。它最大的局限在于数据稀缺:当支撑集每类只有 1 个样本时,原型的方差会非常大,就像只凭一两颗星星很难确定星群重心。另一个问题是分布漂移:如果测试时新类别的数据分布与训练时差异很大,原型的均值估计就会失真,分类效果大打折扣——这好比你在北半球练熟了看星的技巧,突然被扔到南半球,熟悉的星群全变了样。

为了应对这些局限,研究者提出了若干改进方向:一是多原型方法,允许一个类别拥有多个原型,以刻画类内的多峰分布;二是半监督扩展,利用无标注数据来修正原型位置;三是与度量学习结合,通过更强大的嵌入函数让同类样本在嵌入空间中更加紧凑。这些方向都是在原型网络这个坚实基线之上的自然延伸。

理解原型网络的边界,与理解它的优点同样重要。就像一位成熟的观星者,既知道如何用星群重心快速判断归属,也知道何时该拿出星图辅助、何时该借助更精密的仪器。

AI 应用场景

罕见病影像识别

阶段:小样本分类落地

解决的问题:罕见病在临床上样本极其稀缺,难以为每个病种准备充足的训练数据。传统监督学习在样本不足时严重过拟合,模型难以泛化。原型网络通过在大量已知病种上训练嵌入网络,使新病种只需要几张标注影像即可快速建立分类原型,完成识别。

具体案例:某医院积累了 2000 张常见皮肤病的皮肤镜影像,但新引入的一种罕见皮肤病的标注图像只有 8 张。医生使用原型网络在 2000 张常见病影像上元训练嵌入网络,再加入 8 张罕见病图像作为支撑集,模型立刻可以对新患者影像进行分类,无需重新训练。原型向量的可视化还帮助医生验证了模型关注区域的合理性。

新品类商品识别

阶段:增量学习与上线部署

解决的问题:电商平台每周都会上架全新品类的商品,传统分类器需要重新收集大量数据、重训模型,周期长且成本高。原型网络的“无需微调即支持新类”特性,让运营人员只需为新品类上传少量样例,就能在嵌入空间中立即生成原型并开始分类。

具体案例:某电商平台在鞋服分类系统中部署原型网络。当出现“洞洞鞋”这一新品类时,运营人员上传 5 张不同角度的商品图,系统自动计算新类别原型,并即刻对所有新商品图完成分类。整个过程不到 10 分钟,而旧方案需要一周的数据标注与模型重训周期。

Python 演示

python105 行
"""Prototypical Networks 原型网络:合成小样本分类"""import torchimport torch.nn as nnimport torch.optim as optimimport numpy as np class EmbeddingNet(nn.Module):    """把原始 2D 坐标映射到嵌入空间的编码器"""    def __init__(self, input_dim=2, hidden_dim=64, output_dim=8):        super(EmbeddingNet, self).__init__()        self.encoder = nn.Sequential(            nn.Linear(input_dim, hidden_dim),            nn.ReLU(),            nn.Linear(hidden_dim, hidden_dim),            nn.ReLU(),            nn.Linear(hidden_dim, output_dim)        )     def forward(self, x):        return self.encoder(x)  def compute_prototypes(support_emb, support_y, num_classes):    """对每个类别求支撑集嵌入的均值,得到原型向量"""    prototypes = []    for cls in range(num_classes):        mask = support_y == cls        class_emb = support_emb[mask]        prototypes.append(class_emb.mean(dim=0))    return torch.stack(prototypes)  def euclidean_distance(x, y):    """批量计算查询嵌入与所有原型之间的欧氏距离"""    x2 = (x ** 2).sum(dim=1, keepdim=True)    y2 = (y ** 2).sum(dim=1, keepdim=True)    cross = 2.0 * torch.matmul(x, y.t())    return torch.sqrt(x2 + y2.t() - cross + 1e-8)  def train_one_episode(model, optimizer, support_x, support_y,                      query_x, query_y, num_classes):    """单个 episode 训练:嵌入->原型->距离->损失->反向传播"""    model.train()    support_emb = model(support_x)    query_emb = model(query_x)    prototypes = compute_prototypes(support_emb, support_y, num_classes)    dists = euclidean_distance(query_emb, prototypes)    logits = -dists    loss = nn.functional.cross_entropy(logits, query_y)    optimizer.zero_grad()    loss.backward()    optimizer.step()    return loss.item()  def sample_episode(features, labels, num_classes, support_size, query_size):    """从数据集随机采样一个 episode:选类、抽支撑集和查询集"""    classes = np.random.choice(np.unique(labels), num_classes, replace=False)    support_x, support_y, query_x, query_y = [], [], [], []    for new_cls, old_cls in enumerate(classes):        idx = np.where(labels == old_cls)[0]        np.random.shuffle(idx)        support_idx = idx[:support_size]        query_idx = idx[support_size:support_size + query_size]        for i in support_idx:            support_x.append(features[i])            support_y.append(new_cls)        for i in query_idx:            query_x.append(features[i])            query_y.append(new_cls)    return (torch.tensor(np.stack(support_x), dtype=torch.float32),            torch.tensor(support_y, dtype=torch.long),            torch.tensor(np.stack(query_x), dtype=torch.float32),            torch.tensor(query_y, dtype=torch.long))  def main():    """在 4 类高斯点云合成数据上训练原型网络"""    np.random.seed(42)    torch.manual_seed(42)    num_classes, support_size, query_size = 4, 5, 15    means = np.array([[0, 0], [4, 0], [0, 4], [4, 4]])    features, labels = [], []    for cls, mean in enumerate(means):        points = np.random.randn(200, 2) * 0.8 + mean        features.append(points)        labels.extend([cls] * 200)    features = np.concatenate(features)    labels = np.array(labels)     model = EmbeddingNet()    optimizer = optim.Adam(model.parameters(), lr=1e-3)    for epoch in range(200):        s_x, s_y, q_x, q_y = sample_episode(            features, labels, num_classes, support_size, query_size)        loss = train_one_episode(model, optimizer, s_x, s_y, q_x, q_y,                                 num_classes)        if (epoch + 1) % 50 == 0:            print("epoch %d | loss %.4f" % (epoch + 1, loss))    print("训练完成")  if __name__ == "__main__":    main()
目的:在一个 4 类高斯点云合成数据集上,实现并训练一个原型网络,演示“支撑集求原型 + 欧氏距离分类 + episode 元训练”的完整流程。
  1. class EmbeddingNet(nn.Module)定义嵌入网络,把原始 2D 坐标映射到 8 维嵌入空间,网络参数就是全部的“可学习参数”。
  2. self.encoder = nn.Sequential(...)三层线性层加 ReLU 激活,构成一个简单的特征提取器。
  3. def compute_prototypes(...)遍历每个类别,用布尔掩码筛出该类支撑样本,然后 mean(dim=0) 求原型。
  4. prototypes.append(class_emb.mean(dim=0))这是原型计算的核心:类内嵌入的均值。
  5. def euclidean_distance(x, y)用平方展开方式计算两两欧氏距离,避免显式写循环。
  6. logits = -dists把距离取负号,距离越近得分越高,作为 logits。
  7. loss = nn.functional.cross_entropy(logits, query_y)对查询集计算交叉熵损失,驱动嵌入网络更新。
  8. def sample_episode(...)随机选类、随机抽支撑集与查询集,构造一个元学习任务。
  9. classes = np.random.choice(np.unique(labels), num_classes, replace=False)从数据集中不重复抽取 4 个类别。
  10. for epoch in range(200)训练 200 个 episode,每个 episode 都面对不同的类别组合。

常见误区

误区原型就是支撑集样本直接求平均,跟嵌入网络没关系;只要有了支撑集,不做任何训练也能分类。网上很多简化教程让初学者以为原型网络“零训练”。

正解原型向量虽然是支撑集均值,但均值计算建立在嵌入网络已经训练好的前提上。嵌入网络决定了样本在空间中的分布方式——如果嵌入很差,同类样本的均值可能落在其他类附近,分类自然一塌糊涂。原型网络的本质是“训练一个优秀的嵌入网络”,均值只是最后临门一脚。就像星群中心只有在星星已经按星座聚集时才有意义,如果满天星星乱序排列,求出的“中心”没有任何代表性。

为何常见:因为原型向量的计算式子太过简单,初学者容易忽略背后的嵌入训练,误以为完全不需要学习过程。

误区反正都是度量距离,欧氏距离和余弦距离在原型网络里可以任意替换,效果差别不大。有些同学在实现时随手换成 cosine 距离,以为只是换一行代码的事。

正解原论文的实验表明,在小样本分类基准上,欧氏距离显著优于余弦距离。原因在于欧氏距离保留了向量的模长信息,在训练良好的嵌入空间中,样本距离原型的“绝对距离”具有判别力;而余弦距离只比较方向,丢弃了模长这一维宝贵的信息。换距离度量相当于换了整个分类空间的几何结构,不是简单替换。

为何常见:大量自监督学习(如 SimCSE)和对比学习模型都偏爱余弦相似度,容易让初学者形成惯性思维,误以为所有向量任务都该用余弦距离。

误区直觉上总认为加大支撑集规模(比如从 5-shot 加到 50-shot),原型网络的分类准确率就会无限提高。

正解支撑集越大,原型的方差确实会降低,但最终效果还受嵌入空间质量的约束。如果嵌入网络的表达能力不足,或者不同类别的分布本身高度重叠,即便支撑集再大,原型的区分度也不会提升。此外,随着支撑集规模增大,episode 内数据分布的多样性增加,模型反而可能面临“元训练与元测试不匹配”的问题。原型网络的设计初衷就是小样本场景,盲目扩大支撑集偏离了它的适用区间。

为何常见:传统监督学习的经验告诉我们“数据越多越好”,这种思维惯性与元学习任务的目标存在根本冲突。

面试题

Q1. 原型网络中原型向量的定义是什么?

单选题 · easy

  • A.某个支撑样本的原始输入向量
  • B.类别内所有支撑样本嵌入的平均向量← 正确答案
  • C.查询样本对应的嵌入向量
  • D.神经网络第一个隐藏层的输出

答案:B。原型向量由支撑集样本经嵌入网络映射后取均值得到(B 正确)。A 丢掉嵌入映射,C 是查询嵌入,D 是网络中间特征,均非类别原型。

Q2. 原型网络进行小样本分类时,新样本的类别如何确定?

单选题 · easy

  • A.随机选择一个类别
  • B.找到距离最近的那个类别的原型← 正确答案
  • C.与所有支撑样本逐一比较取投票
  • D.直接输出预设类别

答案:B。原型网络将查询样本嵌入,再与各类原型计算距离,归入距离最小的类别。C 是一对一比对,属于 Matching Networks 的做法。

Q3. 在 N-way K-shot 设定中,“N-way”和“K-shot”分别指什么?

单选题 · mid

  • A.N个类别、每类K个支撑样本← 正确答案
  • B.N个支撑样本、K个类别
  • C.N个查询样本、K个测试集
  • D.N个训练集、K个验证集

答案:A。N-way 代表每次任务使用 N 个类别,K-shot 代表每个类别提供 K 个支撑样本。这是小样本学习任务的标准描述。

Q4. 原型网络的训练为什么要用 Episode 方式?

单选题 · mid

  • A.为了避免过拟合单个样本
  • B.让模型学会面对新类别组合快速分类← 正确答案
  • C.减少数据加载的内存占用
  • D.因为交叉熵只能用于 episode

答案:B。Episode 元训练随机组合类别与样本,模拟测试时“见到新类别”的场景,迫使模型学会通用的原型归纳与距离判断能力,而不是记忆特定类别。

Q5. 欧氏距离与余弦距离在原型网络中的区别是什么?

单选题 · mid

  • A.欧氏距离关注方向,余弦距离关注长度
  • B.欧氏距离关注绝对位置,余弦距离关注方向夹角← 正确答案
  • C.两者数学上完全等价
  • D.余弦距离计算更慢

答案:B。欧氏距离计算空间中两点直线长度,对向量模长敏感;余弦距离只关注向量的方向夹角。原型网络的实验表明欧氏距离通常更优。

Q6. 原型网络与 Matching Networks 最本质的差异是什么?

单选题 · mid

  • A.原型网络不用嵌入网络
  • B.原型网络先把同类样本聚合成原型,再算距离← 正确答案
  • C.Matching 不需要支撑集
  • D.两者没有任何区别

答案:B。Matching Networks 对每个支撑样本单独计算注意力权重,原型网络则先用均值聚合出类别原型,再以“查询到原型”的距离分类,计算量更小、归纳更强。

Q7. 为什么原论文中欧氏距离比余弦距离效果更好?

单选题 · hard

  • A.欧氏距离可微而余弦距离不可微
  • B.欧氏距离等价于高斯判别模型,数学解释更清晰← 正确答案
  • C.余弦距离需要额外归一化网络参数
  • D.欧氏距离在反向传播时梯度更大

答案:B。在欧氏距离下,带线性嵌入的原型网络可以等价于特定协方差结构的高斯判别分析,具备理论保证;余弦距离丢弃了模长信息,削弱了嵌入空间的表征能力,因此实践中通常略逊一筹。

Q8. 原型向量在推理阶段有哪些用途?

多选题 · mid

  • A.表示类别在嵌入空间的中心位置← 正确答案
  • B.计算查询样本到每个类别的距离← 正确答案
  • C.作为分类决策的直接依据← 正确答案
  • D.存储所有支撑样本的原始像素

答案:ABC。原型向量是类别的中心表征(A),被用于计算查询样本与各类的距离(B),并进一步决定分类结果(C)。D 描述的存储原始支撑样本并非原型向量的用途。

Q9. 原型网络在哪些情况下容易出现性能下降?

多选题 · hard

  • A.支撑集每类只有 1 个样本,原型方差大← 正确答案
  • B.训练分布与测试分布差异显著← 正确答案
  • C.类别样本内部呈现多峰分布← 正确答案
  • D.查询集样本数量非常庞大

答案:ABC。单样本导致原型不稳定(A),分布漂移让均值估计失真(B),多峰分布下单一原型难以代表整个类别(C)。D 查询集数量本身不影响原型质量,只影响推理时间。

Q10. 以下哪些是原型网络的合理改进方向?

多选题 · mid

  • A.每类学习多个原型以刻画多峰分布← 正确答案
  • B.引入无标注数据修正原型位置← 正确答案
  • C.训练更强的嵌入网络使同类更紧凑← 正确答案
  • D.增加全连接层直接输出类别编号

答案:ABC。多原型、半监督修正、更好嵌入网络都是原型网络的经典扩展方向。D 的全连接输出类别编号违背了小样本“类别不可预知”的核心假设。