Hugging Face SmolLM3训练手册:世界级小模型背后的系统工程挑战与实践 Best Partners TV 2025-11-06

揭秘世界级小模型训练的幕后挑战

大家好,这里是最佳拍档。如果你单看大模型(Large Language Model, LLM: 指参数量巨大、拥有强大语言理解和生成能力的深度学习模型)相关的学术论文,可能会觉得训练一个顶尖的模型很简单,好像选个架构、拼个数据集、堆够GPU(Graphics Processing Unit: 图形处理器,常用于加速深度学习计算),最后就能拿到平滑的损失曲线和漂亮的benchmark(基准测试: 用于衡量模型性能的标准测试集或任务)分数。

但是最近,Hugging Face(一家专注于自然语言处理和机器学习的开源社区与平台)的12位工程师发布了一份指南,可能会彻底打破这种滤镜。这份**《The Smol Training Playbook》(Hugging Face发布的关于SmolLM3模型训练过程的指南),记录了他们训练SmolLM3**(Hugging Face团队训练的一个小参数量语言模型)的全过程,可以说是一本模型训练的幕后纪实。里面有凌晨2点调试数据加载器的崩溃、突然飙升的损失曲线、藏在张量并行里的隐形Bug,还有为了平衡多语言与数学能力而重启1T token(词元: 文本处理中的基本单位,可以是单词、子词或字符)训练的无奈。今天,我们就来拆解一下这份指南,看看训练一个世界级的小模型到底要闯多少关。

明确训练动机:为什么训练模型?

很多人拿到GPU集群的第一个反应是赶紧训练一个模型,比如看到100张H100(NVIDIA推出的一款高性能GPU)就定个随机大小、凑个数据集开始跑。但是Hugging Face团队在开篇就泼了冷水,很多训练项目的失败不是因为代码或者超参数(Hyperparameters: 在模型训练前设定的参数,如学习率、批次大小等)错了,而是从为什么要训练开始就没想明白。

在开始训练前,你应该先问自己一个问题:为什么要训练一个模型?它真的需要么?不是有了GPU、别人都在训练、AI是未来这些模糊的理由,而应该是一个具体的、可落地的动机。指南里把它分成了三类:

第一类是研究动机。你想回答一个明确的学术问题,比如新的优化器(Optimizer: 深度学习中用于调整模型权重以最小化损失函数的算法)能够支撑10B以上的模型吗?不用监督微调(Supervised Fine-Tuning, SFT: 使用带有标签的数据集对预训练模型进行进一步训练,使其适应特定任务),单靠强化学习(Reinforcement Learning, RL: 一种机器学习范式,通过与环境交互学习如何做出决策以最大化累积奖励)能够让模型推理吗?或者只用合成数据(Synthetic Data: 通过算法或模型生成的数据,而非真实世界采集)能训练出好的小模型吗?这类训练的关键是假设要具体,比如你想要验证开源数据(Open-source Data: 公开可获取、可自由使用和修改的数据)能不能达到闭源数据(Closed-source Data: 不公开或受限制访问的数据)的效果,就得先明确使用哪些开源数据、测试哪些benchmark,而不是泛泛地做研究。

第二类是生产动机。比如现有模型解决不了你的具体需求。这里又分三种情况:一是领域特殊性,比如你需要处理DNA序列、法律金融文本等等,现有的通用模型对这些领域的词汇处理效率低;二是部署约束,比如模型要跑在无人机或者私有FPGA上,需要适配硬件的延迟和内存;三是安全合规,比如你在医疗、金融等强监管行业,需要完全控制训练数据、模型的更新周期,甚至需要向监管层证明模型里没有敏感数据。但是,指南里建议你先花几天基于Qwen3Gemma3这些现有的SOTA模型(State-Of-The-Art Model: 在特定任务上达到当前最佳性能的模型)做一下提示词工程(Prompt Engineering: 设计和优化输入给语言模型的提示词,以引导其生成期望的输出)或者微调(Fine-tuning: 在预训练模型的基础上,使用特定任务数据进行进一步训练,以提高模型在该任务上的表现)。如果能够达到目标,就没必要从头训练,毕竟微调1T token比从头训练10T token要便宜多了。

