Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

预训练技术综述

前面十章,我们一步步搭建并预训练了一个 GPT 模型:

整体来讲,我们实现的基本是 GPT-2 的架构(GPT-3 在此基础上主要是放大了规模,并在部分层使用了稀疏注意力)。但是和今天的主流大模型(Llama、Qwen、DeepSeek、Gemma 等)相比,从分词到注意力,从模块细节到训练数据,几乎每个环节都已经发生了很大的变化。

这些新的大模型架构,已经很难使用小型的代码和数据展示。本章我们将梳理预训练阶段的前沿技术,建立一张完整的技术地图。感兴趣的读者可以继续深入研究。

大模型技术演进很快,本章内容截至 2026 年 11 月。

技术对比

通过一张对比表,我们来比较一下我们实现的 GPT 和现代主流大模型有哪些不同:

组件我们的 GPT现代主流大模型
分词字符级,词表 65 左右字节级 BPE,词表 3 万到 25 万
位置编码可训练的绝对位置嵌入旋转位置编码(RoPE)
注意力多头注意力(MHA),全部是全局注意力分组查询注意力(GQA)或多头潜在注意力(MLA);局部与全局交替、稀疏注意力,部分模型混入线性注意力
归一化层归一化(LayerNorm),前置均方根归一化(RMSNorm),前置,部分模型加 QK-Norm
前馈网络GELU,隐藏层 4 倍SwiGLU,隐藏层约 2.7 到 3.5 倍,或者混合专家(MoE)
线性层偏置有通常没有
随机失活有通常没有
输入输出嵌入各自独立小模型常常共享,大模型通常独立
数值精度FP32BF16 混合精度,FP8,部分探索 FP4
优化器AdamWAdamW,部分模型使用 Muon
学习率调度预热 + 余弦衰减预热 + 余弦衰减,或者预热-稳定-衰减(WSD)
上下文尺寸256128K 到 1M
训练数据约 110 万字符的莎士比亚剧本数万亿词元,经过清洗、去重、配比

分词

字符级分词

我们使用的是字符级分词:每个字符是一个词元,词表只有几十个。简单,但是代价也大:

另一个极端是词级分词:每个单词是一个词元。序列短了,但是词表巨大,而且无法处理没见过的词(Out of Vocabulary,OOV),比如新造词、拼写错误、人名等。

子词分词

子词分词(Subword Tokenization)是折中方案:常见的词保持完整,罕见的词拆分成更小的片段。主要有三种算法:

训练分词器常用 SentencePiece(直接在原始文本上训练,把空格也当作普通字符,适合中文、日文等没有空格的语言)和 Hugging Face 的 tokenizers。

字节级 BPE

目前最主流的方案是字节级 BPE(Byte-level BPE):合并从 256 个字节开始,而不是从字符开始。任何文本都可以表示成字节序列,所以不会出现 OOV,也不需要为各种语言的字符预留位置。GPT-2 开始使用。

BPE 分词前通常还有一个预分词(Pre-tokenization)步骤:用正则表达式先把文本粗略地切分成单词、数字、标点等,再在每个片段内部做 BPE,避免合并跨越单词的天然边界。OpenAI 的 tiktoken 是常用的高速编码库,但它只负责编码,不负责训练分词器。

词表大小

词表大小是一个权衡的结果:

典型的词表大小:

趋势是越来越大,尤其是为了更好地支持多语言。

特殊词元

除了文本片段,词表中还有一些特殊词元(Special Token):序列开始和结束标记、填充标记,以及对话中区分系统、用户、助手角色的标记。结束标记尤其重要:模型需要靠它学会“什么时候停下来”。我们在微调章节里会看到它们的用法。

多模态词元

多模态模型同样需要把图像、音频变成词元序列:

嵌入共享

我们的模型中,嵌入层的词元嵌入权重和输出层的线性层权重是两个独立的矩阵。但是它们的形状正好相同:都是 (词表大小, 嵌入尺寸)(我们的线性层权重按 (输出, 输入) 存放)。

嵌入共享(Weight Tying)让两者使用同一份参数。GPT-2 就是这样做的。在词表很大、模型较小的时候,嵌入层和输出层参数占比非常可观,所以小模型(比如 Gemma、Llama 3.2 的小尺寸、Qwen 的小尺寸等)常常采用;模型变大以后,这部分参数占比很小,通常不再共享。

