Chameleon 与早融合的纯 token 多模态模型
我们到目前为止见过的每个 VLM 都把图像和文本分开。视觉 token 来自视觉编码器,流进投影器,然后在 LLM 内部与文本相遇。视觉词表和文本词表从不重叠。Chameleon(Meta,2024 年 5 月)问:如果它们重叠呢?训一个 VQ-VAE,把图像变成一串来自共享词表的离散 token。现在每份多模态文档都是一条序列——文本 token 和图像 token 交错,一个自回归损失。副作用是:模型能在单次推理调用里生成混合模态输出——交替吐出文本 token 和图像 token。本节课通读早融合论点,并从头到尾搭一个玩具版。
类型: Build 语言: Python(标准库,VQ-VAE 分词器 + 交错解码器) 前置要求: Phase 12 · 05、Phase 8(生成式 AI) 预计时间: ~180 分钟
学习目标
- 解释为什么共享词表 + 单一损失改变了模型能做什么。
- 描述 VQ-VAE 如何把一张图分词成一条与 transformer 下一 token 目标兼容的离散序列。
- 说出 Chameleon 的训练稳定性技巧:QK-Norm、dropout 放置、LayerNorm 排序。
- 把 Chameleon 与 BLIP-2 的 Q-Former 路线作比较,并描述各自在什么情况下是正确选择。
问题背景
基于适配器的 VLM(LLaVA、BLIP-2、Qwen-VL)把文本和图像当成两种不同的东西。文本 token 走 embed(text_token);图像走 visual_encoder(image) → projector → ... pseudo_tokens。模型有两条输入路径,在中途合并。
三个后果:
- LLM 只能消费图像,不能吐出图像。输出只有文本。
- 混合模态文档(段落和图像交替,像一篇文章那样)很别扭——你要么在模型外面解析多模态输入,要么把生成链起来。
- 分布不匹配。视觉 token 和文本 token 住在隐藏空间的不同区域,制造出微妙的对齐问题。
Chameleon 拒绝这个前提:图像不过是来自共享词表的一串离散 token。在交错文档上训模型,一个损失、一个自回归解码器,你就免费解锁了混合模态生成。
核心概念
VQ-VAE 作为图像分词器
分词器是一个向量量化的变分自编码器。架构:
- 编码器:CNN + ViT,把图像映射到一张空间特征图,比如 32x32 个维度 256 的特征。
- 码本:一个学出来的 K 个向量的词表(Chameleon 用 8192),也是维度 256。
- 量化:对每个空间特征,按 L2 距离查最近的码本条目。用整数索引替换连续特征。
- 解码器:CNN,把量化特征还原成像素。
训练:VAE 重建损失 + commitment 损失 + 码本损失。码本索引构成了图像的离散字母表。
对 Chameleon:一张图变成 32*32 = 1024 个 token,取自一个 8192 的词表。与文本 token(来自 LLM 的 BPE 词表,比如 32000)拼接。最终词表:40192。transformer 看到一条序列、一个损失。
共享词表
Chameleon 的词表把文本 token、图像 token 和模态分隔符合在一起。每个 token 有单一 ID。输入嵌入层把每个 ID 映射到一个 D 维隐藏向量。输出投影把隐藏映射回词表 logit。softmax 挑下一个 token,不管什么模态。
分隔符很要紧:<image> 和 </image> 标签括住图像 token 序列。生成时,如果模型吐出 <image>,下游软件就知道接下来 1024 个 token 是要送给解码器渲染像素的 VQ 索引。
混合模态生成
推理就是在共享词表里做下一 token 预测。示例 prompt:"Draw a cat and describe it."Chameleon 吐出:
<image> 4821 1029 2891 ... (1024 image tokens) </image>
The cat is orange, sitting on a windowsill...模型自主挑顺序——它可能先图后文、先文后图,或交错。同一个解码器,同一个损失。
对比适配器 VLM 那种只能生成文本的情况。Chameleon 重新打开了模型输出模态这个问题。
训练稳定性—— QK-Norm、dropout、LayerNorm 排序
早融合训练在大规模上不稳定。Chameleon 的论文记录了三个技巧:
- QK-Norm。在注意力内部、点积之前,对 query 和 key 投影施加 LayerNorm。防止深度处 logit 幅度爆炸。被多个 2024 年后的大模型采用。
- dropout 放置。每次残差相加之后都做 dropout,而不只在注意力和 MLP 之后。当来自图像 token 的梯度可能主导时,需要更多正则化。
- LayerNorm 排序。残差分支上用 Pre-LN(标准),加上对最后一个块跳跃连接的一个额外 LN。稳定末层梯度流。
没有这些技巧,34B 参数的 Chameleon 训练在多个 checkpoint 处发散。有了它们,它收敛。训练配方和架构一样是贡献的一部分。
分词器的重建天花板
VQ-VAE 是有损的。在 8192 个码本条目、每张 512x512 图 1024 个 token 下,重建 PSNR 封顶在 26-28 dB 左右。这足以做可辨认的图像生成,但明显比连续空间扩散差(Stable Diffusion 3 达到 32+ dB)。
分词器是瓶颈。更好的分词器(MAGVIT-v2、IBQ、SBER-MoVQGAN)抬高天花板。Emu3(第 12.12 课)光靠更好的分词器就达到了 SDXL 级质量的生成。
Chameleon vs BLIP-2 / LLaVA
Chameleon(早融合,共享词表):
- 一个损失,一个解码器。
- 生成混合模态输出。
- 分词器是质量天花板。
- 贵:推理路径上每生成一张图都要跑一次 VQ-VAE 解码器。
BLIP-2 / LLaVA(晚融合,分开的塔):
- 视觉进,只出文本。
- 复用预训练 LLM。
- 理解时没有分词器瓶颈。
- 便宜:单次前向。
按任务挑。如果你需要图像生成,选 Chameleon 家族。如果你只需要理解,适配器 VLM 更简单,也复用了更多预训练算力。
Fuyu 与 AnyGPT
Fuyu(Adept,2023)是一个相关路线:彻底跳过独立的视觉编码器,把原始图像 patch 当作 token 一样过 LLM 的输入投影,不用分词器。比 Chameleon 简单,但丢掉了共享词表的输出生成能力。
AnyGPT(Zhan 等人,2024)把 Chameleon 扩展到四种模态:文本、图像、语音、音乐。每种用同样的 VQ-VAE 戏法,共享 transformer。任意到任意生成。第 12.16 课讲得更多。
vq-codebook实际使用
code/main.py 搭了一个玩具级端到端早融合模型:
- 一个微型 VQ-VAE 式量化器,把 8x8 patch 映射到码本索引(K=16)。
- 一个共享词表:(文本 id 0..31) + (图像 id 32..47) + (分隔符 48, 49)。
- 一个玩具自回归解码器(bigram 表),在合成 caption + 图像 token 序列上训练。
- 一个采样循环,给定 prompt 吐出交替的文本 + 图像 token。
代码故意把 transformer 保持得极小(bigram),好让你从头到尾追踪信号流。
拿去用
本节课产出 outputs/skill-tokenizer-vs-adapter-picker.md。给定一个产品规格(只理解 vs 理解 + 生成、所需图像质量、成本预算),它在 Chameleon 家族(早融合)和 LLaVA 家族(晚融合)之间挑选,并用定量的经验法则佐证。
练习
Chameleon 用 K=8192 个码本条目、每张 512x512 图 1024 个 token。估算它相对一张 24 位 RGB 图的压缩比。它有损吗?多有损?
一张 4K 图(3840x2160)在同样的 VQ-VAE 密度下产出多少图像 token?一个 Chameleon 式模型能在单次推理调用里生成一张 4K 图吗?什么先崩——上下文、分词器质量,还是 KV cache?
用纯 Python 实现 QK-Norm。给定一个 64 维的 query 和 key,展示 LayerNorm 前后的点积。为什么深度处的幅度控制重要?
读 Chameleon 第 2.3 节关于训练稳定性的内容。描述论文在 34B 上不用 QK-Norm 时观察到的确切失败模式。"范数爆炸"的特征是什么?
扩展那个玩具解码器,让它在只给文本 prompt 时吐出一个混合模态回应。在训练数据分布 60% 先文 / 40% 先图下,测一下模型多频繁选先图 vs 先文。
关键术语
| 术语 | 大家怎么说 | 它实际指什么 |
|---|---|---|
| 早融合 | "统一 token" | 图像从第一步起就转成与 transformer 词表共享的离散 token |
| VQ-VAE | "图像分词器" | CNN + ViT + 码本,把图像映射成 transformer 能预测的整数索引 |
| 共享词表 | "一本字典" | 涵盖文本 + 图像 + 模态分隔符的单一 token ID 空间 |
| QK-Norm | "注意力稳定器" | 在 query 和 key 点积之前对它们施加 LayerNorm,防止范数暴涨 |
| 混合模态生成 | "文本 + 图像输出" | 一次前向里自主产出交错文本和图像 token 的推理 |
| 码本大小 | "K 个条目" | VQ-VAE 能量化到的离散向量数;在压缩和保真之间取舍 |
| 分词器天花板 | "重建上限" | 解码 VQ token 能达到的最佳 PSNR;为模型的图像质量封顶 |