第三类是战略开源动机。你发现开源生态里有空白。Hugging Face自己就是最好的例子,2020年GPT-3出来后,他们发现没有开源替代,担心被少数公司垄断,于是搞了BigScience workshop,集合几十人训练了175B的Bloom。这类训练的关键是具体的目标,比如你不是要做最好的模型,而是要做最好的3B端侧模型、做第一个支持1M上下文的小模型,这样才能真正的填补空白。

确定训练内容:模型类型与数据混合

想清楚为什么训练之后,我们再来看训练什么,包括模型的类型(比如稠密模型MoE模型还是混合模型)、模型的大小、数据混合的方式、AI助手的类型等等。这里的逻辑是用为什么训练来倒推训练什么。比如你要做端侧模型,就选稠密架构、3B以内的小参数;要做多语言模型,就得选128k以上的大词表;要做超长上下文,可能就需要混合架构。

举SmolLM3的例子,他们的目标是做端侧的强推理小模型,所以选择了稠密的Llama风格架构,词表选用Llama3的128k。数据混合里加了FineMath、Stack-Edu,还专门做了长上下文扩展。这些选择全是从端侧+多语言+推理的核心需求来的。

预训练环节:数据、基线与架构改动

确定了训练什么之后,就进入了预训练(Pre-training: 使用大量无标签数据对模型进行初步训练,使其学习通用的语言表示)的环节。这是最容易想当然的地方,比如很多人觉得用最高质量的数据肯定好。但是指南里举了个反例,用arXiv(一个收录物理学、数学、计算机科学等领域预印本论文的在线文库)的STEM论文数据,直觉上能够提升模型的科学能力,但是在实操中,尤其是小模型,用了反而会让性能下降。原因很简单,arXiv的论文太专业、风格太窄,而小模型的学习能力有限,学不会这种小众风格,反而会影响对通用文本的理解。

所以,Hugging Face团队的核心原则是所有决策都要通过消融实验(Ablation Experiment: 实验中逐步移除或修改模型或系统中的某个组件,以评估其对整体性能的影响)来验证。而且消融要做到不仅能够快速迭代,还能将结果迁移到大规模的训练。这其中的第一步就是要选一个经受过考验的基线模型(Baseline Model: 用于比较和评估新模型性能的参考模型)。你不用从零设计一个架构,因为好的架构是无数团队迭代几年的结果,比如标准TransformerAdam优化器背后是成千上万的实验和Bug修复。

选基线的核心标准有四个:匹配你的约束条件、经过大规模的验证、文档完善和有框架的支持。指南里给了2025年的几个主流基线选项,比如稠密架构里有Llama3.1(8B/70B)、Llama3.2(1B/3B)、Qwen3(0.6B-32B)、Gemma3(12B/27B)、SmolLM2/3(135M-3B);MoE架构里有Qwen3 MoE(30B-A3B/235B-A122B)、Kimi Moonlight(16B-A3B);混合架构里有Zamba2(1.2B-7B)、Falcon-H1(0.5B-34B)。

选好基线后,你可能想添加各种新的特性,比如换个注意力机制、改个位置编码。但是指南强调,任何改动必须先证明它能够提升目标能力或者带来效率收益,且不损害核心的性能才行。比如SmolLM3在基线基础上做的几个关键改动,每一个都经过了消融验证:

第一个是注意力机制。他们将MHA(Multi-Head Attention: 多头注意力机制,Transformer中的核心组件)换成了GQA(Grouped Query Attention: 分组查询注意力,MHA的一种变体,减少KV缓存)。MHA每个注意力头都有独立的KV,KV缓存(Key-Value Cache: 在Transformer解码过程中存储键值对的内存区域,用于加速生成)大;GQA是多个query头共享一组KV头,能够减少KV缓存。他们用1B模型训练了45B token来进行消融实验,对比MQA、GQA、MHA,发现GQA的性能和MHA几乎持平,但是KV缓存减少了75%,这对于端侧部署太重要了,所以最终决定采用。

