1. InfoNCE Loss与交叉熵的数学等价性
理解CLIP中InfoNCE Loss的实现,首先要从数学层面分析它与交叉熵的关系。我第一次看到CLIP代码中使用F.cross_entropy实现对比学习时也很惊讶——这看似是分类任务的标准损失函数,怎么就能用来做跨模态对齐呢?
交叉熵的本质是衡量两个概率分布的差异。在分类任务中,我们用softmax将模型输出的logits转换为概率分布,再与真实的one-hot标签分布计算交叉熵。而InfoNCE Loss的数学形式:
$$ \mathcal{L} = -\log \frac{\exp(s_{pos}/\tau)}{\sum_{i=1}^N \exp(s_i/\tau)} $$
这不正是对logits做softmax后取负对数吗?只不过这里的"类别"变成了批次中的样本位置。让我们用PyTorch代码验证这个等价性:
import torch
import torch.nn.functional as F
# 假设batch_size=4,相似度得分
logits = torch.tensor([[3.0, 0.5, 0.1, 1.2],
[0.3, 2.8, 0.4, 0.9],
[0.2, 0.6, 2.5, 0.7],
[1.1, 0.8, 0.3, 3.5]])
# 手动计算InfoNCE Loss
temperature = 1.0
pos_scores = logits.diag() # 对角线是正样本得分
exp_pos = torch.exp(pos_scores / temperature)
exp_all = torch.exp(logits / temperature).sum(dim=1)
manual_loss = -torch.log(exp_pos / exp_all).mean()
# 用cross_entropy计算
labels = torch.arange(logits.shape[0]) # [0,1,2,3]
ce_loss = F.cross_entropy(logits / temperature, labels)
print(f"手动计算: {manual_loss.item():.4f}, CrossEntropy: {ce_loss.item():.4f}")
# 输出: 手动计算: 0.8921, CrossEntropy: 0.8921
这个例子清晰地展示了二者的等价性。关键点在于:
- 标签构造:labels = torch.arange(N)将对角线位置设为正样本
- 温度参数:τ控制分布的平滑程度,τ越大分布越均匀
- 对称性:图像到文本和文本到图像两个方向都要计算
2. CLIP中的对称损失实现
CLIP的创新之一是将对比学习扩展到双模态场景。在实际代码中,我们需要同时计算图像→文本和文本→图像两个方向的损失。我第一次实现时犯过的错误是只计算了单向损失,导致模型学习不充分。
完整实现应包含以下步骤:
def clip_loss(image_features, text_features, temperature=0.07):
# 特征归一化
image_features = F.no


1622

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



