5.3 Flamingo 与 BLIP-2 架构 本节深入两个最有教学价值的中期融合案例:DeepMind 的 Flamingo 与 Salesforce 的 BLIP-2。它们的设计哲学一致——冻结大模型,只训练中间桥接模块——但具体实现差异显著。 一、共同的动机:保护昂贵的预训练投入 训练一个 LLM 通常需要数千 GPU·天,成本数百万美元。如果为了多模态能力把它全部微调,存在两个风险: 灾难性遗忘:LLM 原有的语言、代码、推理能力被多模态训练数据冲淡 训练不稳:多模态数据分布与纯文本不同,全量微调可能导致损失发散 Flamingo 与 BLIP-2 都选择「冻结大模型 + 训练桥接模块」策略,只让少量参数承担多模态对齐工作。
本节深入两个最有教学价值的中期融合案例:DeepMind 的 Flamingo 与 Salesforce 的 BLIP-2。它们的设计哲学一致——冻结大模型,只训练中间桥接模块——但具体实现差异显著。
训练一个 LLM 通常需要数千 GPU·天,成本数百万美元。如果为了多模态能力把它全部微调,存在两个风险:
Flamingo 与 BLIP-2 都选择「冻结大模型 + 训练桥接模块」策略,只让少量参数承担多模态对齐工作。这种思路后来被称为「Parameter-Efficient Fine-Tuning for Multimodal」。
DeepMind 在 2022 年发表的 Flamingo 是首个在少样本视觉任务上接近人类水平的模型。它的整体架构如下:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 880 460" font-family="sans-serif" font-size="13"> <text x="440" y="25" text-anchor="middle" font-weight="bold" font-size="16">Flamingo 架构</text> <!-- 视觉前端 --> <g transform="translate(40,80)"> <rect x="0" y="0" width="160" height="100" fill="#e1f5ff" stroke="#333" rx="8"/> <text x="80" y="22" text-anchor="middle" font-weight="bold">视觉前端</text> <text x="80" y="45" text-anchor="middle">NFNet 冻结</text> <text x="80" y="68" text-anchor="middle">输入: 图像/视频帧</text> <text x="80" y="88" text-anchor="middle">输出: 视觉特征</text> </g> <!-- Perceiver Resampler --> <g transform="translate(240,80)"> <rect x="0" y="0" width="180" height="100" fill="#fff4e1" stroke="#333" rx="8"/> <text x="90" y="22" text-anchor="middle" font-weight="bold">Perceiver Resampler</text> <text x="90" y="45" text-anchor="middle">可学习 query x 64</text> <text x="90" y="68" text-anchor="middle">Cross-Attention 抽取</text> <text x="90" y="88" text-anchor="middle">输出: 64 个固定 token</text> </g> <!-- 冻结 LLM --> <g transform="translate(460,80)"> <rect x="0" y="0" width="180" height="100" fill="#f5e1ff" stroke="#333" rx="8"/> <text x="90" y="22" text-anchor="middle" font-weight="bold">冻结 LLM</text> <text x="90" y="45" text-anchor="middle">Chinchilla 70B</text> <text x="90" y="68" text-anchor="middle">原始权重不动</text> <text x="90" y="88" text-anchor="middle">每 N 层插入 X-Attn</text> </g> <!-- Gated Cross-Attention --> <g transform="translate(680,80)"> <rect x="0" y="0" width="160" height="100" fill="#ffe1e1" stroke="#333" rx="8"/> <text x="80" y="22" text-anchor="middle" font-weight="bold">Gated X-Attn</text> <text x="80" y="45" text-anchor="middle">tanh 门控</text> <text x="80" y="68" text-anchor="middle">训练初期为 0</text> <text x="80" y="88" text-anchor="middle">渐进打开</text> </g> <!-- 数据流 --> <line x1="200" y1="130" x2="235" y2="130" stroke="#333" stroke-width="2" marker-end="url(#ar)"/> <line x1="420" y1="130" x2="455" y2="130" stroke="#333" stroke-width="2" marker-end="url(#ar)"/> <line x1="640" y1="130" x2="675" y2="130" stroke="#333" stroke-width="2" marker-end="url(#ar)"/> <!-- 文本输入输出 --> <g transform="translate(40,260)"> <rect x="0" y="0" width="160" height="80" fill="#fff" stroke="#333" rx="6"/> <text x="80" y="25" text-anchor="middle">文本输入</text> <text x="80" y="48" text-anchor="middle"><image> 这是什么?</text> <text x="80" y="68" text-anchor="middle">分词 → token</text> </g> <g transform="translate(680,260)"> <rect x="0" y="0" width="160" height="80" fill="#fff" stroke="#333" rx="6"/> <text x="80" y="25" text-anchor="middle">文本输出</text> <text x="80" y="48" text-anchor="middle">"这是一只猫"</text> <text x="80" y="68" text-anchor="middle">逐 token 自回归生成</text> </g> <!-- 训练流程注释 --> <g transform="translate(40,380)"> <rect x="0" y="0" width="800" height="60" fill="#e8f5e1" stroke="#333" rx="6"/> <text x="400" y="22" text-anchor="middle" font-weight="bold">训练策略</text> <text x="400" y="42" text-anchor="middle">冻结 NFNet + 冻结 Chinchilla,只训练 Perceiver Resampler + Gated X-Attn (约 10B 参数中的 3B)</text> </g> <defs> <marker id="ar" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"> <path d="M0,0 L8,4 L0,8 z" fill="#333"/> </marker> </defs> </svg>
视觉编码器输出的特征可能是变长的(视频帧、多图),直接送进 LLM 会破坏 LLM 的固定上下文。Perceiver Resampler 用一组固定的可学习 query(如 64 个)通过 Cross-Attention 从变长视觉特征中「抽取」信息:
可学习 query [64, d] ──Q──┐ ↓ 变长视觉特征 [N_v, d] ─K,V─→ Cross-Attention → 输出 [64, d]
无论输入是 1 张图(256 patch)还是 10 张视频帧(2560 patch),输出都是 64 个 token,计算开销固定。
Flamingo 在 LLM 的每 N 层(通常 N=4)之间插入一个带门控的 Cross-Attention 层:
其中 \alpha 是可学习标量,初始化为 0。
Flamingo 支持图文交错的输入——一段对话中可以插入多张图,每张图的位置用 <image> 占位符标记:
<image> 第一张图的内容是什么? <image> 这两张图有什么不同?
这种交错格式让 Flamingo 天然适合视觉对话与视频理解。
Flamingo 训练时见过大量「示例 + 问题 + 答案」格式,因此推理时可以给几个示例(few-shot):
<image> 这是什么? → 猫 <image> 这是什么? → 狗 <image> 这是什么? → 模型输出:鸟
这种少样本能力是 Flamingo 命名的由来——它能像「火烈鸟」一样灵活适应新任务。
Salesforce 在 2023 年发布的 BLIP-2 把「冻结」推到了极致——不仅冻结 LLM,视觉编码器也冻结,只训练中间的 Q-Former 模块。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 880 460" font-family="sans-serif" font-size="13"> <text x="440" y="25" text-anchor="middle" font-weight="bold" font-size="16">BLIP-2 架构</text> <!-- 视觉编码器 --> <g transform="translate(40,80)"> <rect x="0" y="0" width="160" height="100" fill="#e1f5ff" stroke="#333" rx="8"/> <text x="80" y="22" text-anchor="middle" font-weight="bold">视觉编码器</text> <text x="80" y="45" text-anchor="middle">EVA-CLIP-G</text> <text x="80" y="68" text-anchor="middle">完全冻结</text> <text x="80" y="88" text-anchor="middle">输出: 图像 patch 特征</text> </g> <!-- Q-Former --> <g transform="translate(260,80)"> <rect x="0" y="0" width="200" height="100" fill="#fff4e1" stroke="#333" rx="8"/> <text x="100" y="22" text-anchor="middle" font-weight="bold">Q-Former ( trainable )</text> <text x="100" y="45" text-anchor="middle">32 个可学习 query</text> <text x="100" y="68" text-anchor="middle">+ Self-Attention</text> <text x="100" y="88" text-anchor="middle">+ Cross-Attention</text> </g> <!-- 投影 --> <g transform="translate(520,80)"> <rect x="0" y="0" width="160" height="100" fill="#e8f5e1" stroke="#333" rx="8"/> <text x="80" y="22" text-anchor="middle" font-weight="bold">线性投影</text> <text x="80" y="45" text-anchor="middle">映射到 LLM 词表</text> <text x="80" y="68" text-anchor="middle">可训练</text> <text x="80" y="88" text-anchor="middle">输出: 32 个视觉 token</text> </g> <!-- 冻结 LLM --> <g transform="translate(720,80)"> <rect x="0" y="0" width="120" height="100" fill="#f5e1ff" stroke="#333" rx="8"/> <text x="60" y="22" text-anchor="middle" font-weight="bold">冻结 LLM</text> <text x="60" y="45" text-anchor="middle">OPT 6.7B</text> <text x="60" y="68" text-anchor="middle">或 FlanT5</text> <text x="60" y="88" text-anchor="middle">完全冻结</text> </g> <line x1="200" y1="130" x2="255" y2="130" stroke="#333" stroke-width="2" marker-end="url(#ar2)"/> <line x1="460" y1="130" x2="515" y2="130" stroke="#333" stroke-width="2" marker-end="url(#ar2)"/> <line x1="680" y1="130" x2="715" y2="130" stroke="#333" stroke-width="2" marker-end="url(#ar2)"/> <!-- 两阶段训练 --> <g transform="translate(40,260)"> <rect x="0" y="0" width="380" height="160" fill="#fff" stroke="#333" rx="8"/> <text x="190" y="22" text-anchor="middle" font-weight="bold">阶段一:表示学习</text> <text x="20" y="50">训练目标:</text> <text x="40" y="72">• 图文对比 (ITC)</text> <text x="40" y="92">• 图文匹配 (ITM)</text> <text x="40" y="112">• 图像字幕生成 (ITG)</text> <text x="20" y="140">目标: 让 Q-Former 学会抽取与文本对齐的视觉特征</text> </g> <g transform="translate(460,260)"> <rect x="0" y="0" width="380" height="160" fill="#fff" stroke="#333" rx="8"/> <text x="190" y="22" text-anchor="middle" font-weight="bold">阶段二:生成学习</text> <text x="20" y="50">训练目标:</text> <text x="40" y="72">• 把 32 个视觉 token 拼接进 LLM</text> <text x="40" y="92">• 让 LLM 以视觉 token 为条件生成文本</text> <text x="40" y="112">• 训练 Q-Former + 投影层</text> <text x="20" y="140">目标: 让 Q-Former 输出对 LLM 友好的视觉表示</text> </g> <defs> <marker id="ar2" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"> <path d="M0,0 L8,4 L0,8 z" fill="#333"/> </marker> </defs> </svg>
Q-Former 是 BLIP-2 的灵魂,本质上是一个带可学习 query 的小型 Transformer:
Q-Former 的工作方式可以理解为「模型带着 32 个问题去询问图像」:
BLIP-2 把训练分成两个阶段:
冻结视觉编码器,让 Q-Former 学会从图像中抽取与文本对齐的特征。用三个对比学习/生成目标:
把 Q-Former 输出的 32 个 token 通过线性投影送进 LLM 的词表空间,让 LLM 以这些视觉 token 为条件生成文本。这阶段冻结 LLM,训练 Q-Former + 投影层。
| 维度 | Flamingo | BLIP-2 |
|---|---|---|
| 视觉编码器 | NFNet(冻结) | EVA-CLIP-G(冻结) |
| 视觉特征压缩 | Perceiver Resampler (64 token) | Q-Former (32 token) |
| LLM | Chinchilla 70B(冻结) | OPT 6.7B / FlanT5(冻结) |
| LLM 与视觉交互方式 | Gated Cross-Attention 插入层间 | 视觉 token 拼接进 LLM 入口 |
| 训练阶段 | 单阶段端到端 | 两阶段(表示学习 + 生成学习) |
| 训练参数 | 约 3B | 约 188M |
| 强项 | 少样本、视频、对话 | 图文对齐、VQA、生成 |
| 数据 | M3W +图文对 | LAION + CC + COCO 等 |
Flamingo 与 BLIP-2 共同确立了几个多模态大模型的关键设计原则:
这些原则深刻影响了后续 LLaVA、MiniGPT-4、Qwen-VL 等模型的设计。即便早期融合派 LLaVA 在工程上更简单,BLIP-2/Flamingo 的思想仍是多模态大模型设计的理论基石。
Flamingo 与 BLIP-2 也有共同短板:
LLaVA 系列之所以后来居上,正是因为它用极简架构(早期融合 + MLP 投影)达到了不输甚至超过 BLIP-2 的效果,且实现门槛大幅降低。下一节我们钻进 Q-Former 与 Adapter 的设计哲学。
Flamingo 与 BLIP-2 都用「冻结大模型 + 训练桥接模块」的策略,前者通过 Perceiver Resampler + Gated Cross-Attention 实现,后者通过 Q-Former 两阶段训练。它们确立了视觉特征压缩、渐进式引入、多阶段训练等关键设计原则,深刻影响了后续多模态大模型的发展。
下一节(5.4)我们钻进 Q-Former 这个组件的设计哲学,以及更广泛的 Adapter 系列(LoRA、Prefix Tuning 等)在多模态融合中的应用。