Decoder-only 架构与 GPT 家族:从单向预测到大语言模型时代

在学习 BERT 时,我们看到 Transformer 的 Encoder 可以通过双向注意力充分理解上下文,从而完成分类、标注、匹配等任务。但如果把视线转向今天最主流的大语言模型,会发现另一条路线取得了压倒性成功:只保留 Decoder 的 Decoder-only 架构。这一路线的代表就是 GPT 家族。

从表面上看,Decoder-only 似乎比完整的 Encoder-Decoder 更“残缺”:它没有 Encoder,也没有 Cross-Attention,只能从左到右地看前文。但正是这种看似简单的结构,配合大规模数据、大规模算力和“预测下一个 Token”的训练目标,最终催生出了具备强大生成、推理和上下文学习能力的大语言模型。

本文将系统梳理 Decoder-only 架构的设计动机、GPT 的训练方式、从 GPT-1 到 GPT-3 的范式变化,以及现代大模型中常见的工程与结构改进,包括稀疏注意力、MoE、SwiGLU、RMSNorm、GQA/MQA 等。对于学习过程中常见的疑问,例如“GPT 是不是只是更大的工程堆叠”“预测下一个 Token 的损失函数如何定义”“为什么 GPT 可以不做微调”“In-context Learning 是否有理论依据”“MoE 的专家是不是预先训练好的”等,也会自然地融入正文解释中。

一、为什么 GPT 选择 Decoder-only

1. Encoder 与 Decoder 的分工

完整 Transformer 包含两部分:

  • Encoder:擅长理解输入序列。它的 Self-Attention 通常允许每个位置同时看到左右上下文,因此可以构建双向语义表示。
  • Decoder:擅长生成输出序列。它通过 Causal Mask 限制每个位置只能看到自己之前的位置,从而保证生成过程符合从左到右的顺序。

因此,Encoder 更像是一个“阅读理解器”,Decoder 更像是一个“逐字写作器”。

BERT 选择了 Encoder 路线,通过完形填空任务学习双向语义表示。GPT 则选择了 Decoder 路线,通过不断预测下一个词元来学习语言生成能力。

2. 生成任务天然是单向的

如果模型的目标是写文章、续写对话、生成代码,那么它在生成第 $t$ 个词时,不能依赖还没有生成的未来词。

例如,给定:

今天天气

模型需要继续生成:

很好,适合出门。

在生成“很好”的时候,模型只能看到“今天天气”,而不能提前看到后面的“适合出门”。这与人类写作的过程一致:下笔时只能基于已有内容继续推进。

因此,对于生成任务而言,Decoder 的单向性不是缺陷,而是与任务本身天然一致的性质。

3. 砍掉 Encoder 与 Cross-Attention 的好处

GPT 的设计者做了一个非常大胆但极其有效的选择:去掉 Encoder,也去掉 Decoder 中对 Encoder 输出的 Cross-Attention,只保留带有 Causal Mask 的 Self-Attention 和前馈网络。

这样做有几个直接好处。

第一,任务接口非常统一。训练时,模型的任务是“给定前文,预测下一个词”;推理时,用户输入一段提示词,模型继续预测后续词。训练和推理的数据流几乎完全一致。

第二,工程实现更简单。没有 Encoder,没有 Cross-Attention,模型主体就是一组结构相同、可以不断堆叠的 Transformer Block。这种纯粹结构非常适合大规模并行训练和推理优化。

第三,相同算力下更容易扩大规模。减少一部分模块后,可以把计算资源集中用于增加层数、扩大隐藏维度、增加注意力头数,从而训练更大的模型。

因此,Decoder-only 架构可以被简单概括为:

$$\text{Decoder-only} = \text{带 Causal Mask 的 Self-Attention} + \text{FFN}$$

当然,现代模型还会加入归一化层、残差连接、位置编码、词嵌入等基础组件,但其核心计算逻辑仍然可以这样理解。

二、GPT 的核心训练任务:自回归语言建模

1. 预测下一个 Token

BERT 的训练任务主要是完形填空,而 GPT 的训练任务可以形象地称为“词语接龙”。

给定前面的词元序列:$x_1, x_2, \dots, x_{t-1}$,模型需要预测下一个词元$x_t$,也就是建模条件概率:

$$p_\theta(x_t \mid x_1, x_2, \dots, x_{t-1})$$

对于整个序列$x_1, x_2, \dots, x_T$,模型的目标是最大化联合概率:

$$p_\theta(x_1, x_2, \dots, x_T) = \prod_{t=1}^{T} p_\theta(x_t \mid x_1, \dots, x_{t-1})$$

在实际训练中,通常使用交叉熵损失(等价于负对数似然)。假设词表大小为 $V$,模型在每个位置输出一个长度为 $V$ 的 logits 向量 $z_t$。经过 Softmax 后,真实下一个词 $x_t$ 对应的概率为:

$$p_\theta(x_t = v \mid x_{<t})=\frac{\exp(z_{t,v})}{\sum_{k=1}^{V} \exp(z_{t,k})}$$

