Arganzheng's Blog

stay hungry, stay foolish

预训练(01):一次预训练是怎么跑起来的:从两个网页文件到一个会续写英文的模型

Pretraining End to End: From Two Common Crawl Files to a Model That Writes English, on a Laptop

后面四篇各讲预训练的一个环节——分词、scaling law、数据、配方——每篇都会把公式代进 Llama 3 和 DeepSeek-V3 的数字。但如果你从来没有见过一次预训练从头到尾是什么样,那些数字就没有地方放。所以这一篇先走一遍:在一台 MacBook 上,从两个 Common Crawl 的原始网页文件出发,过滤、去重、训 tokenizer、打包、选模型大小、定配方、训练、评测,最后得到一个会续写英文的小模型。每一步都回答三个问题:做什么、为什么要做、做完之后剩下多少——文档数、字节数、token 数、参数量、loss。每一步末尾指向后面展开它的那一篇。 它与《Transformer 与 LLM》第四篇(nanoGPT 训莎士比亚)的区别:那一篇的数据...

预训练:从 tokenizer 到训练配方(总纲)

Pretraining: Tokenizers, Scaling Laws, Data Pipelines and Training Recipes

内容简介 《预训练:从 tokenizer 到训练配方》是一组共五篇正文加一篇总结的系列文章,面向要做或要读懂一次预训练的算法工程师,以及要为一次预训练做容量与 I/O 规划的训练基础设施工程师。第一篇先在一台笔记本上把一次预训练从原始网页到能续写英文的模型完整走一遍,让后面四篇的每个公式与数字都有落脚的地方。它是《Transformer 与 LLM:结构、算量与数值》那张成本表的训练侧:那八篇把 token 数、参数量、数据量当作给定的输入,算出模型每一步算多少、读多少、存多少;本系列讲这几个输入各自是怎么定下来的——tokenizer 决定 token 数,scaling law 决定参数量与数据量的分配,数据管线决定有多少 token 可用、怎么配,训练配方...

Transformer 与 LLM:系列总结与通关自测

Transformers and LLMs: Series Recap and Final Self-Test

十三篇正文分三段回答了三个问题。第一段(01–04):Transformer 是什么、为什么是这个样子、怎么写出来——五种部件各自为什么在那里、一个 token 在训练和推理时怎么流过它们、nanoGPT 的 330 行怎么把图变成代码、336 行的训练脚本怎么在笔记本上训出一个会续写莎士比亚的模型。第二段(05–09):今天的模型为什么不是 GPT-2 的样子——Llama 改的五处、attention 的 K/V 怎么省、位置怎么外推、FFN 怎么换成专家、训练目标怎么加密。第三段(10–13):这样的结构每一步花多少——从 config.json 算出参数量、FLOPs 与字节数,建立 Roofline 上的成本模型,再看数值格式、量化、投机解码、LoRA、多...

Transformer 与 LLM(13):多模态:vision encoder 的算量与 image token 的 KV 代价

Multimodal LLMs: The Cost of Vision Encoders and Image Tokens

前十二篇讨论的模型只有一种输入:token id。它查一张 embedding 表得到向量,然后进入 decoder。这个前提决定了前面所有的账——参数量、FLOPs、KV cache——都只与 token 数有关,而 token 数由 tokenizer 决定。 多模态模型打破了这个前提。一张图片不经过 tokenizer,它先经过一个独立的神经网络(vision encoder,通常是 ViT),被切成几百到几千个向量,再由一个连接层(connector)变成 decoder 认得的 token embedding,插进 prompt 的对应位置。于是出现了三笔新账:encoder 自己的算量、connector 决定的 token 数、以及这些 token ...

Transformer 与 LLM(12):量化、投机解码与 LoRA

Quantization, Speculative Decoding and LoRA: Three Ways to Reshape the Computation

第五至十一篇把一个 Transformer 拆成了四组变量:参数量 \(N\)、每 token 的 FLOPs、每步要搬的字节数、每 token 的 KV cache。这些变量由结构决定——层数、hidden、GQA 的组数、专家数——一旦 config.json 定下来,它们就定下来了。 本篇讲的是三种不改结构、只改计算形态的方法。它们分别攻击前面算出的三个成本项: 量化减少权重(和 KV cache)的字节数,攻击的是 decode 每步要搬的 16 GB; 投机解码用一次前向验证多个 token,攻击的是 decode 每步只产出一个 token 的串行形态; LoRA 把可训练参数从 \(N\) 降到 \(N\) 的千分之几,攻击的是训练状...

