一、论文背景:为什么需要 CLIP
传统计算机视觉模型大多是在固定类别集合上训练的,比如 ImageNet 里的 1000 类。这种方式的问题在于:
- 类别集合是封闭的,模型只能识别训练时见过的类别;
- 想识别新概念,就必须重新收集数据并重新标注;
- 监督信号依赖人工标签,成本高且扩展性差。
论文提出的核心想法是:
不要只依赖人工类别标签,而是直接利用互联网上大量的图文对,让模型从自然语言中学习视觉概念。
这带来的好处是:
- 标签空间变开放了;
- 监督信息更丰富;
- 模型可以直接用文本描述去做分类,也就是 zero-shot。
二、CLIP 的核心思路
CLIP 的目标不是训练一个传统分类器,而是训练一个图像编码器 和一个文本编码器,把图像和文本映射到同一个语义空间中。
1. 训练目标
给定一个 batch 中的图像和文本配对:
- 正样本:正确配对的图像和文本;
- 负样本:batch 中其他不匹配的组合。
模型要做的是:
- 提高正确图文对的相似度;
- 降低错误图文对的相似度。
2. 训练方式
CLIP 使用的是对比学习(contrastive learning) 。
它本质上是在 batch 内做一个"分类问题":
- 对每张图像,从 batch 中的所有文本里找出正确描述;
- 对每段文本,从 batch 中的所有图像里找出正确配对。
三、对比损失 InfoNCE 的理解
CLIP 的损失函数本质上就是 InfoNCE,可以看成是交叉熵损失的一个变体。
设 batch size 为 (N),图像为 (I_1, I_2, ..., I_N),文本为 (T_1, T_2, ..., T_N)。
经过编码器后得到:
vi=f(Ii),ti=g(Ti) v_i = f(I_i), \quad t_i = g(T_i) vi=f(Ii),ti=g(Ti)
然后计算图像和文本之间的相似度:
sij=vi⋅tjτ s_{ij} = \frac{v_i \cdot t_j}{\tau} sij=τvi⋅tj
其中 (τ\tauτ) 是温度系数。
1. 为什么是正样本和负样本?
对固定一张图像 (I_i) 来说:
- 正样本只有 1 个:(T_i)
- 负样本有 (N-1) 个:batch 里其他文本
所以从单个 anchor 的角度看,就是 1 个正样本 + (N-1) 个负样本。
但是 CLIP 会对 batch 中每一对都做一次这样的比较:
- 一共有 (N) 个图像 anchor;
- 每个图像对应 (N-1) 个负样本;
- 所以从整个 batch 的角度看,负样本总数是 (N(N-1))。
2. 损失公式为什么像交叉熵?
图像到文本方向的损失可以写成:
Li=−logexp(sii)∑j=1Nexp(sij) L_i = -\log \frac{\exp(s_{ii})}{\sum_{j=1}^{N}\exp(s_{ij})} Li=−log∑j=1Nexp(sij)exp(sii)
这个式子和交叉熵非常像,因为它本质上就是:
- 用 softmax 把 batch 内所有文本变成一个概率分布;
- 正确配对的位置作为监督标签;
- 对正确位置的概率取负对数。
因此,InfoNCE 可以理解成:
在 batch 内做分类,目标是让正确配对的概率最大。
3. 为什么要有负号?
因为训练时优化器通常是最小化损失 。
我们希望正确配对概率越大越好,所以先取 (\log p),再加负号变成最小化问题:
- 正确概率越大,loss 越小;
- 正确概率越小,loss 越大。
4. log 的作用
log 的作用有两个:
- 放大错误样本的惩罚;
- 把 softmax 的乘法结构转化成更稳定的加法结构。
当正确样本概率很低时,(−logp-\log p−logp) 会迅速变大,这会迫使模型更关注难样本。
5. 为什么能自动实现"正样本最大,负样本最小"?
展开损失后可以看到:
Li=−sii+log∑j=1Nexp(sij) L_i = -s_{ii} + \log \sum_{j=1}^{N}\exp(s_{ij}) Li=−sii+logj=1∑Nexp(sij)
第一项 (-s_{ii}) 会推动正样本相似度变大;
第二项 (\log \sum \exp(s_{ij})) 会惩罚所有相似度过高的候选项,尤其是负样本。
所以这个损失天然就实现了:
- 拉近正样本;
- 推远负样本。
6. 对抗项是什么?
分母里的:
∑j=1Nexp(sij) \sum_{j=1}^{N}\exp(s_{ij}) j=1∑Nexp(sij)
就是所谓的"对抗项"。
因为 batch 中的其他样本都在争夺 softmax 的概率质量,它们之间是竞争关系。
某个负样本分数越高,正样本被分到的概率就越低,这就形成了对抗。
四、为什么要做归一化
CLIP 中会先把图像特征和文本特征归一化到单位长度:
v^=v∣v∣,t^=t∣t∣ \hat{v} = \frac{v}{|v|}, \quad \hat{t} = \frac{t}{|t|} v^=∣v∣v,t^=∣t∣t
然后计算点积:
v^⋅t^ \hat{v} \cdot \hat{t} v^⋅t^
这等价于余弦相似度。
为什么要归一化?
如果不归一化,模型可能通过简单地把向量的 norm 变大来"作弊",从而让点积变大、loss 下降,但实际上并没有学到更好的语义表示。
归一化的作用主要是:
- 避免向量长度影响相似度;
- 防止 embedding 无限变大;
- 让模型专注于"方向"而不是"长度"。
五、embedding 爆炸是什么
所谓 embedding 爆炸,就是向量的范数不断变大,数值越来越大。
如果不做归一化,模型可能会不断增大向量长度,让点积变得很大,softmax 很容易饱和,出现:
- 梯度变小;
- 训练不稳定;
- 甚至数值溢出。
所以归一化是 CLIP 训练里非常关键的一个稳定化手段。
六、温度参数 τ 的作用
CLIP 在计算 softmax 之前,会对 logits 做缩放:
sijτ \frac{s_{ij}}{\tau} τsij
这里的 (\tau) 是温度参数,而且是可学习的。
作用是什么?
- (τ\tauτ) 小:softmax 更尖锐,模型更"果断";
- (τ\tauτ) 大:softmax 更平滑,分布更平均。
这个参数能帮助模型自动找到合适的对比强度。
七、CLIP 的模型结构
CLIP 采用的是双编码器结构(dual encoder):
- 图像编码器:ResNet 或 ViT;
- 文本编码器:Transformer。
二者分别把图像和文本编码成向量,再在同一个语义空间里做相似度计算。
1. 图像编码器
论文里考虑了两种图像编码器:
- ResNet
- Vision Transformer (ViT)
2. 文本编码器
文本编码器是一个 Transformer,结构上类似 GPT-2:
- 12 层;
- hidden size 512;
- 8 个 attention heads;
- 使用 masked self-attention。
需要注意的是:
虽然它长得像 GPT,但训练目标不是语言建模,而是图文对齐。
八、ResNet 的改造
CLIP 并没有直接使用原版 ResNet,而是做了几个重要改动:
1. ResNet-D
用更合理的 stem 结构替代原始的 7×7 卷积 + max pool,减少信息损失。
2. Anti-aliased blur pooling
在下采样之前先做低通滤波,减少混叠,提高特征稳定性。
3. Attention pooling
把最后的 global average pooling 替换成 attention pooling。
这点非常重要,因为:
- 平均池化对所有位置一视同仁;
- Attention pooling 可以自动学习哪些位置更重要。
这更适合图文对齐任务,因为模型需要关注图像中真正和文本相关的语义区域。
九、ViT 的使用
对于 ViT,CLIP 基本沿用了原始结构,说明 ViT 本身已经很适合做大规模表征学习。
ViT 的基本流程
- 把图像切成 patch;
- 每个 patch 映射成 token;
- 输入 Transformer;
- 取 [CLS] token 或全局表示作为图像 embedding。
常见模型命名
- ViT-B/32
- ViT-B/16
- ViT-L/14
其中:
- B / L 表示 Base / Large;
- 32 / 16 / 14 表示 patch size。
patch 越小,token 越多,细节越丰富,但计算也越贵。
十、CLIP 的 scaling 思想
CLIP 不是只训练一个模型,而是训练了多个不同规模的模型,研究扩展规律。
1. ResNet 系列
包括:
- RN50
- RN101
- RN50x4
- RN50x16
- RN50x64
其中 x4、x16、x64 表示网络宽度扩大倍数。
2. ViT 系列
包括:
- ViT-B/32
- ViT-B/16
- ViT-L/14
3. scaling 的三个维度
- width:宽度;
- depth:深度;
- resolution:输入分辨率。
CLIP 的一个重要结论是:
在大规模数据下,扩大模型规模会显著提升性能。
十一、文本编码器与词表
CLIP 的文本编码器使用的是 BPE(Byte Pair Encoding)词表。
1. BPE 是什么
BPE 是一种子词分词方法,不是按完整单词切,而是按 subword 切分。
例如:
- unbelievable
可能被切成 - un / believ / able
这样可以兼顾词表大小和泛化能力。
2. 词表规模
CLIP 使用约 49,152 个 token 的词表,这个规模和 GPT-2 是比较接近的。
3. 序列长度
CLIP 将文本长度截断为 77 tokens,并加入:
-
SOS\]:开始标记;
通常会取 [EOS] 的表示作为整句的文本 embedding。
十二、CLIP 和 LLM 的关系
这是很多人会困惑的地方。
1. 为什么说不完全一致
CLIP 和 LLM 虽然都可能使用 Transformer、BPE、token embedding,但它们的训练目标不同:
- LLM:预测下一个 token;
- CLIP:做图文对齐。
因此它们学到的 embedding 空间并不相同。
2. 会不会脱节?
不会脱节,但也不会天然完全兼容。
更准确地说:
- 它们可以通过投影层对接;
- 可以通过 bridge 模块连接;
- 可以作为不同子系统协同工作。
因此 CLIP 更像是一个视觉-语言对齐模块 ,而 LLM 更像是语言生成模块。
十三、Zero-shot 推理
CLIP 最重要的能力之一是 zero-shot 分类。
1. 传统分类方式
传统方法需要训练一个线性分类器:
image→feature→classifier→label image \rightarrow feature \rightarrow classifier \rightarrow label image→feature→classifier→label
2. CLIP 的方式
CLIP 不训练任务专属分类器,而是:
- 把类别改写成自然语言 prompt;
- 计算图像 embedding 和文本 embedding 的相似度;
- 选择相似度最高的类别。
例如分类 "dog" 时,可以写成:
- a photo of a dog
- a picture of a dog
3. 为什么这样有效
因为 CLIP 训练时本来就是在做 image-text 对齐,所以类别只要转成一句自然语言,就可以直接拿来和图像比较。
十四、Prompt Engineering 的重要性
CLIP 论文发现,prompt 的写法会显著影响结果。
1. 为什么 prompt 会影响性能
因为训练数据是"图像 + 自然语言描述",而不是单独的类别标签。
因此模型更容易理解自然语言模板,而不是孤立的词。
2. 例子
- "dog"
不如 - "a photo of a dog"
这是因为后者更接近训练时的文本分布。
3. Prompt Ensemble
可以使用多个 prompt 模板,然后把它们的文本 embedding 平均起来,提高稳定性和鲁棒性。
十五、CLIP 的本质总结
CLIP 本质上不是一个传统分类器,而是一个:
学习图像与文本对齐的通用多模态表示模型。
它做的事情可以概括为:
- 用大规模图文对进行预训练;
- 学会把图像和文本映射到同一语义空间;
- 在测试时可以直接用文本 prompt 完成 zero-shot 分类;
- 通过 prompt engineering 可以进一步提升性能。
十六、适合记住的几个关键点
1. CLIP 为什么强
因为它用大规模图文对替代了人工类别标签,学到的是更开放、更通用的语义空间。
2. InfoNCE 为什么像交叉熵
因为它本质上就是在 batch 内做分类。
3. 为什么要归一化
为了防止向量长度作弊,稳定训练。
4. 为什么 prompt 重要
因为 CLIP 训练的是"句子-图像对齐",而不是单词分类。
5. CLIP 和 LLM 的关系
它们不是一回事,但可以通过 embedding 接口进行连接和融合。
十七、这一部分的学习建议
读 CLIP 时不要只盯着"模型长什么样",更重要的是抓住三个核心层次:
1. 问题层
传统视觉模型为什么不够通用?
2. 方法层
CLIP 如何用图文对比学习解决这个问题?
3. 推理层
为什么只用 prompt 就能 zero-shot 分类?
这三个层次串起来,CLIP 的逻辑就会非常清楚。