该位置的损失为 $\ell_t=-\log p_\theta(x_t \mid x_{<t})$:如果模型给真实下一个词分配的概率很高,损失就小;如果概率很低,损失就大。对长度为 $T$ 的序列取平均,总损失为:

$$\mathcal{L}=-\frac{1}{T}\sum_{t=1}^{T}\log p_\theta(x_t \mid x_{<t})$$

训练时通过反向传播更新参数,使模型在海量文本上不断提升预测下一个词的能力。这就是自回归语言建模,也称 Autoregressive Language Modeling。

2. Causal Mask 的作用

为了让模型在预测当前位置时只看到历史信息,Decoder-only 模型在 Self-Attention 中使用 Causal Mask。

假设注意力分数矩阵为$A_{ij}$,其中 $i$ 表示当前要计算的位置,$j$ 表示被关注的位置。Causal Mask 的规则是:

$$A_{ij} = -\infty, \quad \text{如果 } j > i$$

也就是说,位置 $i$ 不能注意到任何位于它之后的位置。经过 Softmax 后,这些被遮蔽位置的注意力权重会接近 0。

例如,对于句子:

我 喜欢 吃 苹果

模型在预测“喜欢”时只能看到“我”;在预测“吃”时可以看到“我 喜欢”;在预测“苹果”时可以看到“我 喜欢 吃”。这种机制确保训练目标与生成过程一致。

3. 预训练数据如何组织

GPT 类模型的预训练数据通常来自大规模文本语料,例如网页、书籍、百科、代码、论文、论坛等。训练前,这些文本会被分词成 Token 序列,然后拼接成一个非常长的连续序列。

假设模型支持的最大上下文长度是 $L$。训练时可以从这个超长序列中截取长度为 $L$ 的片段。如果窗口内容为$x_1, x_2, \dots, x_L$,常见做法是进行错位对齐:

  • 模型输入:$x_1, x_2, \dots, x_{L-1}$
  • 目标标签:$x_2, x_3, \dots, x_L$

也就是说,标签就是输入向右移动一位后的结果。

这样,每个位置都会参与一次“预测下一个 Token”的训练。模型并不是只学习句子的最后一个词,而是在整个序列的每个位置上都学习如何根据前文预测后文。

如果文本中存在结束符,例如 [EOS],模型也需要学习在合适的位置预测结束符。这对于后续生成任务非常重要,因为模型需要知道什么时候可以停止生成。

4. 推理阶段还需要 Causal Mask 吗

一个常见问题是:训练时 Causal Mask 保证模型不能看到未来词,那么推理阶段还需要它吗?

答案是:因果关系仍然必须存在,只是实现方式可能不同。

在推理时,模型通常逐词生成。生成第 $t$ 个词时,模型只能基于已经生成的$x_1, x_2, \dots, x_{t-1}$进行预测。未来词还不存在,自然无法被看到。

为了提高效率,推理阶段通常会使用 KV Cache。模型会把之前 Token 的 Key 和 Value 缓存下来。生成新 Token 时,只需要计算当前 Token 的 Query,并与历史 Key、Value 做注意力计算,而不必重新计算整个前序序列。

在这种实现中,完整的掩码矩阵可能不再显式存在,但“当前位置只能看到历史位置”的约束仍然通过自回归生成过程和 KV Cache 的使用得以保持。

三、从 GPT-1 到 GPT-3:规模带来的能力跃迁

1. GPT-1:证明 Decoder-only 的可行性

GPT-1 出现在 2018 年,参数规模约为 1.17 亿。它的训练方式与当时的 BERT 有相似之处:先在无标注文本上进行预训练,再在具体下游任务上进行微调。

不过,GPT-1 使用的是 Decoder-only 架构,训练目标是预测下一个词。它证明了即使没有双向 Encoder,只靠自回归语言建模,也可以学习到有效的语言表示,并在若干 NLP 任务上取得不错效果。

但在当时,BERT 的双向预训练在理解类任务上表现非常突出,因此 GPT-1 的影响力相对有限。

2. GPT-2:Zero-shot 能力的出现

GPT-2 发布于 2019 年,参数规模扩大到约 15 亿。随着模型规模和数据规模增加,研究者发现模型开始表现出一种新能力:不需要针对特定任务进行微调,只通过输入中的自然语言指令,就可以完成某些任务。

这就是零样本能力,即 Zero-shot。

例如,输入:

请将以下英文翻译成中文:Hello world.

模型可能直接输出:

你好,世界。

这里并没有人为更新模型权重,也没有提供标注数据。模型只是根据预训练中学到的文本模式,顺着输入继续生成合理内容。

这说明,当模型足够大、预训练数据足够丰富时,许多任务的格式和逻辑可能已经在语言建模过程中被隐式学习。

3. GPT-3:In-context Learning 的爆发

GPT-3 发布于 2020 年,参数规模达到 1750 亿,相比 GPT-2 增加了约百倍。正是在这个规模上,上下文学习,即 In-context Learning,展现出了惊人效果。

所谓 In-context Learning,是指不更新模型参数,只在输入中提供少量示例,模型就能完成新任务。

例如,输入:

苹果 -> 水果
胡萝卜 -> 蔬菜
宝马 ->

模型可能输出:

