多模态大模型的整体架构通常由三部分组成:视觉编码器负责把图像转成特征序列,语言模型负责理解和生成文本,而两者之间需要一个桥接模块来完成模态对齐。桥接模块看似只是一个小组件,实际上直接决定了模型的训练效率、视觉理解精度和推理成本。Flamingo采用的Resampler和BLIP-2采用的Q-Former代表了两种经典设计思路,虽然它们都依赖可学习查询向量从视觉特征中抽取固定长度的信息,但在具体结构、训练目标和计算量上存在明显差异。

Resampler的设计思路与实现细节
Flamingo发表于2022年,其核心贡献之一就是Resampler模块。视觉编码器(如NFNet或ViT)输出的特征图通常是高分辨率patch序列,一张高分辨率图像可能产生上千个token。如果直接把这些token输入语言模型,注意力计算量会随序列长度平方增长,训练成本难以承受。Resampler的做法是初始化一组固定数量的可学习查询向量,在Flamingo中是64个,让这些查询通过交叉注意力机制从视觉特征中提取信息,最终输出恒定长度的64个视觉token,无论输入图像分辨率如何变化。
Resampler的结构本质上是一个单层的Perceiver风格模块。查询向量作为Query,视觉特征作为Key和Value,经过多头交叉注意力后再接前馈网络和LayerNorm。为了让视觉信息保持 locality 先验,Flamingo还给视觉特征额外加上了位置编码。这种设计的好处是结构简单、参数量小,64个查询通过一次交叉注意力就能完成信息压缩,非常轻量。同时由于输出长度固定,语言模型侧的序列长度完全可控,方便训练时的batch组织。
import torch
import torch.nn as nn
class Resampler(nn.Module):
def __init__(self, num_queries=64, dim=1024, visual_dim=1280, heads=16):
super().__init__()
self.queries = nn.Parameter(torch.randn(1, num_queries, dim))
self.cross_attn = nn.MultiheadAttention(dim, heads, batch_first=True)
self.norm_q = nn.LayerNorm(dim)
self.norm_kv = nn.LayerNorm(visual_dim)
self.ffn = nn.Sequential(
nn.Linear(dim, dim * 4),
nn.GELU(),
nn.Linear(dim * 4, dim)
)
self.norm_out = nn.LayerNorm(dim)
def forward(self, visual_feats):
# visual_feats: [B, N, visual_dim], N为patch数量
b = visual_feats.shape[0]
q = self.queries.expand(b, -1, -1)
kv = self.norm_kv(visual_feats)
attn_out, _ = self.cross_attn(self.norm_q(q), kv, kv)
out = self.norm_out(attn_out + self.ffn(attn_out))
return out # [B, 64, dim],固定长度输出不过Resampler的局限也很明显。它是纯无监督地从视觉特征中做信息抽取,压缩时没有任何文本侧的监督信号,视觉token里保留了什么、丢掉了什么,完全依赖模型在后续训练中自己摸索。这导致Flamingo必须依靠超大规模的图文交错数据配合门控交叉注意力才能训练出好的效果,普通团队很难复现。这也是后来BLIP-2对其进行改进的直接动因。
Q-Former的结构创新与两阶段训练
BLIP-2的Q-Former在概念上延续了可学习查询向量压缩视觉特征的思路,同样使用32个查询向量作为Query,与冻结的视觉编码器特征做交叉注意力。但它不再是单一模块,而是一个轻量级的Transformer结构,包含共享自注意力层和交叉注意力层,图像与文本可以共同在这个结构中交互。查询向量在自注意力层中彼此通信,在交叉注意力层中从视觉特征中抓取信息,最终输出的32个视觉token再通过一个全连接层映射到语言模型的嵌入空间。
Q-Former最大的特点是引入了两阶段训练策略。第一阶段进行表示学习,使用三个损失函数:图文对比学习对齐整体语义、图文匹配判断细粒度关联、图像引导的文本生成让查询向量学会提取与文本相关的视觉信息。第二阶段把Q-Former接到冻结的语言模型上,用生成损失训练,让视觉token能够被语言模型理解并用于回答问题。这种以文本为监督的压缩方式,使查询向量明确学会了丢弃与语言任务无关的信息,比如图像中不构成语义核心的背景纹理。
import torch
import torch.nn as nn
class QFormerLayer(nn.Module):
def __init__(self, dim=768, heads=12):
super().__init__()
self.self_attn = nn.MultiheadAttention(dim, heads, batch_first=True)
self.cross_attn = nn.MultiheadAttention(dim, heads, batch_first=True)
self.ffn = nn.Sequential(
nn.Linear(dim, dim * 4), nn.GELU(), nn.Linear(dim * 4, dim)
)
self.norms = nn.ModuleList([nn.LayerNorm(dim) for _ in range(3)])
def forward(self, queries, visual_feats):
# 查询先做自注意力,让查询之间交换已捕获的信息
q1, _ = self.self_attn(self.norms[0](queries),
self.norms[0](queries),
self.norms[0](queries))
queries = queries + q1
# 再从冻结视觉特征中做交叉注意力提取信息
q2, _ = self.cross_attn(self.norms[1](queries), visual_feats, visual_feats)
queries = queries + q2
queries = queries + self.ffn(self.norms[2](queries))
return queries从训练成本看,Q-Former的策略效率极高。视觉编码器和语言模型全程冻结,只有Q-Former和投影层参与训练,可训练参数不到2亿,却能在多个视觉语言基准上超过动辄微调数十亿参数的模型。这证明了高质量桥接模块加高效训练目标,比盲目堆参数更有效。相比之下,Flamingo的训练需要海量交错图文数据和完整的计算集群,门槛完全不在一个量级。
两者的核心差异与对后续模型的影响
把两者放在一起对比,差异主要体现在四个方面。第一是监督信号:Resampler是无监督压缩,Q-Former是有文本监督的对齐压缩。第二是结构复杂度:Resampler是单层交叉注意力加前馈网络,Q-Former是多层的共享自注意力加交叉注意力结构,深度更大、表达能力更强。第三是查询数量:Flamingo用64个查询,BLIP-2用32个查询,后者用更少的token承载了更相关的信息。第四是训练成本:Flamingo需要端到端大规模训练,BLIP-2冻结两端只训中间模块,资源需求低一个数量级。
| 对比维度 | Flamingo Resampler | BLIP-2 Q-Former |
|---|---|---|
| 查询数量 | 64个 | 32个 |
| 结构 | 单层交叉注意力 | 多层自注意力加交叉注意力 |
| 监督方式 | 无显式文本监督 | 对比学习加匹配加生成三重监督 |
| 视觉编码器 | 参与训练 | 完全冻结 |
| 语言模型 | 冻结但用门控适配 | 完全冻结 |
有意思的是,后续开源社区的实践给出了另一条路线的验证。LLaVA直接用一个简单的两层MLP做投影,不做token压缩,依靠CLIP的高分辨率特征直接映射进语言模型,效果同样出色且实现极简。mPLUG-Owl、MiniGPT-4等模型则沿用了Q-Former的设计。这表明当视觉编码器足够强、语言模型足够大时,复杂的桥接模块未必是必需的;但在视觉特征序列很长或需要多图、视频输入的场景下,Resampler和Q-Former这类压缩式桥接依然有不可替代的价值。
从架构演进的角度看,两者共同的贡献在于确立了可学习查询向量作为模态间信息瓶颈的设计范式:用固定数量的查询控制信息通量,用交叉注意力实现选择性提取,用文本监督引导信息取舍。理解这两个模块的异同,就理解了当前绝大多数多模态大模型在视觉侧的来龙去脉。未来随着原生多模态模型(如将视觉token直接嵌入语言模型预训练的方案)兴起,独立的桥接模块可能会逐渐淡化,但其中蕴含的模态对齐思想会长期存在于多模态系统的设计中。
Flamingo Resampler BLIP-2 Q-Former 多模态大模型修改时间:2026-09-01 07:03:40