位置编码

绝对位置嵌入

我们使用的是可训练的绝对位置嵌入:每个位置有一个独立的位置向量,加到词向量上。它有两个局限:

位置编码的演进

旋转位置编码

旋转位置编码(Rotary Position Embedding,RoPE)不是把位置向量加到词向量上,而是通过旋转向量来表达位置。

RoPE 把查询向量(Query,qq)和键向量(Key,kk)每两个维度分成一组,把每组看作二维平面上的一个向量,旋转一个与词元位置 mm 成正比的角度 mθim\theta_i,不同的组使用不同的频率 θi\theta_i。经过旋转后,位置为 mm 的查询向量与位置为 nn 的键向量做点积运算时,其结果只取决于两者的相对距离,而与它们的绝对位置 mm、nn 无关:

(Rmq)⊤(Rnk)=q⊤Rn−mk(R_m q)^\top (R_n k) = q^\top R_{n-m} k

这里:

这种设计让模型天然具备相对位置感知能力,也不需要再把位置向量加入词向量。Llama、Qwen、DeepSeek、Gemma、Mistral 等绝大多数主流开源大模型都采用 RoPE。

上下文扩展

训练时的上下文尺寸往往远小于最终支持的长度,因为长序列的训练成本很高。常见的做法是:

注意力

自注意力的计算量和注意力分数矩阵的大小,都和序列长度 nn 的平方成正比:O(n2d)O(n^2d)。上下文从 4K 扩展到 128K,注意力部分的计算量增加了约 1000 倍。

这是预训练中注意力研究最核心的驱动力:怎么让注意力更快、更省,或者干脆绕开平方复杂度。

减少键值头

标准的多头注意力(Multi-Head Attention,MHA),每个查询头对应一组独立的键和值。表达能力强,但是推理时需要缓存的键和值太多,显存和带宽消耗大。让多个头共享键和值,缓存就能成倍缩小:

这些算法的主要动机是减少推理时的键值缓存(KV Cache),但是都改变了模型结构,通常在预训练阶段就要确定下来。也有从 MHA 模型出发、用少量继续训练转换成 GQA 的做法。目前主流大模型大多采用 GQA,DeepSeek、Kimi 等采用 MLA。

高效注意力计算

标准注意力需要把完整的注意力分数矩阵写入显存,再读出来做 Softmax 和加权求和,大量时间花在数据搬运上。

FlashAttention 通过分块(Tiling)的方式,把查询、键、值切成小块,在高速缓存中完成 Softmax 和加权求和,不需要把完整的注意力矩阵写入显存,将这部分的显存占用从 O(n2)O(n^2) 降到了 O(n)O(n) ,速度也显著提高。它的输出和标准注意力一致,是精确计算,不是近似。FlashAttention 之后又有针对新一代 GPU 架构的改进版本。现在主流大模型的预训练几乎都默认启用它。

稀疏注意力

注意力矩阵的大部分权重其实接近 0,因此可以选择只计算最重要的位置:

线性注意力和状态空间模型

另一条路是彻底绕开平方复杂度。线性注意力和状态空间模型(State Space Model,比如 Mamba)把注意力改写成递推形式:用一个固定大小的状态来概括历史,而不是不断增长的 KV 缓存。计算量随序列长度线性增长,推理时的显存占用也是恒定的。

但是压缩成固定大小的状态是有代价的:在需要精确回忆某个细节的任务上,纯线性模型弱于完整注意力。所以 2025 年以来,更常见的做法是混合架构:多数层使用线性注意力或状态空间层,少数层保留完整注意力,例如 Qwen3-Next(Gated DeltaNet 与门控注意力)、Kimi Linear(线性注意力与 MLA)、Nemotron 3(Mamba 层、注意力层与 MoE)。

注意力的稳定性

QK-Norm 在计算注意力分数之前,先对查询和键做归一化,防止分数过大导致 Softmax 饱和,使训练更稳定。Qwen3、Gemma 3、OLMo 2 等模型都采用了它。

Transformer 模块的演进

