引言:一个简单但深刻的想法

想象你在教一个孩子认识动物:

传统监督学习的方式

你指着一只猫说:"这是猫"
你指着另一只猫说:"这也是猫"
你指着一只狗说:"这是狗"
你指着另一只狗说:"这也是狗"

孩子学到:
猫的标签 = "猫"
狗的标签 = "狗"

但孩子可能不理解:
为什么这两只猫都叫"猫"?
猫和狗的本质区别是什么?

对比学习的方式

你拿出两只不同的猫照片说:
"这两个很像,对吧?它们都是猫"

然后拿出一只猫和一只狗的照片说:
"这两个很不像,对吧?一个是猫,一个是狗"

孩子学到:
✓ 猫和猫应该"相似"
✓ 猫和狗应该"不同"
✓ 理解了"相似性"的概念

更深层的理解:
不仅知道标签,还理解了特征空间中的距离关系

这就是**对比学习(Contrastive Learning)**的核心思想:

通过拉近相似样本、推远不同样本,让模型学习到有区分度的特征表示。

在过去5年中,对比学习彻底改变了无监督学习和半监督学习的格局,催生了SimCLR、MoCo、CLIP等突破性工作。今天,让我们深入理解这个强大的技术。


一、对比学习的核心理念

1.1 特征空间的几何直觉

问题:什么是好的特征表示?

糟糕的特征空间

想象一个2D平面,不同类别的样本混在一起:

    🐱      🐶
  🐶  🐱  🐱  🐶    ← 猫狗混杂
    🐱  🐶  🐱
  🐶    🐱    🐶

问题:
✗ 无法通过简单的线性分类器区分
✗ 相似的样本距离远
✗ 不同的样本距离近

理想的特征空间

通过对比学习后:

  🐱🐱🐱           
  🐱🐱🐱  ← 猫聚在一起       🐶🐶🐶
  🐱🐱🐱                    🐶🐶🐶 ← 狗聚在一起
                          🐶🐶🐶
       ←─────────────→
         距离很远

特点:
✓ 类内紧凑(intra-class compactness)
✓ 类间分离(inter-class separation)
✓ 易于分类

数学表达

目标:学习一个编码器 f(·),使得:

对于相似样本 x_i 和 x_j:
  distance(f(x_i), f(x_j)) → 小
  
对于不同样本 x_i 和 x_k:
  distance(f(x_i), f(x_k)) → 大

其中 distance 通常用:
- 欧氏距离:||f(x_i) - f(x_j)||²
- 余弦距离:1 - cos(f(x_i), f(x_j))

1.2 正样本对与负样本对

对比学习的关键概念

正样本对(Positive Pair)

定义:应该"相似"的样本对

在监督学习中:
- 同一类别的两个样本
  例:两只不同的猫

在无监督/半监督学习中:
- 同一图像的不同增强版本
  例:原图 + 旋转版本
      原图 + 裁剪版本

核心假设:
数据增强不改变语义
→ 增强前后应该在特征空间中靠近

负样本对(Negative Pair)

定义:应该"不同"的样本对

常见构造方式:
1. 不同类别的样本(监督)
   例:猫 vs 狗

2. 不同图像(无监督)
   例:图像A vs 图像B(假设它们不同)

3. 同一batch内的其他样本
   例:当前样本 vs batch中所有其他样本

关键:
负样本的质量很重要
→ 太简单的负样本(如纯黑图)无用
→ 需要"hard negatives"(难以区分的负样本)

例子:图像分类的对比学习

输入:一张猫的照片 [🐱原图]

构造正样本对:
- 原图 + 水平翻转版本
- 原图 + 裁剪版本  
- 原图 + 颜色调整版本
→ 5个正样本对

构造负样本对:
- 原图 vs batch中的其他图像(狗、车、房子...)
→ 假设batch_size=256,有255个负样本

对比学习目标:
让原图与其增强版本在特征空间中接近
让原图与其他图像在特征空间中远离

1.3 对比学习 vs 传统监督学习

对比视角

维度监督学习对比学习
学习目标预测正确的类别标签学习良好的特征表示
监督信号类别标签(如"猫")样本间的相似性关系
损失函数交叉熵损失对比损失(InfoNCE等)
特征质量可能次优(关注分类边界)通常更好(关注特征空间结构)
标注需求需要精确的类别标签可以无标注或少量标注
泛化能力依赖标注数据分布更强(学到了底层结构)

深层差异

监督学习:
- 告诉模型"这是什么"
- 学习判别边界
- 容易过拟合标签

对比学习:
- 告诉模型"什么相似、什么不同"
- 学习特征空间的几何结构
- 学到更可迁移的表示

类比:
监督学习 = 死记硬背(记住标签)
对比学习 = 理解概念(理解相似性)

二、对比学习的演进历程

2.1 早期探索:度量学习(Metric Learning)

Siamese Network (1994):孪生网络

核心思想:训练两个参数共享的网络

