本章定位:把 Ch2 的 InfoNCE 推广到 (1) 跨模态——CLIP 用图文对训练,成为多模态 LLM 的视觉骨干;(2) 文本——SimCSE 把 InfoNCE 引入 NLP,BGE/E5 训出现代 RAG 检索器。
承上:Ch2 §A 的 InfoNCE 损失、§B 的 In-batch 负样本机制。
启下:Ch4 转向无负样本路线(BYOL/SimSiam/DINO)。
§A 数学原理
1. CLIP 的对称 InfoNCE
CLIP(OpenAI 2021)的核心是双塔对比:图像塔与文本塔分别将各自模态映射到同一个表示空间。
设一个 batch 含 $N$ 个图文对 ${(I_i, T_i)}_{i=1}^N$:
- Image Encoder(ViT 或 ResNet)$\to v_i \in \mathbb{R}^d$
- Text Encoder(Transformer)$\to t_i \in \mathbb{R}^d$
- 二者 L2 归一化到单位球面
对称损失:构造 $N \times N$ 相似度矩阵 $S_{ij} = v_i^T t_j / \tau$。对角线为正样本,其余 $N-1$ 为负样本。两个方向的交叉熵相加:
关键工程细节:
- 温度 $\tau$ 是可学习参数:CLIP 让 $\log(1/\tau)$ 直接参与训练,初始化为 $\log(1/0.07)$。这样模型自己决定相似度尺度。
- 训练规模:4 亿图文对(WIT 数据集),batch size 32768——巨大的 batch 等价于巨大的负样本池
2. SimCSE:NLP 对比学习的”SimCLR 时刻”
文本是离散 token,无法做 Crop/Color Jitter。SimCSE(EMNLP 2021)发现一个简单到震惊的方案:两次不同的 Dropout 当作正样本对。
2.1 Unsupervised SimCSE
同一句话 $x$ 两次过同一个 BERT,由于 Dropout mask 不同,得到 $h_1, h_2$,作为正样本对。Batch 内其他句子作负样本。损失就是标准 InfoNCE:
2.2 Supervised SimCSE
用 NLI(自然语言推理)数据:
- 正样本:(premise, entailment)(蕴含)
- Hard Negative:(premise, contradiction)(矛盾)
- 加 hard negative 后效果显著提升
2.3 为什么 Dropout 这么简单的方案有效?
Dropout 在表示空间施加了最小但语义保持的扰动:
- 保留 anchor 的语义(输入文本完全不变)
- 制造足够的随机性让模型学到鲁棒特征
- 复杂的文本增强(同义词替换、删词)反而可能改变语义,引入噪声标签
核心洞察:对比学习的成功核心是”语义保持的扰动 + 互斥的负样本池“。增强的强度只要够引入随机性即可,不必复杂。
3. In-batch Negatives 的数学
对 retrieval 任务,batch 内 $N$ 个 (query, positive) 对,构造 $N \times N$ 相似度矩阵:
- 对角线 $S_{ii}$ = (query_i, positive_i) 得分
- 非对角线 $S_{ij}, j \neq i$ = (query_i, positive_j) 得分 → 当作 query_i 的负样本
一次前向就拿到了 $N-1$ 个免费负样本。损失:
这是 DPR、BGE、E5 等所有 retriever 的标配做法。Batch size 越大,负样本越多,效果越好——这与 SimCLR 的逻辑一致。
§B 模型结构(PyTorch 实现)
B.1 CLIP 完整 forward + loss
1 | import torch |
为什么用 logit_scale.exp() 而非直接学 $\tau$?
- $\tau > 0$ 是硬约束,直接学 $\tau$ 会导致优化时跑出可行域
- 学 $\log(1/\tau)$ 然后取 exp 自动满足正性约束(参数化技巧,类似 reparameterization)
B.2 SimCSE Dropout 增强 + 损失
1 | class SimCSE(nn.Module): |
两个易错点:
- 必须开启 model.train():否则 dropout 不生效,两次 forward 完全一样,loss 永远为 0
- In-batch 负样本依赖 batch size:常见 64–256,太小效果差
B.3 BGE/E5 Retrieval 模型 + Hard Negative
实际 RAG 检索器训练时,每个 (query, pos) 还要配 $K$ 个 hard negatives:
1 | class RetrievalModel(nn.Module): |
这是 BGE / E5 训练的”压舱石”代码——理解这段代码就理解了现代 RAG 检索器的训练。
§C 训练与推理
C.1 训练视角:BGE / E5 / GTE 的三阶段训练
当前主流开源 Embedding 模型几乎都遵循:
| 阶段 | 数据 | 损失 | 数据规模 |
|---|---|---|---|
| 1. 弱监督对比预训练 | 爬虫”标题-正文”、”问题-答案”等天然配对 | In-batch InfoNCE | 百亿级 |
| 2. 监督对比微调 | MS MARCO、NLI 等高质量标注 | InfoNCE | 千万级 |
| 3. Hard Negative 蒸馏 | 用 cross-encoder 教师挖难负例 | InfoNCE + KL 蒸馏 | 百万级 |
Hard Negative Mining 的四种方法:
| 方法 | 思路 | 代价 |
|---|---|---|
| BM25 Hard Negatives | 用 BM25 召回 top-k,去掉真 positive | 便宜,但负样本质量一般 |
| ANCE (Microsoft) | 用上一版本模型自挖负例,定期刷新 | 中等,需多轮训练 |
| RocketQA | Cross-encoder 二次过滤”伪负样本” | 贵,但效果最好 |
| MoCHi (NeurIPS 2020) | 在特征空间 mixup 合成 hard negatives | 中等 |
C.2 推理视角一:FAISS 索引构建 + 召回
训练完 embedding 模型后,RAG 系统的推理流程:
1 | import faiss |
关键工程细节:
- 必须 L2 归一化:embedding 模型训练时归一化的,索引也必须归一化
- 用 IndexFlatIP 而非 IndexFlatL2:内积比余弦快 30%(呼应 Ch1 §C.2)
- 大规模用 IVF + PQ:暴力 IndexFlatIP 在亿级数据上太慢,IVF + PQ 牺牲少量精度换速度
C.3 推理视角二:完整 RAG 流程
1 | 用户 Query |
为什么要两阶段(召回 + 重排)?
- 召回阶段:双塔模型,离线编码所有文档,向量检索极快但只看”语义相似”
- 重排阶段:cross-encoder(query 和 doc 拼起来过一次模型),考虑细粒度交互,但只能处理少量候选
C.4 推理视角三:CLIP 在多模态 LLM 中扮演什么角色
多模态 LLM(LLaVA、GPT-4V、Qwen-VL)的标准做法:
1 | 图像 ──→ [CLIP Vision Encoder] ──→ 视觉 token ──┐ |
关键工程点:
- 冻结 CLIP:训练时 vision encoder 通常不动,只训练投影层 + LLM 微调
- 投影层(Projection):一个轻量 MLP,把 CLIP 的视觉 token 维度对齐到 LLM 的词嵌入空间
- 训练成本:相比从零训练 vision encoder,CLIP 已经把”看图”能力打包好了
为什么 CLIP 这么”通用”?
- 4 亿图文对训练 → 几乎覆盖了人类所有视觉概念的语言描述
- 对比学习 → 视觉特征天然与”语言描述”对齐,LLM 理解起来天然顺畅
§D 章末速查
D.1 三种 InfoNCE 变体对比
| 方法 | 正样本来源 | 负样本来源 | 温度 | 典型 batch |
|---|---|---|---|---|
| SimCLR(Ch2) | 同图像两次增强 | Batch 内其他图像 | 固定 0.5 | 4096+ |
| CLIP | 配对的图文 | Batch 内其他图文对 | 可学习 | 32768 |
| SimCSE | 同句子两次 Dropout | Batch 内其他句子 | 固定 0.05 | 64–256 |
| BGE / E5 | 配对的 (q, pos) | In-batch + Hard Neg | 固定 0.02 | 数百到上千 |
D.2 关键工程要点回顾
- ✅ L2 归一化 + 内积索引 = 余弦相似度的工程化(Ch1 §C.2)
- ✅ 可学习温度:CLIP 的关键技巧,让模型自决定相似度尺度
- ✅ Dropout = 最小增强:SimCSE 的洞察,复杂增强反而引入噪声
- ✅ In-batch + Hard Negative:BGE/E5 训练范式
- ✅ 召回 + 重排:RAG 标准两阶段架构
承上启下
本章和 Ch2 一起,把对比学习的”有负样本路线”讲完了:
- Ch2:视觉、SimCLR/MoCo
- Ch3:跨模态/文本、CLIP/SimCSE/BGE
下一章 Ch4 进入完全不同的路线:没有负样本如何训表征模型? BYOL/SimSiam/DINO 给出了惊人的答案——只要打破对称性(Stop-gradient + Predictor),模型就不会塌缩。这套机制后来直接被 RLHF 借鉴(Reference Policy ≈ Target Network)。