我们实现的 Transformer 模块是:归一化 → 注意力 → 随机失活 → 残差连接;归一化 → 前馈网络 → 随机失活 → 残差连接。现代大模型在每个子模块都做了改进。

归一化

前馈网络

门控线性单元(Gated Linear Unit,GLU):前馈网络不再是“线性 → 激活 → 线性”,而是增加一个门控机制:

FFN(x)=(Swish(xW1)⊙xW3)W2\text{FFN}(x) = \left(\text{Swish}(x W_1) \odot x W_3\right) W_2

这里:

用激活后的一路,去“门控”线性的另一路。这种结构称为 SwiGLU,在相同参数量下效果稳定地优于 GELU,成为多数主流大模型的标配。

前馈网络还有两项改进:

MoE 的几个设计要点:

残差连接

标准的残差连接只有一条“主干道”。超连接(Hyper-Connections)把残差流加宽成多条并行的通道,并让它们之间可以互相混合,增强表达能力。但是不加约束的混合会让信号在深层网络中被放大,训练不稳定。DeepSeek 提出的 * mHC*(Manifold-Constrained Hyper-Connections)把混合矩阵约束在特定的流形上,恢复了残差连接的恒等映射性质。DeepSeek-V4 已经采用了 mHC。这是目前仍在探索中的方向。

随机失活

我们在模型中使用随机失活(Dropout)防止过拟合。但是现代大模型的预训练通常不使用它:训练数据通常只过一遍,模型处在欠拟合而不是过拟合的状态,随机失活只会拖慢收敛。

只有数据量不足、需要重复训练多个轮次的场景(比如我们的模型),随机失活才比较有价值。大模型预训练中的权重衰减,主要作用也不是防止过拟合,而是配合学习率调节优化的动力学。

线性层偏置

现代大模型的线性层通常去掉偏置,减少参数并简化实现。个别模型曾经在注意力的 QKV 投影上保留偏置(比如 Qwen2),后来也去掉了(Qwen3 改用 QK-Norm 稳定训练)。

训练目标

我们训练的是最基本的下一词元预测:每个位置预测下一个词元。现代大模型在此基础上有一些扩展:

优化

优化器

我们使用的 AdamW 也是目前比较常用的优化器。常见的大模型预训练配置包括:

Muon 是近年来最受关注的 AdamW 替代方案。它只对二维的权重矩阵使用:先对动量做正交化处理,再更新参数,其余参数(如嵌入、归一化)仍然使用 AdamW。Muon 只保存一份动量,优化器状态比 AdamW 更省显存,样本效率也有优势。Kimi K2(1.04T 参数、15.5T 词元)使用了它的改进版 MuonClip,GLM-4.5、GLM-5 和 DeepSeek-V4 也使用了 Muon。

学习率调度器

我们使用预热余弦衰减学习率调度器,通过预热和余弦衰减两个步骤,实现学习率增长到峰值,然后衰减的过程。

但是它也有一个缺点:必须事先确定总训练步数,不灵活。

WSD(Warmup-Stable-Decay)不需要事先确定训练量:

这样可以从稳定阶段的任意检查点出发,再决定怎么收尾,也方便在稳定阶段之后继续训练或者调整数据。

超参数的缩放

小模型上调好的超参数,在大模型上往往不再最优。通常的做法是:大模型的峰值学习率比小模型更小,批大小随训练进行逐步增大;也有 μP(Maximal Update Parametrization)这类方法,通过调整初始化和各层的学习率缩放,让小模型调好的超参数可以直接迁移到大模型。

训练稳定性

大模型预训练动辄持续几周甚至几个月,训练中途出现损失尖峰(Loss Spike)甚至发散,代价非常高。常见的诱因包括:学习率过大、注意力分数增长过快导致 Softmax 饱和、数值溢出、个别异常数据。常用的应对方法:

训练数据

模型的能力,很大程度上取决于数据。数据工作通常占据预训练团队的大部分精力。

数据来源

公开的大规模预训练数据集,比如 FineWeb(约 15 万亿词元),让研究者可以复现完整的数据处理流程。

数据清洗

原始数据必须经过多道处理才能使用,典型的流程是:

数据配比