架构:
输入A → [编码器] → 特征A
                      ↓
                   计算距离
                      ↓
输入B → [编码器] → 特征B
      (共享参数)

损失函数(Contrastive Loss):
- 如果A和B相似:最小化 ||特征A - 特征B||²
- 如果A和B不同:最大化 ||特征A - 特征B||²(但有上限margin)

数学表达:
L = y * ||f(A) - f(B)||² + (1-y) * max(0, margin - ||f(A) - f(B)||²)
    ↑ 相似样本拉近        ↑ 不同样本推远(但不超过margin)

应用场景

人脸验证:
- 输入:两张人脸照片
- 输出:是否是同一个人
- 训练:用已知的正负样本对

签名验证:
- 输入:两个签名图像
- 输出:是否出自同一人

局限性

✗ 一次只处理一对样本(效率低)
✗ margin参数难以调节
✗ 不能充分利用batch中的信息

Triplet Loss (2015):三元组损失

核心改进:从"pair"到"triplet"

概念:
每次采样三个样本:
- Anchor(锚点):参考样本
- Positive(正样本):与锚点同类
- Negative(负样本):与锚点不同类

目标:
让 distance(Anchor, Positive) < distance(Anchor, Negative)

损失函数:
L = max(0, distance(A,P) - distance(A,N) + margin)
           ↑ 正样本距离   ↑ 负样本距离   ↑ 安全边界

直观理解:
正样本应该比负样本至少近 margin 这么多

可视化

特征空间中:

     🐱 Anchor
    /  \
   /    \
  🐱     🐶
  ↑      ↑
Positive Negative

要求:
d(Anchor, Positive) + margin < d(Anchor, Negative)

效果:
强制正样本靠近,同时推开负样本

Hard Triplet Mining

问题:
大多数triplet很容易满足约束
→ 对学习无帮助(梯度为0)

解决:挑选困难的triplet

Hard Positive:
在正样本中,选择离Anchor最远的
→ 最难拉近的正样本

Hard Negative:
在负样本中,选择离Anchor最近的
→ 最难推远的负样本

效果:
训练效率提升3-5倍
最终性能提升2-3%

FaceNet的成功

任务:人脸识别

数据:200万张人脸,8,000个身份

使用Triplet Loss训练:
- 准确率:99.63%(LFW数据集)
- 超越人类水平(97.53%)

关键:
Triplet Loss学到了人脸的判别性特征
不仅能识别训练集的人
还能泛化到未见过的新面孔

2.2 现代对比学习:多负样本的威力

从Triplet到N-pair

问题:Triplet Loss的局限

每次只用1个负样本
→ 信息利用不充分
→ 需要更多训练迭代

例子:
Anchor: 一只橘猫
Positive: 同一只橘猫的另一张照片
Negative: 一只狗

问题:
batch中可能还有:车、房子、飞机...
这些都没被利用!

N-pair Loss (2016)

核心思想:
同时使用batch中所有其他样本作为负样本

设定:
- 1个Anchor
- 1个Positive
- N-1个Negatives(batch中其他所有样本)

损失函数(简化版):
L = -log( exp(sim(A,P)) / (exp(sim(A,P)) + Σ exp(sim(A,N_i))) )
         ↑ 正样本相似度          ↑ 所有负样本相似度之和

效果:
充分利用batch信息
→ 学习更高效
→ 特征质量更好

为什么多负样本有效?

1. 更丰富的对比信息

1个负样本:
"猫"应该与"狗"不同

100个负样本:
"猫"应该与"狗"、"车"、"房子"、"飞机"...都不同
→ 学到更全面的判别性特征

2. 更难的学习任务

从100个样本中找到正样本
比从2个样本中选择
更具挑战性

类比:
单选题 vs 百选一
→ 后者需要更精细的特征

3. 隐式的难负样本挖掘

batch中总会有一些样本
在特征空间中恰好接近anchor
→ 自然形成"hard negatives"

例如:
Anchor: 黄色的猫
Batch中的负样本:
- 黄色的狗 ← hard negative(颜色相似)
- 白色的飞机 ← easy negative

模型必须学会:
不被颜色迷惑,关注形状和纹理

2.3 InfoNCE:统一的对比学习框架

CPC (2018):Contrastive Predictive Coding

提出了InfoNCE损失,成为现代对比学习的标准:

核心公式

L_InfoNCE = -log( exp(sim(q,k+)/τ) / Σ exp(sim(q,k_i)/τ) )
                  ↑ 正样本           ↑ 正样本+所有负样本

其中:
- q: query(查询,通常是anchor的特征)
- k+: key(正样本的特征)
- k_i: keys(所有负样本的特征)
- sim(·,·): 相似度函数(通常是余弦相似度或点积)
- τ: 温度参数(temperature)

为什么叫InfoNCE?

Info = Information(信息论)
NCE = Noise Contrastive Estimation(噪声对比估计)