第二个是文档掩码(Intra-Document Masking: 一种数据处理技术,确保模型在处理打包文档时,一个token只关注同一文档内的token)。标准的打包会把多个短文档拼成一个长序列,导致一个token会注意到其他文档的内容,既浪费计算又会引入噪声。文档掩码可以让token只能注意同一个文档内的token。Llama3曾经验证过它对短上下文影响不大,但是对长上下文的扩展很有帮助。SmolLM3用1B模型做了消融实验,发现损失和下游分数和无掩码几乎一致,还能加速长上下文训练,所以也保留了这项改动。

第三个是嵌入共享(Tied Embeddings: 输入嵌入层和输出投影层共享同一组权重参数)。大语言模型有输入嵌入和输出投影,不共享的话,小模型的嵌入参数占比太高。于是团队做了消融实验,对比绑定嵌入和不绑定嵌入,发现绑定嵌入的1.2B模型性能和1.46B的不绑定模型几乎持平,还少18%参数。这对于小模型来说也十分关键,所以SmolLM3保留了绑定嵌入。

第四个是位置编码。RoPE(Rotary Position Embeddings: 旋转位置编码,一种常用的位置编码方式)是目前主流的位置编码方式,但是长上下文扩展时,位置角度会衰减得太快;而NoPE(No Position Embeddings: 一种位置编码策略,通过在某些层去除RoPE让模型隐式学习位置信息)是每隔几层去掉RoPE,让模型隐式学习位置信息,能够更好地应用到长上下文上。他们用1B模型做了消融实验,对比纯RoPE、NoPE、NoPE+文档掩码,发现三者在短上下文的损失和分数几乎一致,但是NoPE在长上下文预训练时的表现更好,所以SmolLM3最终采用了NoPE+文档掩码的组合。

训练框架选择:稳定大规模训练的关键

接下来,训练框架决定你能不能稳定跑大规模训练。指南对比了几个主流的框架:比如英伟达的Megatron-LM,它比较成熟,支撑过Kimi K2,3D并行做得好,但是代码复杂,新手难改;微软DeepSpeed,它是ZeRO优化(Zero Redundancy Optimizer: DeepSpeed中的一种优化技术,通过消除内存冗余来训练更大的模型)的先驱,支撑过BLOOM、GLM,功能全,但是代码量大,调试较难;PyTorchTorchTitan,它很轻量、模块化,适合快速实验,但是框架较新,稳定性有待验证;Hugging Face的nanotron,它是为Hugging Face预训练定制的,比较灵活,支撑过StarCoder、SmolLM,但是需要自己做很多测试。

SmolLM3最终选用了nanotron,因为他们之前用它训练过StarCoder,熟悉代码,能够快速定位Bug;而且nanotron对稠密模型的优化足够,能够满足3B参数、11T token的训练需求。但是如果你是新手,更建议从DeepSpeed或者TorchTitan开始,能够避免自己造框架的坑。

预训练中的四大挑战与解决方案

当你把架构、数据、框架这些都调好,点击开始训练的时候,真正的挑战其实才刚刚开始。SmolLM3用384张H100训练了近一个月,期间遇到了4个致命的问题,每个都差点让训练重启或报废。

第一个坑,吞吐量(Throughput: 单位时间内处理的数据量,衡量系统效率的指标)的突然暴跌。训练刚开始几小时,团队发现吞吐量从预期的每GPU每秒13.5k-14k个token突然跌到6k,还伴随着频繁的卡顿。他们先检查了硬件,GPU温度、内存都正常;再去查数据加载,发现数据虽然存在FSx(Amazon FSx: AWS提供的一系列完全托管的文件系统服务)的网络存储上,但是24TB的训练数据把Weka的缓存都挤满了,导致系统频繁把冷数据驱逐到S3(Amazon S3: AWS提供的对象存储服务),需要的时候再拉回来,造成数据停滞。解决办法是把数据从FSx搬到每个节点的本地NVMe RAID(Non-Volatile Memory Express Redundant Array of Independent Disks: 一种高性能固态硬盘阵列,提供高速读写)上。但是新的问题来了,如果节点挂了,新节点没有数据,从S3下载要3个小时。他们的应对方法是预留备用的节点,在Slurm集群里留1个节点,提前把数据拷进去;这样如果节点挂了,就可以直接用备用节点替换,零等待。经过这个改动后,吞吐量恢复到每GPU每秒13.8k个token。

