过去几年,打造更强 AI 模型的思路很简单:把它做大。
直到 2022 年,DeepMind 训练了一个叫 Chinchilla 的模型,参数量为 700 亿,却击败了他们自家参数量 2800 亿 的老模型 Gopher——体积只有四分之一,成绩反而更好。
凭什么?Chinchilla 的架构设计并不更聪明,它只是“读”了多得多的数据。
我想亲眼验证这一点,于是在自己的笔记本上训练了一堆小模型。以下是我的发现。
先明确两个词
- 参数(Parameters):模型内部可调节的数字。"70B" 表示 700 亿个参数,可以理解为模型“大脑”的体积。
- Token:模型在训练时读取的文本片段,可以理解为它的“学习量”。
训练要消耗算力,算力大约等于参数量乘以 token 数(想精确到毛估版本的话,再乘个 6)。这意味着同样的预算有两种花法:养一个大脑袋但少学习,或者养一个小脑袋但拼命学习。
旧经验与它的修正版
2020 年,OpenAI 的一篇论文(Kaplan 等人)发现:随着参数、数据或算力的增加,模型误差会平滑且可预测地下降。这很有用——你可以据此做规划。他们给出的建议是:在预算固定的情况下,选一个非常大的模型,用相对适中的数据量训练,并且在模型完全收敛之前就停下来。
两年后,Chinchilla 论文(Hoffmann 等人)更严谨地重新研究了这个问题,得出了不同的结论:模型规模和训练 token 数应该同步增长。模型翻倍,数据也要翻倍。
为了证明这一点,他们用了和训练 Gopher 大致相同的算力预算,但换了一种分配方式:

| 参数量 | 训练 token 数 | MMLU 得分 | |
|---|---|---|---|
| Gopher | 280B | 300B | 60.0% |
| Chinchilla | 70B | 1.4T | 约 67.5% |

(MMLU 是一个大型多选题知识测试。论文摘要里写的是 67.5%,文中某张表格里则是 67.6%,反正都差不多。)在众多任务上,Chinchilla 同样胜过了 GPT-3(175B)、Jurassic-1(178B)和 Megatron-Turing NLG(530B)。
论文的结论是:当时许多大模型都训练不足——脑子太大,书读得太少。
人们从中总结出的经验法则是:每个参数大约对应 20 个 token 的训练数据。Chinchilla 本身是 1.4T / 70B,正好是 20 倍。
一个计算器
把这条经验法则和上面的估算公式结合起来,就能得到一个简易计算器。若算力为 6 × N × D,且 D = 20 × N,则 compute = 120 × N²。反过来推:
from math import sqrt
def split_budget(compute_flops, tokens_per_param=20):
n = sqrt(compute_flops / (6 * tokens_per_param))
return n, tokens_per_param * n
for c in [1e22, 5.76e23, 1e24]:
n, d = split_budget(c)
print(f"{c:.2e} FLOPs -> {n/1e9:.1f}B parameters, {d/1e12:.2f}T tokens")
1.00e+22 FLOPs -> 9.1B parameters, 0.18T tokens
5.76e+23 FLOPs -> 69.3B parameters, 1.39T tokens
1.00e+24 FLOPs -> 91.3B parameters, 1.83T tokens
中间那条线就是 Chinchilla 论文表格里的计算量数值。套公式算出来是 690 亿参数、1.4 万亿 token——仅凭一行算术,就得到了 Chinchilla。
现在用我的笔记本试试
几十亿参数我玩不起,但“固定预算下存在最优模型规模”这一思路,应该在任何尺度上都成立。于是我做了个玩具版实验。
实验设置:
- 数据:取标准库里约 1200 万字符的 Python 源代码,留出 5% 用于测试。
- 模型:处理单个字符的小型 GPT 式 Transformer,参数量从约 3000 到 320 万不等。
- 预算:四个固定计算预算,从 1e11 到 3e12 FLOPs。
-
诀窍:对每个预算和每种模型规模,先算出预算内能塞下多少 token(
tokens = compute / (6 × parameters)),然后严格按这个量训练。大模型配少数据,小模型配多数据,成本相同。
一共跑了 35 次训练。然后我在模型从未见过的文本上测量损失(越低越好)。
每条彩色线代表一个预算,星星标出赢家。
我观察到:
过大的模型输得很惨。在最大预算下,320 万参数的模型损失为 2.61;而一个小它约 150 倍、用多得多的文本训练出来的模型,损失只有 1.75。那个大模型总共只读到约 15.5 万 token——平均每个参数摊不到 0.05 个 token,相当于一个天才大脑只把书囫囵翻了翻。
预算越大,赢家越大。预算分别为 1e11、3e11、1e12 和 3e12 时,最优规模约为 7.4k、7.4k、10.7k 和 20.6k 参数。
每条曲线的底部都很平缓。在 1e12 预算下,7.4k、10.7k 和 20.6k 参数的模型分别拿到 2.068、2.039 和 2.047。你不必找到那个完美规模,只要别大到离谱就行。
| 预算(FLOPs) | 最优规模(参数) | 训练 token 数 | 留出集损失 |
|---|---|---|---|
| 1e11 | 7,408 | 2.2M | 2.477 |
| 3e11 | 7,408 | 6.7M | 2.282 |
| 1e12 | 10,688 | 15.6M | 2.039 |
| 3e12 | 20,640 | 24.2M | 1.750 |
这和 Chinchilla 论文描述的规律一模一样:预算固定时,模型太大反而吃亏;预算越大,最优模型也越大。
我没有声称的事
这只是个小玩具实验,所以我得把话说清楚:
- 我没有复现“每参数 20 个 token”这一结论。我实验中的赢家,每个参数训练了几百到几千个 token,和 20 相差很远。我觉得有几件事混在了一起:单字符文本和单词是完全不同的问题;我的训练规模极小(从几十步到约两万步);位置编码也算参数,而在 7k 参数的模型里占了很大比重。另外我也没有针对每个模型规模单独调参。
- 最大预算下的赢家处在边缘。预算为 3e12 时,最优模型是我能测的最小那个,因为再小的模型对我的数据就得重复训练超过 2.5 遍了。所以它真正的最优规模可能更小,仅凭这些数据判断不出来。
- 有些小模型把数据读了好几遍。对最小的几个模型,我允许训练文本重复至多约 2.5 遍。在这个规模下无伤大雅,但毕竟不同于论文里“新鲜数据只过一遍”的干净设定。
- 每组设置只跑一次。没有重复实验,所以细微差距可能只是噪声。但大差距不会是。
所以请把它理解为“连玩具实验都能看出这个规律”,而不是“我验证了 Chinchilla 的数字”。想要确切数字,请读原论文。
就算你从不训练模型,为什么也值得关心
- 参数量对模型质量的指示作用很弱。用大量数据训练的小模型,可以胜过数据不足的大模型。挑选模型时,“训练数据有多少”和“模型有多大”同样重要。
- 它是切分训练预算的参照基准。“把模型做大就行”不再是默认答案,“这个规模需要多少数据”成了标准问题。
- 再后来,事情变得更离奇了。现在有些实验室故意让小模型的训练数据远远超出 20 倍法则。这是下一篇文章的内容。
如果你也想动手试试,整个实验大约只需 100 行 PyTorch 代码。你可以改改数据、预算或模型规模,看看得到的曲线是和我一样,还是完全不同——欢迎告诉我你的结果。
