多模态融合的核心问题
多模态模型要解决一个根本问题:如何让模型理解不同模态(文本、图像、音频、视频)之间的语义关联。这包含两个子问题:
- 表征对齐:将不同模态的输入映射到统一的语义空间
- 推理融合:在统一空间中进行跨模态的推理与生成
多模态融合的三个阶段
| 阶段 | 时间 | 代表模型 | 核心方法 |
|---|---|---|---|
| 对比学习 | 2021-2022 | CLIP, ALIGN | 双塔编码器 + 对比损失 |
| 桥接融合 | 2023 | BLIP-2, LLaVA | 视觉编码器 + Q-Former/投影层 + LLM |
| 原生多模态 | 2024-2026 | GPT-4V, Gemini | 端到端训练的多模态Transformer |
第一阶段:对比学习对齐(CLIP)
CLIP的核心思想
CLIP(Contrastive Language-Image Pre-training)通过简单的对比学习,将图像和文本映射到同一语义空间:
import torch
import torch.nn as nn
import torch.nn.functional as F
class CLIPModel(nn.Module):
def __init__(self, image_encoder, text_encoder, projection_dim=512):
super().__init__()
self.image_encoder = image_encoder # ViT
self.text_encoder = text_encoder # Transformer
self.image_projection = nn.Linear(
image_encoder.dim, projection_dim
)
self.text_projection = nn.Linear(
text_encoder.dim, projection_dim
)
self.logit_scale = nn.Parameter(torch.ones([]) * np.log(1/0.07))
def forward(self, images, texts):
# 编码图像和文本
image_features = self.image_encoder(images) # (batch, img_dim)
text_features = self.text_encoder(texts) # (batch, txt_dim)
# 投影到共享空间
image_embeds = self.image_projection(image_features) # (batch, proj_dim)
text_embeds = self.text_projection(text_features) # (batch, proj_dim)
# L2归一化
image_embeds = F.normalize(image_embeds, dim=-1)
text_embeds = F.normalize(text_embeds, dim=-1)
# 对比损失:对角线为正样本,其余为负样本
logit_scale = self.logit_scale.exp()
logits_per_image = logit_scale * image_embeds @ text_embeds.t()
logits_per_text = logits_per_image.t()
labels = torch.arange(len(images), device=images.device)
loss_i2t = F.cross_entropy(logits_per_image, labels)
loss_t2i = F.cross_entropy(logits_per_text, labels)
loss = (loss_i2t + loss_t2i) / 2
return loss
CLIP的局限
- 表征能力有限:对比学习只学了"相似/不相似",无法做细粒度理解
- 无法生成:CLIP只能做检索和分类,无法生成图像描述
- 固定分辨率:ViT需要固定输入分辨率,处理高分辨率图像时信息丢失
第二阶段:桥接融合(BLIP-2 / LLaVA)
BLIP-2:Q-Former桥接
BLIP-2引入了Q-Former(Querying Transformer),用一组可学习的Query从视觉特征中提取与语言相关的信息:
class QFormer(nn.Module):
"""BLIP-2的Q-Former:从冻结的视觉编码器中提取语言相关信息"""
def __init__(self, num_queries=32, d_model=768, num_heads=12):
super().__init__()
# 可学习的Query Tokens
self.query_tokens = nn.Parameter(
torch.randn(num_queries, d_model)
)
# Cross-Attention:Query关注视觉特征
self.cross_attn = nn.MultiheadAttention(
d_model, num_heads, batch_first=True
)
# Self-Attention:Query之间交互
self.self_attn = nn.MultiheadAttention(
d_model, num_heads, batch_first=True
)
# FFN
self.ffn = nn.Sequential(
nn.Linear(d_model, d_model * 4),
nn.GELU(),
nn.Linear(d_model * 4, d_model)
)
self.norm1 = nn.LayerNorm(d_model)
self.norm2 = nn.LayerNorm(d_model)
self.norm3 = nn.LayerNorm(d_model)
def forward(self, image_features, text_input=None):
"""
image_features: (batch, num_patches, img_dim) 来自冻结的ViT
text_input: (batch, seq_len, d_model) 可选的文本输入
"""
batch_size = image_features.shape[0]
queries = self.query_tokens.unsqueeze(0).expand(batch_size, -1, -1)
# Self-Attention
attn_out = self.self_attn(queries, queries, queries)[0]
queries = self.norm1(queries + attn_out)
# Cross-Attention(关注图像特征)
cross_out = self.cross_attn(queries, image_features, image_features)[0]
queries = self.norm2(queries + cross_out)
# FFN
queries = self.norm3(queries + self.ffn(queries))
# 输出: (batch, num_queries, d_model) — 固定长度的视觉表示
return queries
LLaVA:简单投影的力量
LLaVA证明了一个简单的线性投影层就能实现出色的多模态能力:
class LLaVA(nn.Module):
"""LLaVA: 最简洁的多模态融合方案"""
def __init__(self, vision_encoder, llm, d_vision=1024, d_llm=4096):
super().__init__()
self.vision_encoder = vision_encoder # 冻结的CLIP ViT
self.llm = llm # 冻结的LLM
# 核心就是一个线性投影层
self.projection = nn.Linear(d_vision, d_llm)
def forward(self, images, text_tokens, attention_mask):
# 1. 提取视觉特征
with torch.no_grad():
image_features = self.vision_encoder(images) # (batch, num_patches, d_vision)
# 2. 投影到LLM的嵌入空间
visual_embeds = self.projection(image_features) # (batch, num_patches, d_llm)
# 3. 将视觉嵌入与文本嵌入拼接
text_embeds = self.llm.get_input_embeddings()(text_tokens)
# [视觉Token] [文本Token] → 拼接输入
combined_embeds = torch.cat([visual_embeds, text_embeds], dim=1)
# 4. 送入LLM生成
outputs = self.llm(inputs_embeds=combined_embeds,
attention_mask=attention_mask)
return outputs
LLaVA的成功说明:冻结的视觉编码器 + 简单投影 + 冻结的LLM,仅通过训练投影层就能实现强大的多模态能力。这极大降低了多模态训练的门槛。
第三阶段:原生多模态(GPT-4V / Gemini)
原生多模态的设计原则
GPT-4V和Gemini代表了多模态融合的最新范式——从训练第一天起就是多模态的:
原生多模态训练流程:
阶段1 - 预训练:
数据: 图文对 + 纯文本 + 图像描述
方法: 所有模态共享Transformer backbone
特点: 视觉Token与文本Token在同一个序列中
阶段2 - 指令微调:
数据: 多模态指令对话数据
方法: SFT + RLHF
特点: 学习按指令理解图像、回答问题
阶段3 - 能力增强:
数据: OCR、图表理解、空间推理
方法: 针对性数据增强
特点: 细粒度视觉理解能力
视觉Token化方案
原生多模态模型需要将图像转化为Token序列。三种主流方案:
方案1:Patch Embedding(ViT风格)
class PatchEmbedding(nn.Module):
"""将图像分割为Patch并转化为Token"""
def __init__(self, img_size=224, patch_size=16, d_model=4096):
super().__init__()
self.num_patches = (img_size // patch_size) ** 2
self.proj = nn.Conv2d(
3, d_model,
kernel_size=patch_size, stride=patch_size
)
# 位置编码
self.pos_embed = nn.Parameter(
torch.randn(1, self.num_patches, d_model)
)
def forward(self, images):
# images: (batch, 3, 224, 224)
patches = self.proj(images) # (batch, d_model, 14, 14)
patches = patches.flatten(2).transpose(1, 2) # (batch, 196, d_model)
return patches + self.pos_embed
方案2:多分辨率Token
class MultiResolutionTokenizer:
"""多分辨率视觉Token化"""
def __init__(self, d_model):
self.d_model = d_model
# 不同分辨率的编码器
self.encoders = nn.ModuleDict({
'low': PatchEmbedding(224, 16, d_model), # 196 tokens
'mid': PatchEmbedding(448, 16, d_model), # 784 tokens
'high': PatchEmbedding(896, 16, d_model), # 3136 tokens
})
def forward(self, image, detail_level='auto'):
if detail_level == 'auto':
# 根据图像复杂度自动选择分辨率
complexity = self._estimate_complexity(image)
if complexity < 0.3:
return self.encoders['low'](image)
elif complexity < 0.7:
return self.encoders['mid'](F.interpolate(image, size=448))
else:
return self.encoders['high'](F.interpolate(image, size=896))
else:
return self.encoders[detail_level](image)
def _estimate_complexity(self, image):
"""简单的图像复杂度估计"""
gray = image.mean(dim=1)
edges = torch.abs(gray[:, :, 1:] - gray[:, :, :-1]).mean()
return float(edges.clamp(0, 1))
方案3:动态Token数量
根据图像内容动态决定Token数量——简单图像用少量Token,复杂图像用更多Token。这在精度与效率之间取得平衡。
跨模态注意力机制
原生多模态模型中,视觉Token和文本Token在同一个注意力层中交互:
class MultiModalAttention(nn.Module):
"""支持模态感知的多模态注意力"""
def __init__(self, d_model, num_heads):
super().__init__()
self.num_heads = num_heads
self.d_head = d_model // num_heads
# 共享的QKV投影
self.q_proj = nn.Linear(d_model, d_model)
self.k_proj = nn.Linear(d_model, d_model)
self.v_proj = nn.Linear(d_model, d_model)
self.o_proj = nn.Linear(d_model, d_model)
# 模态偏置项(让模型区分视觉和文本Token)
self.modal_bias = nn.ParameterDict({
'VV': nn.Parameter(torch.zeros(num_heads)), # 视觉→视觉
'VT': nn.Parameter(torch.zeros(num_heads)), # 视觉→文本
'TV': nn.Parameter(torch.zeros(num_heads)), # 文本→视觉
'TT': nn.Parameter(torch.zeros(num_heads)), # 文本→文本
})
def forward(self, x, modal_types):
"""
x: (batch, seq_len, d_model)
modal_types: (batch, seq_len) — 0=文本, 1=视觉
"""
batch, seq_len, _ = x.shape
Q = self.q_proj(x).view(batch, seq_len, self.num_heads, self.d_head)
K = self.k_proj(x).view(batch, seq_len, self.num_heads, self.d_head)
V = self.v_proj(x).view(batch, seq_len, self.num_heads, self.d_head)
# 计算注意力分数
scores = torch.einsum('bqhd,bkhd->bhqk', Q, K) / (self.d_head ** 0.5)
# 添加模态偏置
# 构造 (q_modal, k_modal) → bias 的映射
q_modal = modal_types.unsqueeze(1) # (batch, 1, seq)
k_modal = modal_types.unsqueeze(2) # (batch, seq, 1)
for q_type in [0, 1]:
for k_type in [0, 1]:
key = ('T' if q_type == 0 else 'V') + ('T' if k_type == 0 else 'V')
mask = (q_modal == q_type) & (k_modal == k_type)
bias = self.modal_bias[key].view(1, -1, 1, 1)
scores = scores + mask.unsqueeze(1) * bias
# Softmax和加权求和
attn = F.softmax(scores, dim=-1)
out = torch.einsum('bhqk,bkhd->bqhd', attn, V)
out = out.reshape(batch, seq_len, -1)
return self.o_proj(out)
评估基准与性能
多模态理解能力对比(2026年)
| 模型 | MMMU | MMBench | DocVQA | ChartQA | 视觉推理 |
|---|---|---|---|---|---|
| GPT-4V | 75.4 | 83.2 | 92.1 | 78.5 | 68.3 |
| Gemini 2.0 | 73.8 | 81.5 | 90.3 | 80.1 | 65.7 |
| Qwen-VL-Max | 68.2 | 76.8 | 88.5 | 72.3 | 58.4 |
| InternVL-2 | 65.5 | 74.3 | 85.2 | 70.8 | 55.1 |
| LLaVA-1.6 | 52.1 | 62.5 | 70.4 | 55.2 | 42.3 |
从CLIP到GPT-4V的演进,本质上是从"表征对齐"到"推理融合"的跃迁。CLIP解决了"猫的图片"和"一只猫"这个文本在语义空间中对齐的问题;而GPT-4V则能理解"这张图中的猫为什么在打哈欠"这样的复杂跨模态推理。
未来方向
- 任意模态融合:不仅是图文,还包括音频、视频、3D、触觉的统一建模
- 实时多模态推理:视频流实时理解,延迟<100ms
- 多模态生成:从理解到生成,统一的"输入任意模态→输出任意模态"框架
- 高效视觉Token:将196+个视觉Token压缩到16个以内,同时保持理解能力
- 空间理解增强:精确的空间位置感知和几何推理能力
多模态融合正在从"图文检索"走向"通用多模态推理"。这条路上的每一步创新,都在推动AI从"语言智能"迈向"感知智能",最终走向"具身智能"。