第二个坑,数据加载器的隐藏索引问题。解决存储后,吞吐量还是有频繁的小幅度下跌。他们用单节点测试,发现只要把训练步数从3.2M改成32k,下跌就会消失。最后定位到了nanotron的默认数据加载器nanosets,它会构建一个全局索引,步数越多,索引越大,占用的共享内存就会过高,导致卡顿。解决办法就是放弃nanosets,改用SmolLM2用过的TokenizedBytes数据加载器。这是一个基于Megatron-LM的加载器,不会构建全局索引,而是按批次读取。替换之后,吞吐量稳定在了13.5k-14k,没有再出现下跌。

第三个坑,数据没做序列级打乱(Sequence-level Shuffling: 在数据加载时,将所有分词后的序列随机打乱,再打包成批次)。更换了加载器后,损失曲线比预期的更加嘈杂,正常应该是平滑下降,结果却有频繁的小尖峰。他们通过查看数据处理,发现TokenizedBytes是按文档顺序读取的,比如一个批次全是低质量的代码,导致损失突然升高。标准做法是序列级打乱,把所有经过分词的序列打乱,再打包成批次,而不是按照文档顺序打包。打乱后,损失曲线恢复平滑,尖峰消失。

第四个坑,张量并行(Tensor Parallelism, TP: 一种并行训练策略,将模型的张量(如权重矩阵)在不同设备上进行切分)的随机种子(Random Seed: 用于初始化随机数生成器的值,确保实验的可复现性)Bug。填完前面三个坑,没想到最致命的问题来了。他们训练到1T token的时候,拿中间的checkpoint(检查点: 模型训练过程中的快照,包含模型权重和优化器状态,用于恢复训练或评估)做评估,发现3B的SmolLM3性能居然比1.7B的SmolLM2还低。他们排查了数据、超参数,都没问题。最后怀疑到了张量并行,因为SmolLM2是1.7B,能够单卡训练,没开张量并行;而SmolLM3是3B,需要TP=2的张量并行。于是,他们做了个关键的实验,用1.7B模型分别在无TP和TP=2的情况下训练,发现TP=2的模型损失比无TP高0.1,下游分数低4-6个百分点。最后定位到了TP的随机种子问题,在nanotron里所有TP rank用的是同一个种子,导致不同rank的权重初始化高度相关,破坏了并行训练的独立性,收敛变慢。解决方法是修改代码,让每个TP rank的种子=基础种子+TP rank。修正后,重新训练1.7B模型,TP=2的性能和无TP几乎一致;随后重启了SmolLM3的训练,后续的checkpoint性能终于超过了SmolLM2。

后训练策略:监督微调、偏好优化与强化学习

经过预训练后,我们一般得到的是一个擅长预测下个token的基础模型,但是用户需要的是能听话、会推理的助手,这就需要进行后训练(Post-training: 在预训练之后对模型进行的进一步训练,以提升其特定能力或对齐人类偏好)。指南里强调后训练的核心是循序渐进,先做监督微调打基础,再用偏好优化(Preference Optimization: 使用人类偏好数据来优化模型,使其生成更符合人类喜好的输出)来调对齐,最后用强化学习来做实时的反馈优化。很多人会跳过监督微调,直接上强化学习。但是指南里说,几乎所有有效的后训练都从监督微调开始的,因为监督微调有三个优势:一、便宜,比强化学习省70%的计算;二、稳定,不会像强化学习那样突然发散;三、是最好的基线,后续优化都能基于监督微调进行对比。

SmolLM3的监督微调数据集也是一个精心挑选的混合包,覆盖了三大能力,分别是基础对话、指令跟随和推理能力。他们还遇到了一个低级但是相当致命的Bug,那就是数据里的系统指令被设为None,导致模型永远在用默认的系统提示,无法切换角色。最后检查数据处理的代码,发现是一个赋值错误,把custom_instructions设成了None。修正后,模型终于能够用系统指令来切换角色了。监督微调的超参数也很关键,学习率采用了1e-5,批大小为128,采用用户轮次掩码,只计算模型输出的损失,不计算用户的输入。最后监督微调后的模型,指令跟随的分数比基础模型提升了12个百分点。