Transformer 与 LLM(11):浮点格式、数值稳定性与混合精度

Floating-Point Formats, Numerical Stability and Mixed Precision

第四篇的 train.py 里有两行一直没解释:torch.amp.autocast(dtype=bfloat16) 与 GradScaler(enabled=(dtype == "float16"))——为什么训练要用两种精度、为什么 fp16 需要一个放大器而 bf16 不需要。前面几篇又算了大量的字节数:Llama-3-8B 的权重 16.06 GB、KV cache 每 token 128 KiB、decode 一步至少搬 16 GB,全都默认”每个数占 2 字节”,也就是 BF16。这一篇把镜头再推近一层,从”每个数占几个字节”进入”这几个字节里到底存了什么”,回答一个在训练和推理系统里都绕不开的问题: BF16 的相对精度只有 FP16 的 1/...

Transformer 与 LLM(10):前向的算量与访存量

FLOPs, Bytes and Roofline: Prefill versus Decode

第三段开始算账。第五篇把一个 decoder-only Transformer 拆到了能数出每一个参数的粒度,结论可以压缩成一个公式: \[N \approx L \cdot \left[ d \cdot (d + 2 d_{kv} + d) + 3 \cdot d \cdot d_{ff} \right] + 2 \cdot V \cdot d\] 其中 \(d_{kv} = n_{kv} \cdot d_{head}\)。代入 Llama-3-8B(\(d = 4096\),\(L = 32\),\(n_{kv} = 8\),\(d_{head} = 128\),\(d_{ff} = 14336\),\(V = 128256\)):每层 attention ...

Transformer 与 LLM(09):MTP——改训练目标而不改主干的多 token 预测

Multi-Token Prediction: Denser Supervision from the Same Data, and a Free Speculative Draft

前八篇改的都是结构:换归一化、换位置编码、换 FFN、换 attention 的 K/V、把 FFN 换成专家。这一篇改的是另一样东西——训练目标。从第二篇起,模型学的一直是”看前文、预测下一个 token”,每个位置只有一个正确答案、一份监督信号。MTP(multi-token prediction,多 token 预测)让每个位置额外预测后面第 2、第 3 个 token:同一批数据,榨出两三倍的监督信号;训完之后那几个额外的预测头还能拿来做投机解码的草稿(第十二篇),白送一个 1.8 倍的生成加速。DeepSeek-V3 把它写进了正式的训练配方,是 2024 年以后”改目标”这一条路上最成功的例子。 这一篇讲清三件事:MTP 为什么可能有用、DeepSee...

Transformer 与 LLM(08):MoE 的路由、激活参数量与通信形态

Mixture of Experts: Routing, Active Parameters and Communication Patterns

到这里为止讨论的都是 dense 模型:每个 token 经过每一层时,会用到这一层的全部权重。参数量、每 token 算量、每步 decode 的权重读取量,三者之间只差一个常数——参数量 \(N\) 对应每 token \(2N\) FLOPs,对应每步读 \(N \times \text{bytes/elem}\) 字节。 混合专家(Mixture of Experts,MoE)把这三个数拆开了。DeepSeek-V3 的技术报告里写着”总参数 671B,每 token 激活 37B”,从算量看它比 Llama-3-70B 便宜一半,但实际部署时它需要几十张 GPU 组成的专家并行集群,而 70B 一台 8 卡机器就能跑得很好。本篇要回答的核心问题是: ...

Transformer 与 LLM(07):位置编码与长上下文

Positional Encoding and Long Context: RoPE Wavelengths, Extrapolation and Cost

第一篇的换序实验说明 attention 是集合运算——把输入 token 打乱,输出只是跟着换位置——所以位置必须显式喂给模型;GPT-2 的做法是查一张 1024 行的位置表,代价是第 1025 个位置没有对应的向量,上下文的硬上限就是这么来的。Llama 换成了 RoPE。前几篇的账里有一个变量一直被当作常数处理:上下文长度 \(s\)。第六篇算 KV cache 时取 \(s = 131072\),第十篇算 prefill 时取 \(s = 8192\),但都没有回答两个问题:模型凭什么知道一个 token 在第几个位置?以及,一个模型能处理的上下文长度到底由什么决定? 这两个问题在结构上由同一个部件回答——位置编码。它在参数量表里几乎不占位置(RoPE ...

×