汽车

这里模型没有经过梯度更新,也没有针对“类别归纳”任务进行微调。它只是根据上下文中的示例格式,继续生成最可能的后续内容。

这带来了一个重要变化:过去我们通常通过微调让模型适应任务,而在大模型时代,很多时候可以通过设计合适的 Prompt 来激发模型已有能力。

4. Scaling Law:规模、数据与算力的幂律关系

GPT-3 的成功离不开一个关键经验规律:Scaling Law,即缩放定律。

OpenAI 在 2020 年前后的研究表明,当模型参数量、训练数据量和计算量增加时,语言模型的测试损失会以较为平滑的幂律形式下降。具体来说,Kaplan 等人发现测试损失可以近似表示为:

$$L(N, D, C) \propto N^{-\alpha_n} D^{-\alpha_d} C^{-\alpha_c}$$

其中 $N$ 为模型参数量,$D$ 为训练数据量,$C$ 为计算量(FLOPs),$\alpha_n, \alpha_d, \alpha_c$ 为对应的幂律指数。这意味着只要持续提升规模,损失就会持续下降,并且在相当大的范围内没有明显饱和。

这给工业界带来了强烈信号:只要持续提升模型规模、数据规模和算力投入,模型能力还可能继续增长。当然,数据质量、训练稳定性、推理成本、对齐方法、安全机制等同样重要。但从经验上看,Scaling Law 确实为大模型的发展提供了重要指导。

5. 为什么单向预测也能产生强大能力

一个自然的疑问是:BERT 可以看到左右上下文,信息更全面;GPT 只能看到左侧上下文,为什么最后反而是 GPT 路线取得了更大成功?

可以从几个方面理解。

第一,生成即理解。为了准确预测下一个词,模型必须深度理解前文中的语义、逻辑、事实和格式。尤其在代码、数学、推理链、对话等场景中,预测下一个词需要模型掌握复杂的结构性规律。

第二,任务接口统一。训练时是“给上文,预测下文”;推理时也是“给上文,生成下文”。因此,用户的指令、示例、问题都可以作为上文的一部分,模型自然会顺着上下文继续生成。这使 In-context Learning 成为可能。

第三,规模扩展更直接。Decoder-only 结构简单,适合大规模并行训练和推理优化。当模型规模达到千亿甚至万亿级别时,简单结构反而更容易被工程系统充分扩展。

因此,GPT 的成功并不只是因为它“看得少”,而是因为它把单向生成、统一接口、规模扩展和海量数据结合成了一条可持续演化的技术路线。

四、微调、零样本与上下文学习

1. 微调是什么

微调,英文为 Fine-tuning,是指在预训练模型的基础上,用特定任务的标注数据继续训练模型。

预训练模型像是一个接受过通识教育的人。它读过大量文本,具备语言能力,但并不一定知道某个具体任务的输出格式。

例如,对于情感分类任务,我们希望模型输入一条评论,输出“正面”或“负面”。如果直接把评论交给早期 GPT 模型,它可能会继续续写评论,而不是给出分类标签。

这时可以准备一批带标签的数据:

这部电影太精彩了 -> 正面
剧情拖沓,人物单薄 -> 负面
服务态度很好,值得推荐 -> 正面

然后用这些数据继续训练模型。训练时通常使用较小学习率,更新模型参数,使模型学会在给定输入后输出任务期望的结果。

微调的本质是:在通用语言能力的基础上,让模型适应特定任务的输入输出分布。

2. 为什么 GPT-2 和 GPT-3 可以不做微调

GPT-2 和 GPT-3 之所以能够表现出 Zero-shot 或 In-context Learning 能力,核心原因在于规模和预训练数据。

互联网文本中天然包含大量类似任务格式的内容,例如问答、翻译、列表、说明、指令、代码注释、邮件往来等。模型在预测下一个词的过程中,会隐式接触这些结构。

当用户输入:

请将以下英文翻译成中文:Hello world.

模型并不一定“理解”这是一个翻译指令,但它可能在预训练中见过大量类似表达。因此,根据上下文,最自然的后续内容就是翻译结果。

也就是说,模型没有改变权重,而是利用已有权重中的知识和文本模式,通过生成方式完成任务。

3. 上下文学习与提示词

In-context Learning 可以看作比 Zero-shot 更进一步的能力。

Zero-shot 通常只给指令:

将以下句子翻译成英文:今天天气很好。

Few-shot In-context Learning 则会在输入中提供示例:

中文:今天天气很好。
英文:The weather is nice today.
中文:我喜欢吃苹果。
英文:

模型会根据示例格式继续生成答案。

这种方式的关键是:模型参数不更新。示例只影响模型的注意力计算和生成过程,而不是通过梯度下降改变权重。

如果面对一个模型预训练时从未见过的新任务,例如某种人工构造的“火星文翻译”:

地球 -> 咕噜
苹果 -> 吧啦
地球苹果 ->

如果只是想临时测试,可以在 Prompt 中给出足够清晰的示例,让模型通过 In-context Learning 尝试完成。