监督微调虽然能够让模型听话,但是不能让它做出更好的选择,比如同样回答一个数学题,一个步骤清晰,一个步骤混乱,监督微调是无法区分的。而偏好优化是基于偏好数据来进行优化,核心算法有DPO(Direct Preference Optimization: 一种直接偏好优化算法)、APO(Aligned Preference Optimization: 一种偏好优化算法)、KTO(Kahneman-Tversky Optimization: 一种偏好优化算法)等等。SmolLM3选择了APO,因为DPO是优化答案A和B的概率比,而APO能够更精准地控制优化幅度,避免过度偏向偏好数据而丢失基础的能力。团队采用了Qwen3-32BQwen3-0.6B分别来生成偏好数据,对同一个提示词,Qwen3-32B的回答是好答案,Qwen3-0.6B的是坏答案,总共生成了超过25万个偏好样本。消融的结果很明显,APO在指令跟随基准上比监督微调提升了15-20个百分点,比DPO高3-5个百分点;而且在AIME25LiveCodeBench上,APO也能保持监督微调的性能,没有出现偏科。这对多能力模型非常重要,所以团队最终采用了APO。

如果你的目标是要训练一个强推理的模型,那么偏好优化还不够,因为偏好数据是离线的,无法覆盖所有场景。强化学习能够用实时反馈来进行优化,比如DeepSeek-R1就是用强化学习来提升的推理能力。SmolLM3虽然没有做完整的强化学习,但是团队做了一个关键实验,那就是针对/no_think模式,用GRPO(Generalized Reinforcement Learning with Policy Optimization: 一种强化学习算法)+长度惩罚(Length Penalty: 在生成任务中,对模型生成输出的长度施加惩罚,以控制输出长度)来进行优化。实验发现,没加惩罚时模型会生成16k token的推理链,虽然在AIME25的分数提升了,但是不符合简洁要求。而加了2.5-3k的长度惩罚后,AIME25分数会比APO再提升8个百分点,而且回答长度控制在2k左右。这证明强化学习能够进一步优化模型的效果,但是需要仔细设计奖励函数。

被忽视的隐形成本:基础设施设计

讲完训练的过程,我们再来看看模型训练过程中有哪些被忽略的隐形成本。很多人觉得训练模型就是堆GPU,但是指南里花了大量篇幅讲基础设施,因为同样的GPU数量,基础设施的设计不好,吞吐量能差3-5倍。比如SmolLM3如果用网络存储而非本地NVMe,训练时间会从1个月变成3个月;如果用PCIe而非NVLink做GPU间通信,多节点训练的吞吐量会掉一半。

GPU与内存:计算单元的配合

我们先来看GPU,它的核心是计算单元和内存的配合,因为计算再快,内存喂不饱,也是白搭。以H100为例,BF16(Bfloat16: 一种半精度浮点数格式,常用于深度学习训练)的理论峰值是990 TFLOPs(Tera Floating-point Operations Per Second: 每秒万亿次浮点运算,衡量计算性能的单位),但是在实测中,矩阵乘法能达到714-758 TFLOPs,利用率为72-77%,这是因为H100的Tensor Core对BF16的优化极好;但是FP8的实测只有1210-1457 TFLOPs,利用率为31-37%。这不是因为计算不够,而是HBM3(High Bandwidth Memory 3: 高带宽内存,GPU中使用的内存技术)的带宽喂不饱FP8的计算需求,造成了内存瓶颈。

在内存方面,HBM是最大但是也是最慢的,3.35 TB/s;L2缓存可以达到13 TB/s、L1+共享内存可以达到31 TB/s、寄存器最小也最快。优化的关键是让数据尽量在快内存里停留,比如Flash Attention把注意力计算的中间结果放在L1/共享内存,而不是写回HBM,吞吐量可以提升2-4倍。基于计算和内存的匹配度考虑,SmolLM3最终采用了BF16进行训练。

