深度解析孪生网络
在深度学习的版图里,孪生网络(Siamese Network) 是一种独特的存在。它不追求直接对目标进行分类,而是追求对目标之间'相似度'的极致衡量。这种架构在人脸识别(如手机刷脸解锁)、签名校验、文本语义匹配以及时间序列异常检测中都有着广泛的应用。
核心概念:什么是孪生网络?
孪生网络,顾名思义,就像是一对双胞胎。它由两个(或多个)结构完全相同、且共享权重(Shared Weights)的子网络组成。
1.1 工作原理
当你输入两张图片 X_1 和 X_2 时,这对'双胞胎'子网络会分别将它们映射到高维特征空间,得到特征向量 G(X_1) 和 G(X_2)。
孪生网络的目标不是告诉你 X_1 是猫还是狗,而是计算 G(X_1) 与 G(X_2) 之间的距离。如果距离近,说明两者相似(如同一个人);如果距离远,说明两者不同。
1.2 为什么需要'共享权重'?
共享权重是孪生网络的灵魂。它保证了模型对两个输入的特征提取逻辑是完全一致的。如果不共享权重,模型可能会学会'偏心',导致即便输入相同的图片,提取出的特征也会因网络差异而产生巨大偏差,从而失去对比的意义。
核心算法:损失函数的艺术
在普通分类任务中,我们常用交叉熵(Cross-Entropy)。但在孪生网络中,我们需要更特殊的损失函数。
2.1 对比损失 (Contrastive Loss)
其公式通常定义为:
L = (1-Y) * 0.5 * Dw^2 + Y * 0.5 * {max(0, m - Dw)}^2
- 其中 Dw 是两个向量的欧氏距离,m 是边际(Margin)。
- 当 Y=0(样本相似)时,损失函数只保留前半部分,目标是让距离趋近于 0。
- 当 Y=1(样本不同)时,损失函数保留后半部分,目标是让距离至少大于 m。
2.2 三元组损失 (Triplet Loss)
这是 Google 在 FaceNet 中提出的进阶版。它输入三个样本:锚点(Anchor)、正样本(Positive)和负样本(Negative)。
目标是让 Anchor 离 Positive 越近越好,离 Negative 越远越好。
常用使用技巧与实战 Demo
在 Windows 环境下,我们使用 PyTorch 来实现一个简单的孪生网络。
3.1 简单入门:构建网络结构
import torch
import torch.nn as nn
import torch.nn.functional as F
class SiameseNetwork(nn.Module):
def __init__(self):
super(SiameseNetwork, self).__init__()
# 两个子网络共享这套 CNN 结构
self.cnn = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=3),
nn.ReLU(inplace=),
nn.MaxPool2d(, ),
nn.Conv2d(, , kernel_size=),
nn.ReLU(inplace=),
nn.Flatten()
)
.fc = nn.Linear( * * , )
():
output = .cnn(x)
output = .fc(output)
output
():
output1 = .forward_once(input1)
output2 = .forward_once(input2)
output1, output2

