我从零构建了一个扩散语言模型。它能写出语法完美的句子,但毫无意义,而这正是有趣之处。
摘要
作者从零构建了Joey,一个1.7亿参数的掩码扩散语言模型,在FineWeb-Edu上训练并在DailyDialog上微调,由于容量限制,模型能生成流畅但不连贯的句子。该项目突出了与自回归LLM的差异,以及从构建和调试系统中获得的经验教训。
# 大多数LLM预测下一个token。Joey不这么做。
GPT风格的模型是自回归的:从左到右逐token生成,每个token依赖于之前的token。Joey属于不同的家族,**掩码扩散**(MDLM / LLaDA系列工作)。它不是从左到右写,而是:
1. 从100% `[MASK]`的序列开始
2. 并行预测**每个**token
3. 只保留它最确信的token
4. 重新掩码剩下的
5. 重复直到整个序列解析完成
这个重新掩码循环(MaskGIT / LLaDA风格)也消除了朴素单遍采样器会陷入的重复崩溃问题。
用一张图表示:
FineWeb-Edu ── BPE ──▶ packed token blocks
│
mask each token w.p. t (forward process, fixed)
│
bidirectional Transformer(+ t) (reverse process, learned)
│
1/t-weighted cross-entropy on masked positions
│
(after training) all-[MASK] ──▶ predict · keep confident · re-mask rest ──▶ text (sampling)
* **前向过程:** 以随机速率`t`用`[MASK]`替换token来破坏文本。
* **反向过程:** 一个双向的、时间步条件化的Transformer预测原始token。
* **损失:** 仅在掩码位置上的交叉熵,带有`1/t`权重(MDLM目标)。
# 架构
|属性|值|
|:-|:-|
|参数量|~1.7亿|
|骨干网络|双向Transformer(无因果掩码),时间步条件化|
|`d_model` / 层数 / 头数|1024 / 12 / 16|
|上下文长度|256个token|
|词汇表|16,384(自定义ByteLevel BPE + `[PAD] [BOS] [EOS] [MASK]`)|
|MLP|4x GELU,预归一化,权重共享头|
|扩散|掩码/吸收态(MDLM / LLaDA家族)|
一切都是手写的:16K ByteLevel BPE分词器、双向时间步条件化Transformer、扩散损失以及迭代重新掩码采样器。没有`Trainer`,没有预训练权重。以测试驱动构建,每个模块都有单元测试。
# 训练
|阶段|详情|
|:-|:-|
|数据|FineWeb-Edu,约20亿token,使用自有的16K BPE分词器|
|基础训练|A100-40GB,bf16 + EMA,余弦学习率 + 预热,174K步(约6小时),梯度累积,中断开关|
|微调|DailyDialog,仅响应掩码(LLaDA风格SFT)|
|采样器|重新掩码(MaskGIT / LLaDA)+ 重复惩罚 + top-p|
# 真实结果
经过基础训练和对话微调后,下面是真实的交流:
你> 你好!
Joey> 哦,我没错!这是我喜欢的,我们一直在一起很久了……
你> 你喜欢音乐吗?
Joey> 我不太了解。但我觉得没有人……
Joey能正确打招呼,组成语法正确的句子,保持对话语体。它流畅但尚未真正连贯:局部语法正确,但缺乏持续的全局意义。这不是我放弃的bug,而是容量上限的标志。在1.7亿参数下,模型已基本收敛到其大小能学习到的极限。它在学习语言听起来像什么之前,就用完了学习实际要说什么的空间。获得真正的连贯性主要是一个规模问题(更多的参数和token),这是下一个里程碑。
# 实际出过的问题及教训
我学到最多的两个失败:
* **训练时的CUDA OOM**——这迫使我真正理解内存布局、梯度累积和批处理打包,而不是复制一份配置。
* **采样时的重复崩溃**——这恰恰是重新掩码策略发挥作用的地方。朴素单次解码会自我循环。预测所有token,只保留置信度高的,重新掩码其余部分,打破了循环。
直到你在凌晨2点调试过自己的OOM,亲眼看着损失曲线在你面前变平,你才算真正理解扩散LLM。没有任何论文或课程能教会你这些。构建那个有缺陷的版本才会。
# 路线图
* \[x\] 从头实现分词器、模型、扩散损失、采样器、训练循环
* \[x\] 在约20亿token上的基础预训练 + 对话SFT
* \[x\] 用于消除重复循环的重新掩码采样器
* \[ \] 扩大规模(约4亿至10亿)以实现真正连贯性,进行中
* \[ \] 更大、更干净的指令微调数据
* \[ \] 用于条件采样的无分类器指导
* \[ \] 更长的上下文
# 代码和权重
* 评论区有链接
建立在MDLM (Sahoo et al., 2024), LLaDA (Nie et al., 2025), D3PM (Austin et al., 2021), SEDD (Lou et al., 2024), 和MaskGIT (Chang et al., 2022)的肩膀上。如果你研究过文本离散扩散,我很想听听你如何看待自回归与扩散的权衡,尤其是并行解码的速度优势是否能在大规模场景下持续。
相似文章
自己从零写扩散语言模型比我想的简单多了[P]
开发者分享了一个极简的750万参数扩散语言模型,用莎士比亚文本从头训练,并开源代码供学习。
@volokuleshov: 新博客文章:如何构建扩散语言模型。扩散LLM从开放问题变为现实,用了2年时间 (Me…)
由Volodymyr Kuleshov的康奈尔团队撰写的综合博客文章,解释了如何构建扩散语言模型,涵盖了核心技术如掩码扩散、迭代细化、变长生成、可控生成、快速采样器和RL后训练,并以开源模型如Mercury、Gemma Diffusion和Nemotron Diffusion为例。
扩散语言模型:实验分析
一项系统性的实验分析,评估了八种最先进的扩散语言模型在多个基准测试上的表现,分析了生成质量与计算效率之间的权衡。
LangFlow:连续扩散在语言建模中可与离散扩散相媲美
LangFlow提出了首个可与离散扩散方法相媲美的连续扩散语言模型,挑战了长期以来认为连续扩散在语言建模中劣于离散扩散的观点。该工作引入了基于最优Gumbel噪声调度等关键要素,并展示了与离散扩散基线相比具有竞争力的困惑度和迁移学习性能。
改进的大型语言扩散模型
iLLaDA是一个80亿参数的掩码扩散语言模型,具有完全双向注意力机制,从头开始在12万亿token上训练。与LLaDA相比,它在多个方面都有显著改进,并在多个基准测试上与Qwen2.5 7B保持竞争力。模型和代码已开源。