理论基础:
最大化query和正样本之间的互信息
同时把负样本当作"噪声"对比

直观理解:
从一堆噪声(负样本)中
识别出信号(正样本)

温度参数τ的作用

τ的影响:

τ → 0(低温):
- 分布变得尖锐
- 模型必须非常确定地区分正负样本
- 关注最相似的样本

例子(τ=0.1):
sim(q,k+) = 0.8  → exp(0.8/0.1) = exp(8) = 2981
sim(q,k-) = 0.7  → exp(0.7/0.1) = exp(7) = 1097
差异被放大!

τ → ∞(高温):
- 分布变得平滑
- 所有样本接近等权重
- 学习信号变弱

例子(τ=10):
sim(q,k+) = 0.8  → exp(0.8/10) = exp(0.08) = 1.08
sim(q,k-) = 0.7  → exp(0.7/10) = exp(0.07) = 1.07
差异很小

最佳实践:
τ = 0.07-0.1(常用值)
需要根据具体任务调整

温度的几何意义

在特征空间中:

低温(τ=0.05):
    🐱🐱🐱 极度紧凑
      
               🐶🐶🐶 极度分离

高温(τ=1.0):
  🐱 🐱    🐱  分散
      
      🐶  🐶   🐶   混合

适中温度(τ=0.1):
   🐱🐱🐱  紧凑但不过度
   
           🐶🐶🐶  清晰分离

结论:
温度控制特征空间的"松紧度"

三、里程碑方法详解

3.1 SimCLR (2020):简单而强大

Google提出的SimCLR震撼了整个领域

核心设计哲学

"Simple Framework for Contrastive Learning of Visual Representations"

关键词:Simple(简单)
→ 不需要记忆库
→ 不需要特殊架构
→ 只需要:大batch + 强数据增强 + 简单的对比损失

完整流程

Step 1:数据增强(关键!)

一张原始图像 → 两次随机增强 → 两个视图

增强操作(随机组合):
1. 随机裁剪后缩放(RandomResizedCrop)
2. 随机水平翻转(p=0.5)
3. 颜色扭曲(Color Distortion)
   - 亮度
   - 对比度
   - 饱和度
   - 色调
4. 随机转灰度(p=0.2)
5. 高斯模糊(p=0.5)

示例:
原图:[🐱清晰的猫照片]
↓
视图1:[🐱裁剪+变亮的猫]
视图2:[🐱翻转+模糊的猫]

这两个视图形成正样本对

SimCLR的关键发现

数据增强的重要性:

不同增强组合的效果(ImageNet):
1. 裁剪 + 翻转:48.2%
2. + 颜色扭曲:58.7%(↑10.5%)← 关键
3. + 高斯模糊:66.2%(↑18.0%)← 更关键

结论:
强数据增强 > 复杂的模型架构
颜色扭曲和模糊特别重要

Step 2:编码器

使用标准的ResNet作为编码器

x_i(视图1)→ [ResNet-50] → h_i(特征,2048维)
x_j(视图2)→ [ResNet-50] → h_j(特征,2048维)

注意:
两个视图使用同一个编码器(参数共享)
→ 保证特征空间一致

Step 3:投影头(Projection Head)

关键创新:在特征上再加一个小网络

h_i → [MLP] → z_i(投影特征,128维)
h_j → [MLP] → z_j(投影特征,128维)

MLP结构:
Linear(2048 → 2048) + ReLU + Linear(2048 → 128)

为什么需要投影头?
原因1:降维(2048→128),对比学习更高效
原因2:投影头学习"对比任务",而编码器学习"通用特征"
原因3:实验发现加投影头提升10%+性能!

Step 4:对比损失

在一个batch中(batch_size=N):
- 有N个原始图像
- 每个生成2个视图
- 总共2N个样本

对于样本i:
- 正样本:它的另一个视图(1个)
- 负样本:batch中其他2N-2个样本

InfoNCE损失:
l(i,j) = -log( exp(sim(z_i,z_j)/τ) / Σ_{k=1}^{2N} exp(sim(z_i,z_k)/τ) )
              ↑ 正样本对                ↑ 所有样本(包括正样本)

总损失:
对batch中所有正样本对求平均

SimCLR的威力:Batch Size的重要性

ImageNet预训练(100 epochs):

Batch Size = 256:
Top-1准确率:58.9%

Batch Size = 1024:
Top-1准确率:64.5%(↑5.6%)

Batch Size = 4096:
Top-1准确率:69.3%(↑10.4%)

Batch Size = 8192:
Top-1准确率:69.8%(↑0.5%,边际收益递减)

关键洞察:
更大的batch = 更多负样本
→ 更丰富的对比信息
→ 更好的特征表示

但是:
需要强大的计算资源
8192 batch需要64-128块GPU!

为什么大batch如此重要?

1. 更多的负样本

Batch=256:
每个样本有254个负样本

Batch=8192:
每个样本有8190个负样本

差异:
32倍的对比信息!