但如果这个任务需要长期、稳定、高效地使用,尤其是示例规则复杂、准确率要求高、调用次数多,那么更可靠的方式仍然是微调。微调可以把新规则写入模型参数,而 In-context Learning 则更像是在模型的短期工作记忆中临时使用规则。

4. In-context Learning 是否有理论依据

一个非常深刻的问题是:In-context Learning 和 Scaling Law 是否有严格的理论解释,还是仅仅是经验观察?

目前较准确的答案是:它们在很大程度上仍然是经验观察。科学界已经提出了许多解释,但尚未形成统一、严格、被普遍接受的理论。

对于 Scaling Law,研究者通过实验发现损失随模型规模、数据规模、算力规模呈幂律下降。传统统计学习理论中常见的“参数越多越容易过拟合”的直觉,并不能完全解释大模型在海量数据下反而泛化更好的现象。

对于 In-context Learning,一种有影响力的假说认为:大模型在预训练过程中隐式学习了某种元学习能力。当输入中出现示例时,Transformer 的注意力机制可能在内部执行了类似任务适配的过程,甚至有研究认为其前向传播在某种条件下可以模拟梯度下降。

但这些解释仍然有很多开放问题。例如,什么条件下 In-context Learning 会失效?示例顺序为什么会影响结果?模型到底是记住了任务格式,还是真正形成了某种抽象推理?这些都还没有完全清晰的答案。

因此,大语言模型的许多能力目前仍处于“工程上可复现、经验上可观察、理论上未完全解释”的状态。

五、稀疏注意力:长文本效率优化及其局限

1. 问题的来源:$O(N^2)$ 复杂度

在前面讨论 Attention 时我们已经知道,标准 Self-Attention 需要计算 $N \times N$ 的注意力矩阵,计算量和显存开销与序列长度的平方成正比。当 $N$ 较小时问题不大,但当 $N$ 达到数万甚至数十万时,显存和算力都会成为瓶颈。为了处理长文本,研究者提出了多种稀疏注意力方法,核心思想是:不改变 Attention 的数学本质,而是限制每个位置能够关注的范围,从而降低计算量。

2. 三种典型的稀疏方案

局部窗口注意力的思想是:每个 Token 只关注其附近一定范围内的 Token,例如前后各 512 个位置。这样复杂度可以从$O(N^2)$降低到近似$O(N \cdot w)$($w$ 是窗口大小)。这种方法符合语言的局部性:很多语法搭配和局部指代确实只需要附近上下文就能理解。但如果关键信息出现在窗口之外——例如文章开头定义了某个概念,而几万字之后才需要用到——单纯局部窗口就可能不够。

全局节点注意力为了缓解长距离传递问题,引入少量全局 Token,例如每隔一段距离设置一个锚点节点,或者使用类似 [CLS] 的特殊节点。局部 Token 通过全局节点间接交换远距离信息。但问题在于,如果所有远距离信息都必须经过少数全局节点,这些节点可能成为信息瓶颈。

块稀疏注意力将序列切分成若干块,块内部使用较密集的注意力,块之间只允许部分连接,例如每个块只关注相邻块。这样可以在局部表达能力和全局信息传递之间取得折中。但块边界也可能切断重要依赖——如果两个强相关位置恰好被分到不同块,模型仍然可能丢失信息。

3. 稀疏注意力的局限与现代方案

稀疏注意力的核心问题是:它通过人为限制注意力范围来降低计算量,但这种限制可能牺牲真实文本中必要的长距离依赖。因此,现代长文本模型往往不会简单依赖静态稀疏注意力,而是结合更多工程与算法手段。例如 FlashAttention 通过 IO 感知的分块计算在不改变注意力范围的前提下大幅加速,Ring Attention 采用分布式方式将长序列切分到多张卡上并行处理,此外还有更高效 KV Cache 管理、注意力压缩、检索增强等机制。这些方法的目标是在保持较长上下文能力的同时,控制显存和计算成本。

需要特别强调的是,稀疏注意力和 MoE 虽然都带有“稀疏”二字,但它们不是同一类技术。稀疏注意力主要减少 Token 之间的注意力连接,属于序列维度的稀疏;MoE 主要减少每个 Token 激活的 FFN 参数,属于参数计算维度的稀疏。

六、MoE:参数维度的稀疏化与专家路由

1. MoE 与稀疏注意力的区别

MoE 的全称是 Mixture of Experts,即混合专家。

稀疏注意力关注的是:一个 Token 应该关注哪些 Token。
MoE 关注的是:一个 Token 应该经过哪些 FFN 参数进行计算。

在标准 Transformer Block 中,每个 Token 都会经过同一个 FFN。假设 FFN 很大,那么每个 Token 的计算成本也很高。

MoE 的做法是:把 FFN 替换为多个专家网络。每个 Token 进入 MoE 层后,由一个 Router 决定它应该交给哪几个专家处理。

这样,模型可以拥有非常大的总参数量,但每个 Token 在前向传播时只激活其中一小部分专家,从而控制计算量。

例如,一个模型可能有 8 个、16 个甚至更多专家。每个 Token 只激活 Top-1 或 Top-2 个专家。于是,模型总参数可以很大,但每次计算只使用一部分参数。

