训练一个大模型之前,要做的决定比想象中多得多:该不该训?训多大?用什么结构、什么数据?每个选择又怎么知道是对的?Hugging Face 训 SmolLM3(3B 参数、11T token 的多语言推理模型)时,消融和调试花掉的 GPU 小时超过了正式训练的一半。这些算力花在一件事上:先想清楚为什么要训,把目标翻译成具体的选项,再用小规模实验(消融)一个一个地验证。
这听起来像管理学,但每一步背后都有可以算的东西:参数量怎么对齐、评测分数的噪声有多大、一轮消融要烧多少 GPU 小时、给定算力该训多大的模型。
训练罗盘:Why → What → How
机器学习这个领域对「优化」有一种执念:盯着 loss 曲线、网络结构、吞吐。但在这些之前,还有一个更早的问题:这个模型到底该不该训?开源社区几乎每天都有新的强模型发布(Qwen、Gemma、DeepSeek、Kimi、OLMo……),大多带宽松的许可证。很多失败的训练项目不是死在超参或 bug 上,而是死在「训了一个世界并不需要的模型」上。
所以不妨把整件事组织成一个三段的「罗盘」:
这三段是有方向的:Why 的答案决定 What 的取值范围,What 的选择又决定 How 的难度。比如「要在手机上跑」(Why)直接把模型大小卡在几 B 以内、把 MoE 排除在外(What),进而决定你用一台 8 卡机器就能做大部分消融(How)。这些是战略层面的问题,不涉及技术细节,却决定了后面所有技术工作的方向。
Why:先问该不该训
四个不算理由的理由
先看一个太常见的场景:某个团队拿到了一批 GPU,「我们有 100 张 H100 三个月,训个模型吧!」模型大小随手一拍,数据有啥用啥;半年后算力和士气都烧光了,模型没人用,因为从没有人问过为什么。下面四个常听到的理由,其实都不成立:
| 说法 | 为什么不成立 |
|---|---|
| 「我们有算力」 | 算力是资源,不是目标 |
| 「别人都在训」 | 这是同辈压力,不是策略 |
| 「AI 是未来」 | 这是口号,不是计划 |
| 「我们想要最好的模型」 | 太泛,不能指导任何具体决策 |
决策流程:能用现成的,就别从头训
技术上,判断的顺序很简单:先看现有模型靠 prompt 能不能解决;不行再看微调(后训练或继续预训练)能不能解决;都不行,才考虑从头预训练。
一个很实用的检验:先花几天时间在 Qwen3、Gemma 3 这类当前最强的开源模型上搭一下,看 prompt、工具调用、后训练能不能达到你的指标。达不到,才说明可能需要自己训。还有一个经济账:即使需要的后训练规模非常大,也往往比从头训便宜——在已有模型上继续训 1T token,比从零训 10T+ token 省得多。(规模大到这一步,人们一般就不叫它后训练,而改叫「mid-training」了。)
三类站得住的理由
研究。研究项目的共同点是一开始就有一个定义清楚的问题。几个例子,每个都对应一篇真实的论文:新优化器能不能扩到 10B 以上(Muon is Scalable for LLM Training);只用强化学习、不做 SFT 能不能得到推理能力(DeepSeek-R1);只用合成的「教科书」数据能不能训出好的小模型(Textbooks Are All You Need);只用开放许可的数据能不能有竞争力(The Common Pile v0.1)。假设越具体、对所需实验规模想得越清楚,成功概率越高。
生产。公司不能直接用现成模型,通常有三个原因,两个技术的、一个治理的:
- 领域特殊性:数据或任务有现成模型处理不好的词表和结构,比如 DNA 模型(独特的词表、超长程依赖)、法律或金融模型(大量专业术语和逻辑)。
- 部署约束:模型要适配特定的硬件、延迟或隐私要求,比如跑在无人机上,或跑在带 FPGA 之类定制硬件的私有化系统上。
- 安全与治理:受监管的行业或高风险应用,需要完全掌控训练数据、模型行为和更新周期,要能向监管方证明模型里到底有什么。这种情况下有时没有别的选择。
战略性开源。成熟的实验室发布新开源模型,最常见的原因是发现了生态里的某个空缺:没有强的长上下文端侧模型;多语言模型在低资源语言上很弱;世界模型这类新方向没有好的开源权重。你有理由相信自己能做得更好——更好的数据、更好的配方、或者有算力把模型训得比别人更久(overtrain)。目标要具体:不是「史上最强模型」,而是「最好的端侧 3B 模型」「第一个有 1M 上下文的小模型」。
Hugging Face 自己的例子
Hugging Face 自己的历史就是「发现空缺 → 填上」这个模式:GPT-3 发布后没有开放的替代品,于是有了 BigScience 和 176B 的 BLOOM,几十位贡献者花一年搭训练栈、分词器和语料;OpenAI 的 Codex 闭源,于是和 ServiceNow 一起在 BigCode 下做了 The Stack 数据集和 StarCoder 15B;StarCoder2 则来自一个教训——当初应该训得更久,而且多个训得更久的小模型可能比一个大模型更有用,于是训了 3B/7B/15B 一个系列、数万亿 token。SmolLM 系列同理:强的小模型很少,而他们刚做出了 FineWeb-Edu。SmolLM(135M/360M/1.7B)→ SmolLM2(更好的数据、训得更久)→ SmolLM3(扩到 3B,加上混合推理、多语言和长上下文)。
这些例子的共同点:每个项目开始之前,都能用一句话说清楚「现在缺什么、为什么我们能补上」。
What:把目标翻译成决策
想清楚 why 之后,what 是可以推出来的。这里的 what 指:模型类型(dense、MoE、混合结构或别的)、模型大小、结构细节、数据配比。几个例子:
- 要做快的端侧模型 → 小而高效的模型;
- 要做多语言模型 → 大词表的分词器;
- 要超长上下文 → 考虑混合结构。
除了用例驱动的选择,还有一类选择是为了让训练本身更好:更稳定、样本效率更高、更快。这类选择没有那么一目了然。整个决策过程可以分成两阶段:
- 规划(Planning):做实验之前,把每条约束映射到要决定的组件上。部署环境决定模型大小的上限;时间线决定能承担哪些结构风险;目标能力决定数据需求。
- 验证(Validation):有了起点和一张「可能的修改」清单之后,系统地测试。测试很贵,所以只测那些可能对你的用例或训练效率有实质帮助的修改。这一步就是消融。
要学会判断什么值得测,而不只是会测。在无关紧要的选项上做完美的消融,和在重要选项上做粗糙的消融,浪费的算力一样多。
团队:迭代速度与数据
能把模型训好的团队,通常有两个「超能力」。第一是迭代速度:训练 LLM 是边做边学的手艺,训得越频繁,团队越强。一年训一个模型的团队和一季度训一个的团队,后者进步快得多;Qwen、DeepSeek 都有持续快速发布的历史。第二是数据:人们天然倾向于钻研结构来改进模型,但最强的团队是对高质量数据最执着的那些。
和迭代速度挂钩的是团队规模。主预训练任务只需要少数几个人加上足够的算力——今天要训一个 Llama 3 这样的模型,大概两三个人就够;等到要做多模态、多语言、后训练等更多方向时,再为每个方向加几个人。建议是:从一个小而装备齐全的团队开始,每两三个月训一个新模型。
为什么一切从小消融开始
开训之前要做很多决定:用什么结构?什么优化器和学习率调度?混哪些数据?人们常以为这些靠深思熟虑就能定。但 LLM 的很多事情不符合直觉。举个例子:直觉上 arXiv 这种海量科学文本「质量最高」,训上去应该更好;实际上并不会,对小模型甚至有害(DeepSeekMath 观察到了这一点)。原因是 arXiv 论文虽然知识密集,但高度专门化、文体狭窄,和模型最能学到东西的多样通用文本差别很大。
所以办法只有一个:像经验科学家那样做大量实验。今天的机器学习有点像统计力学出现之前的热力学:有可靠的经验定律和设计原则,深层理论还在路上。
这里的消融(ablation)是一个宽泛的说法:固定其他一切,只改一个组件(去掉、替换或调整它),看结果怎么变。对消融实验有两个要求:
- 快:跑得越快,能测的假设越多;
- 可靠:要有足够的区分度。如果看的指标在早期分不清不同设置,消融就说明不了什么;如果指标很嘈杂,我们就是在追逐噪声。
这两个要求互相拉扯:越小越快,但越小越可能不准、不可外推。搭消融的大部分技巧,都是在这两者之间找平衡。
选 baseline 与「去风险」
从一个被验证过的起点出发
每个成功的模型都建立在一个已被验证的基础上,再按需修改:Qwen 第一代从 Llama 的结构出发;Meta 训 Llama 3 从 Llama 2 出发;Kimi K2 从 DeepSeek-V3 的 MoE 结构出发。这不只适用于结构,也适用于超参和优化器。原因是好的结构和训练设置是很多机构多年迭代出来的,失败模式、不稳定性、高效实现都已被人踩过;从零设计意味着自己把所有坑再踩一遍。
一个好的起点应当:
- 符合约束:和部署目标、用例对齐;
- 在规模上被验证过:在相近或更大的规模上跑过数万亿 token;
- 文档完整:有公开的、被证明可用的超参;
- 框架支持好:你打算用的训练框架和推理框架都支持。
截至 2025 年下半年,常见的候选起点如下:
| 类型 | 模型族 | 尺寸 |
|---|---|---|
| Dense | Llama 3.1 / 3.2 | 8B、70B / 1B、3B |
| Dense | Qwen3 | 0.6B、1.7B、4B、14B、32B |
| Dense | Gemma 3 | 12B、27B |
| Dense | SmolLM2、SmolLM3 | 135M、360M、1.7B、3B |
| MoE | Qwen3 MoE、gpt-oss、Moonlight、Kimi K2、DeepSeek-V3 | 30B-A3B … 1T-A32B |
| Hybrid | Zamba2、Falcon-H1 | 0.5B–34B |
| MoE + Hybrid | Qwen3-Next、MiniMax-01、MiMo-V2-Flash | 80B-A3B、456B-A46B、309B-A15B |
「30B-A3B」这种写法表示总参数 30B、每个 token 激活 3B(MoE 的概念在下一篇细讲)。选法:找到你的结构类型,挑一个参数量接近目标的,不必想太多——起点不是一成不变的。
去风险:没测过就不改
拿着 baseline 直接训(只要数据配比好),多半能得到一个不错的模型,很多成功项目就是这么做的。但 baseline 是为别人的约束设计的,所以通常有值得改的地方。问题在于每次结构改动都有风险:可能提升、可能拉垮、也可能毫无作用还白烧了消融算力。管控这种风险的纪律叫 derisking(去风险):没有测试证明它有帮助,就什么都不改。
什么叫「去风险了」?测试表明,这个改动要么提高了目标能力上的表现,要么带来了实际好处(推理更快、显存更少、训练更稳),同时性能损失在可接受范围内。
可改的组件很多:注意力、位置编码、激活函数、优化器、超参、归一化、模型布局……而且组件之间常有非线性的交互。你既没有时间也没有算力去测所有组合。可行的做法是增量式 baseline:
算力允许的话,也可以对每个改动单独测试,再做 leave-one-out 分析(全部改动都加上,每次去掉一个,看去掉哪个损失最大),ScaleRL 论文就是这种方法的一个好范例。不要掉进对每个超参做穷举网格搜索、或测试每个新出的结构变体的陷阱。测任何改动之前先问两个问题:
- 它会帮到我的用例吗?
- 它会优化我的训练吗?
两个都回答不了「是」,就跳过。
选训练框架
第一个具体决定是用什么框架——它同时也是所有消融要用的框架。一条很实在的建议:不要在消融和正式训练之间换框架,那是通往痛苦的路。三个考量:框架要支持目标结构或容易扩展;要稳定、能用于生产、不会训到一半莫名其妙坏掉;吞吐要高。这三者常常互相冲突。
| 框架 | 功能 | 实战检验 | 优化 | 代码行数(核心/总计) | 可扩展与调试 |
|---|---|---|---|---|---|
| Megatron-LM | 很全 | Kimi K2、Nemotron | 3D 并行的开创者 | 93k / 269k | 对新手难 |
| DeepSpeed | 很全 | BLOOM、GLM | ZeRO 与 3D 并行的开创者 | 94k / 194k | 对新手难 |
| TorchTitan | 在快速增加 | 较新,PyTorch 团队测过 | dense 优化好,MoE 在改进 | 7k / 9k | 中等:需要懂并行 |
| Nanotron | 精简,为 HF 预训练定制 | StarCoder、SmolLM | 为 HF 的规模优化过 | 15k / 66k | 中等:需要懂并行 |
前三个框架的行数来自 TorchTitan 技术报告。HF 自己从零写了 Nanotron,这让他们彻底理解了大规模预训练(后来整理成了 The Ultra-Scale Playbook),但代价是大量的人力投入。另一条路是 fork 一个现成框架再改,比如 Thinking Machines Lab 的内部预训练库就是 TorchTitan 的 fork。最终取决于团队经验、目标功能和愿意投入多少开发时间。多个框架都满足需求时,在你自己的硬件上比较吞吐;做快速实验时,代码简单的往往胜出。
消融怎么搭:缩小规模、对齐参数量
两种缩小方式
消融的目标是:在小规模上跑实验,得到能放心外推到正式训练的结论。缩小有两种方式:
- 目标尺寸、更少 token:SmolLM3 的一部分消融直接用 3B 模型训 100B token,而不是正式的 11T。
- 更小的代理模型(proxy):目标太大时用小模型代替。比如 Kimi 开发 1T 总参、32B 激活的 K2 时,部分消融用的是 3B 总参、0.5B 激活的 MoE。
关键问题是小规模的结论能不能迁移。经验是不对称的:小规模上有害的东西,基本可以放心地在大规模上排除;小规模上有效的东西,则要确保训了足够多的 token,才能以较高把握认为它会外推。训得越久、消融模型越接近最终模型,结论越可靠。
HF 的 1B 消融配置
他们的主力消融设置是一个照搬 Llama 3.2 1B 结构的 vanilla Transformer,训 45B token,在一台 8×H100 上用 Nanotron 大约一天半(每卡每秒约 42k token)。这个尺寸的 Chinchilla 最优训练量大约是 35B token,多训一些是为了让信号更稳定。时间可以这样估算:
$$t = \frac{45\times10^{9}\ \text{tokens}}{42\times10^{3}\ \text{tokens/s/GPU}\times 8\ \text{GPU}} \approx 1.34\times10^{5}\ \text{s}\approx 1.55\ \text{天}.$$对应的 Nanotron 配置,关键字段如下:
data_stages: # 数据:三个源及权重
dataset_folder: [fineweb-edu, stack-edu-python, finemath-3plus]
dataset_weights: [0.7, 0.2, 0.1]
model_config: # 结构:Llama 3.2 1B
hidden_size: 2048
num_hidden_layers: 16
num_attention_heads: 32
num_key_value_heads: 8
intermediate_size: 8192
max_position_embeddings: 4096
rope_theta: 50000.0
tie_word_embeddings: true
optimizer: # AdamW + 预热 + cosine
clip_grad: 1.0
learning_rate: 0.0005
lr_warmup_steps: 2000 # 线性预热
lr_decay_starting_step: 2000
lr_decay_steps: 28000 # cosine 衰减到 min_decay_lr
min_decay_lr: 5.0e-05
weight_decay: 0.1
adam_beta1: 0.9
adam_beta2: 0.95
adam_eps: 1.0e-08
parallelism: {dp: 8, tp: 1, pp: 1} # 1B 只需数据并行
tokens:
sequence_length: 4096
micro_batch_size: 3
batch_accumulation_per_replica: 16
train_steps: 30000
全局 batch(global batch size, GBS)由数据并行度、梯度累积步数、micro-batch 和序列长度相乘得到:
$$\text{GBS} = \underbrace{8}_{dp}\times\underbrace{16}_{\text{accum}}\times\underbrace{3}_{\text{micro-batch}}\times\underbrace{4096}_{\text{seq}} = 1{,}572{,}864\ \text{tokens}\approx 1.5\text{M}.$$按 1.5M token 一步、30,000 步算,正好是 45B token(精确值约 47B)。学习率调度:前 2000 步线性升到 5e-4,之后 28,000 步按 cosine 衰减到 5e-5。这些超参的含义会在第三篇展开。
做消融时,按要测的东西改对应的段落,其余保持不变:测结构改 model,测优化器和超参改 optimizer,测数据改 data_stages。
一次只改一处。同时改了多个变量、性能变好了,你不会知道是谁的功劳。先逐个测,再把有效的合起来重新评估。
改结构时要对齐参数量
有些结构改动会显著改变参数量:把共享 embedding 改成不共享,embedding 参数翻倍;把多头注意力(MHA)换成分组查询注意力(GQA)或多查询注意力(MQA),注意力参数大幅减少。如果不处理,比较的其实是「改动 + 参数量变化」两个变量。公平的做法是记录参数量,必要时调整层数或宽度,让两边参数量大致相同。
对一个 Llama 式的 dense 模型,参数量可以手算。记隐藏维度 \(h\)、层数 \(L\)、query 头数 \(n_h\)、KV 头数 \(n_{kv}\)、每头维度 \(d=h/n_h\)、MLP 中间维度 \(I\)、词表大小 \(V\):
- 注意力:\(W_Q, W_O\) 各 \(h\times h\);\(W_K, W_V\) 各 \(h\times n_{kv}d\)。合计 \(2h^2 + 2h\,n_{kv}d\)。
- 门控 MLP(SwiGLU):gate、up、down 三个矩阵,合计 \(3hI\)。
- 每层两个 RMSNorm,各 \(h\) 个参数;最后还有一个 \(h\)。
- Embedding:输入 \(Vh\);输出投影(LM head)\(Vh\),共享时只算一次。
代入 baseline(\(h{=}2048\)、\(L{=}16\)、\(n_h{=}32\)、\(n_{kv}{=}8\)、\(d{=}64\)、\(I{=}8192\)、\(V{=}128256\),共享 embedding):每层注意力 \(2\cdot2048^2+2\cdot2048\cdot512 = 10.49\text{M}\),MLP \(3\cdot2048\cdot8192=50.33\text{M}\),16 层约 973M;embedding \(128256\times2048\approx262.7\text{M}\);合计约 1.24B。embedding 占了两成多——这就是为什么小模型几乎都共享 embedding。
实践中也可以直接用 transformers 的 LlamaConfig 实例化一个模型再数参数。下面的计算器按上面的公式算(门控 MLP、标准头维度、每层两个 norm、无 bias):
试试 GQA 消融里的对齐方法:在 1B 预设上把 KV 头数改成 32(MHA),总参数从 1.24B 涨到约 1.34B;再把层数降到 14,就回到约 1.20B。下一篇的 GQA 消融正是这样对齐参数量的(MHA 用 14 层,16 个 KV 头的 GQA 用 15 层)。预设的结构数字来自各模型公开的 config;Qwen 这类带 QKV bias 的模型,实际参数会比公式多一点点。
评测:用什么判断谁赢了
只看 loss 不够
第一反应是看 loss:它应当平滑下降、没有剧烈尖峰。对很多结构改动,loss 和下游表现相关性很好,单看 loss 就够了。但有四种情况 loss 会误导人:
- 数据消融:在 Wikipedia 上训的 loss 比在网页上训的低(下一个 token 更好猜),但这不等于模型更能干。
- 换了分词器:文本切分方式不同,loss 不能直接比(每个 token 的平均信息量都变了)。
- 针对特定能力的改动:比如影响推理或数学的改动,可能在平均 loss 里被冲淡。
- loss 收敛后下游还在涨:预训练 loss 平了以后,下游任务还可能继续提升(Liu et al. 2022)。
所以需要更细的下游评测,覆盖知识、理解、推理以及你关心的其他领域。
好评测任务的四个标准
消融阶段的评测,要挑早期就有信号、不太嘈杂的任务。HF 在 FineTasks 和 FineWeb2 的工作里给出了四条标准,每条都有具体的量化方法:
| 标准 | 含义 | 怎么量化 |
|---|---|---|
| 单调性 | 训得越久分数越高 | 训练步数和分数之间的 Spearman 秩相关,要求所有训练 run 平均 ≥ 0.5 |
| 低噪声 | 同设置不同随机种子,分数不应大幅波动 | 多个种子在每一步的标准差取平均(avg-std);SNR = 30B token 时的平均分 / avg-std,目标 SNR > 20 |
| 高于随机 | 不能长期停在随机水平 | 随机基线 = 各题 1/选项数 之和;看所有模型最高分离基线多远 |
| 排序一致 | 早期的优劣顺序在后期保持 | 相邻两个 checkpoint 之间模型排名的 Kendall τ 的平均(只看 15B token 之后) |
Spearman 秩相关 \(\rho_s\) 只看排名,所以分数非线性增长也能被识别为单调;Kendall τ 数的是「两两顺序一致的对数 − 不一致的对数」占总对数的比例。SNR 这一条最要紧:它直接决定你多大概率选错赢家。
题目怎么问:MCF、CF、FG
任务质量还取决于题目形式(怎么问模型)和打分方式(怎么算分)。三种常见形式:
- 多选格式(MCF):选项明确写在 prompt 里,前缀 A/B/C/D(MMLU 的标准做法),比较模型输出各字母的概率。
- 完形格式(CF):选项不出现在 prompt 里,分别计算每个选项文本接在问题后面的似然,看哪个最大。
- 自由生成(FG):看贪心生成的答案对不对。它要求模型有大量潜在知识,对短的预训练消融通常太难,信号很弱。
所以小消融用 MCF 或 CF。进一步,研究表明模型在训练早期很难做 MCF(OLMES、Du et al.、DataComp-LM),所以 CF 更适合早期信号。HF 的做法:小消融全部用 CF,正式训练里再加入 MCF(训练后期它信号更好)。对后训练模型,FG 才是主要形式。
MCF 为什么早期会停在随机水平?因为它要求模型额外学会一个「格式技能」:把选项内容和字母对应起来,再在字母上输出正确的概率。这个技能来得很晚:OLMES 发现 7B 模型在 MMLU 的 MCF 上要到约 500B token 才明显高于随机,SmolLM2 的 1.7B 模型要到 6T token。Du et al. 认为本质上是预训练 loss 要降到某个阈值以下,这个能力才会出现。
CF 怎么打分:长度归一化
CF 里每个选项是一段文本,log 概率是逐 token 相加的:
$$\log P(a_i\mid q)=\sum_{j=1}^{|a_i|}\log P\big(a_{i,j}\mid q, a_{i,\lt j}\big).$$每多一个 token 就多加一个负数,所以不归一化的话模型会系统性偏好短的答案。FineTasks 比较了几种打分:
$$\text{acc}=\arg\max_i \log P(a_i|q),\qquad \text{acc\_char}=\arg\max_i \frac{\log P(a_i|q)}{\#\text{chars}(a_i)},$$ $$\text{acc\_token}=\arg\max_i \frac{\log P(a_i|q)}{\#\text{tokens}(a_i)},\qquad \text{acc\_pmi}=\arg\max_i \log\frac{P(a_i|q)}{P(a_i|u)},\ u=\text{“Answer:”}.$$PMI 版本衡量「有了问题之后,这个选项变得多可能了多少」,对 MMLU 这类难任务有时是唯一高于随机的指标,但平均最弱、计算量也翻倍。HF 的消融用的是按字符数归一化的版本(acc_char):选「平均每个字符 log 概率最高」的选项。按字符而不按 token 归一化的好处是不依赖分词器——比较不同分词器时这一点很重要。
消融用的评测集
HF 的消融评测集沿用 FineWeb 消融的那组基准,去掉了太嘈杂的 SIQA;加上 GSM8K、HumanEval 测数学和代码,长上下文消融再加 RULER。为了加速,每个基准只评 1000 题(以多一点噪声为代价);GSM8K、HumanEval、RULER 在 3B 消融里全量评,1B 消融里不评。选择题全部用 CF。评测框架是 LightEval。
| 基准 | 领域 | 题型 | 题数 | 测什么 |
|---|---|---|---|---|
| MMLU | 知识 | 多选 | 14k | 57 个学科的学术知识 |
| ARC | 科学与推理 | 多选 | 7k | 小学科学推理 |
| HellaSwag | 常识推理 | 多选 | 10k | 日常情境的叙事续写 |
| WinoGrande | 常识推理 | 二选一 | 1.7k | 需要世界知识的代词消解 |
| CommonSenseQA | 常识推理 | 多选 | 1.1k | 日常概念 |
| OpenBookQA | 科学 | 多选 | 500 | 小学科学事实 + 推理 |
| PIQA | 物理常识 | 二选一 | 1.8k | 日常物体的物理常识 |
| GSM8K | 数学 | 自由生成 | 1.3k | 小学数学应用题 |
| HumanEval | 代码 | 自由生成 | 164 | 根据 docstring 写 Python 函数 |
消融用什么数据?结构消融用一个固定的高质量混合(FineWeb-Edu 英文、FineMath 数学、Stack-Edu-Python 代码),因为结构上的结论应能外推到别的数据(包括多语言),数据保持简单即可。数据消融则反过来:固定结构,系统地改变数据配比。另外,差距很小时,算力允许就换几个种子重跑同一个消融,看结果波动多大。
评测噪声:你选对赢家的概率有多大
设想两个配置 A 和 B,B 在「真实」能力上比 A 高 \(\Delta\) 个百分点。你各训一次、在一个 \(n\) 题的基准上评一次,B 的分数高于 A 吗?不一定。分数里至少有两种噪声:
- 种子噪声:同样的配置换个随机种子(初始化、数据顺序),训出来的模型本身就不同。记标准差 \(\sigma_s\)(单位:准确率百分点)——这就是 FineTasks 里的 avg-std。
- 题目抽样噪声:基准只是题目总体的一个有限样本。单个模型的准确率估计方差是 \(p(1-p)/n\)(二项分布)。
比较两个模型时,题目抽样噪声有一个细节:两个模型做的是同一批题,它们在每道题上的对错是正相关的(难题大家都错)。记逐题对错的相关系数为 \(\rho\),配对差值的方差是
$$\operatorname{Var}\big(\hat p_B-\hat p_A\big)_{\text{题目}}=\frac{p_A(1-p_A)+p_B(1-p_B)-2\rho\sqrt{p_A(1-p_A)p_B(1-p_B)}}{n}\approx\frac{2p(1-p)(1-\rho)}{n}.$$每个配置训 \(k\) 个种子取平均,种子噪声的方差除以 \(k\);但题目抽样噪声不会因为多训种子而下降(题目没变)。如果再把 \(m\) 个互相独立的基准取平均,两项都再除以 \(m\)(这是一个乐观的近似,真实的基准之间并不独立)。合起来,观察到的差值 \(D\) 近似服从
$$D\sim\mathcal N\!\left(\Delta,\ \sigma_D^2\right),\qquad \sigma_D^2=\frac{1}{m}\left(\frac{2\sigma_s^2}{k}+\frac{2p(1-p)(1-\rho)}{n}\right),$$选对赢家的概率就是 \(P(D>0)=\Phi(\Delta/\sigma_D)\),其中 \(\Phi\) 是标准正态的累积分布函数。如果想要 95% 的把握(单侧),需要 \(\Delta \ge 1.645\,\sigma_D\)。
默认参数为示意。直方图是蒙特卡洛:每次独立抽种子噪声和(相关的)题目噪声,橙色部分是「选错了」的实验。
拖一拖就能看出几件事:
- 只评 1000 题、\(p\approx0.55\)、\(\rho=0.5\) 时,题目噪声一项的标准差约 \(\sqrt{2\cdot0.2475\cdot0.5/1000}\approx1.6\) 个点。真实差距 1 个点时,就算种子噪声为零,选对的概率也只有七成多。「每个基准只评 1000 题」付出的噪声代价就在这里。
- 题目噪声和种子噪声的地位不同:多训种子降不了题目噪声,多加题目降不了种子噪声。看「方差比」读数判断哪个是瓶颈,再决定钱花在哪。
- 把多个基准平均(比如同时看六个基准)是最便宜的降噪方式,但前提是它们的误差不完全相关、而且改动在多个基准上方向一致。
这也解释了 FineTasks 为什么要求 SNR > 20:如果某任务在 30B token 时平均分 50、avg-std 2.5,SNR 就是 20;这时 1 个点的差距相对于种子噪声只是 0.4σ,单次比较几乎是抛硬币。
扎实的消融还有另一层价值:正式训练出问题时(一定会出问题),你需要对每个决定都有把握,并能迅速找到哪些组件没测过。扎实的消融能节省调试时间。
消融的成本
消融很香,但要花 GPU 时间。SmolLM3 预训练阶段的完整算力账如下:
| 阶段 | GPU | 天数 | GPU 小时 |
|---|---|---|---|
| 正式预训练 | 384 | 30 | 276,480 |
| 预训练消融 | 192 | 15 | 69,120 |
| 中训练消融 | 192 | 10 | 46,080 |
| 重启 / 调试 | 384 / 192 | 3 / 4 | 46,080 |
| 合计 | 437,760 |
每行都可以验算:\(384\times30\times24=276{,}480\);\(192\times15\times24=69{,}120\);\(384\times3\times24+192\times4\times24=27{,}648+18{,}432=46{,}080\)。
关键数字:消融加调试共 161,280 GPU 小时,超过正式训练的一半(276,480)。整个开发过程跑了 100 多个消融:20 天预训练消融、10 天中训练消融、7 天从一个意外的训练问题中恢复。评测另算,略低于 1 万 GPU 小时:完整评测套件(英文、多语言、数学和代码)每个 checkpoint 约 1.5 GPU 小时,11T token 里每 10B token 评一次,加上大量消融;长上下文评测尤其贵,每次约 8 卡 1 小时。
这也提醒我们怎么读别人公布的训练成本:DeepSeek-V3 发布时全世界盯着它报告的 560 万美元训练成本,很多人把它当成了全部研发成本。实际上那只是最后一次训练;消融、失败的 run、调试这些看不见的研究成本要大得多。
所以预算要按「正式训练 + 消融 + 意外缓冲」来做。如果你追求 SOTA、要实现新结构、或者手上没有现成的配方,消融会是一个大的成本中心,而不是零头。下面这个计算器用标准的 \(6ND\) 估算(每个参数每个 token 约 6 次浮点运算:前向 2 次、反向 4 次,忽略注意力的额外开销):
$$\text{GPU 秒}=\frac{6ND}{\text{峰值 FLOP/s}\times\text{MFU}},\qquad \text{每卡吞吐}=\frac{\text{峰值}\times\text{MFU}}{6N}\ \text{tokens/s}.$$MFU(model FLOPs utilization)是实际有效计算占硬件峰值的比例,SmolLM3 的正式训练约 30%。
正式训练:,,
3B 预设的 GPU 数为示意。只算 6ND,不含注意力 FLOPs、评测、故障停机和重启,所以是下限。1B 预设推算出每卡约 4 万 token/s、单次约 1.6 天,和实测的 42k token/s、一天半吻合;正式训练按 30% MFU、989 TFLOP/s 推算约 19 万 GPU·h,实际记账是 27.6 万(含停机和余量)。
Scaling law:多大的模型,训多少 token
「What」里最核心的是两个数:参数量 \(N\) 和训练 token 数 \(D\)。给定算力,钱该花在更大的模型上,还是更多的数据上?
从 Kaplan 到 Chinchilla
深度学习早期,训练并不太受算力约束:挑硬件能装下的最大模型和 batch,训到过拟合或数据用完为止。即便如此,人们已感觉到规模有用,比如 Hestness et al. 2017 就系统地展示了更大的模型训更久能带来可预测的收益。
LLM 时代我们总是受算力约束。Kaplan et al. 2020 证明语言模型的表现在多个数量级上都高度可预测,于是规模竞赛开始了。算力受限时最重要的问题是:钱花在更大的模型上,还是更多的数据上?Kaplan 的 scaling law 建议把多得多的算力给模型规模,这促成了「175B 参数、只训 300B token」的 GPT-3。
Hoffmann et al. 2022(Chinchilla)发现 Kaplan 的方法有问题:他们给不同 token 数的模型用了固定长度的 cosine 学习率调度,于是低估了数据量的作用(第三篇讲学习率调度时会再遇到这件事)。重新推导的结论是训练时长应该多得多——按 Chinchilla,175B 的 GPT-3 计算最优的训练量是 3.7T token。常被引用的经验比例是每个参数约 20 个 token。
训练算力的标准估算是
$$C\approx 6ND.$$它的直觉:每个 token 的前向,每个参数参与一次乘加(2 FLOPs);反向要对激活和权重各求一次梯度(约 4 FLOPs)。所以 1B 模型训 100B token 的算力,是 2B 模型训 100B token 或 1B 模型训 200B token 的一半。
为什么大家都「过度训练」
Chinchilla 回答的是「给定训练算力,什么 \(N,D\) 让 loss 最低」,但没算训练之后的事:模型越大,推理越贵。如果模型会被大量使用(比如开源发布),用同样的训练算力去训一个更小的模型、训得远比 Chinchilla 建议的久,总成本反而更低(Sardana et al.;Harm de Vries 的 Go Smol or Go Home)。如今「过度训练」已是标准做法:Qwen3 系列号称训了 36T token。
选择过度训练,意味着 \(N\) 和 \(D\) 要自己定。SmolLM3 的做法:
- 先定 N:参考 Qwen3-4B、Gemma 3 4B、Llama 3.2 3B,3B 大到足以有推理、工具调用这类有意义的能力,又小到可以在本地快速推理。
- D 由算力决定:拿到 384 张 H100 约一个月,按约 30% MFU 能训 11T token。
反过来,也可以从 token 数推需要多少张 GPU。H100 上 BF16 矩阵乘实测大约能跑到 720 TFLOP/s(低于 989 的标称峰值),再乘 30% 的 MFU,训 4 周:
$$C=6\times3\times10^{9}\times11\times10^{12}=1.98\times10^{23}\ \text{FLOPs},$$ $$\#\text{GPU}=\frac{1.98\times10^{23}}{720\times10^{12}\times0.30\times4\ \text{周}\times604{,}800\ \text{s/周}}\approx 379.$$最后拿了 384 张,和并行策略对得上,还留了一些应对节点故障和重启的余量。按 \(D/N\) 算,11T / 3B 约是每参数 3600 个 token,是 Chinchilla 比例的 180 倍左右。
即便不照搬,scaling law 仍有实际价值:它给实验设计提供基线(很多人用 Chinchilla 最优的设置做消融,HF 的 1B × 45B 也在这个量级附近),也能预测某个模型大小能不能达到目标表现。de Vries 还指出,模型缩小到某个「临界大小」以下,再缩就进入收益递减区。
实验守则
做消融的态度可以概括成一句话:保持多疑。具体是四条守则:
- 先验证评测套件。训任何模型之前,确认你的评测能复现要对比的模型的公开结果。生成式基准(如 GSM8K)要格外小心,手动检查几个样本,确认 prompt 格式正确、后处理抽取的答案正确。评测指导每一个决定,这一步错了全盘皆错。
- 每个改动都要测,无论多小。不要低估一次「无害」的库升级或「只改了两行」的提交。需要一个对你关心的场景有强测试覆盖的代码库。(反过来,有时升级库反而能修好 bug,Elana Simon 的这篇调试博客就是一个精彩的例子。)
- 一次只改一个变量。改动之间可能有意想不到的交互,先评估单独贡献,再试组合。
- 训足够多的 token,用足够多的评测。偷工减料会得到嘈杂的结果和错误的决定——上面的模拟器就是这句话的定量版本。
黄金原则:一旦有了好的设置,没有任何改动可以不经测试。否则你会花好几天调查一个神秘的性能下降,最后发现是几天前某个无关依赖的更新导致的。
SmolLM3 的答案
套到 SmolLM3 上,从目标到决策的链条是这样的:
| 目标 / 约束 | 推出的决策 | 详见 |
|---|---|---|
| 端侧运行(手机) | 3B dense;排除 MoE(所有专家都要放进内存) | 架构篇 |
| 约三个月工期、团队熟悉 dense | 不碰混合结构;Llama 式 baseline | 架构篇 |
| 多语言(6 种欧洲语言为主) | Llama 3 的 128k 词表分词器;约 12% 多语言数据 | 第三篇 |
| 长上下文(目标 128k) | 从一开始就用 NoPE 混合与文档内 mask | 架构篇 |
| 可延长训练、方便做中途实验 | WSD 学习率调度 | 第三篇 |
| 384 张 H100 约一个月 | 11T token(大幅过度训练) | Scaling law |
其中「长上下文」那一行最能说明为什么要先想 why:SmolLM2 在预训练末尾扩上下文时遇到了困难,所以 SmolLM3 从训练开始就做了有利于长上下文的结构选择,回头看这一步做对了。具体是哪些选择(NoPE 混合、文档内 mask),见架构篇。
参考与延伸阅读
- Loubna Ben Allal et al., The Smol Training Playbook(2025)。主要依据其中 Introduction、Training Compass: Why → What → How、Every Big Model Starts with a Small Ablation、Scaling Laws: How Many Parameters, How Much Data? 几节,以及 Infrastructure 章中 How Many GPUs Do We Need? 的算例。想看每组消融的原始曲线和更多实验细节,推荐直接读这几章。
- HF, FineTasks(评测任务的四条标准、SNR、Kendall τ、acc_char/acc_token/acc_pmi 的定义);Penedo et al., FineWeb2(2025)。
- Gu et al., OLMES: A Standard for Language Model Evaluations(2024)。
- Kaplan et al., Scaling Laws for Neural Language Models(2020);Hoffmann et al., Training Compute-Optimal Large Language Models(2022);Hestness et al., Deep Learning Scaling is Predictable, Empirically(2017);Sardana et al., Beyond Chinchilla-Optimal(2024)。
- Liang et al., TorchTitan(2024);Kimi Team, Kimi K2(2025);The Art of Scaling Reinforcement Learning Compute for LLMs(ScaleRL)(2025)。
- SmolLM3 的结构数字来自其 config.json;Llama 3.2 1B 消融配置见 training-guide-nanotron-configs。
- Harm de Vries, Go Smol or Go Home(2023);HF, The Ultra-Scale Playbook(大规模并行训练)。