2. 更稳定的梯度

小batch:
负样本采样随机性大
→ 梯度噪声大
→ 训练不稳定

大batch:
负样本覆盖更全面
→ 梯度更稳定
→ 训练更平滑

3. 隐式的难负样本挖掘

batch越大,越可能包含:
- 与anchor相似的其他类别样本
- 不同视角的同类样本(应该是正样本但在batch中是负样本)

这些"hard negatives"强迫模型学习更精细的特征

SimCLR的成就

ImageNet线性评估(冻结特征训练分类器):

监督学习(ResNet-50):
Top-1: 76.5%

SimCLR(ResNet-50, 1000 epochs):
Top-1: 69.3%

SimCLR(ResNet-50×4, 1000 epochs):
Top-1: 76.5%(匹配监督学习!)

SimCLR(ResNet-50×4, 1000 epochs)+ 微调:
Top-1: 78.2%(超越监督学习!)

关键:
无监督预训练 + 少量标注微调
→ 超越从头监督训练

3.2 MoCo (2020):动量对比

Facebook AI提出的MoCo解决了SimCLR的计算瓶颈

SimCLR的问题

为了获得足够多的负样本
→ 需要超大的batch size(4096-8192)
→ 需要几十上百块GPU
→ 普通实验室无法复现

能否在小batch下也有效?

MoCo的核心创新:记忆库(Memory Bank)

直观理解

SimCLR:
只能使用当前batch的样本作为负样本
→ batch small = 负样本少

MoCo:
维护一个"记忆库",存储历史样本的特征
→ 负样本数量不受batch size限制

类比:
SimCLR = 只记得今天见过的人
MoCo = 有一本通讯录,记得所有见过的人

MoCo架构

两个编码器

Query Encoder(查询编码器):
- 正常梯度更新
- 编码当前batch的样本
- 参数:θ_q

Key Encoder(键编码器):
- 动量更新(缓慢更新)
- 编码记忆库的样本
- 参数:θ_k

动量更新公式:
θ_k ← m * θ_k + (1-m) * θ_q
其中 m=0.999(非常接近1)

为什么需要两个编码器?

问题:
如果记忆库中的特征是用旧参数编码的
当前样本是用新参数编码的
→ 特征不一致,对比学习失效

MoCo的解决:
Key Encoder缓慢更新
→ 特征保持一致性
→ 记忆库仍然有效

类比:
就像考试时,评分标准不能频繁变化
否则前后试卷无法比较

记忆库(Queue)的设计

结构:First-In-First-Out队列

初始化:
创建大小为K的队列(如K=65536)
用随机特征填充

训练时:
1. 编码当前batch(batch_size=256)
2. 用Key Encoder得到256个特征
3. 这256个特征入队
4. 最老的256个特征出队

对比学习:
Query vs (1个Positive + 65536个Negatives)
       ↑ 记忆库提供大量负样本

优势:
✓ 负样本数量不受batch size限制
✓ 计算高效(不需要大batch)
✓ 特征一致性好(动量更新)

MoCo vs SimCLR对比

特性SimCLRMoCo
负样本来源当前batch记忆库
负样本数量2×batch_size-2队列大小K(通常65536)
需要的batch size很大(4096+)小(256即可)
GPU需求64-128块8块即可
特征一致性天然一致(同一编码器)动量更新保证
训练效率受batch size限制更灵活

MoCo的效果

ImageNet线性评估(ResNet-50, 200 epochs):

SimCLR(batch=4096):
Top-1: 69.3%
GPU需求:128块

MoCo v2(batch=256):
Top-1: 71.1%(更好!)
GPU需求:8块

关键:
小batch + 记忆库 ≥ 大batch
更加实用和高效

3.3 MoCo v2 和 MoCo v3:持续演进

MoCo v2 (2020):借鉴SimCLR的优点

改进点:

1. 加入MLP投影头
   原MoCo:直接使用编码器特征
   MoCo v2:添加2层MLP
   效果:+2.9%

2. 更强的数据增强
   借鉴SimCLR:加入高斯模糊
   效果:+1.5%

3. 余弦学习率调度
   效果:+0.5%

总提升:+4.9%
最终:71.1% Top-1(200 epochs)

MoCo v3 (2021):适配Vision Transformer

动机:
ViT(Vision Transformer)成为新架构
原MoCo在ViT上训练不稳定

关键改进:

1. 去除记忆库
   →  发现ViT不需要记忆库也能稳定训练
   
2. 使用更大的batch
   → batch_size=4096(但比SimCLR小)

3. 预测头设计
   → 在Query端添加额外的预测头

效果:
ImageNet(ViT-B, 300 epochs):
MoCo v2:72.5%
MoCo v3:76.7%(↑4.2%)

3.4 BYOL (2020):无需负样本的对比学习

DeepMind提出的BYOL挑战了对比学习的基本假设

惊人发现:不需要负样本也能学习!

传统对比学习的假设

