SmolLM3 试过 Muon,最后用的还是 AdamW,超参和 Llama 1 那一组几乎一样;第一阶段数学数据只占 3%,因为可用的数学语料只有 54B token,再多就要重复 5 遍以上。网络结构(见架构篇)之外,开训前还有三件事要定:分词器、优化器与训练超参,以及数据配比。分词器决定模型看到的基本单元是什么;架构决定模型怎么学,数据决定它学什么;超参则决定这个学习过程能不能稳定、高效地走完。
分词器:词表大小、BPE、怎么评估
分词器可能是语言模型里最被低估的组件。它把原始文本切成一串离散的单元(token),每个映射成一个整数 id。设计之前先回答三个问题:
- 要支持哪些语言?多语言模型如果配一个只见过英文的分词器,非英文文本会被切成多得多的 token,训练成本、推理速度、效果都受影响。
- 哪些领域重要?数学和代码需要仔细处理数字。
- 目标数据配比是什么?如果自己训分词器,最好在一个接近最终训练配比的样本上训。
词表大小
词表越大,压缩越好(同样的文本 token 更少),但 embedding 矩阵也越大:输入 embedding \(V\times h\)、输出层再一个 \(V\times h\)。对小模型这是不小的参数比例(1B 消融 baseline 里共享后的 embedding 也占两成多),模型越大相对代价越小。经验上:只做英文约 50k 就够;多语言通常要 100k 以上;Llama 3 这类模型用了 128k 以上。同一家族的小模型用 embedding 共享来压低占比,同时享受大词表。
Dagan et al. 从三个角度分析了词表大小:压缩率的收益随词表增大指数下降,所以存在一个最优大小;推理时,大模型更受益于大词表,因为 token 变少省下的前向计算超过了 softmax 多出来的开销;显存方面,最优大小取决于序列长度和 batch——上下文越长、batch 越大,大词表通过减少 token 数省下的 KV cache 越多。还有一个工程细节:把词表大小设成 128 的倍数(比如 50,304 而不是 50,000),GPU 上矩阵维度能被 2 的高次幂整除时内存对齐更好、吞吐更高。
BPE 算法
用现成分词器还是自己训,取决于覆盖:现有分词器在目标词表大小下能不能处理好你的语言和领域。现有分词器里最流行的算法是字节对编码(BPE)(Sennrich et al.);WordPiece、SentencePiece 等也存在但用得少(也有直接在字节或字符上工作、不需要分词器的研究方向)。BPE 的训练过程很简单:
- 把语料切成「词」(预分词,现代分词器用正则把文本切成单词、数字串、标点等块,合并不会跨越块边界),统计每个词的频次;
- 初始词表是所有基本符号(字符,或字节级 BPE 里的 256 个字节,后者保证任何文本都能编码、不会有未知 token);
- 统计所有相邻符号对在语料中的出现次数(按词频加权),把最频繁的一对合并成新符号,加入词表,记下这条合并规则;
- 重复第 3 步,直到词表达到目标大小。
编码新文本时,按学到的合并规则的顺序依次应用。拿 Sennrich 论文里的经典小例子(low、lower、newest、widest,_ 表示词尾)一步一步跑,也可以换成你自己的文本:
按空白分词、每个词末尾加 _;频次相同的符号对按字典序取第一个。橙色的 token 是最近一步合并出来的。右边的「token / 词」就是 fertility。
怎么衡量分词器好坏
不能看几个例子就下结论。常用的是 FineWeb2 里的两个指标:
- Fertility(繁殖率):平均每个词需要多少个 token。越低压缩越好,训练和推理越快。
- 被切开的词的比例(proportion of continued words, PCW):被切成 2 个及以上 token 的词占多少。越低越好。
「词」需要用每种语言合适的分词工具切(spaCy、Stanza,DataTrove 里封装了各语言的 word tokenizer),这样跨语言比较才有意义。只比较单一语言时,也可以用字符数或字节数代替词数(characters-to-tokens、bytes-to-tokens),但它们跨语言有缺陷:UTF-8 里汉字占 3 字节、拉丁字母 1–2 字节;字符数又没考虑不同语言的词长差异(中文的词比德语复合词短得多)。
在 Wikipedia 上每种语言抽 100 篇文章,比较四个分词器,部分结果如下:
| 分词器 | 英语 | 中文 | 法语 | 西班牙语 | 阿拉伯语 |
|---|---|---|---|---|---|
| Llama 3 | 1.48 / 0.32 | 1.60 / 0.43 | 1.73 / 0.48 | 1.72 / 0.46 | 2.35 / 0.72 |
| Gemma 3 | 1.41 / 0.26 | 1.47 / 0.33 | 1.56 / 0.40 | 1.59 / 0.41 | 2.25 / 0.70 |
| Mistral Small | 1.59 / 0.37 | 1.78 / 0.47 | 1.69 / 0.47 | 1.70 / 0.46 | 2.15 / 0.66 |
| Qwen3 | 1.54 / 0.33 | 1.45 / 0.31 | 1.75 / 0.48 | 1.76 / 0.47 | 2.26 / 0.66 |
每格是 fertility / PCW。Gemma 3 在多种语言上都最低,归功于多语言训练数据和很大的词表(262k,约是 Llama 3 128k 的两倍);Qwen3 在中文上最好,但英、法、西语落后于 Llama 3;Mistral Small 阿拉伯语最好,英文和中文较弱。
数字需要专门看。多数现代分词器把数字拆成单个数位,「123」变成「1」「2」「3」(PaLM、DeepSeek-V2)。看起来反直觉,但如果「342792」是一个不可分的 token,模型得记住它和其他每个数字 token 做加减乘的结果;拆开后,模型学的是逐位运算的规则。Llama 3 则是把 1 到 999 编成独立 token、更大的数由它们拼成(实现上是预分词正则把连续数字切成最多 3 位一组)。
用现成的还是自己训
很多新模型从 GPT-4 的分词器出发、补充多语言 token。如果你的语言和领域和上面这些分词器的覆盖吻合,直接用它们——久经考验。SmolLM3 选了 Llama 3 的分词器:在目标语言(英、法、西、葡、德、意)上质量有竞争力,128k 的词表对 3B 模型也不算太大;更大的模型里 embedding 占比小,Gemma 3 的效率优势就更有吸引力。低资源语言或独特的数据配比则可能需要自己训。这有个先有鸡还是先有蛋的问题:做数据消融需要分词器,训分词器又需要知道最终配比。办法是先用一个凑合的分词器做数据消融,正式开训前按确定的配比重训分词器,再确认下游效果提升、fertility 仍然好。
另外两个和分词器有关的提醒:换了分词器,loss 就不能直接比(见评测);50k 的英文分词器干不了严肃的多语言,但如果你不覆盖那么多语言,也不需要 256k 的词表。
AdamW:为什么所有人都还在用它
优化器决定每个参数每一步实际怎么更新,同时它也很吃显存和算力,会影响需要多少卡、训多快。看看近年公开的大模型:除了 Kimi K2、GLM-4.5 用 Muon,几乎所有人都用 AdamW。为什么?一方面 AdamW 长期在各个规模上都好用;另一方面换掉这么核心的组件很吓人,在很长的训练里验证一个新优化器又很贵。
公平比较优化器也比看上去难:规模会改变动力学,小消融难以模拟;每个优化器都需要自己的超参搜索(一维?二维?三维?),不能拿调好的 AdamW 超参直接套。还常见基线没调好、新优化器跟一个弱的 AdamW 比的情况,Marin 团队的 Fantastic Pretraining Optimizers 显示光这一点就会严重夸大报告的收益。
Adam 的更新
Adam 是一阶方法(只用梯度),用历史梯度的动量为每个参数自适应调节步长。对参数 \(\theta\)、第 \(t\) 步梯度 \(g_t\):
$$m_t=\beta_1m_{t-1}+(1-\beta_1)g_t,\qquad v_t=\beta_2v_{t-1}+(1-\beta_2)g_t^2,$$ $$\hat m_t=\frac{m_t}{1-\beta_1^t},\quad \hat v_t=\frac{v_t}{1-\beta_2^t},\qquad \theta_t=\theta_{t-1}-\eta_t\Big(\frac{\hat m_t}{\sqrt{\hat v_t}+\epsilon}+\lambda\,\theta_{t-1}\Big).$$\(m\) 是梯度的指数滑动平均(一阶矩,动量),\(v\) 是梯度平方的滑动平均(二阶矩);除以 \(1-\beta^t\) 是修正初期从 0 开始带来的偏小;\(\hat m/\sqrt{\hat v}\) 让每个坐标的步长大致归一——梯度一直很大的参数步子不会更大。它相当于一个对角的预条件器。每个参数要额外存 \(m, v\) 两个 FP32 状态,即 8 字节。
W:解耦的权重衰减
SGD 里加 L2 正则就是在 loss 上加 \(\frac\lambda2\|\theta\|^2\),梯度多一项 \(\lambda\theta\)。在 Adam 里这么做,这一项也会进入 \(m\) 和 \(v\),被除以 \(\sqrt{\hat v}\):梯度大的参数,正则被削弱;正则强度变得依赖梯度幅度。AdamW 把衰减从自适应部分里拿出来,直接作用在参数上(上式括号里的 \(\lambda\theta_{t-1}\) 不经过 \(m,v\)),每步相当于把参数乘 \(1-\eta_t\lambda\)。
这些年 AdamW 的超参几乎没动过:\(\beta_1=0.9,\ \beta_2=0.95\),梯度裁剪 1.0(全局梯度范数超过 1 就整体缩放到 1),权重衰减 0.1(Llama 3 405B 降到 0.01)。同一组数从 Llama 1、2、3 用到 DeepSeek V1、V2、V3。
Muon:正交化的更新与 Newton–Schulz 迭代
Muon 把每个参数矩阵当作一个整体来更新:
$$G_t=\nabla_\theta\mathcal L_t(\theta_{t-1}),\quad B_t=\mu B_{t-1}+G_t,\quad O_t=\mathrm{NewtonSchulz5}(B_t)\approx UV^\top\ \ (B_t=U\Sigma V^\top),\quad \theta_t=\theta_{t-1}-\eta O_t.$$就是带动量的梯度,然后把它「正交化」:保留奇异向量、把所有奇异值都换成 1。它有三个关键点:
- 矩阵几何而非逐参数:AdamW 对每个参数单独做(对角)预条件;Muon 把权重矩阵当成一个对象,沿 \(UV^\top\) 更新,捕捉的是行、列子空间的结构。
- 正交化带来各向同性的步长:SVD 把 \(G=U\Sigma V^\top\) 分成大小(\(\Sigma\))和方向(\(U,V\))。换成 \(UV^\top\) 就丢掉了奇异值,让步长在活跃子空间里各向同性。乍看是丢了信息,但它减少了偏向少数主方向的倾向,让那些奇异值很小、本来会被压制的方向也得到探索。这种探索会不会给模型带来 loss 看不出的能力差异,还是开放问题。
- 经验上更能容忍大 batch:这可能是采用 Muon 的关键动机(大 batch 为什么重要,见 Batch size)。
为什么是 \(UV^\top\):谱范数下的最速下降
为什么偏偏是 \(UV^\top\)?一个干净的解释(Jeremy Bernstein)是把它看成某种范数下的最速下降。线性化 loss,一步更新 \(\Delta W\) 带来的变化是 \(\langle G,\Delta W\rangle=\operatorname{tr}(G^\top\Delta W)\)。如果限制更新的谱范数(最大奇异值,衡量矩阵对任意输入向量的最大放大倍数)不超过 \(\eta\):
$$\min_{\|\Delta W\|_{\text{op}}\le\eta}\ \operatorname{tr}(G^\top\Delta W)=-\eta\sum_i\sigma_i(G),\qquad \text{取到最小值的是}\ \Delta W=-\eta\,UV^\top.$$(由 von Neumann 迹不等式,\(\operatorname{tr}(G^\top\Delta W)\ge-\sum_i\sigma_i(G)\sigma_i(\Delta W)\ge-\eta\sum_i\sigma_i(G)\),等号在 \(\Delta W\) 与 \(G\) 共享奇异向量、奇异值全为 \(\eta\) 时成立。)对比之下,在逐元素的 \(\ell_\infty\) 约束下最速下降方向是 \(-\eta\,\operatorname{sign}(G)\),这正是不带动量平滑时 Adam 的极限形式。所以 Adam 和 Muon 的区别可以看成「用什么范数衡量一步走多远」。
Newton–Schulz:不做 SVD 的正交化
每步对每个矩阵做 SVD 太慢。Newton–Schulz 迭代只用矩阵乘法逼近 \(UV^\top\)。关键观察:对 \(X=U\Sigma V^\top\),有 \((XX^\top)X=U\Sigma^3V^\top\),所以任何形如
$$X_{k+1}=aX_k+b\,(X_kX_k^\top)X_k+c\,(X_kX_k^\top)^2X_k$$的迭代都不改变奇异向量,只把每个奇异值独立地映射为 \(\varphi(\sigma)=a\sigma+b\sigma^3+c\sigma^5\)。要得到 \(UV^\top\),只需让 \(\varphi\) 反复作用后把 \([0,1]\) 里的每个数都推到 1 附近。先把 \(X_0=G/\|G\|_F\) 归一化,保证所有奇异值 \(\le1\)。经典的三次版本 \(\varphi(\sigma)=\tfrac32\sigma-\tfrac12\sigma^3\) 能精确收敛到 1,但对很小的奇异值,每步只放大 1.5 倍,太慢。Keller Jordan 的做法是把系数调成
$$(a,b,c)=(3.4445,\ -4.7750,\ 2.0315),$$让 \(\varphi'(0)=a\) 尽量大(小奇异值增长最快),代价是不再精确收敛到 1,而是在大约 \([0.7,1.3]\) 之间振荡——他发现这个误差不影响训练 loss。5 步就够。实际代码里还在 BF16 下做迭代,矩阵行多于列时先转置(让 \(XX^\top\) 是较小的那个方阵)。拿一个 2×2 矩阵看这个过程最直观:它把单位圆映成椭圆,椭圆的两个半轴就是两个奇异值;正交化就是把椭圆变回圆。
σ₂ 滑块是对数刻度(10 的幂),默认 σ₂ = 0.05、σ₁ = 5,原始条件数 100。左:灰色是单位圆,紫色是 Xk 作用后的形状(先 /‖G‖F 归一化)。右:曲线是 φ(σ),对角线是 y = σ,橙/紫折线是两个奇异值逐步的轨迹(蛛网图)。矩阵真的按上面的公式做了矩阵乘法,不是只算标量。
Muon 只用于隐藏层的二维权重;embedding、输出层以及向量和标量参数(norm 的增益、bias)仍用 AdamW(Keller Jordan 的建议,embedding 和输出头用 AdamW 效果更好)。扩到大模型还需要两个改动,来自 Moonlight(Muon is Scalable):加上权重衰减;以及按矩阵形状缩放更新——形状 \([A,B]\) 的满秩矩阵,正交化后更新的 RMS 理论上是 \(\sqrt{1/\max(A,B)}\),于是乘 \(0.2\sqrt{\max(A,B)}\),让各矩阵更新的 RMS 都接近 0.2,和 AdamW 典型的 0.2–0.4 对齐,这样学习率和权重衰减可以和 AdamW 部分共用:
$$W_t=W_{t-1}-\eta_t\big(0.2\,O_t\sqrt{\max(A,B)}+\lambda W_{t-1}\big).$$优化器的「动物园」还很大:Shampoo、SOAP、PSGD、CASPR、DION、Sophia、Lion,AdamW 自己也有 NAdamW、StableAdamW 等变体。想系统了解,推荐 Marin 的那篇系统比较,它的核心教训是比较时超参调优有多重要。
学习率:预热、cosine、WSD、multi-step
学习率(LR)控制每步按梯度改多少。太低训练慢得痛苦,loss 曲线平平,可能困在差的局部;太高会越过好的解、不收敛,甚至发散。而且最优学习率不是常数:离好解远的早期大学习率好用,接近收敛时就会不稳定。所以要有调度:从 0 预热避免早期混乱,最后衰减让模型落进好的极小值。
预热:多数现代 LLM 用固定的预热步数(比如 2000),与模型大小和训练长度无关(DeepSeek-V2、V3 都是 2000 步)。很短的训练常用总步数的 1–5%;对更长的训练,加长预热一般不影响最终效果。
cosine 的问题
改变学习率能帮助收敛早已是共识(Smith 2018),很长时间里 cosine 衰减(SGDR)是训 LLM 的默认:预热到峰值后按余弦曲线平滑降到最小值:
$$\eta(t)=\eta_{\min}+\tfrac12(\eta_{\max}-\eta_{\min})\Big(1+\cos\frac{\pi(t-W)}{T-W}\Big),\quad W\le t\le T.$$简单好用,缺点是不灵活:必须事先知道总步数 \(T\)。训到一半模型还没到平台、又拿到了更多算力想多训?或者做 scaling law、要在不同 token 数上训同一个模型?cosine 只能从头再来。这种不灵活还曾让早期 scaling law 研究跑偏——Kaplan 等人对不同 token 数的模型用了固定长度的 cosine,低估了数据量的作用;Chinchilla 让调度长度匹配每个模型实际的训练时长,纠正了这一点。
WSD 与 multi-step
很多团队改用不必在预热后立刻开始衰减的调度。Warmup–Stable–Decay(WSD)(MiniCPM):预热后保持恒定的高学习率,最后 10–20% 的 token 迅速衰减。Multi-step(DeepSeek LLM):恒定后分几次台阶式下降。DeepSeek LLM 的具体做法是 2000 步预热到峰值,训完 80% token 时降到峰值的 31.6%,90% 时再降到 10%。
好处:可以中途延长训练而不必重来;可以提前衰减来看清进度;可以在一次主训练里做不同 token 数的 scaling law 实验(从稳定段的不同位置分叉出去衰减)。研究表明 WSD 和 multi-step 都能达到 cosine 的效果(Hägele et al.、DeepSeek LLM)。(GLM-4.5 提到 WSD 在 SimpleQA、MMLU 上不如 cosine,但没给结果。)
新的超参也随之出现:
- WSD 的衰减多长:训练越长,匹配 cosine 所需的衰减比例越小;一般建议 10–20% 的 token。Hägele et al. 还比较了衰减曲线的形状,发现 \((1-\sqrt{\cdot})\) 形状比线性好:\(f(n)=1-\sqrt{(n-(N-N_{\text{decay}}))/N_{\text{decay}}}\)。
- multi-step 的台阶怎么放:DeepSeek LLM 的 80/10/10(稳定到 80%,80–90% 第一级,90–100% 第二级)能匹配 cosine,改成 70/15/15、60/20/20 还能略好。DeepSeek-V2 用了 60/30/10;DeepSeek-V3 更花:恒定段之后从 67% 到 97% 用 cosine 衰减,然后短暂恒定,最后一次陡降。V2、V3 的报告没有给出这些改动的消融。实践上,先用简单的 WSD 或 multi-step,再通过消融调参数。
横轴是原计划总步数的百分比。「中途延长」把计划从 100% 延长到更多:WSD 和 multi-step 只需把衰减段往后挪,已训的部分(实线)完全可以复用;cosine 和线性衰减的已训部分与新计划下的曲线(虚线)对不上。Multi-step 的两级固定为峰值的 31.6% 和 10%(DeepSeek LLM 的数值),最小 LR 滑块对它无效。
消融:WSD 能追上 cosine
在 1B 模型上比较 cosine 和两种 WSD(衰减 10%、20%)。最终表现相近。过程很有意思:稳定段里 cosine 的 loss 和评测(尤其 HellaSwag)都更好,因为它的学习率已经在降了;WSD 一进入衰减段,loss 和下游指标几乎线性地改善,最后追平。所以 10–20% 的衰减足以匹配 cosine,同时保留中途延长的灵活性;SmolLM3 用了 10% 衰减的 WSD。一个比较时的坑:拿稳定段的 WSD checkpoint 和 cosine 比,要先对 WSD checkpoint 做一次衰减,否则不公平。
学习率扫描
最优学习率依赖训练时长:短消融里收敛最快的,未必是长训练的最优。先用简单扫描排除明显太高或太低的值。在 1B、45B token 上试 1e-4、5e-4、5e-3、5e-2:5e-2 几乎立刻发散,loss 尖峰后再也回不来;1e-4 太保守,稳定但收敛慢得多;5e-4 和 5e-3 收敛更好、表现相近。SmolLM3 在 3B、100B token、AdamW + WSD 上比较了几个值:2e-4 比 1e-4 收敛快得多(loss 和下游都是),3e-4 只比 2e-4 好一点,却增加了长训练不稳定的风险,于是选了 2e-4。
Batch size 与临界 batch
Batch size 是每次更新前处理的样本(LLM 里通常按 token 计)数。硬件和训练栈能很好地横向扩展时,加大 batch 能提高吞吐(每秒处理的 token 数)。但超过某个点,大 batch 开始损害数据效率:达到同样的 loss 需要更多的 token。这个转折点叫临界 batch size(McCandlish et al.):
- 低于临界值时加大 batch(并重新调学习率):用同样多的 token 达到同样的 loss,不浪费数据;
- 高于临界值时加大 batch:墙钟时间可能还在下降(更多卡在干活),但需要更多 token(更多钱)才能达到同样的 loss。
为什么要随 batch 调学习率
设单个样本的梯度 \(\tilde g^{(i)}\) 的均值是真梯度 \(g\)、协方差是 \(\Sigma\)。对 \(B\) 个样本取平均:
$$\tilde g_B=\frac1B\sum_{i=1}^B\tilde g^{(i)},\qquad \mathbb E[\tilde g_B]=g,\qquad \operatorname{Cov}(\tilde g_B)=\frac{\Sigma}{B}.$$SGD 更新 \(\Delta w=-\eta\tilde g_B\) 的方差 \(\propto\eta^2\Sigma/B\)。batch 变成 \(k\) 倍时,要保持更新的噪声大致不变,学习率乘 \(\sqrt k\):
$$B\to kB\quad\Rightarrow\quad \eta\to\sqrt k\,\eta.$$这条平方根缩放对 AdamW、Muon 是个有用的经验法则,但具体怎么缩放依赖优化器,AdamW 里还和 \(\beta_1,\beta_2\) 有交互。作为对照,SGD 文献里更常见的是线性缩放规则,出发点是保持「每个样本对参数的平均推动」不变,而不是保持噪声不变。两者都只是近似。
临界 batch 从哪来:梯度噪声尺度
McCandlish et al. 用一个简单的统计量预测临界 batch,叫梯度噪声尺度。在 Hessian 近似为单位阵倍数的简化下:
$$\mathcal B_{\text{simple}}=\frac{\operatorname{tr}(\Sigma)}{|G|^2},\qquad \frac{\mathbb E\big[|G_{\text{est}}-G|^2\big]}{|G|^2}=\frac{\mathcal B_{\text{simple}}}{B}.$$它就是「单样本梯度的总方差」与「真梯度的平方范数」之比:\(B\) 比它小时,batch 梯度的噪声比信号还大,加大 batch 收益接近线性;比它大时,梯度已经很准,再加 batch 几乎白费。论文推出训练步数 \(S\) 与消耗样本数 \(E\) 之间的权衡:
$$\Big(\frac{S}{S_{\min}}-1\Big)\Big(\frac{E}{E_{\min}}-1\Big)=1,\qquad S=S_{\min}\Big(1+\frac{\mathcal B}{B}\Big),\quad E=E_{\min}\Big(1+\frac{B}{\mathcal B}\Big),$$临界 batch \(\mathcal B_{\text{crit}}=E_{\min}/S_{\min}\)。在 \(B=\mathcal B_{\text{crit}}\) 处,步数和数据量都是各自最小值的 2 倍。训练早期 \(|G|^2\) 大,噪声尺度小,临界 batch 小;之后模型更新趋稳,临界 batch 变大(论文说常常在训练中增长一个数量级以上)。这解释了batch size 预热:DeepSeek-V3 前约 469B token 用 12.6M 的 batch,之后加到 62.9M。MiniMax-01 把 loss 当作临界 batch 的代理,最后阶段用到 128M 的 batch;他们没有相应提高学习率,所以这个 batch 调度起到了类似学习率衰减的作用。
Merrill et al. 2025 提了一个更实用的检验:从当前训练分出一个短分支,一支保持原 batch,一支用更大的 batch 和重新缩放的学习率(切换时预热学习率、重置优化器状态),在一个窗口内比较两条 loss 曲线是否吻合(容差和窗口都凭经验定),吻合才采用大 batch。他们的结果表明 \(\mathcal B_{\text{simple}}\) 这个估计(本身也有噪声)低估了实际的临界 batch。
超参的 scaling law
最优学习率和 batch size 不只取决于结构和大小,还取决于算力预算 \(C\approx6ND\)(\(N\) 参数、\(D\) token;每参数每 token 约 6 FLOPs)。DeepSeek LLM 和 Qwen2.5 都演示了怎么为超参拟合 scaling law。DeepSeek LLM 的流程:
- 选好调度(最好是 WSD 或 multi-step,这样同一个 run 可以延长到不同 token 数,不用重来);
- 在一系列算力预算(1e17 到 2e19 FLOPs)上,扫学习率和 batch size;
- 把泛化误差不超过最小值 0.25% 的配置都算作「近似最优」,每个给出一个数据点 \((C,\eta)\) 或 \((C,B)\);
- 在 log–log 坐标下拟合幂律。
他们得到的是
$$\eta_{\text{opt}}=0.3118\cdot C^{-0.125},\qquad B_{\text{opt}}=0.2920\cdot C^{0.3271}\ \ (\text{token}).$$直觉:训练越大越长,越需要稳的更新(更小的学习率)和更准的梯度估计(更大的 batch)。另一个重要发现:在固定的模型大小和预算下,表现在很宽的超参范围内都很稳定,最优点是一片宽的区域,所以只需要「足够接近」。但要记住:scaling law 给的是起点,目标不是「每个梯度最优的样本数」,而是「在时间和卡数约束下能达到的最低 loss」。实践中常可以把 batch 开到比预测更大,换取明显更高的吞吐,只要不超过临界 batch。
上半:McCandlish 的模型 S = Smin(1 + 𝓑/B)、E = Emin(1 + B/𝓑)。下半:默认是 SmolLM3(3.08B、11T)。注意 DeepSeek 的 C 用的是「非 embedding FLOPs/token × token 数」,这里用 6ND 近似;公式是在他们的数据和设置上拟合的,迁移到别处只能当起点。代入 7B、2T 会得到约 4.2e-4 和 9.2M token,和 DeepSeek LLM 7B 实际用的 4.2e-4、9.4M 吻合;代入 SmolLM3 得到约 3.8e-4、12M,而 SmolLM3 实际用了 2e-4 和 2.36M。
μP:调超参还有另一条路。μP(Maximal Update Parametrization)通过按宽度缩放初始化方差和每层学习率,让最优超参在模型变宽时基本不变,于是可以在小模型上调好直接迁移到大模型,和上面「拟合超参随 C 的幂律」是两种思路。Cohere 的 Command A 用了 μP;怎么把它用到 MoE 上,目前还是开放问题。
SmolLM3 的选择与守则
优化器:在 1B、100B token 上比较了 AdamW、AdEMAMix 和 Muon。调好的 Muon 能胜过 AdamW,但对学习率敏感、容易发散;AdEMAMix 的 loss 和 Muon 相近,敏感度更低;AdamW 最稳,但最终 loss 高于调好的两个。扩到 3B 后,Muon 和 AdEMAMix 发散更频繁。原因可能是后来才发现的一个并行 bug,但这一点没有再验证。最终选了非常「香草」的设置:AdamW(\(\beta_1=0.9,\beta_2=0.95\)),权重衰减 0.1,梯度裁剪 1。
调度:WSD。SmolLM2 就用过它,HF 团队认为这是他们做过的最好的决定之一:易用,训练总长可以灵活调整,还能做中途的衰减实验。学习率扫描后定为 2e-4。全局 batch 试了 2M 到 4M token,对 loss 和下游影响很小,于是选了吞吐最好的 2.36M token。
优化器和超参上的经验可以概括为:平衡探索与执行,完成胜过完美。
- 合理分配时间。花几周打磨一个新方法的小改进,不如把同样的算力投到更好的数据或更彻底的结构消融上。也许会让结构爱好者失望,但最大的提升通常来自数据。
- 拿不准时选灵活和稳定。两种方法效果相当,选更灵活、实现更成熟稳定的那个:能延长训练、能做中途实验的 WSD,比一个收敛也许略好但僵硬的调度更有价值。
- 知道什么时候停止优化、开始训练。总还有一个超参可以调、一个优化器可以试。给探索定截止日期并遵守它——真正训完的模型永远胜过从未开训的完美模型。
数据配比:为什么它最重要
设想:架构打磨了几周、超参调好了、基础设施最稳,模型漂亮地收敛了,然后它写不出连贯的代码,基础数学吃力,说着说着还换了语言。问题通常出在数据上。架构决定模型怎么学,数据决定它学什么,再多的算力和优化器调参也弥补不了学错了内容。得到对的训练数据不只是有好的数据集,还要组好配比(mixture):在冲突的目标间平衡(比如强英文 vs 多语言),调整各部分比例以对齐性能目标。要回答的是:想让模型擅长什么?每个领域用哪些数据集、怎么混?对目标训练规模,有没有足够的高质量数据?
配比反直觉的地方
网页这种充足的数据源覆盖不了全部所需的知识和能力,所以近期模型还依赖数学、代码等专门领域的预训练数据。直觉的做法是:找出目标能力、为每个领域收集高质量数据、混起来。现实更复杂,因为各领域在争夺同一份训练预算:为了代码能力把代码数据调高,就隐含地把其他所有来源调低了,可能损害别的能力。
每个来源里还常有一个「高质量」子集特别有用。为什么不只用高质量数据?因为对 SmolLM3 这样 11T token 的训练预算,极端过滤意味着把数据重复很多遍。Muennighoff et al. 研究了数据受限下的 scaling:在固定算力下,重复最多 4 个 epoch 与使用全新数据相比 loss 几乎没有差别;再多重复,增加算力的价值逐渐衰减到零。所以理想情况是同时用好高质量和较低质量的数据。下面的计算器可以按配比算每个来源要过几遍(会把超过 4 个 epoch 的标出来)。
模型在任何任务上的表现很大程度上取决于它见过多少相关数据,所以调配比是平衡各领域能力最直接的手段。这些权衡依赖于模型、难以预测,消融不可或缺。
多阶段训练(课程)
配比不必全程不变。早期的 GPT-3 和早期 Llama 全程用一个静态配比;现在的趋势是多阶段(SmolLM2 就是),配比随训练变化。动机是模型最终的行为强烈受训练末尾数据的影响(Chen et al.)。于是策略是:早期多用量大的来源,末尾混入量小但质量高的来源。什么时候换?没有通用规则,但有两条原则:
- 由表现驱动:盯住关键基准,针对能力瓶颈调整配比。比如别的能力都在涨、数学平了,就是引入更高质量数学数据的信号。
- 把高质量数据留到后期:小而精的数学、代码数据在退火阶段(最后的学习率衰减阶段)引入,效果最大。
这里和学习率调度连上了:WSD 的衰减段就是天然的「退火阶段」,高质量数据放在这里,既符合「末尾数据影响最大」,又利用了衰减段 loss 快速下降的特性。
怎么做数据消融
和结构消融的一个关键区别:数据消融尽量在目标规模上做。小模型和大模型容量不同:很小的模型可能吃不下很多种语言,大模型却能吸收而不牺牲别的能力。在太小的规模上做数据消融,可能得出错误的配比结论。SmolLM3 的主要数据消融直接用 3B 模型、50B 和 100B token 的短训练(从头训)。
另一种设置是退火实验(annealing ablation):不从头训,而是从主训练的一个中间 checkpoint(比如 7T token 处)出发,换一个数据组成继续训并把学习率衰减到 0。SmolLM2、Llama 3、OLMo 2 都用过。它测试的是多阶段训练里后期配比的改动。SmolLM3 的具体做法:在约 7T token(stage 1 后期)的 checkpoint 上跑 50B token 的退火,配比是 40% 原 stage 1 配比 + 60% 待测数据集。比如测 MegaMath 是否提升数学,就用 40% stage 1 数据(保持 75/12/10/3 的领域比例)+ 60% MegaMath。评测上也扩展了基准,加入多语言任务,以便权衡不同语言比例。
自动找配比的方法:DoReMi 用一个小代理模型学习各领域的权重,以最小化验证 loss;RHO-LOSS 按 holdout loss 挑单个训练样本,优先选「可学、值得学、还没学会」的;RegMix 把配比当回归问题,用正则化回归在多个评测目标和数据域之间平衡。HF 在以前的项目里试过 DoReMi 和 RHO-LOSS,发现它们倾向于收敛到大致等于各数据集自然大小比例的分布——基本是在说「哪个多就多用哪个」,没有胜过仔细的手动消融。近期的 SOTA 模型仍靠系统消融和退火实验手动调配比,SmolLM3 也是。
SmolLM3 的数据配比
目标:英文和多语言都能处理,数学和代码要强。方法对低资源语言或金融、医疗等特定领域同样适用:找候选数据集、做消融、设计平衡所有目标领域的配比。高质量数据集本身怎么造,FineWeb、FineWeb2、Stack-Edu 和 FineMath 的报告里有详细记录;配比要做的是把这些现有数据集组合起来。起点是 SmolLM2 在 1.7B 上已经验证过的英文网页配方,以及当时能拿到的最好的数学和代码数据。
- 英文网页:FineWeb-Edu 和 DCLM 是当时最强的开放英文网页数据,合计 5.1T token。FineWeb-Edu 帮教育和 STEM 类基准,DCLM 帮常识推理。在 3B、100B token 上扫了 20/80、40/60、50/50、60/40、80/20,60/40 或 50/50 最平衡(和 SmolLM2 的发现一致),stage 1 用 50/50。另加了 pes2o、Wikipedia & Wikibooks、StackExchange,对表现没影响,为了多样性。
- 多语言网页:主攻法、西、德、意、葡五种语言,取自 FineWeb2-HQ,共 628B token;另有中文、阿拉伯语、俄语等 10 种语言以小比例加入,不是为了 SOTA,而是方便别人在这些语言上继续预训练(FineWeb2-HQ 不支持的语言用 FineWeb2)。关键问题是非英文占多少:在 3B 上消融发现 12% 多语言(约占网页部分的 14%)最平衡,多语言提升、英文不掉。只有 628B 非英文对 5.1T 英文,再高就得更多重复多语言数据。
- 代码:stage 1 来自 StarCoder2 / The Stack v2 语料:The Stack v2(16 种语言,按 StarCoder2Data 过滤)、GitHub pull request(真实的代码评审推理)、Jupyter 和 Kaggle notebook(可执行的分步工作流)、GitHub issue 和 StackExchange 讨论。Aryabumi et al. 发现代码能提升代码之外的能力(自然语言推理、世界知识),建议 25% 代码。SmolLM3 从 25% 开始消融,英文基准(HellaSwag、ARC-C、MMLU)明显下降;降到 10% 后,相比 0% 代码英文基准没有提升,但因为代码生成本身很重要,还是保留了。教育过滤的 Stack-Edu 推迟到后期阶段加入(高质量数据留到后期)。
- 数学:早期用较大、较通用的 FineMath3+ 和 InfiWebMath3+;后期上采样 FineMath4+、InfiWebMath4+,并引入 MegaMath 和 OpenMathInstruct、OpenMathReasoning 等指令与推理数据。stage 1 只用 3% 数学(两者各半):可用的只有 54B token,而 stage 1 规划为 8T–9T token(最终训了 8T),再多就要超过 5 个 epoch。
合起来,stage 1 的领域比例是英文网页 / 多语言 / 代码 / 数学 = 75 / 12 / 10 / 3。后续阶段再上采样 Stack-Edu、FineMath4+ 这类高质量的代码和数学数据。
| 来源 | 可用(B token) | 权重 % | 分到(B) | epoch |
|---|
默认是 SmolLM3 stage 1 的领域比例和 8T 的总量;英文网页 5.1T、多语言 628B、数学 54B 是各来源的实际可用量,代码的可用量为示意值。超过 4 个 epoch 的行标为橙色(Muennighoff et al. 的经验界)。可以改任意数字,或加一个来源。
按默认数字算:数学 3% × 8T = 240B,对 54B 约 4.4 个 epoch;如果 stage 1 训到 9T,就正好 5 遍,所以数学的比例不能再高了。英文网页约 1.2 遍,多语言约 1.5 遍。
参考与延伸阅读
- The Smol Training Playbook:主要来源,对应 Designing the Model Architecture → The Tokenizer;Optimizer and Training Hyperparameters(Optimizers: AdamW and Beyond、Learning Rate、Batch Size、Scaling Laws for Hyperparameters、SmolLM3、Rules of Engagement);The Art of Data Curation 全章。各组消融的完整曲线推荐直接去读原书。
- 分词器:Sennrich et al.(BPE);Dagan et al.;FineWeb2(fertility、PCW)。
- 优化器:Adam;AdamW(Decoupled Weight Decay);Keller Jordan, Muon(Newton–Schulz 系数、基线 (2, −1.5, 0.5)、[0.7, 1.3] 的目标区间、embedding/输出层用 AdamW);Jeremy Bernstein, Deriving Muon;Liu et al., Muon is Scalable for LLM Training(更新 RMS 匹配 0.2√max(A,B));Wen et al., Fantastic Pretraining Optimizers。
- 学习率:SGDR;MiniCPM(WSD);Hägele et al.(1−sqrt 冷却);DeepSeek LLM(multi-step 80/10/10、31.6%/10%、超参 scaling law 0.3118·C−0.125 与 0.2920·C0.3271、0.25% 近似最优)。
- Batch size:McCandlish et al.(𝓑simple、S/E 权衡);Merrill et al.;DeepSeek-V3。
- 数据:Muennighoff et al.(4 个 epoch);Chen et al.;DoReMi;RHO-LOSS;RegMix;Aryabumi et al.;SmolLM2(Stack-Edu、FineMath)。