共计 2017 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
在跨模态学习(如图像 - 文本)中,最大的挑战是如何让不同模态的特征在同一个空间中对齐。传统的单模态损失函数(如交叉熵、MSE 等)很难直接应用于这类问题,因为它们无法捕捉模态间的复杂关联。

- 传统方法的局限性:
- 单模态损失函数假设输入输出在同一空间
- 无法处理模态间的语义鸿沟
- 缺乏对负样本的显式利用
技术解析
CLIP 的双塔架构
CLIP 采用双塔结构:一个图像编码器和一个文本编码器,将两种模态映射到同一语义空间。
- 对比学习机制:
- 正样本:匹配的图像 - 文本对
- 负样本:不匹配的图像 - 文本对
-
目标:最大化正样本相似度,最小化负样本相似度
-
对称式 InfoNCE 损失
损失函数定义如下:
$$\mathcal{L}{i2t} = -\frac{1}{N}\sum$$}^N \log\frac{\exp(s_{i,i}/\tau)}{\sum_{j=1}^N \exp(s_{i,j}/\tau)
$$\mathcal{L}{t2i} = -\frac{1}{N}\sum$$}^N \log\frac{\exp(s_{i,i}/\tau)}{\sum_{j=1}^N \exp(s_{i,j}/\tau)
总损失为两者平均:$\mathcal{L} = (\mathcal{L}{i2t} + \mathcal{L})/2$
- 温度系数 τ
- 控制相似度得分的分布尖锐程度
- 太小:模型过于自信
- 太大:难以区分正负样本
- 经验值:通常在 0.01 到 0.1 之间
代码实战
PyTorch 实现
import torch
import torch.nn as nn
import torch.nn.functional as F
class CLIPLoss(nn.Module):
"""
可微调的 CLIP 对比损失层
Args:
tau: 温度系数
"""
def __init__(self, tau=0.07):
super().__init__()
self.tau = tau
self.logit_scale = nn.Parameter(torch.ones([]) * 1.0/self.tau)
def forward(self, image_features, text_features):
"""
Args:
image_features: [batch_size, feat_dim]
text_features: [batch_size, feat_dim]
"""
# 特征归一化
image_features = F.normalize(image_features, dim=-1)
text_features = F.normalize(text_features, dim=-1)
# 计算相似度矩阵 [batch_size, batch_size]
logits_per_image = self.logit_scale * image_features @ text_features.t()
logits_per_text = logits_per_image.t()
# 创建标签 [0,1,...,batch_size-1]
batch_size = image_features.shape[0]
labels = torch.arange(batch_size, device=image_features.device)
# 计算双向损失
loss_i = F.cross_entropy(logits_per_image, labels)
loss_t = F.cross_entropy(logits_per_text, labels)
loss = (loss_i + loss_t) / 2
return loss
关键实现细节
- 特征归一化:
- 使用 L2 归一化保证特征在单位球面上
-
避免特征尺度影响温度系数
-
相似度计算:
- 矩阵乘法高效计算所有样本对
-
注意转置操作实现双向计算
-
梯度检查:
# 梯度检查示例 model = CLIPLoss() img_feat = torch.randn(16, 512, requires_grad=True) txt_feat = torch.randn(16, 512, requires_grad=True) loss = model(img_feat, txt_feat) loss.backward() assert img_feat.grad is not None assert txt_feat.grad is not None
避坑指南
- 批次大小与温度系数
- 大批次需要更小的 τ(更多负样本)
-
小批次可适当增大 τ
-
混合精度训练
- 使用梯度缩放避免下溢
-
对 logits 进行适当裁剪
-
负样本比例
- 实际 batch 中所有不匹配对都是负样本
- 增大 batch size 相当于增加负样本
延伸思考
- 扩展到视频 - 文本
- 视频编码器替换图像编码器
-
考虑时序池化策略
-
与其他模型对比
- BLIP:额外添加图文匹配头
- ALIGN:使用更大的 batch size
总结
CLIP 损失函数通过对比学习巧妙解决了跨模态对齐问题。温度系数 τ 是需要重点调节的超参数,而 大批次训练 能显著提升性能。实际应用中可以根据硬件条件调整实现细节,如使用梯度累积模拟大批次。
正文完
发表至: 未分类
近三天内
