Show-o 与离散扩散统一模型 本节摘要:Transfusion 混合连续与离散表示。Show-o(Xie 等人,2024 年 8 月)走另一条路:文本 token 用因果下一 token 预测,图像 token 用 MaskGIT 风格的掩码离散扩散。两者都坐进一个带混合注意力掩码的 Transformer。结果在一个主干、每模态一个分词器、一种损失形式(下一 token 推广到掩码预测)上,统一了 VQA、文生图、图像补全与混合模态生成。本节走读 Show-o 的设计——为什么掩码离散扩散是一种并行的、少步的图像生成器——并与 Transfusion、Emu3 对比。
本节摘要:Transfusion 混合连续与离散表示。Show-o(Xie 等人,2024 年 8 月)走另一条路:文本 token 用因果下一 token 预测,图像 token 用 MaskGIT 风格的掩码离散扩散。两者都坐进一个带混合注意力掩码的 Transformer。结果在一个主干、每模态一个分词器、一种损失形式(下一 token 推广到掩码预测)上,统一了 VQA、文生图、图像补全与混合模态生成。本节走读 Show-o 的设计——为什么掩码离散扩散是一种并行的、少步的图像生成器——并与 Transfusion、Emu3 对比。
阅读完本节,你应当能够:
Transfusion 的双损失训练有效,但动力学更棘手——连续扩散损失与离散 NTP 损失不在一个数值量级上,平衡损失权重是个超参搜索,架构有效但复杂。
Show-o 的回答:两种模态都保持离散(像 Chameleon),但图像用掩码离散扩散并行生成,而非逐 token 串行。训练目标变成单一的掩码 token 预测,自然地推广了下一 token 预测。
Chang 等人(2022)的 MaskGIT 技巧很优雅。从一张全掩码图像(每个 token 都是特殊 <MASK> ID)出发,每步并行预测所有掩码 token,然后保留 top-K 最有信心的预测,把其余重新掩码。约 8~16 次迭代后所有 token 填满。每步揭示多少 token 的调度要调——余弦调度效果好。
训练很简单:从 [0, 1] 均匀采样一个掩码比例,应用到图像的 VQ token 上,训练 Transformer 恢复被掩码的。这正是 BERT 对文本做的事,扩到图像生成。
Show-o 把 MaskGIT 放进一个因果语言模型 Transformer。注意力掩码是:
训练交替:
统一损失是 <MASK> token 上的交叉熵,同时覆盖文本 NTP(只有最后一个 token 算「掩码」)与图像掩码扩散(随机子集被掩码)。
Show-o 约 16 步生成一张图,而非约 1000 步(逐 token 自回归)或约 20 步(扩散)。每步并行预测所有掩码 token,提交 top-K 有信心的,重复。
对比:
Show-o 在同等规模下比 Chameleon 快,步数大致持平 Transfusion,但每步成本更低(离散词表 logits vs 连续 MSE 损失)。
Show-o 推理时支持四种任务,按 prompt 格式选择:
补全能力从掩码预测训练免费获得——掩码 VQ 网格的一块,喂其余部分加文本 prompt,预测掩码 token。
每步揭示多少 token 的调度影响质量。Show-o 推荐余弦:
mask_ratio(t) = cos(pi * t / (2 * T)) # t = 0..T
第 0 步全掩码(比例 1.0),第 T 步全无掩码。余弦把质量集中在中段比例——那里预测最有信息量。线性调度也行,但平台化更快。
Show-o2(2025 后续,arXiv 2506.15564)扩规模:更大 LLM 基座、更好分词器、改进掩码调度,架构模式不变。
2026 年的分类法里:
按任务挑:要在一个开源模型里同时做 T2I + 补全 + VQA 且速度合理,选 Show-o;质量 paramount 且能负担双损失管道,选 Transfusion。
code/main.py 模拟 Show-o 采样:
def maskgit_sample(model, prompt, n_tokens=1024, steps=16): tokens = [MASK] * n_tokens # 全掩码起步 for t in range(steps): logits = model(prompt, tokens) # 并行预测所有掩码位置 probs = softmax(logits, axis=-1) confidence = probs.max(axis=-1) # 每个位置的最大概率 # 余弦调度: 本步揭示多少 keep_ratio = 1.0 - cos(pi * t / (2*steps)) n_keep = int(keep_ratio * n_tokens) # 只在仍是 MASK 的位置里挑 top-K 信心 masked_idx = [i for i,v in enumerate(tokens) if v == MASK] top_idx = topk(confidence[masked_idx], n_keep) for i in top_idx: tokens[masked_idx[i]] = argmax(probs[masked_idx[i]]) return tokens
def show_o_loss(sequence, model): # 文本位置: 只掩码「下一个」(等价 NTP) # 图像位置: 随机掩码一个子集 masked_seq = apply_masking(sequence, strategy="mixed") logits = model(masked_seq, mask=hybrid_attention_mask(sequence)) # 统一交叉熵, 只算被掩码位置 return cross_entropy(logits[masked_positions], sequence[masked_positions])
💡 关键洞察:Show-o 把「下一 token」推广成「掩码 token」——NTP 是掩码预测的特例(只掩码最后一个)。这一个统一损失同时驱动文本生成与图像并行解码,是它比 Transfusion 双损失更简洁的根源。
def hybrid_mask(seq_layout): # 文本: 因果; 图像块内: 全双向; 跨模态: 文本看之前图, 图看之前文本 # 与 Transfusion 块三角掩码同构, 但图像块内是全双向而非因果 ...
工程取舍:要开源单模型多任务(理解+生成+补全)且速度合理用 Show-o;要最高生成质量用 Transfusion/MMDiT;要最简代码用 Chameleon/Emu3(逐 token NTP);要纯图像并行生成用 MaskGIT。
本节产出 outputs/skill-unified-gen-model-picker.md。给定一个既需理解(VQA、caption)又需生成(T2I、补全)、且有开源权重约束的产品,它在 Show-o 系、Transfusion/MMDiT 系、Emu3/Chameleon 系间选择,给出具体权衡。
为何不只 1 步:掩码离散扩散约 16 步。为什么不能 1 步?第 0 步全揭示会崩什么?
补全用例:补全在掩码扩散里免费。提出一个真实或假想的产品用例,Show-o 的补全胜过专门模型。
调度对比:余弦 vs 线性调度,T=8 时追踪每步揭示的 token 数,哪个更均衡?
压缩比:512×512 的 Show-o 图是 1024 token,K=16384 词表,模型输出 1024·log2(16384)=14336 位(约 1.75 KiB)。Stable Diffusion 输出 512·512·24=6291456 位(约 768 KiB)原始像素。压缩比是多少?买到了什么质量?
读 LlamaGen:读 LlamaGen(arXiv:2406.06525),它的类条件自回归图像模型与 Show-o 的掩码方法有何不同?
<MASK> 上的交叉熵,同时覆盖文本 NTP(掩码最后一个)与图像掩码扩散(掩码随机子集)。下一节,我们将进入 Janus-Pro——它进一步解耦,让理解与生成各用最佳视觉编码器(SigLIP 理解、VQ 生成),共享 Transformer 主体,是「解耦编码器」路线的代表。