2. 加入 MoE 后的 Transformer Block 结构

MoE 通常只替换 Transformer Block 中的 FFN 部分。Self-Attention、LayerNorm、残差连接等组件基本保持不变。

一个包含 MoE 的 Transformer Block 可以这样理解:

输入 $x$ 首先经过注意力子层:

$$x_{mid} = x + \text{Attention}(\text{Norm}(x))$$

然后进入 MoE 子层。MoE 子层内部先对 $x_{mid}$ 做归一化,得到:

$$h = \text{Norm}(x_{mid})$$

接着,Router 根据 $h$ 计算每个专家的得分,并选择 Top-K 个专家。假设选择了两个专家 $E_1$ 和 $E_2$,对应权重为 $g_1$ 和 $g_2$,则 MoE 输出为:

$$y = g_1 E_1(h) + g_2 E_2(h)$$

最后通过残差连接返回主路径:

$$x_{out} = x_{mid} + y$$

因此,MoE 并没有改变 Transformer 的整体流程,而是把原来单一的 FFN 换成了一个带路由机制的专家系统。

3. Router 如何工作

Router 通常是一个很简单的线性层。对于输入向量 $h$,Router 计算每个专家的得分:

$$s_i = h^\top w_i$$

或者写成矩阵形式$s = h W_g$,其中 $W_g$ 是 Router 的可学习参数。

得到得分后,通常会使用 Softmax 得到一个概率分布:

$$p_i = \frac{\exp(s_i)}{\sum_j \exp(s_j)}$$

然后选择概率最高的 Top-K 个专家。假设选择集合为 $S$,则最终路由权重可以写成:

$$ g_i = \begin{cases} \frac{p_i}{\sum_{j \in S} p_j}, & i \in S \\ 0, & i \notin S \end{cases}$$

最终 MoE 输出为:

$$y = \sum_{i \in S} g_i E_i(h)$$

如果 Top-K 等于 1,则每个 Token 只激活一个专家;如果 Top-K 等于 2,则激活两个专家,并按权重加权融合。

4. 专家不是预先训练好的

一个常见误解是:MoE 的专家矩阵是不是预先训练好的?是不是先准备一堆 FFN,然后让 Router 学习如何调用它们?

更准确的理解是:在标准 MoE 训练中,Router 和所有专家都是从随机初始化开始,在同一个训练目标下端到端联合训练出来的。

也就是说,并不存在一个先验的“专家库”被外部预先训练好,然后接入模型。专家之所以成为专家,是在训练过程中逐渐分化出来的。

训练初期,所有专家参数都是随机噪声,没有明确分工。随着训练进行,Router 学习如何分配 Token,专家学习如何处理分配给自己的 Token。最终,不同专家可能在不同类型的数据上表现更好,从而形成某种“分工”。

5. 负载均衡损失:避免所有 Token 都去同一个专家

MoE 训练中有一个关键问题:如果某个专家在初期表现稍好,Router 可能越来越倾向于把大量 Token 都分配给它。

这会导致严重后果:

  • 被频繁选中的专家得到大量梯度,变得越来越强;
  • 不被选中的专家几乎没有梯度,参数长期不更新;
  • 最终模型退化成只有一个专家在工作。

这种现象称为模式崩溃,或赢者通吃。

为了避免这一问题,MoE 通常会在主损失之外加入负载均衡损失。

一种常见思路是惩罚专家使用率的不均匀。假设有 $n$ 个专家,令:

  • $f_i$ 表示实际被路由到专家 $i$ 的 Token 比例;
  • $P_i$ 表示 Router 给专家 $i$ 的平均概率。

一种典型辅助损失形式为:

$$\mathcal{L}{aux}=\alpha n \sum{i=1}^{n} f_i P_i$$

其中 $\alpha$ 是权重系数。

如果 Router 把过多 Token 集中到少数专家,辅助损失会变大。总损失通常写成:

$$\mathcal{L}{total}=\mathcal{L}{LM}+\mathcal{L}_{aux}$$

其中 $\mathcal{L}_{LM}$ 是语言建模损失。

这样,Router 不仅要尽量选对专家,还要尽量让不同专家得到相对均衡的训练机会。

6. 专家容量限制

除了负载均衡损失,工程上还经常使用专家容量限制。

所谓专家容量,是指在一个批次中,某个专家最多处理多少个 Token。如果 Router 分配给某个专家的 Token 超过容量,超出部分可能被丢弃、溢出到其他专家,或采用其他兜底策略。

这相当于从物理层面防止某个专家被过度使用。它和负载均衡损失共同作用,迫使 Router 学会更分散地分配 Token。

7. MoE 的反向传播数学

假设某个 Token 经过 Router 后激活了两个专家 $E_1$ 和 $E_2$,权重分别为 $g_1$ 和 $g_2$。MoE 输出为:

$$y = g_1 E_1(h) + g_2 E_2(h)$$

设总损失为 $L$。我们关心损失对专家参数和 Router 参数的梯度。

对于专家 $E_1$ 的参数 $\theta_{E_1}$,链式法则给出:

$$\frac{\partial L}{\partial \theta_{E_1}}=\frac{\partial L}{\partial y}\frac{\partial y}{\partial E_1(h)}\frac{\partial E_1(h)}{\partial \theta_{E_1}}$$

因为:

$$y = g_1 E_1(h) + g_2 E_2(h)$$

所以:

$$\frac{\partial y}{\partial E_1(h)} = g_1$$

因此:

$$\frac{\partial L}{\partial \theta_{E_1}}=g_1\frac{\partial L}{\partial y}\frac{\partial E_1(h)}{\partial \theta_{E_1}}$$

这说明,专家接收到的梯度会被路由权重缩放。

如果某个专家没有被选中,即$g_i = 0$,那么它对应的梯度也为 0,参数不更新。这就是 MoE 中“谁被激活,谁获得梯度”的基本机制。

对于 Router 来说,问题更复杂。Router 需要学习如何输出权重 $g_i$,但 Top-K 操作本身是离散的硬选择(从 $n$ 个专家中选出 $K$ 个),这个选择过程不可直接求导。具体来说,$g_i$ 的计算分为三步:先算 Softmax 得概率 $p_i$,再用 Top-K 筛选,最后归一化。其中 Softmax 是可微的,但 Top-K 掩码是不可微的——路由器参数 $W_g$ 的微小变化可能改变 Top-K 的选择结果,产生梯度跳变。

实际实现中通常采用直通估计器(Straight-Through Estimator, STE)来近似处理:在前向传播时正常执行 Top-K 选择和归一化;在反向传播时,把 Top-K 掩码视为常数,让梯度直接穿过它传回 Softmax 输出,再经由 Softmax 的 Jacobian 传回 Router 参数。也就是说,Router 参数的梯度可以通过下式近似计算:

$$\frac{\partial L}{\partial W_g} \approx \frac{\partial L}{\partial g_i} \cdot \frac{\partial g_i}{\partial p_i} \cdot \frac{\partial p_i}{\partial W_g}$$

其中 $\frac{\partial p_i}{\partial W_g}$ 就是标准 Softmax 对线性层参数的梯度。在 Top-1 的简单情形下,$g_i = p_i$,梯度计算更为直接:$\frac{\partial L}{\partial W_g} = \frac{\partial L}{\partial p_i} \cdot \frac{\partial p_i}{\partial W_g}$,即被选中专家的损失梯度通过 Softmax Jacobian 传回 Router。

直观理解是:如果 Router 把较高权重分配给某个专家,但该专家的输出导致损失变大,梯度会告诉 Router 下次降低该专家的得分;如果某个专家的输出有助于降低损失,Router 则会倾向于在类似输入下更常选择它。

与此同时,辅助负载均衡损失 $\mathcal{L}{aux}$ 也会向 Router 传梯度。由于 $\mathcal{L}{aux}$ 同时依赖 Router 输出的概率 $P_i$ 和实际的 Token 分配比例 $f_i$,其梯度会推动 Router 调整得分,使不同专家的使用率趋于均衡。

因此,Router 实际上同时受到两个目标约束:

  • 主损失要求它选得准;
  • 辅助损失要求它分得匀。

在这两种力量的共同作用下,模型才可能稳定训练,并逐渐形成有效的专家分工。

8. “数学专家”“代码专家”是真的存在吗

我们经常会听到这样的说法:某个专家擅长数学,某个专家擅长代码,某个专家擅长文学。

严格来说,这些标签通常是人类事后观察得到的总结,而不是模型内部预先定义的角色。

在初始化时,所有专家都是随机参数,没有谁天生是数学专家或代码专家。训练过程中,由于不同专家接收到的数据分布不同、梯度更新路径不同,它们可能逐渐在某些类型的数据上表现更好。

研究者可以通过观察哪些 Token 更容易激活哪些专家,发现某些专家似乎更常处理代码,某些专家更常处理对话,某些专家更常处理数学符号。于是,人类会给它们贴上相应标签。

但这并不意味着模型内部存在一个明确写着“数学专家”的模块。所谓专家分工,是训练目标、路由机制、负载均衡约束和梯度下降共同作用下涌现出来的结果。

七、现代大模型的常见架构改进

1. 主流大模型的架构现状与演进

目前常见的大语言模型,例如 LLaMA、Qwen、DeepSeek、Mistral、ChatGLM 等,其文本生成主干大多采用 Decoder-only 架构。一些闭源模型如 Claude、Grok、Kimi 等,核心文本生成能力也建立在自回归 Decoder 之上,具体实现可能包含 MoE、长上下文优化、注意力改进等工程策略,但基本生成逻辑仍然是“根据前文预测下一个 Token”。Gemini 这类多模态模型底层可能融合多种架构,但从文本生成角度看,仍然表现出自回归生成的特征。

从 GPT-1 到 GPT-3,再到现代开源大模型,最核心的训练范式仍然是自回归语言建模。但这并不意味着它们只是简单地把参数堆大——现代模型在训练稳定性、推理效率、长上下文能力、显存占用等方面做了大量改进,包括但不限于:更稳定的归一化方式、更强的前馈网络激活函数、更高效的注意力 KV 缓存、更先进的位置编码、更复杂的并行训练策略、MoE 等参数稀疏化机制、更精细的数据清洗和配比、指令微调和人类偏好对齐等。因此,现代大模型不是“只是更大的 GPT-3”,而是在相同基本范式上进行了大量工程和算法优化。接下来我们分别介绍其中几个最重要的架构改进。

