Understanding LLMs in 200 Lines I: Training & Parameters
给定一段文字,猜下一个字是什么。输入”床前明月”,模型输出一组概率分布:下一个最可能是”光”,也可能是”色”或”夜”。把”光”接上,让模型继续预测下一个字。
所有 LLM 本质上都在做这件事——写诗、写代码、回答问题,底层全是逐步预测下一个 token。
单步预测看起来简单,但只要预测得足够准,把每步结果接起来(自回归生成),就能产生连贯的长文本。能力的来源是大量训练:模型见过海量”上文→下一个字”的样本,学会了语言的统计规律。
microgpt 用三万多个人名作训练数据。代码朴素:按行读取、去空白、存列表,然后打乱顺序。
如果按字母顺序训练,模型一开始只看 a 开头,后面才看 z 开头——学到的是有偏的数据分布,先学的规律会被后学的覆盖(灾难性遗忘)。打乱后,每步训练看到的数据接近随机分布,模型学得更均匀。
这是机器学习的通用做法。训练数据要充分打乱,分批(mini-batch)喂给模型。GPT-4 的训练数据是互联网级文本,本质一样,只是规模大得多——都是把字符串随机喂给模型。
模型只能处理数字,不能直接处理字符。需要一个翻译层把字符映射成整数——这就是 tokenizer。
microgpt 的做法:收集所有出现过的字符(26 个字母),按字母顺序排好,每个字母对应一个 id(a=0, b=1, …, z=25)。
| 字符级 | 子词级(BPE) | |
|---|---|---|
| 单位 | 单个字符 | 常见字符组合 |
| 例子 | hello → h,e,l,l,o | hello → 一个 token |
| 词表大小 | 小(几十) | 大(几万) |
| 序列长度 | 长 | 短 |
GPT-4 用 BPE(Byte Pair Encoding),把 hello 这类常见组合压成一个 token。但核心原理没变:建立查找表,字符串进来、整数序列出去。
只有 tokenizer 还不够,模型还要知道一个名字从哪开始、在哪结束。所以加一个特殊符号 BOS(Beginning of Sequence),id=26,接在最后一个字母后面。
emma 变成:BOS e m m a BOS
推理生成时,模型靠结尾 BOS 判断何时停下。否则模型会一直生成下去停不住。这是所有自回归生成模型的关键机制——需要一个明确的停止信号。
真实的 LLM 都有这类特殊 token:<bos>/<sos>(开始)、<eos>(结束)、<pad>(填充)等。它们不属于正常文本,但控制生成流程。
模型本体就是一堆数字(参数)。microgpt 把所有参数放在一个字典 state_dict 里:
| 参数 | 作用 |
|---|---|
wte | token 嵌入表,把字符 id 变成 16 维向量 |
wpe | 位置嵌入表,告诉模型字符所在位置 |
wq wk wv wo | 注意力的四个矩阵(Query/Key/Value/输出) |
fc1 fc2 | 前馈网络(MLP)的两个矩阵 |
lm_head | 把模型输出映射回 27 个字符的概率 |
wte 是一张查表:字符 id(0–26)→ 16 维向量。这一步把离散的字符变成连续的、可学习的向量表示。模型通过训练调整这些向量,让语义相近的字符向量也相近。
Transformer 本身对输入顺序无感(注意力机制看的是所有位置的关系)。wpe 显式注入位置信息,让模型知道”第几个字符”。没有它,“abc” 和 “cba” 对模型没区别。
所有参数加起来,microgpt 一共 4000 多个数字。这就是它的全部知识——会写出什么名字、学到的字符规律,都编码在这些浮点数里。
| microgpt | GPT-4(估计) | |
|---|---|---|
| 参数量 | ~4000 | ~万亿 |
| 差距 | — | 约 2 亿倍 |
无论 4000 还是万亿,每个参数都是一个浮点数,等待被梯度下降调整。参数越多,能记住的模式越复杂,但训练原理不变:
这就是为什么”看懂 microgpt 的 200 行,就抓住了 GPT-4 训练的核心”——原理同构,只是规模天差地别。