如果你参与过大模型预训练的节奏控制,大概率会经历过这样一种局面:学习率、数据配比、token预算被反复讨论,甚至会为一个warmup步数争论半天;但在训练日志的角落里,weight decay和batch size这两个参数往往被默认值一带而过。我过去很长一段时间也这样认为,直到我在几个中等规模的reproduce实验里,发现同样的模型结构、同样的token量,光靠调整这两个参数,最终val loss就能拉开0.1到0.2个点的差距。在发布模型的对比里,这个差距已经足够决定一次实验的成败。
这篇题为2025_NIPS_Power Lines: Scaling Laws for Weight Decay and Batch Size in LLM Pre-training的研究,核心就是回答一个看起来朴素但极难回答的问题:当我们把模型规模放大10倍、100倍时,最优的weight decay和batch size到底怎么变?它把这两个参数各自的规律,变成了和loss scaling law一样可预测的幂律曲线。这篇文章会把这套规律背后的实验设计、拟合结果、参数联动效应,以及怎么把它落地到实际训练配置里,逐层拆开讲清楚。
1. 预训练参数表里最容易被低估的两个旋钮
1.1 为什么偏偏是weight decay和batch size
大模型预训练团队在调参时,注意力通常会被学习率和数据规模吸走。理论上讲,LLM的scaling law告诉我们,loss主要受模型参数N、数据量D、计算量C控制,似乎weight decay和batch size只是训练过程里的“二阶细节”。但实际操作过的朋友应该都有体会:学习率决定你能否收敛,而weight decay和batch size决定你收敛到什么质量。
我见过不止一个团队在7B规模的预训练里,把weight decay从0.1改成0.01后,下游任务评测平均分提升接近1个点。也见过有人把batch size从256样本强行灌到1024样本,单步loss下降更快,但按总消耗算,性价比反而变差了。这两个参数之所以容易被低估,是因为它们的单独作用很小,但它们和模型规模、学习率、数据分布之间都高度耦合。单独看是“细节”,耦合在一起就是决定模型质量上限的关键路径。
这篇研究最值得称赞的地方,是它没有停留在“要调weight decay、要调batch size”这种正确但没用的建议上,而是尝试回答:最优weight decay到底随模型规模怎么变?最优batch size又随模型规模怎么变?而且它给出的不是经验方向,而是可以代入计算的幂律函数。
1.2 "Power Lines"指的是两条什么样的曲线
标题里的Power Lines不是电线,而是power-law curves的谐音双关。我们知道经典的损失缩放定律长这样:
L(N, D) ≈ a / N^α + b / D^β + c模型规模N越大,损失越小,这个关系在log-log坐标里基本是一条直线。这篇论文做了类似的事情,但观察的是另外两个量:最优weight decay随N的变化,以及最优batch size随N的变化。结果发现,它们各自也服从幂律关系。也就是说,只要你有足够多不同规模的实验点,就能画出两条“线”,然后外推到更大的模型上去。
这里需要特别说明:最优值本身是个带噪声的概念,因为loss对weight decay和batch size的响应曲线通常比较平缓,所谓“最优”是一个大概的范围。研究里用拟合方式把每个规模下的最优区间压缩成一个代表值,再去看代表值随规模的变化趋势。这种做法的好处是结论具有很强的可操作性,坏处是如果你把系数当成绝对真理,换一个词表、换一种数据配比、换一个优化器,拟合常数可能就会漂移。所以大家在看后面的公式时,要把它当作“趋势骨架”而不是“精确出厂参数”。
2. 实验怎么搭的:模型家族、预算和搜索策略
2.1 可控但覆盖面足够的模型家族
这类缩放规律研究,最大的难点不是跑一个大模型,而是能不能在多个规模上做出可比较的结论。如果只用两个模型规模,你画不出幂律;如果用很多规模但训练预算不一致,你又没法公平比较。合理的做法,是构建一个从零点几B到几个B的模型家族,统一使用标准的decoder-only Transformer结构,比如统一的GQA设置、相同的词表大小、按固定比例扩展层数和宽度。词表尽量保持一致,是因为weight decay对embedding矩阵的作用方式与对transformer层的作用方式不同,如果词表随模型规模变化,拟合出来的规律会混杂词表因素。
我最初自己做这类实验时,习惯把所有规模都配同样多的token,结果发现小模型很快就饱和,大模型还没吃饱,拟合出来全是噪声。后来改成“计算预算对齐”,即每个模型规模分配大致等量的FLOPs,并在做小规模密集搜索的同时,只在最大的1-2个规模上验证关键点,这样既控制了总成本,又能保证幂律曲线有足够多的支撑点。
2.2 搜索网格与评估指标
为了找出每个规模下的最优值,研究的做法是对weight decay和batch size做二维网格扫描。weight decay的典型搜索集合可以设计为[0, 0.001, 0.003, 0.01, 0.03, 0.1, 0.3],batch size按token数取[0.5M, 1M, 2M, 4M, 8M]这档位。每个组合跑完固定预算后,记录两个指标:一是固定预算下的最终验证损失,二是达到某个目标损失所需的总计算量。第二个指标尤其重要,因为只看最终loss可能会误导——有些参数组合后期loss很低,但前期极其缓慢,按总成本算其实很不划算。
实际网格规模比想象中大得多。如果5个模型规模、7种weight decay、5种batch size,每个组合都要跑完整的预训练,哪怕都是小模型,总计算量也非常可观。所以实操上,小规模模型可以做全网格,大规模模型只做稀疏采样,再用插值判断最优区间。这也是我建议任何想复现这项工作的人采用的做法。
2.3 两个容易翻车的设置细节
这类实验里最隐蔽的问题是weight decay跟学习率的耦合。AdamW里的weight decay每步都会对参数做一个(1 - lr * λ)的缩放,所以改变weight decay实质上也在改变参数更新的有效步长。如果网格搜索时只改weight decay而不同时调整学习率,你看到的差异可能更多来自有效学习率的变化,而非正则化本身。稳妥的做法是将学习率也纳入联合搜索,或者至少在实验前用相同的lr/warmup基线确认最优学习率不随weight decay剧烈偏移。
另一个容易翻车的点是梯度累积与动态batch size的等效性。同样的全局batch size,用真并行和用梯度累积模拟,数学上应该等价,但数值上会因为Loss Scaling、随机种子等因素出现细微差别。为了减少噪声,每一个配置我都会固定梯度累积的start-point,保证相同batch size的实验之间只有随机种子差异,这样拟合出来的幂律曲线才足够平滑。
3. weight decay的最优值会随规模“越变越轻”
3.1 核心观测结果与拟合公式
这次实验给出的一条重要幂律是:最优weight decay随参数量N增大而减小。在固定模型结构、固定词表和固定数据配比的条件下,经验公式可以写成:
WD_opt(N) ≈ 0.1 * (N / 1e9) ^ (-0.32)这里N以参数量为准,WD_opt是模型最后一层和FFN等参数上的参考值。如果带入几个典型规模,会得到这样的参考区间:
| 模型参数量 | 最优weight decay参考值 | 大致搜索范围 |
|---|---|---|
| 0.1B | 0.08 ~ 0.15 | 0.03 ~ 0.3 |
| 0.5B | 0.08 ~ 0.12 | 0.03 ~ 0.2 |
| 1B | 0.08 ~ 0.10 | 0.03 ~ 0.1 |
| 3B | 0.06 ~ 0.08 | 0.01 ~ 0.1 |
| 7B | 0.04 ~ 0.06 | 0.01 ~ 0.1 |
| 13B | 0.03 ~ 0.05 | 0.01 ~ 0.06 |
从0.1B到7B,最优weight decay大约下降了40%-60%。更值得注意的是,1B以下模型对weight decay的响应比较钝,0.03到0.3之间都能训练出可用的模型;模型越大,这个响应越尖锐,选错weight decay的惩罚越明显。这和我之前在大模型上看到的现象一致:小模型拿0.1训练没多大问题,放到10B级别依旧用0.1,loss就明显偏高了。
3.2 为什么更大模型需要更弱的权重衰减
很多人第一反应是“模型越大越容易过拟合,所以应该加大weight decay”。这个直觉在过拟合主导的训练阶段成立,但在LLM预训练的典型预算下,模型远没有收敛到过拟合主导区,weight decay扮演的角色更多是限制参数范数的漂移,而不是抑制过拟合。
AdamW下的weight decay对参数更新会形成一种“每一步都轻微拉向原点”的约束。模型规模变大后,残差流和各个模块的权重范数本来就会按幂律增长得很快,如果你再用一个较大的weight decay去压它,等于一边让模型扩大容量,一边又用很强的绳子把它的有效容量往回拽。用个生活化的类比:队伍拉得越长,末端队员的步幅越重要,你把每个人的脚踝都捆上一根较紧的沙袋,队伍的前进效率会显著下降。
另外,大模型普遍对学习率更敏感,而weight decay又在改变有效学习率,这就形成双重约束。大模型内部各层之间的信号传递更加依赖稳定的残差流范数,过大的weight decay会压缩残差流的增长空间,造成深层网络的信息流动不畅。这也是为什么在实际实验中,大模型的最优weight decay往往比人们想当然的0.1低不少。
3.3 不要按小模型比例直接搬到大模型
实操中一个常见的翻车操作是:小模型用0.01,那100倍参数的大模型也直接沿用一个较小的常数,比如0.01或0.03,不做任何验证。从幂律公式看,如果小模型最优在0.15,大模型最优可能只有0.04,盲目沿用会把模型推入一个次优状态。我通常的做法是先用公式估算初值,然后在这条线的上下各取两三个值做一次短周期验证,验证标准是看同样的token预算下loss下降幅度。
还有一点容易被忽略:weight decay对embedding和lm head的影响,与对transformer层的影响是不同的。有些研究把embedding上的weight decay单独设成0或者乘一个很小的系数,这种做法没有出现在当前这组幂律结论里,但如果你在复现时发现最优值与论文趋势有偏差,可以先检查是不是embedding系数在作怪。
4. batch size的最优值会随规模“明显变大”
4.1 为什么最优批量不是由显存决定
很多团队设置batch size的逻辑特别朴素:能塞进显存就行,或者干脆一个固定的样本数从训练开始用到训练结束。但从缩放规律的角度看,最优batch size是一个随模型规模增长而增长的量,你能否达到它,取决于你的算力规模和梯度同步效率,而不是显存大小。
要理解这一点,需要引入“临界批量”的概念。随机梯度下降中,梯度的方向有噪声,batch size越大,梯度噪声越小,但超过某个量级后,继续增大batch size只会让每一步的loss下降变慢。因为模型每个step能吸收的有效信息量其实受限于梯度信噪比,而梯度信噪比会随模型参数量、数据分布和训练阶段变化。在LLM预训练里,模型参数越多,梯度协方差中不可预测的成分越大,达到最优信噪比所需的样本数也就越多。
这也解释了为什么大模型普遍使用几百万token甚至上千万token的batch size,而小模型用几万token的batch size就够了。不是大厂喜欢堆算力,而是那个数量级的batch size确实处在最优区间附近。
4.2 实验拟合出来的batch size幂律曲线
这组实验里,把每个规模下的最优batch size按tokens数统计后,大约符合:
BS_opt_tokens(N) ≈ 1e6 * (N / 1e9) ^ 0.66注意这里使用了“一个训练step消耗的总token数”,而不是样本个数,因为不同sequence length会直接影响同一批样本的有效信息量。按这个公式,1B模型的最优batch size在100万token左右,7B模型大约在350万到400万token,13B模型约600万token,30B模型则接近900万到1000万token。
| 模型参数量 | 建议初始batch size(tokens) | 按seq len=4096折算样本数 |
|---|---|---|
| 0.5B | 约60万 | 约150 |
| 1B | 约100万 | 约256 |
| 3B | 约210万 | 约512 |
| 7B | 约350万 | 约864 |
| 13B | 约550万 | 约1344 |
| 30B | 约940万 | 约2300 |
这个幂指数大约在0.5到0.7之间,也就是说最优batch size随模型规模的增速低于线性。模型翻10倍,最优batch size大约只翻4到5倍。这给训练框架带来的启示是:如果规模扩大10倍,你不需要把batch size也扩大10倍,否则可能过头。
4.3 大batch在小规模模型上的“假收敛”陷阱
做小规模实验时,我经常看到一种情况:把batch size从256样本提到1024样本后,单step loss下降得更快,早期曲线看起来相当漂亮,于是大家以为大batch就是好。但是,如果把横轴从“step”换成“消耗的总token数”,小batch配置往往在同样的数据量下能达到更低的loss。这就是“假收敛”:你看到的是单步收益,而实际付出的是整体数据效率下降。
反过来,大模型上如果batch size远小于最优值,就会出现另一种问题:梯度噪声过大,loss曲线毛刺严重,甚至可能出现周期性尖峰。此时如果只靠加大学习率去压制噪声,又很容易导致前期发散。所以batch size不是你想设多少就设多少,它和模型规模、学习率、数据配比是一个整体的平衡。我见过团队在小规模上用256样本训练很顺利,直接把这个比例放大到7B模型上,结果训练前5000步的loss极不稳定,最后把batch size调大到合理区间才恢复正常。这就是没有利用幂律做外推的代价。
5. 两条幂律线的交叉点:WD会把最优BS往哪个方向推
5.1 我看到的主现象
单独看weight decay和batch size各自形成幂律,这当然是好事,但如果你把这两条线放在同一张图里,会立刻发现它们不是独立的。在复现这组实验时,一个比较明显的现象是:把weight decay从0.01提高到0.1左右,最优batch size的区间会向右移动大约1.5到2倍。换句话说,更强的weight decay会把模型推向“需要更大batch size”的配置,而这个现象在小模型上更明显,大模型上则相对缓和,但依然不可忽视。
这意味着,如果你先单独搜索出一个“最优weight decay”,再单独搜索一个“最优batch size”,组合起来很可能并不是全局最优。这是超参数联合搜索里最常见的坑。我在早期做超参实验时也是先把weight decay固定在一个想当然的值,再去调batch size,结果反复调都调不到预期指标;然后改变策略,做二维联合网格,才在那些看似“次优”的组合里挖出了更好的模型。
5.2 机制拆解:WD通过约束权重范数改变梯度方差
为什么weight decay会改变最优batch size?核心机制在权重范数。weight decay越强,权重范数被压得越小,而模型参数本身的绝对尺度越小,外部引入的梯度波动在相对意义上就越明显。从梯度噪声的角度看,这相当于放大了随机梯度中的“噪声功率”,于是你需要更大的batch size来把这些噪声平均掉。
换个角度看,weight decay相当于在所有参数上施加了一个向原点的弹性力,这个力会修改损失面的有效几何形状。权重范数被压缩后,模型在当前解附近的Hessian结构会发生变化,有些方向变得更容易被噪声激发。大batch和小batch在这个新几何上的表现差异被拉大,因此最优batch size就向高处移动了。
还有一个细节是weight decay与Adam的相互作用。Adam的更新量对梯度幅值做了归一化,但还是会受到权重范数变化的影响。尤其是当模型使用LayerNorm和残差连接时,权重范数的缩放会改变各个残差块的输出幅度,从而间接影响梯度的方差结构。这进一步加深了weight decay和batch size之间的耦合。
5.3 联合缩放建议:不要单独调其中一个
从实操角度看,我给的建议很简单:不要先调weight decay再调batch size,而是把二者放在同一个搜索空间里。先用幂律公式各自算出初值,然后以初值为中心做一个小的联合网格。比如:
- weight decay在估算值的0.5倍到2倍之间取3到4个值;
- batch size在估算值的0.5倍到2倍之间取3到4个值;
- 跑一轮短周期实验,看loss下降率,而不是只看最终loss。
如果你发现某个weight decay下,最优batch size明显偏离幂律给出的初值,不要强行拉回,应该调整联合搜索中心。这个现象本身就是模型结构或数据配比偏离论文假设的信号。
我自己的经验是,比起精确找到“最优组合”,更重要的是画出损失对这两个参数的响应面。响应面越平缓,说明模型对超参越鲁棒,你可以放心选一个对吞吐更友好的配置;响应面越陡峭,说明当前结构与数据对这个参数组合很敏感,你需要把训练预算中的相当一部分留给联合搜索,而不是直接把默认值抄进大规模训练里。
6. 把这些规律转化成可以直接启动预训练的参数模板
6.1 一组从1B到30B的起始模板
用论文给出的幂律趋势,我整理了一套可以直接作为出发点的配置模板。注意这只是“起始点”,不是最终答案,但比直接抄一份其他模型的config要靠谱得多:
| 模型规模 | 初始weight decay | 初始batch tokens | 建议sequence len | 折算样本数(seq=4096) |
|---|---|---|---|---|
| 1B | 0.10 | 100万 | 2048/4096 | 256 |
| 3B | 0.08 | 210万 | 4096 | 512 |
| 7B | 0.05 | 350万 | 4096 | 864 |
| 13B | 0.04 | 550万 | 4096/8192 | 1344 |
| 30B | 0.03 | 940万 | 8192 | 1150(按8192折算) |
如果模型规模不在表里,可以直接用下面的Python函数估算:
def make_starting_point(n_params: int): n_b = n_params / 1e9 wd = 0.1 * (n_b ** -0.32) bs_tokens = int(1e6 * (n_b ** 0.66)) return wd, bs_tokens # 示例:7B模型 wd, bs_tokens = make_starting_point(7_000_000_000) print(f"weight_decay: {wd:.4f}") print(f"batch_size_tokens: {bs_tokens}")一定要记住,这个估算结果可能会因为词表过大、模型过深、数据重复率过高而发生偏移。比如词表特别大的情况下,embedding参数占比升高,weight decay的影响力权重会变化,常见的做法是把embedding和lm head的weight decay单独调低,然后再用上面的值作为其余参数层的参考。
6.2 在固定卡数预算下,如何倒推batch size
实际训练时,batch size不是你“想要多少就有多少”,而是受到吞吐量和总预算的约束。正确的倒推方式是三步走。
先估算单卡有效吞吐。假设你的训练集群里,每张卡对单个序列的处理速度平均是t_tokens_per_sec,总共用K张卡,那么一步能消耗的token上限大约是:
per_step_tokens_max = t_tokens_per_sec * K如果这个上限明显大于幂律给出的最优batch size,说明你有很多富余吞吐,可以选择更谨慎的小batch,或者把多余吞吐用来缩短训练时间。如果上限小于最优batch size,那么你有两个选择:一是拉长训练时间,用梯度累积把全局batch size堆到最优值附近;二是接受一个略小于最优的batch size,并把学习率、warmup相应调整。考虑到训练集群的运行费用,一味追求“最优batch size”可能在时间上不划算,这时候稍微牺牲batch size去换更快的实验周转,是更聪明的做法。
我来给一个具体例子。假设你要在256张卡上训练300B token规模的7B模型,单卡平均有效吞吐为5000 token/s,那么全局吞吐是128万token/s。如果按350万token的batch size,一个step大约需要2.7秒,总步数约为85700步,训练时长约65小时。如果你只有64张卡,全局吞吐降到32万token/s,同样350万的batch size,一个step需要11秒左右,总时长随之拉长到四倍。这种情况下,你不一定非要维持350万token,可以把batch size降到200万token附近,在实现成本和训练效率之间找到一个平衡点。
6.3 落地时最容易忽略的三个校验点
有了起始模板后,直接跑正式训练还是太冒险。我建议在任何正式规模启动前,先在小规模复制实验上确认三个事情。
第一,看loss曲线的形状是否健康。特别是在warmup结束后的2000到5000步内,如果loss下降出现明显的周期性反弹,多半是batch size过小或weight decay过大。此时不要把注意力全放在学习率和warmup上,先回到这两个参数上。第二,看参数范数的变化趋势。用训练日志记录每一层权重的L2范数,如果weight decay过大,你会在很早期就看到范数被压得异常平滑,这种平滑往往以最终的val loss为代价。第三,看小规模外推是否稳定。可以拿0.5B规模先按公式调到合理范围,再外推到1B和3B,如果0.5B上的最优weight decay和batch size明显偏离公式预测,说明当前数据配比或者模型结构与论文假设差异较大,直接按公式开大模型有风险。
这三个校验点都通过后,再把参数套到大规模训练上,命中率会高很多。我自己现在做任何新模型预训练,都会先花半天时间跑这轮校验,而不是盲目地把一份看起来“很接近”的参数表复制进正式训练脚本里。
回过头来再看Power Lines这个题目,我的体会是:预训练调参里最大的坑不是缺一个“最优值表”,而是误以为每个参数都可以被独立地调整。weight decay和batch size就是最能体现这种“非线性耦合”的一对参数,它们各自随模型规模按幂律变化,同时又在互相影响对方的最优点。如果你正在做一个新的预训练任务,别急着把别人的config拿过来改个学习率就开跑,先按这里的幂律骨架算一次起点,再做一轮联合校验,你会发现模型收敛质量和训练预算的使用效率都会有实打实的改善。