2. RMSNorm:更轻量的归一化

早期 Transformer 常使用 LayerNorm。LayerNorm 会对向量计算均值和方差:

$$\text{LayerNorm}(x)=\frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}}\gamma + \beta$$

其中:

$$\mu = \frac{1}{d} \sum_{i=1}^{d} x_i$$

$$\sigma^2 = \frac{1}{d} \sum_{i=1}^{d} (x_i - \mu)^2$$

RMSNorm 则省略了均值中心化步骤,只使用均方根进行缩放:

$$\text{RMSNorm}(x)=\frac{x}{\sqrt{\frac{1}{d} \sum_{i=1}^{d} x_i^2 + \epsilon}}\gamma$$

它的优点是计算更简单,显存开销更小,同时在实践中往往足够稳定。

对于超大模型来说,这种看似微小的计算节省,在每一层、每一步、每一张卡上都会累积成可观的效率提升。

3. SwiGLU:更强的前馈网络

传统 FFN 通常写成:

$$\text{FFN}(x)=\sigma(xW_1 + b_1) W_2 + b_2$$

其中 $\sigma$ 可以是 ReLU、GELU 等激活函数。

GLU,即 Gated Linear Unit,引入了门控思想:

$$\text{GLU}(x)=(xW_1) \otimes \sigma(xW_2)$$

其中 $\otimes$ 表示逐元素相乘。

这里可以将$xW_1$看作候选信息,把$\sigma(xW_2)$看作门控信号。门控信号决定哪些信息应该通过,哪些信息应该被抑制。

SwiGLU 是 GLU 的一种常见变体,使用 Swish 作为激活函数:

$$\text{Swish}(x) = x \cdot \text{sigmoid}(x)$$

典型形式可以写为:

$$h = \text{Swish}(xW_{gate}) \otimes xW_{up}$$

然后:

$$y = hW_{down}$$

相比普通 ReLU 或 GELU FFN,SwiGLU 具有更平滑的非线性,并且门控结构使模型可以更精细地控制信息流动。它在许多现代大模型中被广泛使用。

4. MQA 与 GQA:压缩 KV Cache

在自回归推理中,KV Cache 是非常重要的优化。模型会缓存历史 Token 的 Key 和 Value,以避免重复计算。

但标准多头注意力中,每个注意力头都有独立的 Key 和 Value。如果注意力头数很多,KV Cache 会占用大量显存,尤其在长文本生成时非常明显。

为了解决这个问题,研究者提出了 MQA 和 GQA。

MQA,即 Multi-Query Attention,让所有 Query 头共享同一组 Key 和 Value。

假设 Query 头数为 $H_q$。在标准 MHA 中:

$$H_k = H_v = H_q$$

在 MQA 中:

$$H_k = H_v = 1$$

这样 KV Cache 大小会显著降低,推理速度也更快。但缺点也比较明显:表达能力可能下降,模型质量可能受损。

GQA,即 Grouped-Query Attention,是 MHA 和 MQA 之间的折中方案。

它把 Query 头分成若干组,每组共享一组 Key 和 Value。假设 Query 头数为 32,可以使用 8 组 KV。那么每 4 个 Query 头共享一组 Key 和 Value。

可以这样理解:

  • MHA:每个 Query 头都有自己的 KV;
  • MQA:所有 Query 头共享一组 KV;
  • GQA:Query 头分组,每组共享一组 KV。

如果 Query 头数为 $H_q$,KV 头数为 $H_{kv}$,则:

$$1 \le H_{kv} \le H_q$$

当$H_{kv} = H_q$,就是标准 MHA;当$H_{kv} = 1$,就是 MQA;当$1 < H_{kv} < H_q$,就是 GQA。

GQA 的优势在于,它可以在几乎不明显损失模型质量的前提下,大幅降低 KV Cache 占用和推理带宽压力。因此,它已成为许多现代大模型的重要配置。

5. 参数到底指什么

当我们说一个模型有 7B、70B、175B 参数时,“参数”指的是模型中所有可学习张量中的数值总量。

具体包括:

  • 词嵌入矩阵;
  • 位置编码中可学习的部分,如果有;
  • 每个 Transformer Block 中的 $W_Q, W_K, W_V, W_O$;
  • FFN 中的权重矩阵;
  • 归一化层中的缩放参数;
  • 可能存在的 Router 参数;
  • 输出层或语言模型头中的权重,有时可能与词嵌入共享。

如果模型使用 MoE,还要区分总参数量和激活参数量。

例如,一个 MoE 模型可能有 1 万亿总参数,但每个 Token 只激活 100 亿参数。此时:

  • 总参数量反映模型容量;
  • 激活参数量决定单次前向计算成本。

6. 更大的参数规模意味着什么

当模型从 7B 扩大到 70B,通常不是简单把某个数字乘以 10,而是多个维度同时扩大。