必须有负样本
→ 通过"推远不同样本"来学习

否则会发生"模式崩溃"(Collapse):
所有样本的特征都变成相同的向量
→ 模型什么都没学到

例如:所有图像都映射到 [0.5, 0.5, 0.5, ...]
→ 完全无区分度

BYOL的架构

两个网络

Online Network(在线网络):
输入 x → [编码器 f_θ] → [投影头 g_θ] → y_θ → [预测头 q_θ] → z_θ

Target Network(目标网络):
输入 x' → [编码器 f_ξ] → [投影头 g_ξ] → y_ξ
(参数 ξ 是 θ 的EMA,不直接更新)

关键设计:
只有Online Network有预测头!
这是防止崩溃的关键

训练流程

Step 1:数据增强
原图 x → 两个不同的增强视图
- 视图1:v (输入Online Network)
- 视图2:v' (输入Target Network)

Step 2:前向传播
Online: v → y_θ → z_θ (通过预测头)
Target: v' → y_ξ (没有预测头)

Step 3:计算损失(简单的均方误差)
L = || normalize(z_θ) - normalize(y_ξ) ||²
         ↑ 预测              ↑ 目标

Step 4:对称损失(交换视图角色)
L' = || normalize(z_θ') - normalize(y_ξ') ||²
(v'输入Online,v输入Target)

总损失:L_total = L + L'

Step 5:更新参数
- θ:正常梯度下降
- ξ:指数移动平均(EMA)
  ξ ← τ * ξ + (1-τ) * θ
  其中 τ=0.996(非常慢)

为什么BYOL不会崩溃?

1. 预测头的不对称性

如果没有预测头(对称结构):
Online: x → f → g → y
Target: x' → f → g → y'

损失: || y - y' ||²

最简单的解决方案:
让所有输出都相同 → 崩溃!

有预测头(不对称结构):
Online: x → f → g → q → z
Target: x' → f → g → y'

损失: || z - y' ||²

关键:
预测头q必须"理解"数据结构
才能从y预测y'
→ 防止崩溃

2. 动量更新的稳定性

Target Network更新很慢
→ 提供稳定的"移动目标"

如果目标网络更新太快:
可能和在线网络一起崩溃

如果目标网络不更新:
在线网络可能过拟合固定目标

EMA(τ=0.996)的平衡:
足够慢 → 稳定
足够更新 → 持续进步

3. Batch Normalization的隐含作用

研究发现:
BatchNorm在防止崩溃中起关键作用

BatchNorm的效果:
- 中心化:强制输出均值为0
- 标准化:强制输出方差为1
- 不同样本间有交互(通过batch统计)

→ 隐式提供了"负样本"的作用

注意:
去除BatchNorm后,BYOL可能崩溃
这是一个有趣的发现

BYOL vs MoCo对比

┌─────────────────┬──────────────┬──────────────┐
│     特性        │    MoCo      │    BYOL      │
├─────────────────┼──────────────┼──────────────┤
│ 需要负样本      │      是      │      否      │
│ 对比损失        │   InfoNCE    │     MSE      │
│ 记忆库          │      是      │      否      │
│ 预测头          │      无      │      有      │
│ 对称性          │    对称      │   不对称     │
│ 训练稳定性      │     好       │  依赖BN      │
│ ImageNet性能    │   71.1%      │   74.3%      │
│ 理论理解        │    清晰      │   不太清楚   │
└─────────────────┴──────────────┴──────────────┘

BYOL的优势

✓ 不需要调节温度参数τ
✓ 不需要大batch或记忆库
✓ 不需要精心设计负样本
✓ 性能更好(74.3% vs 71.1%)
✓ 训练更简单

但:
✗ 理论机制不完全清楚
✗ 依赖BatchNorm(或其他归一化)
✗ 超参数(EMA系数)敏感

真实效果

ImageNet线性评估(ResNet-50, 1000 epochs):

SimCLR:69.3%
MoCo v2:71.1%
BYOL:74.3%(最好!)

迁移学习(下游任务):
在12个数据集上平均:
BYOL比MoCo v2高2.1%

结论:
无负样本也能训练出色
甚至比有负样本更好!

四、半监督学习中的对比学习

4.1 监督对比学习(Supervised Contrastive Learning)

将对比学习与标签信息结合

核心思想

无监督对比学习:
同一图像的不同增强 = 正样本对

监督对比学习:
同类别的所有样本 = 正样本对
不同类别的样本 = 负样本对

优势:
充分利用标签信息
学习更好的类别判别性特征

SupCon Loss(监督对比损失)

给定一个batch:
- Anchor样本 i
- 类别标签 y_i

正样本集合 P(i):
所有与i同类别的样本(不包括i自己)
P(i) = {j | y_j = y_i, j ≠ i}

负样本集合 N(i):
所有与i不同类别的样本
N(i) = {k | y_k ≠ y_i}

SupCon损失:
L_i = -1/|P(i)| * Σ_{p∈P(i)} log( exp(z_i·z_p/τ) / Σ_{a∈A(i)} exp(z_i·z_a/τ) )
      ↑ 对所有正样本求平均            ↑ 所有样本(正+负)

关键区别:
一个anchor可能有多个正样本
→ 对所有正样本都拉近

可视化理解

传统交叉熵:
只关心分类边界

      猫区域    |    狗区域
    🐱 🐱 🐱   |   🐶 🐶 🐶
                ↑ 只要在正确一侧即可
                
SupCon:
类内样本应该紧凑聚集

      🐱🐱🐱           🐶🐶🐶
       ↑ 聚在一起       ↑ 聚在一起
       
效果:
✓ 类内更紧凑
✓ 类间更分离
✓ 特征更有结构

SupCon vs 交叉熵

ImageNet分类(ResNet-50):

标准交叉熵:
Top-1: 78.8%

SupCon:
Top-1: 81.4%(↑2.6%)

特别优势:
✓ 对类别不平衡更鲁棒
✓ 对标签噪声更鲁棒
✓ 对超参数不敏感

原因:
SupCon学习的是样本间的相对关系
不仅是绝对的分类边界

标签噪声实验

在ImageNet中人为添加标签噪声:

噪声率30%:
交叉熵:62.3% → 52.1%(↓10.2%)
SupCon:81.4% → 75.8%(↓5.6%)← 更鲁棒

原因:
SupCon通过多个正样本投票
单个噪声标签的影响被稀释

4.2 半监督对比学习的挑战

核心问题:如何利用无标注数据?

挑战1:无标注数据没有标签

监督对比学习需要:
知道哪些样本同类(正样本)
知道哪些样本异类(负样本)

无标注数据:
不知道类别
→ 无法直接应用SupCon

挑战2:伪标签的质量问题

简单方案:
用模型预测无标注数据的伪标签
→ 用伪标签构造正负样本对

问题:
早期模型不准确
→ 伪标签错误率高
→ 错误的对比关系
→ 性能下降

案例:
真实标签:"猫"
伪标签:"狗"
→ 把两只猫推远了!

挑战3:确认偏差(Confirmation Bias)

循环问题:
模型A生成伪标签 → 训练模型B
模型B基于伪标签训练 → 强化错误
错误越来越确信 → 难以纠正

类比:
就像回音室效应
错误的观点互相加强

4.3 解决方案:不确定性引导的对比学习

核心思想:结合预测不确定性

策略1:置信度过滤
思路:
只使用高置信度预测构造对比关系

伪代码流程:
for 样本 x in 无标注数据:
    伪标签, 置信度 = model.predict(x)
    
    if 置信度 > threshold(如0.95):
        # 高置信度 → 可能正确 → 用于对比学习
        构造正样本对(同伪标签)
        构造负样本对(不同伪标签)
    else:
        # 低置信度 → 可能错误 → 跳过
        不参与对比学习

效果:
降低错误伪标签的影响
提高对比关系的质量

置信度阈值的选择

阈值0.90:
- 使用60%的无标注数据
- 伪标签准确率:93.2%
- 最终性能:84.3%

阈值0.95:
- 使用35%的无标注数据
- 伪标签准确率:96.8%
- 最终性能:85.7%(最佳)

阈值0.99:
- 使用8%的无标注数据
- 伪标签准确率:98.9%
- 最终性能:83.1%(数据太少)

结论:
0.95是一个平衡点

策略2:软标签对比学习
问题:
硬标签(0/1)忽略了不确定性

改进:
使用软标签(概率分布)

例子:
样本A预测:[猫=0.92, 狗=0.08]
样本B预测:[猫=0.90, 狗=0.10]
样本C预测:[狗=0.85, 猫=0.15]

传统方法:
A和B:正样本对(都预测为猫)
A和C:负样本对

软对比:
计算预测分布的相似度:
sim(A,B) = 余弦相似度([0.92,0.08], [0.90,0.10]) = 0.998
sim(A,C) = 余弦相似度([0.92,0.08], [0.15,0.85]) = 0.120

对比损失考虑相似度:
高相似度的样本权重大
低相似度的样本权重小

好处:
✓ 不是简单的二元关系(正/负)
✓ 考虑了预测的不确定性
✓ 更鲁棒

策略3:困难区域的对比学习

动机:在遥感、医疗等领域的应用

观察:
模型在某些区域不确定性高
- 变化边界
- 细微变化
- 模糊区域

这些区域:
✓ 包含关键判别信息
✓ 最需要学习
✗ 但经常被忽略

解决方案:
专门为困难区域设计对比学习

困难区域对比学习(Difficult Region Contrastive Learning, DRCL)

核心步骤

Step 1:识别困难区域

计算像素级不确定性:
U(x,y) = 1 - |P_change(x,y) - P_unchanged(x,y)|

高不确定性 = 困难区域

例如(建筑物变化检测):
建筑物内部:U ≈ 0.1(确定是变化)
背景区域:U ≈ 0.05(确定是未变化)
建筑物边界:U ≈ 0.7(不确定)← 困难区域

可视化:
[原图]      [不确定性图]
🏠建筑      ░░░░ 低
            ██░░ 边界高
            ░░░░ 低

Step 2:在困难区域采样

策略:
优先从高不确定性区域采样特征

局部采样:
在一个困难区域内:
- 正样本:同类别的其他像素
- 负样本:不同类别的像素

全局采样:
从记忆库中:
- 正样本:历史的同类别困难特征
- 负样本:历史的异类困难特征

重点:
只对比困难区域的特征
→ 聚焦最需要学习的部分

Step 3:加权对比损失

普通对比学习:
所有样本权重相同

困难区域对比:
L_DRCL = Σ w(x,y) * L_contrast(x,y)
         ↑ 不确定性权重

权重函数:
w(x,y) = exp(α * U(x,y))

其中:
- α > 0:放大不确定性的影响
- α = 2-3(典型值)

效果:
困难区域的对比损失权重大
→ 模型更关注困难区域
→ 学习更有效

真实效果(变化检测任务)

LEVIR-CD数据集(5%标注):

基线(FixMatch):
F1 = 88.7%
边界IoU = 73.2%

+ 标准对比学习:
F1 = 89.5%(↑0.8%)
边界IoU = 75.1%(↑1.9%)

+ 困难区域对比学习:
F1 = 90.8%(↑2.1%)
边界IoU = 78.4%(↑5.2%)← 边界改善显著

关键发现:
专注困难区域的对比学习
对边界等关键区域提升更大

4.4 多尺度对比学习

动机:遥感图像的特点

问题:
遥感图像中目标尺度差异大
- 大型建筑:几百像素
- 小型建筑:几十像素

单尺度对比:
可能错过重要信息

多尺度策略

在不同分辨率做对比学习:

原始尺度(256×256):
提取全局特征
→ 大目标的对比

下采样2x(128×128):
提取中等尺度特征
→ 中等目标的对比

下采样4x(64×64):
提取粗粒度特征
→ 上下文的对比

对比损失:
L_multi = L_256×256 + 0.5*L_128×128 + 0.25*L_64×64
          ↑ 精细      ↑ 中等          ↑ 粗糙

跨尺度一致性

除了同尺度对比,还可以跨尺度对比:

同一位置,不同尺度的特征应该相似

例如:
F_256(100,100) ↔ F_128(50,50) ↔ F_64(25,25)
这三个特征对应图像中的同一位置

跨尺度对比损失:
让不同尺度的特征保持一致
→ 学习尺度不变的表示

五、对比学习的实践技巧

5.1 数据增强的选择

对比学习中数据增强极其重要

增强强度的权衡

太弱:
两个视图过于相似
→ 任务太简单
→ 学不到鲁棒特征

例子:
原图 vs 轻微平移2像素
→ 几乎一模一样
→ 没有挑战性

太强:
两个视图差异过大
→ 可能改变语义
→ 引入错误的对比关系

例子:
猫照片 vs 严重模糊+裁剪头部
→ 可能完全不像猫了
→ 对比学习误导

最佳:
保留语义但具有挑战性

SimCLR的增强组合(最佳实践)

关键发现:
不同增强的重要性差异巨大

重要性排序:

1. 随机裁剪(最重要)
   - 强制模型学习局部特征
   - 效果提升:+18.2%

2. 颜色失真(次重要)
   - 强制模型忽略颜色
   - 效果提升:+10.5%

3. 高斯模糊(重要)
   - 破坏纹理细节
   - 效果提升:+7.6%

4. 随机翻转(基础)
   - 标准操作
   - 效果提升:+3.2%

5. 旋转(可选)
   - 根据数据决定
   - 效果提升:+1.5%

推荐组合:
裁剪 + 颜色失真 + 模糊 + 翻转

不同领域的增强策略

自然图像:
✓ 裁剪、翻转、颜色、模糊
✓ 强度:中到高

医疗图像:
✓ 裁剪、翻转
✗ 避免颜色失真(可能改变诊断信息)
✓ 强度:低到中

遥感图像:
✓ 裁剪、任意角度旋转
✓ 多尺度缩放
✓ 轻微颜色调整
✓ 强度:中到高

文本/OCR:
✗ 避免翻转(改变文字)
✓ 轻微旋转(±5度)
✓ 弹性形变
✓ 强度:低

5.2 负样本策略

负样本的质量决定对比学习的效果

策略1:Hard Negative Mining
问题:
大多数负样本太简单
模型轻易就能区分
→ 学习效率低

例子:
Anchor: 橘猫
Easy Negative: 汽车(太容易区分)
Hard Negative: 黄狗(颜色相似,需要关注形状)

Hard Negative Mining:
从负样本中选择最难的

方法1:基于距离
选择与anchor特征距离最近的负样本

方法2:基于损失
选择对比损失最大的负样本

效果:
训练时间减少30-50%
最终性能提升1-2%
策略2:Mixup Negative
创新:生成"混合"的负样本

标准负样本:
纯粹的其他类别样本

Mixup负样本:
混合两个不同类别

例子:
Anchor: 纯猫图像
Negative 1: 纯狗图像
Mixup Negative: 0.5*猫 + 0.5*狗

好处:
✓ 增加负样本多样性
✓ 提供"中间"状态的对比
✓ 更平滑的特征空间

实验效果:
CIFAR-10: +1.3%
ImageNet: +0.8%
策略3:False Negative处理
问题:
batch中可能有"假负样本"

什么是假负样本?
Anchor: 一只猫
Batch中的其他样本:
- 另一只不同的猫 ← 应该是正样本,但被当负样本!

危害:
把应该拉近的样本推远了
→ 破坏特征空间结构

解决方案1:监督信息
如果有标签,过滤掉同类样本

解决方案2:软对比
不是完全推远,而是根据相似度调整

解决方案3:更大的batch
batch越大,假负样本比例越低

5.3 超参数调优指南

温度参数τ

影响:控制分布的"软硬"程度

τ = 0.05(低温):
分布尖锐
→ 只关注最相似的样本
→ 可能过拟合

τ = 0.1(推荐):
平衡
→ 大多数任务的最佳值

τ = 0.5(高温):
分布平滑
→ 所有样本接近等权
→ 学习信号弱

调优策略:
1. 从0.1开始
2. 如果训练不稳定 → 增大τ
3. 如果性能不好 → 尝试降低τ
4. 通常在0.05-0.2范围

Batch Size

SimCLR风格:
需要大batch(4096-8192)
→ 更多负样本
→ 更好的性能

MoCo风格:
小batch即可(256)
→ 记忆库提供负样本
→ 更实用

BYOL风格:
中等batch(1024-2048)
→ 不依赖负样本数量
→ 平衡

建议:
- 8 GPU → batch=256-512
- 32 GPU → batch=1024-2048
- 128 GPU → batch=4096-8192

训练轮数

对比学习需要更长时间训练:

监督学习:
ImageNet: 90-120 epochs足够

对比学习:
SimCLR: 800-1000 epochs
MoCo: 200-800 epochs
BYOL: 300-1000 epochs

原因:
对比学习是自监督
需要更多时间发现数据结构

实践建议:
- 小数据集(CIFAR):400-800 epochs
- 大数据集(ImageNet):200-400 epochs
- 微调阶段:50-100 epochs

六、最新进展与未来方向

6.1 视觉-语言对比学习:CLIP

OpenAI的CLIP(2021):跨模态的对比学习

核心创新:图像和文本的联合对比学习

训练数据:
4亿对(图像,文本)从互联网收集

对比方式:
匹配的(图像,文本)对:正样本
不匹配的(图像,文本)对:负样本

例子:
正样本对:
- 图像:一只猫的照片
- 文本:"a photo of a cat"

负样本对:
- 图像:一只猫的照片  
- 文本:"a photo of a dog"(不匹配)

CLIP的影响

零样本分类能力:
无需训练,直接用文本描述分类

例子:
要识别新类别"长颈鹿":
1. 输入图像
2. 候选文本:["a photo of a giraffe", "a photo of a elephant", ...]
3. 计算图像与每个文本的相似度
4. 选择最相似的

效果:
在ImageNet零样本:76.2%
超过很多监督方法!

应用:
✓ 开放词汇目标检测
✓ 图像生成(DALL-E)
✓ 视觉问答
✓ 图像检索

6.2 对比学习 + Transformer

Vision Transformer (ViT) + 对比学习

趋势:
卷积网络(CNN) → Transformer

MoCo v3, DINO等工作:
将对比学习应用到ViT

发现:
✓ ViT更适合对比学习
✓ 学到的特征更通用
✓ 迁移能力更强

挑战:
✗ ViT训练不稳定
✗ 需要特殊的技巧
✗ 计算成本更高

6.3 小样本对比学习

趋势:用更少的数据

Few-Shot Contrastive Learning:

传统:需要大量数据预训练
新方向:少样本情况下的对比学习

方法:
1. 元学习 + 对比学习
2. 原型网络 + 对比
3. 数据增强 + 对比

效果:
每类5个样本:
传统方法:42.3%
对比学习:58.7%(↑16.4%)

应用:
医疗、遥感等标注稀缺领域

6.4 自监督 → 半监督 → 监督的统一

未来方向:统一框架

目标:
一个模型同时利用:
- 无标注数据(自监督对比)
- 少量标注数据(监督对比)
- 大量标注数据(监督学习)

优势:
✓ 灵活适应不同标注比例
✓ 充分利用所有数据
✓ 性能更优

代表工作:
- SimCLR v2
- SwAV
- SemiCD-VL(用于遥感)

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