Contrastive Learning
对比学习通过拉近匹配样本对的嵌入表示、推远其他样本来训练嵌入。介绍 InfoNCE、SimCLR、MoCo、CLIP 和代码。
对比学习会训练模型生成嵌入,使匹配的样本对(称为正样本)彼此靠近,而不匹配的样本对(称为负样本)彼此远离。样本对可以来自数据本身,例如同一照片的两个增强裁剪图,也可以来自天然成对的数据,例如图像及其说明,因此对比学习不需要类别标签。它是图像自监督学习的主要方法之一,与掩码重建和自蒸馏并列。以此方式训练的编码器可以生成迁移到检测、分类和检索任务的特征;同一目标函数也用于训练 CLIP等视觉语言模型,之后这些模型可以仅通过文本进行图像分类,实现零样本学习。
对比学习的工作原理#
对比学习方法包含三个部分:构造正样本对的方法、将每个样本映射为归一化嵌入的编码器,以及比较相似度的损失函数。在 SimCLR 中,Ting Chen 和 Google 的同事通过随机裁剪、颜色失真和模糊为每张图像创建两个视图,用共享的 ResNet 和一个小型投影头对两个视图分别编码,并将批次中的其他图像视为负样本:
数据增强决定模型要学会忽略什么。由于同一张图像的两个裁剪版本必须映射到相近的点,编码器会学到位置、尺度和颜色变化不会改变图像所呈现的内容,并保留区分不同图像的特征。使用宽度是标准版本四倍的 ResNet-50 时,在 SimCLR 冻结特征上训练的线性分类器在 ImageNet 上达到 76.5% 的 top-1 准确率,与监督训练的 ResNet-50 相当。
对比损失函数#
- 成对对比损失:Raia Hadsell、Sumit Chopra 和 Yann LeCun 在 2006 年提出的损失函数会拉近每一对正样本,并推远每一对负样本,直到两者至少相隔边界值 m。
- 三元组损失:比较一个锚点、一个正样本和一个负样本,并要求正样本至少比负样本近一个边界值。Google 的 FaceNet 于 2015 年使用它训练人脸嵌入。
- InfoNCE:同时将一个正样本与多个负样本进行比较。将相似度 s 除以温度 τ 后,锚点的损失为 −log[exp(s₊/τ) / Σⱼ exp(sⱼ/τ)],这是一个softmax交叉熵,其中正样本是所有候选项中的正确类别。Aaron van den Oord 等人在 2018 年的对比预测编码论文中为其命名;SimCLR 的 NT-Xent 损失和 CLIP 的损失都是它的变体。
- Sigmoid 损失:SigLIP使用 sigmoid将每个样本对作为独立的匹配或不匹配进行评分,因此损失无需在整个批次上进行归一化。
在 PyTorch 中,InfoNCE 可以简化为对相似度矩阵计算交叉熵,其中对角线上的值为正样本:
import torch
import torch.nn.functional as F
torch.manual_seed(0)
# Stand-in embeddings for 8 images, a second view of each (row i of both is a positive pair),
# and 8 unrelated images
view1 = F.normalize(torch.randn(8, 128), dim=1)
view2 = F.normalize(view1 + 0.1 * torch.randn(8, 128), dim=1)
unrelated = F.normalize(torch.randn(8, 128), dim=1)
# InfoNCE: cosine similarities divided by a temperature, then cross-entropy where
# each row's positive (the diagonal) is the correct class among all 8 candidates
temperature = 0.1
targets = torch.arange(8)
for name, keys in [("Augmented views", view2), ("Unrelated images", unrelated)]:
logits = view1 @ keys.T / temperature
print(f"{name}: loss {F.cross_entropy(logits, targets):.3f}")它会打印 Augmented views: loss 0.016 和 Unrelated images: loss 2.505。当每一行中的正样本都是最相似的键时,损失会趋近于零。如果键彼此无关,损失则会升至 ln 8 ≈ 2.08 以上;这是在八个候选项中均匀猜测时的损失,因为除以 0.1 的温度会将偶然相似的样本变成置信度很高的错误猜测。温度越低,softmax 分布越尖锐,损失越集中在最难的负样本上。MoCo 使用 τ = 0.07,CLIP 也将其学习到的温度初始化为相同的值。
负样本、批次大小与变体#
InfoNCE 会随着负样本数量增加而效果提升,因此负样本的数量是一个重要成本因素。SimCLR 使用非常大的批次来获取负样本。Kaiming He 和 Facebook AI Research 的同事提出的 MoCo会将最近批次中的 65,536 个嵌入保存在队列中作为负样本,并使用编码器的慢速更新动量副本对其进行编码,从而将负样本数量与批次大小解耦。随机负样本可能是假负样本,例如另一张同一犬种的照片;而过于简单的负样本也无法提供多少学习信号,因此困难负样本挖掘会寻找容易混淆的样本。有监督对比学习(SupCon)会使用标签,将同一类别的每个样本都视为正样本。BYOL、SimSiam 和 DINO 等非对比方法完全舍弃负样本,并通过非对称网络、停止梯度或中心化来避免所有输入都坍缩为相同的嵌入。
对比学习与相关概念#
- 度量学习:学习距离函数这一更广泛的任务,对比损失和三元组损失都源于此。如今,“对比学习”通常指由 SimCLR 和 MoCo 推广的、自监督且使用大量负样本的方法。
- 自编码器:通过重建输入来学习,因此其特征必须保留像素级细节。对比特征只保留能够区分不同样本的信息。
- JEPA:根据可见图像区域预测隐藏图像区域的嵌入,在嵌入空间中学习而无需负样本对。
- 监督学习:朝着一组固定的人工标注类别进行训练,而对比预训练只需要一种判定样本是否匹配的规则。
应用场景#
- 视觉语言模型:CLIP 使用 32,768 的批次,在 4 亿个图像-说明文字对上训练图像编码器和文本编码器,因此可以通过文本提示对图像进行分类和检索。Ultralytics 的 YOLOE-26模型使用 Apple 的 MobileCLIP2 文本编码器对类别名称进行编码;该编码器通过 CLIP 风格的对比目标训练,并在对比头中将每个候选区域与这些文本嵌入进行评分,因此
set_classes(["forklift", "pallet"])可以用同一组权重将模型转换为能够检测新类别的检测器。 - 语义搜索:将通过对比学习训练的图像和文本嵌入存储在向量数据库中,并按相似度进行搜索。
- 少样本标签的预训练:在医学图像分析等专家标注稀缺的领域,可以先在未标注的扫描图像上进行对比预训练,得到一个骨干网络,再用少量带标签的数据进行微调。
- 人脸识别与重识别:对比损失和三元组损失会训练嵌入,使同一个人或物体的照片彼此接近。FaceNet 的 128 维嵌入在 Labeled Faces in the Wild 基准上达到 99.63% 的准确率。










