一:输入阶段

在真实的物理内存里,权重表 $W$只有唯一的一套。 CPU 绝对不会傻到去复制两份一模一样的 $W$ 来浪费宝贵的显存。

那么,既然只有一套权重表 $W$,怎么做到“同时跑两张图”的呢?

  • 传统网络: 跑法极其简单:1 张图片输入 $\rightarrow$ 前向计算 $\rightarrow$提取特征 $\rightarrow$ 结果。
  • 孪生网络: 无论“先算 A 再算 B”还是“先算 B 再算 A”都不对,而是Batching(批处理)。 CPU 会在AB输入前,把 A 和 B 像双面胶一样“粘”在一起,叠成Batch Size = 2。然后一次性送进同一个网络做前向计算。 GPU在并行处理 A 和 B 两张图,A 和 B 都经过同一个网络、同一组权重 W(权重共享)。

二:末端输出到底是什么

无论是传统分类网络还是孪生网络,在主干特征提取阶段的末端,都会把输入图像编码为一个固定长度的向量(例如 512 维):

$${f}\in \mathbb{R}^{512}$$

这是一组浮点数(如 $[0.8,-1.2,3.4,\dots]$),可理解为图像在特征空间中的表示。 两类网络的关键差异,出现在这一步之后。

1)传统分类网络:从特征向量到类别分数

在传统识别模型中,512 维特征通常还要经过一个全连接分类层(Linear/FC): $logits = Wf + b,\quad logits \in \mathbb{R}^N$ 其中 \(N\) 是类别总数(如 10,000 人)。

  • 这一步输出的是长度为 \(N\) 的logits(未归一化分数);
  • 经过 Softmax 后得到每个类别的概率分布(总和为 1);
  • 最终常用 argmax取最大概率对应的类别 ID,再由业务字典映射成人名/工号。

严格地说,模型本身输出的是数值向量,不直接输出“张三”这样的文本标签。 标签解释是后处理程序完成的。

2)孪生网络:保留特征向量,不做封闭分类

孪生网络通常不保留面向固定类别的分类头(或训练后仅使用编码器部分)。 其核心输出是嵌入向量本身:

  • 对样本 A 输出 $f_A \in \mathbb{R}^{512}$
  • 对样本 B 输出 $f_B \in \mathbb{R}^{512}$

后续通过距离/相似度(欧氏距离、余弦相似度)判断二者关系,而不是在固定 \(N\) 类中做单选题。

对比总结

网络类型主干输出末端结构最终数值输出物理意义
孪生网络512维特征通常不使用封闭分类头(或推理时去掉)一个或多个 512 维向量用于与其他向量比较距离/相似度
传统分类网络512维特征全连接分类层(类别数为 \(N\))长度为 \(N\) 的 logits概率表示“属于各类别”的分布

三:损失计算(Loss)

在得到前向输出后,模型进入损失计算阶段。

1)传统分类网络

传统分类任务通常采用交叉熵损失(Cross-Entropy Loss)。 模型输出每个类别的概率分布,与真实类别标签进行对比,计算分类误差。 若预测类别与真实标签不一致,损失增大,反向传播将推动参数朝“提高正确类别概率”的方向更新。

2)孪生网络

孪生网络不直接预测“类别名”,而是先输出两个样本的嵌入向量 。 随后根据二者的距离/相似度如欧氏距离、余弦相似度)与样本对标签(同类/异类)计算损失,常见形式包括 Contrastive LossTriplet Loss 等。

  • 对于同类样本对:优化目标是缩小距离;
  • 对于异类样本对:优化目标是拉大距离(通常带 margin 约束)。

四:反向传播如何在“共享参数”上完成

孪生网络在反向传播时的核心问题是: 两路输入产生两条误差信号,但参数只有一套 \(W\)。更新如何进行?

答案是:梯度在共享参数处自动汇聚,再统一更新。

设编码器为 $f(\cdot;W)$,输入为样本对 $(A,B)$,得到:

$$z_A=f(A;W),\quad z_B=f(B;W),\quad L=\ell(z_A,z_B,y)$$

其中 \(L\) 是基于两向量距离和配对标签 \(y\) 计算的损失。

1)损失先作用在嵌入空间

反向传播起点不是“类别名”,而是嵌入向量:

$$frac{\partial L}{\partial z_A},\quad \frac{\partial L}{\partial z_B}$$

这两个梯度分别描述:为了让损失下降,$z_A$、$z_B$ 各自应朝什么方向变化。

2)两条分支分别回传到同一套参数

由于两分支都由同一个 \(W\) 生成,其参数梯度为:

$\frac{\partial L}{\partial W}=\frac{\partial L}{\partial z_A}\frac{\partial z_A}{\partial W}+\frac{\partial L}{\partial z_B}\frac{\partial z_B}{\partial W}$

这不是“二选一”,而是两项同时成立并相加。 也就是说,A 分支和 B 分支都会对同一参数给出更新意见,最终形成一份合成梯度。

3)Autograd 的实际行为

在框架实现中(PyTorch/TensorFlow),两条前向路径都会被记录在计算图中。 执行 loss.backward() 时,系统沿两条路径反向求导,并在共享参数的 .grad 上进行累加。 若一个 batch 含多对样本,则先对每对样本产生梯度贡献,再在 batch 维做 sum/mean 归约,得到本次迭代的最终梯度。

4)优化器只更新一次参数

梯度汇总后,优化器执行:

$$W \leftarrow W-\eta \nabla_W L$$

因此,虽然有两路输入,但参数更新是一次、统一、共享约束下完成的。

结论 3传统分类网络主要学习“样本属于哪个类别”;孪生网络主要学习“样本之间应保持怎样的距离关系”。


终极领悟:

当我们弄懂了这套剥皮抽筋的底层区别后,就能得出一个极其颠覆认知的结论: “孪生(同时进两张图互相拉扯)”这个概念,主要发生在训练(挨打)阶段!

当历经百万次梯度累加,如果你把它部署到现实中:当警察抓捕罪犯时,输入一张嫌疑人照片,单塔编码器输出一根 512 维向量,再去库中做近邻比对。但要注意:在1:1核验任务里,推理阶段依然可能是“双输入+距离判断”。

所以更严谨的说法是:孪生是训练期的核心范式,在大量线上系统中会落地为单塔特征提取器,但并非只存在于训练。

所谓孪生,不过是涅槃过程中的脚手架;大成之时,众法归一:皆为最朴实无华的特征提取器。