训练大模型时最常被问的问题不是"用什么架构",而是"参数定多大、数据喂多少"。给你一笔固定的算力预算,你是把大部分钱砸在放大网络上,还是花在扩充数据上?2022年之前,绝大多数团队的答案很粗暴:参数越大越好,有多少卡就堆多大模型。直到Chinchilla这组缩放实验出来,大家才发现这个答案漏掉了整整一半预算——最优参数量N_opt和最优数据量D_opt会随算力等比例增长,token/参数比应该稳定在20附近,而不是随心所欲。
这篇文章不打算复述论文摘要,而是把这套公式从"为什么指数是0.5"一路拆到"给你一张算力账单,到底该怎么花钱"。哪怕你只是听说过Scaling Laws这个名字,看完也能在下次团队讨论时,给出一个有理有据的预算分配方案。
1. 为什么2022年之前大家都在"浪费算力":参数越大越好的直觉错在哪
1.1 从"280B模型只喂了300B token"看算力浪费
在Chinchilla之前,主流训练路径可以概括成一句话:算力涨多少,参数就涨多少,数据则以"能搞到多少就喂多少"的方式跟在后面。这种路径有一个非常典型的样本:一个280B参数的模型,只喂了大约300B token。算一下就知道,token/参数比只有1左右,而Chinchilla后来给出的参考值是20,差了整整20倍。
换成年费的话可能更容易理解:这就好比你花了重金招了280个员工,结果每个人一年只分配到1个项目。大部分人的工位是满的,但产出极其有限。更扎心的是,如果把这280个员工的预算砍到70个人,给每个人分20个项目,在同样的总人力成本下,团队总产出反而更高。
这不是某个团队的个别失误,而是当时系统性的算力浪费:大量参数在"等数据",而数据预算又被参数规模挤占。Chinchilla论文做的事情,本质上就是把这种浪费定量化:对每一个算力档位,找到让训练损失最低的参数量和数据量,而不是单纯地把参数量推到最大。
1.2 6ND约束:参数、数据、算力之间有一本物理账
要拆解这个问题,先得引入大模型训练的"成本等式"。训练一个参数量为N的模型,处理D个token,总算力消耗大约等于6ND FLOPs。这个6是怎么来的?Transformer密集训练中,前向传播大约需要2ND FLOPs,反向传播大约需要4ND FLOPs,加起来就是6ND。工程上可能有激活重计算、序列长度等细节带来的偏差,但6是一个足够靠谱的基准。
有了这条等式,算力预算C瞬间变成了一条约束曲线:
C ≈ 6ND
换句话说,给定C之后,N一旦定了,D也就被绑死了。你不能既让参数翻倍、又让数据翻倍、还算力不变——这不是优化,这是变魔术。正因为存在这条约束曲线,参数和数据之间才出现了"二选一"的博弈,也才有了寻找最优分配的必要。
1.3 为什么"参数越大越好"只对了一半
"参数越大越好"在直觉上很有市场,因为只增大N确实会降低训练损失,模型容量变大,拟合能力变强。但问题在于,算力预算固定时,N变大意味着D必须变小,而D变小会导致loss上升。一个向上拉,一个向下拽,两条力量互相拉扯,中间必然存在一个最优N。
在Chinchilla之前,大家只看到了N带来的好处,没看到D被压缩后付出的代价。Chinchilla给出的不是一句"模型别太大"的定性判断,而是一条可以精确计算的曲线:最优参数量N_opt随算力C按幂律增长。理解了这条曲线,后面的公式就像多米诺骨牌一样,一张一张自然倒下。
2. N_opt与D_opt的数学直觉:算力翻倍为什么只够让参数和数据各乘√2
2.1 "等比例增长"的真实含义:log-log图上的平行线
核心公式写出来就两行:
N_opt = K_N · C^a
D_opt = K_D · C^b
论文在多种拟合方法下给出的指数都接近0.5,标题里直接概括为a=b=0.5。那么"算力上升,参数量和数据量等比例增加"到底是什么意思?
它的意思是:在双对数坐标下,N_opt和D_opt是两条斜率相同的直线。算力扩大m倍,N_opt约乘m^0.5倍,D_opt也约乘m^0.5倍。举例来说:
- 算力×4,最优参数量×2,最优数据量×2;
- 算力×9,最优参数量×3,最优数据量×3;
- 算力×100,最优参数量×10,最优数据量×10。
注意,参数量的增长速度远低于算力增长速度,这是反直觉的。原因在于算力要同时养活参数和数据两头,每一头只能分到"半个指数"。如果你在算力×4时强行把参数量也×4,数据量最多只能乘2,因为C=6ND固定,此时新模型的D/N从20掉到10,模型直接就欠训练了。表面上看参数堆得豪华,实际上买的全是闲置产能。
2.2 指数0.5从哪来:从损失函数做一次极值求解
为什么指数接近0.5,而不是更高或更低?这可以从损失函数的形状推出来。
假设语言建模损失可以写成一个经典形式:
L(N,D) = E + A·N^(-α) + B·D^(-β)
其中E是不可约损失,A、B是量化参数容量和数据量贡献强度的常数,α和β是拟合幂指数。一组常见的典型拟合值是α≈0.34、β≈0.28。在约束C≈6ND下求L最小,用拉格朗日乘子法对N和D求极值,可以推出最优N和D对算力C的缩放指数分别为:
a = β/(α+β) ≈ 0.45
b = α/(α+β) ≈ 0.55
严格来说,两个指数并不完全等于0.5,而是落在0.45~0.55这个区间附近。论文用不同实验设计拟合出来的结果也都在这个范围内波动,所以标题写a=b=0.5是一种工程简化。它背后的物理含义是:参数容量和数据量对损失的边际贡献大致均等,预算在两头之间五五开。这就是为什么我们常说"参数和数据应同步放大"——损失面上两个方向的下坡速度差不多,最优路线自然是一条45度线。
提示:如果你在别的材料里看到"指数是0.5",那通常是指用固定预算扫描N和D后拟合出的幂律结果;细看具体数值,两边各有零点几的偏差,不影响工程判断。
2.3 K_N与K_D:截距常数,而不是普适定律
再看公式里的K_N和K_D。这两个常数不是理论推导出来的,而是实验标定的产物。它们的单位取决于你用什么方式计量算力,常见的是FLOPs或者PF-days。在N_opt = K_N · C^a里,K_N相当于一条log-log直线的截距,K_D同理。
这两个常数对数据分布、tokenizer、词表大小、训练超参数都非常敏感。Chinchilla论文用的是以英语为主的语言建模数据标定出来的一组值;迁移到中文、代码、多语混合场景时,最优的token/参数比往往会出现漂移。所以你可以把K_N、K_D理解为"这个数据分布下的本地常数",而不是放之四海而皆准的物理常数。
3. D/N≈20的"喂饱论":token/参数比是怎么被实验逼出来的
3.1 实验里看到的token/param比:从13到40
接下来是那个被引用最多的数字:D/N≈20,也就是每个参数大约对应20个训练token。这个数字不是理论值,而是在实验里"看"出来的。
做法很朴素:固定一个算力预算,把参数量从几千万一路放到几十亿,每个N配上对应的D=C/6N,训练到损失收敛后比较loss。重复几个算力量级,把每个算力档位下loss最低的点挑出来,就能画出N_opt和D_opt随C变化的轨迹,进而算出token/参数比。
有意思的是,论文里不同实验设计给出的比值并不完全相同:有的系列算下来大约13,有的约25,有的接近40。把多种拟合口径综合下来,最后落在20上下。所以别把20当成物理常数,它更像一个工程参考值:在典型的语言建模数据质量下,按20:1分配参数和token,通常离最优不远。
3.2 低于20是饿肚子,高于20是硬加餐
如果D/N远低于20,比如只有3~5,说明模型很大、数据很薄。训练到后期,损失曲线基本拉平,再加参数只会在推理时增加成本,换不来更低的loss。这种情况我习惯叫"饿肚子训练"——模型的容量摆在那,但没有足够的数据喂饱它。
如果D/N远超20,比如到了40以上,说明同一批数据已经被反复使用,模型开始把重复样本"背下来"而不是真正泛化。在单epoch、均匀采样假设下,这种做法的收益是递减的。但注意,如果数据质量很高、做过重采样和课程排序,"硬加餐"也可以是有效的。所以比例本身不是红线,而是一条基准线,实际训练往往会在基准线附近左右移动。
3.3 小模型为什么能反超:Chinchilla的翻身仗
这个发现最直接的结果,是让"小模型"打了一场漂亮的翻身仗。论文用与一个280B参数基线模型大致相同的算力,去训练一个70B参数、1.4T token的模型。按20:1算,70B配1.4T正好踩在最优曲线上;而280B配300B,D/N只有大约1,严重欠训练。
结果是更小的模型在验证集loss和多项下游任务上赢过了更大的模型。这件事在行业内震动很大,因为它直接挑战了当时"堆参数就是王道"的普遍做法。Chinchilla用一组实验证明:想让算力发挥最大价值,参数和数据必须一起涨,而不是单边狂飙。
4. K_N、K_D实验标定:五组实验和外推的完整链路
4.1 五组标定实验的分工
既然K_N、K_D无法从理论推出来,就必须靠实验标定。论文的标定工作可以归纳成五条实验线,我自己按用途做了归类:
| 实验线 | 在回答什么问题 | 得到的关键量 | 主要风险 |
|---|---|---|---|
| 固定算力扫描N-D组合 | 给定算力,多大模型最优 | N_opt、D_opt、D/N | 未充分收敛会误导 |
| 固定N扫描D | 这个参数量该喂多少token | 训练转折点 | 长训练开销大 |
| 固定D扫描N | 数据量一定时容量上限 | 参数边际收益 | 忽略D的变化 |
| 全局损失面拟合 | 一次性拟合整体规律 | α、β、A、B | 多参数拟合容易过拟合 |
| 稳健性验证 | 结论是否依赖拟合口径 | 指数范围 | 需要足够多实验点 |
第一条线最贴近实际:给定算力预算C,直接去试"多大N、多少D"能拿到最低loss,然后把结果对C做幂律拟合。第二条线回答的是另一个角度的问题:参数规模固定后,训练到多少token就应该收手,继续喂下去收益已经很低。第三条线用来隔离容量红利,第四条线则是把大量(N,D)点一起扔进损失函数公式,一次性拟合出所有指数。最后一条线用来做交叉验证:换用Huber损失、换数据子集,看看结论会不会剧烈变化。
4.2 为什么用"固定算力扫描"作为主依据
五条线不是平级关系。最终论文把"固定算力扫描"当作主要依据,理由很直接:真实问题就是"给定C求N和D",固定算力扫描没有任何绕路。其他方法更多是辅助验证,用来确认第一条线得到的结果是不是稳健。
但扫描法有个天然缺陷:每个算力档位都要训练多组模型,总开销是普通训练的几倍。所以实验时会把参数量控制在几十M到几十B之间,用对数均匀分布的档位覆盖大范围,再外推到更大算力。外推时,指数比截距更可靠,这也是为什么论文反复强调a≈b≈0.5非常稳定,而K_N、K_D的绝对值换个场景就变。
4.3 标定里最常见的三个陷阱
实际标定时最容易踩的坑有三个。
第一,只扫N不扫D。如果你只增大参数量而不管数据量,会得出"模型越大越好"的错误结论,问题是D被算力约束压小了。第二,候选模型训练步数参差不齐。有些模型还没收敛就拿来比loss,扫描结果会系统性偏向小模型,因为小模型收敛快、先达到低loss。第三,数据分布混入了课程顺序或多次重复,K_N会出现偏移,标定出来的不在同一套基准上。
我在自己的小规模标定里就吃过第二个亏。图省事把不同模型的训练步数统一,结果是损失低的几乎全是被"小模型很快收敛"带偏的假象,浪费了一整轮算力。后来改成每个候选模型都训练到验证loss充分收敛再比较,结论才稳定下来。所以看到K_N、K_D这些常数时,先问一句:这套数是在什么数据、什么收敛标准下标定出来的?
5. 一次实战推演:拿到算力账单,把参数与数据预算分清楚
5.1 从70B/1.4T锚点出发的三步计算
公式和常数都有了,下面给一个可以直接照做的流程,全部基于公开结论,不需要你手搓拟合代码。
第一步,锁定你的总算力预算C,单位统一用FLOPs。第二步,找一个可信的锚点。Chinchilla论文里的70B参数配1.4T token是个好锚点,D/N=20,总算力大约是5.9×10^23 FLOPs。第三步,按幂律缩放:如果新预算等于锚点算力的m倍,那么最优参数约等于70B×m^0.5,最优token约等于1.4T×m^0.5。算完记得用C≈6ND做校验,对得上说明分配自洽。
举三个例子:
- 算力×4:最优约140B参数、2.8T token;
- 算力×9:最优约210B参数、4.2T token;
- 算力÷4:最优约35B参数、700B token。
如果团队因为数据采集成本太高想减少D,那就必须接受N也相应缩小,否则会滑向欠训练。反过来也是一样,数据特别充足时,可以适当提高D/N,但不要指望参数规模还能继续匀速放大。
5.2 超参数怎么跟着涨:batch size与学习率
分配好N和D之后,训练超参数也要跟着规模调整。一个比较稳的经验是:N每扩大一个数量级,batch size按平方根倍数放大,大约3倍左右;学习率略降,并配上更长的warmup。训练总步数由D除以batch size再除以序列长度得到,通常小模型要训练几百K步,大模型几十K步就到收敛线了。
这些不是严格推导的公式,而是大量训练里比较稳的经验法则。每个人的数据分布不一样,batch size和学习率的最优组合也会有差异,拿到新规模时先跑一小段试训调一调,不要直接沿用小模型的完整配置。
5.3 那些远超20的模型到底在做什么
放到今天的开源模型生态里看,你会发现很多模型的token/参数比早就超过20了。举两个典型的公开案例:
| 模型配置 | token/参数比 | 与20的关系 |
|---|---|---|
| 280B参数/300B token | ≈1 | 严重欠训练 |
| 70B参数/1.4T token | ≈20 | 论文最优参考点 |
| 405B参数/约15.6T token | ≈38 | 高质量数据重采样加餐 |
| 某MoE模型,总参数约670B/约14.8T token | ≈22(按总参数) | 应看激活参数 |
为什么会出现这种偏离?原因主要有三点。第一,训练数据经过了高质量筛选和重采样,相当于变相提高了有效数据量,模型在相同物理token数下学到的东西更多。第二,推理服务成本让人更偏好小参数模型,宁可多喂数据来压榨参数潜力,也不愿让参数体积膨胀。第三,算力快速增长后,数据侧的边际收益有时候仍然比参数侧高,所以团队主动把D/N推高。
这些都不违反Chinchilla的核心思路——它给的是基准线,不是铁律。实际工程里,我们就是在基准线上下根据数据、成本、推理需求左右移动。
6. 别把20当铁律:数据质量、MoE与合成数据带来的修正
6.1 单epoch假设被打破后,最优比例开始漂移
为什么说20不是铁律?因为这套公式的推导默认了几个前提:单epoch均匀采样、固定的Dense Transformer架构、固定tokenizer、固定数据混合。今天的训练几乎每一项都在突破这些前提。
最典型的是多epoch训练。高质量数据稀缺时,团队会在优质子集上多轮训练,模型对同一批样本的记忆加深,"有效token数"高于物理token数,D/N自然可以超过20。此外,词表扩大、字符压缩密度改变,都会影响每个token携带的信息量。所以不同的数据体系和分词方案下,最优比值根本不该是完全相同的数字。
6.2 MoE模型要按激活参数算账
稀疏模型是另一个重要的修正方向。一个总参数上百B的MoE模型,每次前向只激活其中一小部分参数。如果用总参数量去套20:1,会得出"模型欠训练"的结论,但实际每个token只更新一小部分参数,数据利用率比Dense模型高得多。正确的做法是按激活参数量来计算D/N。
这解释了一个看起来很矛盾的现象:很多旗舰模型总参数很大、训练token也很多,按总参数算比值只有二十几,但按激活参数一算,比值可能高得惊人。它不是"违反"了Chinchilla法则,而是这套法则的适用口径变了。
6.3 合成数据与"有效token"概念:我的实际体会
最后聊聊数据上限。算力按指数级增长,要求数据量按开方级增长,但人类高质量文本总量是有限的。于是业界开始做合成数据、扩展推理数据、构造多语语料。合成数据的意义不只是补量,更在于改变数据分布密度。随着合成数据占比提高,"有效token"这个抽象概念会比物理token数更值得关注。
我在实际操作中的习惯是:先用"70B/1.4T"这个公开锚点做粗估,然后花大约1%的算力做一个小型的Chinchilla式扫描,把K_N和K_D重新拟合到自己当前的数据分布上。数据很干净时,得到的比例可能从20降到15;数据噪声大一些,可能要提高到25到30。每次扫完都会发现,指数a和b还是稳定在0.5附近,变化的只是截距。
这恰恰说明Chinchilla的核心思想依然成立:参数和数据要等比例跟随算力,变的只是那个常数,不变的是那条45度线。