GPU间通信:效率的天壤之别

我们再来看GPU间的通信,有三种方式,效率也是天差地别。首先是同节点内的NVLink,H100采用NVLink 4.0,双向带宽900 GB/s,实测双向786 GB/s,利用率87%。相当于如果两个GPU间传输1GB数据,只要1.27ms,几乎无延迟。SmolLM3的同节点GPU通信全部采用了NVLink,避免走PCIe。

其次是跨节点的EFA(Elastic Fabric Adapter: AWS为EC2实例提供的高性能网络接口,用于高性能计算和机器学习),AWS的EFA网卡单卡100 Gbps,4张EFA卡能到50 GB/s。SmolLM3的EFA跨节点通信实测点到点带宽为42 GB/s,比用TCP快14倍。

第三是GPU和CPU之间、或者GPU间备用的PCIe。PCIe Gen4 x8的实测带宽为14.2 GB/s,比NVLink慢55倍,比EFA慢3倍。因此,只有GPU和CPU之间的通信,比如数据加载才会考虑用PCIe,GPU间通信应该绝对避免。

存储效率:训练数据的生命线

存储方面的效率差距则更加夸张。SmolLM3用8块3.5TB NVMe做RAID 0,实测吞吐量为26.59 GB/s,IOPS(Input/Output Operations Per Second: 每秒输入/输出操作次数,衡量存储设备性能的指标)337k,比网络存储快6倍,适合用来放训练数据和实时Checkpoint。而FSx网络存储实测吞吐量为4.21 GB/s,IOPS 51k,适合放一些共享数据或者备份Checkpoint,但是不适合实时训练。最后是/root用的EBS云盘(Elastic Block Store: AWS提供的一种高性能、可扩展的块存储服务),实测吞吐量为1.1 GB/s,IOPS 730,只适合放系统文件,绝对不能放训练数据。

基于这些数据,SmolLM3的存储策略是:训练数据存在本地NVMe RAID,Checkpoint每2小时保存一次本地,然后立即上传S3备份,本地只保留最新一个Checkpoint。这样既可以保证速度,又避免了存储空间占满。

SmolLM3的成果与核心启示

最终,SmolLM3的成果可以说是相当亮眼。总共只有3B参数,但是在多语言、数学、代码、长上下文等基准测试上,和Qwen3 1.7B、4B都处于同一帕累托前沿(Pareto Frontier: 在多目标优化问题中,一组最优解的集合,其中任何一个解的改进都必然导致至少一个其他目标的恶化)。也就是说,它比1.7B强,又比4B小,对于端侧部署来说更友好。

但是,我想说,这份指南最有价值的不是SmolLM3的参数和分数,而是它揭示的一个真相:那就是现在训练大语言模型,尤其是小模型,早已经不再是拼参数大小、堆GPU数量了,而拼的是系统能力。包括战略决策的清晰度、消融实验的严谨性、基础设施的稳定性以及debug的速度。比如战略上,你要想清楚为什么要训练一个模型,避免训练出一个别人早就有了的模型;其次,实验上,任何改动要先做消融,避免凭着感觉去加特性;在基础设施上,要重视GPU的通信、存储这些隐形细节,它们比多10张GPU更加重要;最后,在debug方面,应该建立从硬件到软件的排查流程,比如发现吞吐量下跌的情况,应该优先查看存储、再查看加载器、最后再查看代码。

最后,指南里有句话让我印象很深刻:学术论文展示的都是所谓整理后的成功,而在实际的操作中,我们可能会花30%的时间来做决策,50%的时间去debug,20%的时间看着损失曲线下降。希望今天的内容能够帮助大家在未来的模型训练中少走一些弯路。如果你想深入了解训练过程中的其他内容,比如消融实验的具体配置、nanotron的使用、APO的实现等等,建议去阅读报告原文。

📌 文中提及的人物和组织

公司/组织: Hugging Face, NVIDIA, Microsoft, AWS

产品/模型: GPT-3, H100, S3, PCIe, NVLink

媒体/书籍: 《The Smol Training Playbook》, arXiv