跨模态Transformer的统一视角:从ViT到CLIP的架构共性抽象

📅 2026/7/14 12:05:24
跨模态Transformer的统一视角:从ViT到CLIP的架构共性抽象
跨模态Transformer的统一视角从ViT到CLIP的架构共性抽象一、Transformer的模态无关性——相同的积木不同的玩法自注意力机制的原始公式$\text{Attention}(Q, K, V) \text{softmax}(\frac{QK^T}{\sqrt{d_k}})V$中没有任何模态特定的假设。Q、K、V只是三个矩阵它们的语义完全由输入决定。这个事实使得Transformer可以无缝迁移到任何能被序列化表示的模态——图像patch序列、语音频谱帧序列、视频时空patch序列、蛋白质氨基酸序列。ViTVision Transformer和CLIPContrastive Language-Image Pre-training代表了跨模态Transformer的两种典型范式单模态编码ViT将图像视为patch序列和双塔对比学习CLIP通过共享的对比目标将图像和文本映射到统一空间。graph TB A[Transformer 通用架构] -- B[ViT 单模态编码] A -- C[CLIP 双塔对比] B -- B1[图像 → Patch序列 →br/Transformer Encoder →br/图像表示] C -- C1[图像 → ViT → 图像Embedding] C -- C2[文本 → Transformer → 文本Embedding] C1 -- C3[对比损失br/最大化配对相似度] C2 -- C3二、从ViT到CLIP的架构共性尽管ViT和CLIP服务于不同的目标图像分类 vs. 多模态对齐它们在架构层面共享以下设计原则序列化策略两者都将非序列数据转化为序列。ViT将图像切分为16×16的patch并线性投影到embedding空间CLIP的文本塔使用小写字节对编码BPE将文本切分为子词。共同原则是找到一种自然的序列化方式使得序列元素的信息密度均匀。位置编码的必要性自注意力本身是置换不变的permutation-invariant——它对输入序列的重新排列给出相同的输出。位置编码打破了这种对称性。ViT使用可学习的1D位置编码虽然在2D图像上但patch的顺序仍然是1D排列CLIP的文本塔使用可学习的绝对位置编码context length77。LayerNorm的放置策略两者都使用Pre-LNLayerNorm在子层之前遵循了大规模Transformer训练的稳定性原则。# ViT与CLIP的架构共性抽象 # 设计思路提取两个模型的共同模式展示模态无关设计 import torch import torch.nn as nn import torch.nn.functional as F class ModalityAgnosticTransformerBlock(nn.Module): 模态无关的Transformer块 这是ViT和CLIP的共同基础组件。 不论输入是图像patch还是文本token这个块的结构完全相同。 唯一的模态特定差异是输入projection在块外部处理。 def __init__( self, dim: int, num_heads: int, mlp_ratio: float 4.0, dropout: float 0.1, ): super().__init__() # Pre-LN架构归一化在注意力之前 self.norm1 nn.LayerNorm(dim) self.attn nn.MultiheadAttention( dim, num_heads, dropoutdropout, batch_firstTrue, ) self.norm2 nn.LayerNorm(dim) self.mlp nn.Sequential( nn.Linear(dim, int(dim * mlp_ratio)), nn.GELU(), # ViT和CLIP都使用GELU nn.Dropout(dropout), nn.Linear(int(dim * mlp_ratio), dim), nn.Dropout(dropout), ) def forward(self, x: torch.Tensor): # Pre-LN残差模式这是ViT和CLIP共享的 x x self.attn(self.norm1(x), self.norm1(x), self.norm1(x))[0] x x self.mlp(self.norm2(x)) return x class UniversalEncoder(nn.Module): 通用编码器——可处理任意序列化后的模态 这个类抽象了ViT和CLIP图像/文本编码器的共同部分。 使用方式 - ViT: UniversalEncoder PatchEmbed - CLIP文本塔: UniversalEncoder TokenEmbed def __init__( self, dim: int 768, depth: int 12, num_heads: int 12, mlp_ratio: float 4.0, ): super().__init__() self.blocks nn.ModuleList([ ModalityAgnosticTransformerBlock( dimdim, num_headsnum_heads, mlp_ratiomlp_ratio, ) for _ in range(depth) ]) self.norm nn.LayerNorm(dim) def forward(self, x: torch.Tensor): for block in self.blocks: x block(x) return self.norm(x) # ViT 特定部分 class PatchEmbed(nn.Module): ViT的Patch嵌入将图像转化为序列 这是ViT与通用编码器之间的模态适配层。 def __init__(self, img_size224, patch_size16, in_chans3, embed_dim768): super().__init__() self.proj nn.Conv2d( in_chans, embed_dim, kernel_sizepatch_size, stridepatch_size ) self.n_patches (img_size // patch_size) ** 2 def forward(self, x): # (B, C, H, W) → (B, embed_dim, H/P, W/P) → (B, n_patches, embed_dim) x self.proj(x) x x.flatten(2).transpose(1, 2) return x # CLIP 文本塔特定部分 class CLIPTextProjection(nn.Module): CLIP的文本投影头 将Transformer输出映射到对比学习的共享嵌入空间。 这是CLIP双塔架构中特有的对齐层。 def __init__(self, embed_dim: int, projection_dim: int 512): super().__init__() self.projection nn.Linear(embed_dim, projection_dim, biasFalse) def forward(self, x): # 取[EOS]位置的输出作为句子表示 # x[:, -1, :] 取序列最后一个tokenCLIP中[EOS]在最后 x x[:, -1, :] # (B, embed_dim) x self.projection(x) return x三、对比学习目标——CLIP的成功秘诀CLIP的核心创新不在于网络架构两个标准Transformer而在于它的训练目标最大化N对(图像, 文本)中N对正样本的余弦相似度同时最小化N²-N对负样本的相似度。这个看似简单的InfoNCE损失在实际中要求极大规模的batchCLIP使用32,768和训练数据400M图文对。对比损失的信息论解读它近似于最大化图像和文本表示之间的互信息Mutual Information的下界。def clip_contrastive_loss( image_embeddings: torch.Tensor, # (B, D) text_embeddings: torch.Tensor, # (B, D) temperature: float 0.07, ) - torch.Tensor: CLIP的对比损失InfoNCE 设计要点 - temperature控制分布的锐度越小越严格 - 对称损失同时计算image→text和text→image两个方向 # 归一化投影到单位球面 image_embeddings F.normalize(image_embeddings, dim-1) text_embeddings F.normalize(text_embeddings, dim-1) # 计算所有配对的相似度矩阵 (B, B) logits (image_embeddings text_embeddings.T) / temperature # 标签对角线位置是正样本 labels torch.arange(len(logits), devicelogits.device) # 对称交叉熵损失 loss_i F.cross_entropy(logits, labels) # image→text loss_t F.cross_entropy(logits.T, labels) # text→image return (loss_i loss_t) / 2四、跨模态Transformer的设计空间graph LR A[跨模态设计选择] -- B[融合时机] A -- C[编码器结构] A -- D[训练目标] B -- B1[早期融合br/如ViLT: 拼接后统一编码] B -- B2[晚期融合br/如CLIP: 分别编码后对比] C -- C1[双塔br/独立编码器,对比对齐] C -- C2[单塔br/拼接编码,交叉注意力] D -- D1[对比学习br/CLIP, ALIGN] D -- D2[生成式br/DALL-E, Parti] D -- D3[掩码建模br/BEiT-3]五、总结ViT到CLIP的演进展示了一个清晰的设计原则Transformer的核心能力是对序列化数据进行全局交互这一能力与模态无关。模态特定的部分仅存在于数据的序列化方式如何将图像/文本/语音转化为token序列和训练目标的设计上。这一观察预示着未来多模态模型的发展方向更统一的序列化策略如将任意模态转化为统一的token词汇表和更通用的训练目标如掩码建模对比学习生成式学习的联合训练。