Chameleon 与早期融合:纯 token 多模态模型 本节摘要:到目前为止我们见过的每个 VLM 都把图像与文本分开。视觉 token 来自视觉编码器,流进投影器,然后在 LLM 内部与文本相遇——视觉与文本词表从不重叠。Chameleon(Meta,2024 年 5 月)问:要是重叠了呢?训练一个 VQ-VAE,把图像变成来自共享词表的离散 token 序列。每个多模态文档现在都是一条序列——文本 token 与图像 token 交错,一个自回归损失。副作用:模型能在一次推理里生成混合模态输出——文本与图像 token 交替。本节读早期融合的论点,并端到端搭一个玩具版。 学习目标 阅读完本节,你应当能够: 解释为什么共享词表 + 单一损失会改变模型能做什么。
本节摘要:到目前为止我们见过的每个 VLM 都把图像与文本分开。视觉 token 来自视觉编码器,流进投影器,然后在 LLM 内部与文本相遇——视觉与文本词表从不重叠。Chameleon(Meta,2024 年 5 月)问:要是重叠了呢?训练一个 VQ-VAE,把图像变成来自共享词表的离散 token 序列。每个多模态文档现在都是一条序列——文本 token 与图像 token 交错,一个自回归损失。副作用:模型能在一次推理里生成混合模态输出——文本与图像 token 交替。本节读早期融合的论点,并端到端搭一个玩具版。
阅读完本节,你应当能够:
基于 adapter 的 VLM(LLaVA、BLIP-2、Qwen-VL)把文本与图像当作两件不同的事。文本 token 走 embed(text_token);图像走 visual_encoder(image) → projector → ... 伪 token。模型有两条输入路径,在中途合并。
三个后果:
Chameleon 拒绝这个前提:图像只是来自共享词表的离散 token 序列。在交错文档上训练,一个损失、一个自回归解码器,就免费解锁混合模态生成。
分词器是一个向量量化变分自编码器。架构:
训练:VAE 重建损失 + 承诺损失 + 码本损失。码本索引构成图像的离散字母表。
对 Chameleon:一张图变成 32×32 = 1024 个 token,来自 8192 大小的词表。与文本 token(LLM 的 BPE 词表,比如 32000)拼接。最终词表 40192。Transformer 看一条序列、一个损失。
Chameleon 的词表融合文本 token、图像 token、模态分隔符。每个 token 有单一 ID。输入嵌入层把每个 ID 映射到 D 维隐藏向量;输出投影把隐藏映射回词表 logits。softmax 选下一 token,无论模态。
分隔符很关键:<image> 与 </image> 标签把图像 token 序列括起来。生成时若模型发出 <image>,下游软件就知道接下来 1024 个 token 是要送给解码器渲染像素的 VQ 索引。
推理就是在共享词表里做下一 token 预测。示例 prompt:「画一只猫并描述它。」Chameleon 发出:
<image> 4821 1029 2891 ... (1024 个图像 token) </image> The cat is orange, sitting on a windowsill...
模型自主决定顺序——可能先图后文、先文后图、或交错。同一解码器、同一损失。
对比 adapter VLM 的生成只有文本。Chameleon 重新打开了「模型输出模态」这个问题。
早期融合训练在大规模上不稳定。Chameleon 论文记录了三个技巧:
没有这些技巧,340 亿参数的 Chameleon 训练在多个 checkpoint 上发散;有了它们才收敛。训练配方与架构一样是贡献。
VQ-VAE 有损。8192 码本项、每张 512×512 图 1024 token,重建 PSNR 封顶约 26~28 dB。对可识别的图像生成够用,但明显差于连续空间扩散(Stable Diffusion 3 达 32+ dB)。
分词器是瓶颈。更好的分词器(MAGVIT-v2、IBQ、SBER-MoVQGAN)抬升天花板。Emu3(第 12 节)仅靠更好的分词器就达到 SDXL 质量的生成。
Chameleon(早期融合,共享词表):
BLIP-2 / LLaVA(晚期融合,分塔):
按任务挑。需要图像生成选 Chameleon 系;只需理解选 adapter VLM,更简单且复用更多预训练算力。
Fuyu(Adept,2023) 是相关思路:完全跳过独立视觉编码器,把原始图像 patch 当 token 一样过 LLM 的输入投影,不用分词器。比 Chameleon 简单,但丢了共享词表的输出生成。
AnyGPT(Zhan 等人,2024) 把 Chameleon 扩到四种模态:文本、图像、语音、音乐。每种都用 VQ-VAE 技巧,共享 Transformer,任意到任意生成。第 16 节详谈。
code/main.py 搭一个玩具级端到端早期融合模型:
代码故意把 Transformer 做到极小(二元),让你能端到端追踪信号流。
# 输入: 图像特征 feat (32, 32, 256), 码本 codebook (K, 256) def vq_quantize(feat, codebook): flat = feat.reshape(-1, 256) # (1024, 256) # 每个特征找最近码本项 (L2) dists = cdist(flat, codebook) # (1024, K) idx = dists.argmin(axis=1) # (1024,) 整数索引 quantized = codebook[idx] # (1024, 256) 量化特征 return idx, quantized # idx 即图像 token 序列 # 训练损失 = 重建(解码回像素) + 承诺(Feat 靠近码本) + 码本(码本靠近 Feat)
# 词表: [文本 0..31999] [图像 32000..40191] [分隔符 40192=<image>, 40193=</image>] # 文档: <image> img_tokens... </image> caption text_tokens... def forward(shared_sequence): # 一条序列, 一个交叉熵损失, 不管模态 logits = transformer(shared_sequence[:-1]) loss = cross_entropy(logits, shared_sequence[1:]) return loss def generate(prompt): out = prompt while not eos(out): next_id = sample(transformer(out)) # 可能是文本/图像/分隔符 out.append(next_id) if next_id == IMAGE_START: # 接下来 1024 个是 VQ 索引 # 收集后送 VQ 解码器渲染像素 return out # 文本与图像交替
💡 关键洞察:早期融合的精髓是模态无特殊待遇——文本 token 与图像 token 走同一个嵌入、同一个注意力、同一个 softmax。这让模型能自主决定何时说话、何时画图,而无需外部调度。
def qk_norm_attention(q, k, v): q = layer_norm(q) # 点积前归一化, 防 logit 爆炸 k = layer_norm(k) attn = softmax(q @ k.T / sqrt(d)) return attn @ v
工程取舍:需要混合模态生成用 Chameleon/Emu3 系;只需理解用 LLaVA/BLIP-2(更便宜);要任意到任意用 AnyGPT;要最简理解用 Fuyu。
本节产出 outputs/skill-tokenizer-vs-adapter-picker.md。给定产品规格(只理解 vs 理解+生成、所需图像质量、成本预算),它在 Chameleon 系(早期融合)与 LLaVA 系(晚期融合)间选择,并用定量经验法则论证。
压缩比:Chameleon 用 K=8192 码本项、每张 512×512 图 1024 token。估算相对 24 位 RGB 图的压缩比。有损吗?多损?
4K 图:同样 VQ-VAE 密度下,4K 图(3840×2160)产多少图像 token?Chameleon 式模型能一次推理生成 4K 图吗?什么先崩——上下文、分词器质量,还是 KV 缓存?
实现 QK-Norm:用纯 Python 实现 QK-Norm,给定 64 维 query 与 key,展示 LayerNorm 前后的点积。为什么深度下量级控制重要?
读论文:读 Chameleon 第 2.3 节关于训练稳定性,描述论文在 34B 无 QK-Norm 时观察到的确切失败模式。「范数爆炸」的特征是什么?
混合生成:扩展玩具解码器,给定纯文本 prompt 发出混合模态响应。训练数据分布 60% 文本优先/40% 图像优先时,测量模型选图先 vs 文先的频率。
下一节,我们将进入 Emu3——它沿用 Chameleon 的早期融合,但证明「只要分词器够好,纯下一 token 预测就能同时做理解和生成,且质量追上专门的扩散与理解模型」。