CLIP
概述
CLIP(Contrastive Language–Image Pretraining)是 OpenAI 提出的一种多模态模型,能够将图像和文本映射到同一个向量空间,从而实现图像和文本的联合理解。CLIP 的核心思想是通过对比学习(Contrastive Learning)来训练模型,使得匹配的图像-文本对的向量相似度尽可能高,而不匹配的图像-文本对的向量相似度尽可能低。
损失函数
CLIP 的损失函数是对比损失(Contrastive Loss),具体实现如下:
图像到文本的对比损失:计算图像特征与文本特征的相似度。
文本到图像的对比损失:计算文本特征与图像特征的相似度。
最终损失是这两部分损失的平均值。
损失函数的数学形式
假设:
图像特征矩阵 I (形状为 B×D ),其中 B 是批量大小, D 是特征维度。 文本特征矩阵 T (形状为B×D)。 温度参数 τ (用于缩放相似度)。
计算相似度矩阵
图像到文本的相似度矩阵 :
文本到图像的相似度矩阵 :
计算对比损失
图像到文本的对比损失:
文本到图像的对比损失:
代码实现
import torch
import torch.nn.functional as F
def clip_loss(image_features, text_features, temperature=0.07):
"""
计算 CLIP 的对比损失。
参数:
image_features (torch.Tensor): 图像特征,形状为 (B, D)。
text_features (torch.Tensor): 文本特征,形状为 (B, D)。
temperature (float): 温度参数,默认为 0.07。
返回:
torch.Tensor: 对比损失。
"""
# 归一化特征
image_features = F.normalize(image_features, dim=-1)
text_features = F.normalize(text_features, dim=-1)
# 计算相似度矩阵
logits_per_image = (image_features @ text_features.T) / temperature
logits_per_text = logits_per_image.T
# 创建标签(对角线为 1,其余为 0)
batch_size = image_features.shape[0]
labels = torch.arange(batch_size, device=image_features.device)
# 计算图像到文本的对比损失
loss_image = F.cross_entropy(logits_per_image, labels)
# 计算文本到图像的对比损失
loss_text = F.cross_entropy(logits_per_text, labels)
# 总损失
loss = (loss_image + loss_text) / 2
return loss
CLIP能力归因分析
CLIP 能够实现 zero-shot 和 few-shot
归因于它的 预训练方式和特征表示:
(1) 大规模的对比学习(Contrastive Learning)
-
CLIP 通过对比学习,让模型在 文本-图像表示空间 之间建立了 广泛的概念对齐,而不是仅限于少数训练类别。
-
这样,即使是 未见过的类别,CLIP 也能利用 概念相似性 进行分类。
(2) 语言引导的分类(Text-Guided Classification)
-
传统分类器需要 固定类别数的分类头,而 CLIP 直接基于 自然语言描述 进行分类,不受固定类别限制。
-
只要提供新的文本提示(Prompt),CLIP 就能适配新的任务。
(3) 共享的视觉-语言嵌入空间
-
CLIP 将图像和文本投影到 相同的特征空间(同样的dimension),并且在训练过程中学习了 丰富的跨模态表示(语义对齐表示)。
-
这意味着,即使 没有见过的类别,它也可以利用语言的语义信息进行推理(主要是想象的图很难用图片描述,但是容易用语言描述,但语言已经在clip中和图片进行了对齐)。
|
能力 |
实现方式 |
|
zero-shot |
通过 文本提示(Prompts) 进行推理,不需要微调,计算文本-图像相似度来完成分类。 |
|
Few-Shot |
通过 少量示例 来调整匹配,快速适应新任务,不需要重新训练整个模型。 |
Note
-
与
其实是互为转置矩阵的,但是这两个矩阵并是不对称矩阵。
-
代码中loss_image 与loss_text value其实是一样的,但是反向传播的梯度是不一样的loss_image 会获得更偏向image encoder的梯度, loss_text 会获得更偏向txt encoder的梯度,所以最终反向传播的loss是这两者求mean,确保image和text中的参数都能被有效更新
-
与supervision 的one-hot 标签相比,clip这种距离度量方式的学习本质上是一种soft target的方式,传统的label ,例如"猫", "狗",这种hard target将每个class离散开来(彼此独立)本质上熵值几乎为0,但是text描述的方式无形中增加熵值,用一种更连续的向量来表达,足够soft,例如“一只鼻子黑黑的高冷短毛猫” 与“一只鼻子黑黑的热情土狗”。
-
标签足够soft,获取的信息就更多,刻画就越准确
MOCO
概述
MoCo(Momentum Contrast)是一种基于对比学习(Contrastive Learning)的自监督学习方法,由 Kaiming He 等人于 2019 年提出。它的核心思想是通过构建一个动态的字典(dynamic dictionary)来学习视觉表征,从而在没有标签数据的情况下训练出强大的视觉表征模型。MoCo 的目标是通过对比学习,将同一图像的不同增强视图(positive pairs)映射到相近的向量空间,而将不同图像的视图(negative pairs)映射到远离的向量空间。其中,正样本是通过augmentation变换得到的,负样本是通过构建动态字典得到的。
关键组件
动态字典(Dynamic Dictionary):
-
字典中存储了大量的负样本(negative samples),用于对比学习。
-
字典是通过一个动量编码器(Momentum Encoder)动态更新的。
动量更新(Momentum Update):
-
动量编码器的参数是通过动量更新机制从查询编码器(Query Encoder)中缓慢更新的。
-
这种方式可以保持字典的一致性(词典内样本表征的一致性),同时避免编码器的快速变化。
Pretext task
采用instance discrimination来作为代理任务,进行对比学习
-
正样本对(Positive Pair): 由 同一图像的两种不同数据增强(Augmentations) 生成的特征表示。
-
负样本对(Negative Pair): 由 不同图像 生成的特征表示。即字典队列中的所有embedding 与当前数batch中的每个sample 互为负样本
InfoNCE
假设:
你是一名老师,正在批改学生的作文,你的任务是判断某句话是 "学生自己写的" 还是 "从互联网上随机摘抄的"。
你的目标是:
-
让你的模型能分辨哪些句子是 真实数据(positive example)。
-
让你的模型能分辨哪些句子是 噪声数据(negative example)(随机从网络上抓取的句子,但是从网络上抓取的句子可能有各种不同类型的网站上抓取,如果按照分类的话可以非常多的类来源, 但你其实只关注是否是自己写的真的数据,是或者不是两类)。
假设你有 1000 篇文章,你要构造一个分类器 ,即 给定一句话 x,它是“学生原创” 的概率。
如果我们用 Softmax 分类器,需要计算:
其中f(x)是句子的logit, N是所有可能的类别数量(比如10000种文章的分布)
如果N 很大,比如有1亿中文章来源,那么就会造成softmax计算归一化分母及其昂贵,甚至不可实现
由此,引申出NCE loss来进行替代softmax。NCE 通过 二分类任务 来替代 Softmax 分类。现在,我们不再去计算 1000 个类别的 Softmax,而是直接让模型学习区分 真实句子 和 噪声句子。
NCE 采用 二元分类(Binary Classification) 方式:
NCE主要用二分类,将类别众多的问题转换为目标类和非目标类两种类别的问题
INFONCE本质上还是一种cross entropy,但是crossentropy内元素代表的是样本pair之间的距离,同时为了避免负类别过多,对与负pair对进行了采样,计算loss的时候采用的是多分类,不是二分类
工作流程
1. 数据增强
对输入图像进行两次随机增强,生成两个视图 xq(查询视图)和 xk(键视图)。
2. 编码器
查询编码器 fq 和动量编码器 fk 分别对 xq和xk 进行编码,得到特征向量 q=fq(xq)和 k=fk(xk)。
3.动态字典
字典中存储了大量的负样本(来自之前的批次)。
将 k 加入字典,同时移除最旧的样本。
4.对比损失
计算查询特征 qq 与字典中所有键特征的相似度
使用 InfoNCE 损失来优化模型。
5. 动量更新
动量编码器的参数通过动量更新机制从查询编码器中更新。
可以理解为moco 其实是将原来 在一个batch 内做对比loss 扩展到了batch中每个sample 与外部巨大词典中的sample 做对比loss,从而扩大了负类别的长度以及多样性,从而提升了结果
MoCo 的优势分析
(1)负样本数量增加
-
通过动态字典,MoCo 可以访问大量的负样本,远远超过批次大小。
-
这使得模型能够更好地学习到数据的全局分布。
(2)负样本多样性提升
-
字典中的样本来自整个训练过程,覆盖了更多的数据分布。
-
这提升了负样本的多样性,使得模型能够学习到更鲁棒的特征表示。
(3)计算效率高
-
尽管字典的大小很大,但 MoCo 通过动量编码器和高效的对比损失计算,保持了较高的计算效率。
(4)结果提升
-
通过增加负样本的数量和多样性,MoCo 在多个视觉任务(如图像分类、目标检测、语义分割等)上取得了显著的性能提升。
|
特性 |
MoCo (Momentum Contrast) |
SimCLR (Simple Framework for Contrastive Learning) |
Memory Bank |
|---|---|---|---|
|
核心思想 |
通过动态字典(Dynamic Dictionary)和动量编码器(Momentum Encoder)扩展负样本的数量和多样性。 |
在单个批次内进行对比学习,使用数据增强生成正样本对。 |
使用一个固定的记忆库(Memory Bank)存储历史样本特征,作为负样本来源。 |
|
负样本来源 |
动态字典,存储大量历史样本特征。 |
当前批次内的其他样本。 |
记忆库,存储历史样本特征。 |
|
负样本数量 |
非常大(如 65536),远超批次大小。 |
受限于批次大小(通常为几十到几百)。 |
较大(如 65536),但记忆库是固定的,无法动态更新。 |
|
负样本多样性 |
高,来自整个训练过程。 |
较低,仅来自当前批次。 |
较高,但记忆库中的样本可能过时。 |
|
动量更新机制 |
使用动量编码器(Momentum Encoder)缓慢更新字典中的特征,保持一致性。 |
无动量更新机制。 |
无动量更新机制。 |
|
计算复杂度 |
较低,通过动态字典和动量编码器实现高效对比学习。 |
较高,需要在批次内计算所有样本对的相似度。 |
中等,记忆库需要存储和更新大量特征。 |
|
实现难度 |
中等,需要实现动态字典和动量编码器。 |
简单,易于实现。 |
中等,需要实现记忆库的存储和更新逻辑。 |
|
主要贡献 |
引入动态字典和动量编码器,显著提升负样本的数量和多样性。 |
提出简单的对比学习框架,强调数据增强和批次内对比的重要性。 |
提出使用记忆库存储历史样本特征,扩展负样本来源。 |
|
解决的问题 |
解决了批次内负样本数量有限和多样性不足的问题。 |
解决了自监督学习中正样本对生成和批次内对比的问题。 |
解决了批次内负样本数量有限的问题,但记忆库中的样本可能过时。 |
|
优点 |
- 负样本数量大、多样性高。 |
- 实现简单。 |
- 负样本数量较大。 |
|
缺点 |
- 实现复杂度较高。 |
- 负样本数量受限于批次大小。 |
- 记忆库中的样本可能过时。 |
|
典型应用场景 |
图像分类、表示学习 |
图像分类、表示学习等任务。 |
图像分类、表示学习等任务。 |
三种方式优缺点概括
SimCLR端到端方式 : 保证一致性,负样本缺乏多样性
Memory Bank:保证负样本多样性,但是缺乏一致性
MOCO:尽量保持一致性,保证负样本多样性
moco v2 更多的是在moco v1基础上加入更多的数据增强,以及参数trick,V3则更有向端到端+大batchsize 投降的意思
本文为原创文章,未经作者允许禁止转载。
2591

被折叠的 条评论
为什么被折叠?