不同来源的数据按什么比例混合,对模型能力影响很大。配比可以靠小模型上的实验来调整,也有 DoReMi 这样自动搜索配比的方法。重复使用同一份数据的收益是递减的:有研究发现,重复 4 个轮次以内的数据,效果接近全新的数据。

现代大模型的预训练通常是分阶段的,后期的数据质量更高。以 Qwen3 为例:

  1. 第一阶段:约 30 万亿词元,序列长度 4K,建立通用的语言能力和知识;

  2. 第二阶段:约 5 万亿词元,提高 STEM、代码、推理等知识密集型数据的占比,并加快学习率衰减;

  3. 第三阶段:用数千亿词元的长文本,把上下文扩展到 32K。

在学习率衰减阶段加入高质量数据,也叫退火(Annealing)。这些后期阶段有时单独称为中期训练(Mid-training)。

合成数据

高质量的自然数据是有限的,所以越来越多地使用合成数据:

合成数据的风险是:模型用自己生成的数据反复训练,可能逐渐丧失多样性。所以必须严格过滤,并且和真实数据混合使用。

缩放定律

损失和规模的关系

缩放定律(Scaling Law)发现:模型的损失和模型参数量 NN、训练数据量 DD、计算量 CC 之间,呈现可预测的幂律关系。一个常用的形式是:

L(N,D)=E+ANα+BDβL(N, D) = E + \frac{A}{N^{\alpha}} + \frac{B}{D^{\beta}}

这里:

训练的计算量大约是 C≈6NDC \approx 6ND。有了缩放定律,就可以在小规模实验上拟合曲线,外推预测大模型的损失,在投入巨额算力之前做决策。

计算最优

给定固定的计算预算,应该训练多大的模型、用多少数据?早期的研究(Kaplan 等)倾向于把更多预算花在增大模型上。后来的 Chinchilla 研究修正了结论:参数量和数据量应该同步增长,计算最优的比例大约是每个参数对应 20 个词元。

过度训练

计算最优只考虑了训练成本。但是模型训练一次,却要推理无数次,更小的模型推理更便宜。所以现代大模型常常过度训练(Overtraining):用远超计算最优的数据量训练一个较小的模型。例如 Llama 3 的 8B 模型训练了约 15 万亿词元,是 Chinchilla 比例的近百倍;Qwen3 使用了 36 万亿词元。

对 MoE 模型,缩放定律中的参数量应该使用激活参数量,数据量的需求则相应变化。

涌现能力

大模型在规模超过某个阈值后,某些能力似乎突然出现,称为涌现能力(Emergent Abilities)。但是也有研究指出,这很大程度上取决于评测指标:用“完全正确才得分”的指标会呈现出突变,换成平滑的指标,能力其实是逐渐提升的。对读者来说,更重要的结论是:能力随规模提升的趋势是可以预测的,但是具体某项能力何时达到可用,仍然需要实测。

后训练和推理阶段也出现了新的缩放维度:强化学习的算力、推理时的计算量,后续章节会介绍。

训练系统

并行策略

大模型无法放进一张 GPU,必须把训练拆分到成百上千张 GPU 上。常用的并行方式有:

实际训练通常把这些方式组合起来使用。Megatron-LM、DeepSpeed、torchtitan 是常用的训练框架。

显存和效率

衡量训练效率的常用指标是模型浮点利用率(Model FLOPs Utilization,MFU):实际达到的计算量占硬件理论峰值的比例。大规模训练的 MFU 通常在 30% 到 50% 之间。

容错和持久化

规模越大,出故障越是常态。Llama 3 在 16K 张 H100 上训练的时候,大约 54 天里发生了 400 多次意外中断,其中大多数是硬件故障。所以大规模训练必须具备:

评估

预训练阶段的评估,目标是判断模型学到了什么,以及训练是否在正确的方向上:

预训练得到的是基座模型,它的评估和对话模型不同,后者会在微调综述中介绍。


本章,我们梳理了预训练领域的主流技术:

我们从零实现的 GPT 模型,是这些技术的起点。Transformer 的基本结构,至今仍是主流模型的骨架,后续的改进大多是在这个骨架上打补丁,而 2025 年以来的混合架构,也在开始改变骨架本身。

参考资料