第一,隐藏层维度变大。记为 $d_{model}$。隐藏维度越大,每个 Token 的表示容量越大。

第二,层数变多。更多 Transformer Block 意味着更长的计算路径,模型可以进行更复杂的特征变换和抽象推理。

第三,FFN 中间维度变大。FFN 通常占据模型参数的很大比例,扩大 FFN 会显著增加模型容量。

第四,注意力头数或 KV 配置变化。更多头数可以让模型从不同子空间捕捉不同类型的依赖关系。

第五,词表、上下文长度、训练数据规模等也可能同步变化。

因此,“更大的参数”并不只是一个抽象数字,而是意味着更大的矩阵、更深的网络、更宽的表示空间,以及更强的拟合能力。

Scaling Law 之所以重要,正是因为在足够数据和算力支撑下,这种容量扩张可以转化为更强的语言建模能力和任务表现。

八、从架构到范式:Decoder-only 的真正意义

1. 简单结构配合统一目标

Decoder-only 架构的成功,首先来自它极其简单的任务接口:给定前文,预测下一个 Token。

这个目标看似朴素,但在海量文本上持续优化时,会迫使模型学习词法、句法、语义、事实知识、代码结构、数学格式、对话模式等大量规律。

它不要求人工设计复杂标签,也不依赖任务特定结构。只要文本存在,就可以继续训练。

2. 从微调到提示再到对齐

早期模型更多依赖微调:为每个任务准备数据,更新模型参数。

大模型时代出现了新的变化:通过 Prompt、Few-shot 示例、指令微调、人类反馈等方式,模型可以更灵活地响应任务。

其中,In-context Learning 让我们看到模型可以在不更新参数的情况下,通过上下文示例适应新任务。指令微调和偏好对齐则进一步让模型更符合人类交流习惯。

这些技术共同改变了 NLP 的开发方式:过去是“为任务训练模型”,现在更多是“通过合适接口激发模型能力”。

3. 工程优化与算法改进同样重要

现代大模型的竞争力不只取决于参数量,也取决于训练和推理效率。

稀疏注意力、长上下文工程、KV Cache 压缩、GQA/MQA、MoE、SwiGLU、RMSNorm 等改进,都是为了让模型在更大规模下仍然可训练、可部署、可推理。

这些改进往往不会改变“预测下一个 Token”的核心目标,但会显著影响模型的成本、速度、上下文长度和实际可用性。

4. 仍然开放的问题

尽管 Decoder-only 大模型已经取得巨大成功,但仍有许多问题没有完全解决。

例如:

  • In-context Learning 的严格理论解释是什么?
  • Scaling Law 在什么条件下会失效?
  • 模型到底是在记忆数据,还是在进行抽象推理?
  • 如何更可靠地评估大模型能力?
  • 如何让模型在保持能力的同时显著降低推理成本?
  • 如何更好地进行长文本建模而不损失关键信息?
  • 多模态模型是否会在架构上产生新的范式?

这些问题意味着,大模型领域仍然处在快速发展阶段。今天看起来成熟的结构,未来也可能被新的架构或训练方法改变。

九、总结

Decoder-only 架构的核心思想非常清晰:去掉 Encoder 和 Cross-Attention,只保留带因果掩码的 Self-Attention 和 FFN,通过自回归方式预测下一个 Token。GPT 家族证明了这个看似简单的架构具有极强的扩展能力:GPT-1 验证了 Decoder-only 预训练的可行性,GPT-2 展示了零样本任务能力,GPT-3 则通过 1750 亿参数的规模带来了上下文学习和涌现能力。Scaling Law 进一步表明,测试损失与参数量、数据量、计算量之间近似满足幂律关系($L \propto N^{-\alpha_n} D^{-\alpha_d} C^{-\alpha_c}$),为大模型的规模扩展提供了经验指导。

在训练层面,GPT 的损失函数本质上是交叉熵损失在每个位置上的平均。预训练数据通常被拼接成长序列,通过输入标签错位的方式,让模型在每个位置都学习根据前文预测后文。在应用层面,微调、零样本和上下文学习代表了三类不同的任务适配方式:微调更新模型参数;零样本依靠指令直接生成;上下文学习则依靠输入中的示例,在不更新参数的情况下引导模型输出。

在架构演进层面,现代大模型仍然采用 Decoder-only 主干,但加入了大量优化:RMSNorm 省去均值中心化步骤以提高归一化效率,SwiGLU 通过门控结构增强 FFN 的表达能力,GQA/MQA 通过分组共享 KV 压缩缓存占用,MoE 则通过专家路由实现参数维度的稀疏化。其中 MoE 值得特别强调:它不是预先训练好一批专家再拼接,而是让 Router 和专家在端到端训练中共同学习;通过负载均衡损失和专家容量限制,模型可以避免赢者通吃,并逐渐形成不同专家的处理偏好。

整体来看,Decoder-only 大模型的成功不是单一因素造成的,而是简单架构、统一训练目标、海量数据、大规模算力、工程优化和规模效应共同作用的结果。预测下一个 Token 这一看似基础的任务,在足够大的规模下,可以演化出复杂而强大的语言能力。