目标:系统性地理解现代大语言模型(如 GPT)背后的核心训练机制,从最基础的因果注意力开始,一直讲到正则化与泛化,形成完整的知识图谱。
前置要求:了解基本的神经网络概念(前向传播、反向传播)和线性代数基础(矩阵乘法、向量点积)。
本文将沿一条清晰的逻辑主线展开:架构设计 → 优化目标 → 学习算法 → 泛化控制。我们将从 Transformer 的核心——注意力机制出发,逐步构建起对大语言模型训练全貌的理解。
在进入正题之前,先简要说明大语言模型训练的"全景图"。一个 LLM 的诞生大致经历三个阶段:预训练(在海量文本上学习语言规律)、监督微调(SFT)(学习遵循指令)和人类偏好对齐(RLHF)(让输出更符合人类期望)。本文聚焦于这些阶段背后通用的基础机制——无论哪个阶段,都离不开注意力架构、损失函数、优化器和正则化。
0. 从文本到向量——Tokenization 与词嵌入
在进入 Transformer 架构之前,需要先解决一个基础问题:如何将人类的文本变成模型能处理的数字? 这个过程分为两步:Tokenization(分词)和词嵌入(Embedding)。
0.1 Tokenization:将文本切分为 Token
最朴素的做法是按空格切分,但这会面临两个严重问题:未登录词(OOV)和词表过大。现代大语言模型普遍采用字节对编码(BPE, Byte Pair Encoding):
- 初始时,词表由单个字符(或字节)组成。
- 统计训练语料中相邻字符对的出现频率,将最频繁的字符对合并为一个新 Token。
- 重复此过程,直到词表达到预设大小。
类比:汉字的偏旁部首。BPE 就像学习汉字时发现"木"+“目”= “相”。常用词被编码为单个 Token(如"hello"),罕见词被拆解为子词片段(如"un"+“common”+“ly”),从而在有限词表下覆盖任意文本。
0.2 词嵌入与权重共享
Tokenization 输出的整数序列需要映射为连续向量。词嵌入层本质上是一个查找表:
$$ \text{Embedding}(x) = E[x] \in \mathbb{R}^{d_{\text{model}}} $$其中 $E \in \mathbb{R}^{|V| \times d_{\text{model}}}$ 是嵌入矩阵,$|V|$ 是词表大小,$d_{\text{model}}$ 是模型维度。
一个重要的技巧是权重共享(Weight Tying):让输入嵌入矩阵和输出层(LM Head)的权重矩阵共享同一组参数。直觉上,语义相近的词在输入和输出空间中应该有相近的表示。这一技巧能大幅减少参数量,同时提升性能。
1. 因果注意力——大语言模型的"眼睛"
1.1 什么是注意力机制
想象你正在阅读一句话:「今天天气真好,我想去____」。当你预测下一个词时,你的大脑会自动"回看"前面的每个词,并赋予不同的关注度——“天气真好"和"想去"对你预测"公园"或"散步"的贡献最大,而"今天"的贡献相对较小。
注意力机制(Attention) 正是对这一过程的数学建模。它让模型在生成每一个新词时,能够动态地"回看"之前的所有词,并根据相关性分配不同的权重。
1.2 Q、K、V 的物理意义
注意力机制的核心是三个向量:Query(查询)、Key(键) 和 Value(值)。它们通过线性变换从输入词嵌入中产生:
$$ Q = XW^Q, \quad K = XW^K, \quad V = XW^V $$其中 $X$ 是输入序列的词嵌入矩阵,$W^Q$、$W^K$、$W^V$ 是可学习的参数矩阵。
类比:图书馆查书
- Query(查询):你脑中的问题——“我想找关于深度学习的资料”
- Key(键):每本书封面的关键词标签——“机器学习”、“烹饪”、“深度学习入门”
- Value(值):每本书的实际内容——书页里的具体文字
注意力的计算过程就是:用你的问题(Q)去和每本书的标签(K)做匹配,匹配度越高的书,你读得越仔细(V 的权重越大)。
1.3 缩放点积注意力
注意力的计算公式如下:
$$ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V $$逐步拆解:
- $QK^T$:计算 Query 和每个 Key 的点积,得到"相关性分数”。维度为 $d_k$ 的两个向量做点积,结果的量级大约是 $d_k$。
- 除以 $\sqrt{d_k}$:当 $d_k$ 很大时,点积的值会很大,导致 Softmax 的输入进入梯度极小的"饱和区"。除以 $\sqrt{d_k}$ 将方差稳定在 1 附近,让梯度传播更健康。
- Softmax:将相关性分数转化为概率分布,确保所有权重之和为 1,且非负。
- 乘以 $V$:用概率分布对 Value 向量做加权求和,得到最终的注意力输出。
Softmax 的数学定义
$$ \text{softmax}(z_i) = \frac{e^{z_i}}{\sum_{j} e^{z_j}} $$它将任意实数向量映射为一个概率分布:每个元素在 0 到 1 之间,且所有元素之和为 1。
数值稳定性技巧:在实际实现中,直接计算 $e^{z_i}$ 可能导致数值溢出(当 $z_i$ 很大时)。解决方案是先减去最大值:
$$ \text{softmax}(z_i) = \text{softmax}(z_i - \max_j z_j) $$这个变换在数学上完全等价(因为 $e^{z_i - c}$ 和 $e^{z_i}$ 只差一个常数因子,会被分母消掉),但数值上避免了溢出。这是所有深度学习框架(PyTorch、TensorFlow)的标准做法。
具体数值示例:假设序列长度为 3,$d_k = 2$,已知:
$$ Q = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}, \quad K = \begin{bmatrix} 1 & 0 \\ 0 & 1 \\ 1 & 1 \end{bmatrix}, \quad V = \begin{bmatrix} 1 & 2 \\ 3 & 4 \\ 5 & 6 \end{bmatrix} $$第一步,计算注意力分数(暂不缩放和掩码):
$$ QK^T = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 1 \\ 0 & 1 & 1 \end{bmatrix} = \begin{bmatrix} 1 & 0 & 1 \\ 0 & 1 & 1 \end{bmatrix} $$第二步,除以 $\sqrt{d_k} = \sqrt{2} \approx 1.414$,然后对每一行做 Softmax:
$$ \text{softmax}\left(\frac{[1, 0, 1]}{\sqrt{2}}\right) = \text{softmax}([0.707, 0, 0.707]) \approx [0.405, 0.190, 0.405] $$第三步,用概率分布加权求和 V:
$$ \text{output}_1 = 0.405 \times [1,2] + 0.190 \times [3,4] + 0.405 \times [5,6] = [2.99, 3.82] $$可以看到,位置 1 的输出对位置 1 和位置 3(相关性分数相同)的 Value 给予了更高的权重。
1.4 因果注意力:下三角掩码
在传统的注意力机制中,每个位置可以看到序列中的所有位置。但对于语言模型来说,这会导致"偷看未来"——生成第 3 个词时不能让它看到第 4 个词的答案,否则就是作弊。
因果注意力(Causal Attention) 通过一个下三角掩码矩阵来解决这个问题:
$$ M_{ij} = \begin{cases} 0 & \text{if } i \geq j \\ -\infty & \text{if } i < j \end{cases} $$掩码加在 Softmax 之前:
$$ \text{CausalAttention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}} + M\right)V $$被设为 $-\infty$ 的位置,经过 Softmax 后权重变为 $e^{-\infty} \approx 0$,相当于被完全屏蔽。
类比:传话游戏中的"只能听到已说过的部分"
想象一排人玩传话游戏,每个人只能听到之前所有人说过的话,不能预知后面的人会说什么。因果注意力就是这个"隔音屏障"——第 $t$ 个位置只能看到位置 $1, 2, \ldots, t-1$ 以及位置 $t$ 自身的信息。
1.5 “只能看到第 1 到 t-1 个词"的真实含义
这里有一个常见的误解需要澄清:当说"第 $t$ 个位置只能看到前 $t-1$ 个词"时,意思是它可以同时看到全部历史,而不仅仅是前一个词。这是一个全局视野,不是滑动窗口。
例如,当模型生成第 10 个词时,它可以同时关注第 1 到第 9 个词中的任何一个。这正是 Transformer 相比 RNN 的一个关键优势——我们将在后文详细讨论。
2. Transformer 的配套设计
2.1 多头注意力(Multi-Head Attention)
单个注意力头只能捕捉一种"关注模式”。但语言中的关系是多维的:一个词可能同时需要关注语法关系、语义关系、位置关系等。
多头注意力的思路很简单:把 $d_k$ 维的 Q、K、V 拆成 $h$ 个头,每个头独立计算注意力,最后拼接起来:
$$ \text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \ldots, \text{head}_h)W^O $$其中每个头:
$$ \text{head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V) $$类比:不同专家看同一幅画
- 专家 A 关注颜色搭配(语法结构)
- 专家 B 关注光影关系(语义关联)
- 专家 C 关注视觉焦点(长距离指代)
每个人从不同角度分析,最后汇总意见,得到更全面的理解。
关于降维的"多角度学习"目的:每个头的维度是 $d_k / h$,这是一种降维操作。其目的不是压缩信息,而是让不同的头在不同的低维子空间中学习不同的注意力模式,实现"多角度学习"。
2.2 位置编码(Positional Encoding)
注意力机制本身是"无序"的——它只关心 Q 和 K 的相似度,不关心位置。如果把句子打乱顺序,注意力的输出不会变。但语言显然有顺序:“狗咬人"和"人咬狗"意思完全不同。
因此需要位置编码来注入位置信息。
绝对位置编码:直接给每个位置一个固定的或可学习的向量,加到词嵌入上:
$$ \text{Input} = \text{TokenEmbedding}(x) + \text{PositionEmbedding}(pos) $$原始 Transformer 使用正弦/余弦函数生成固定编码:
$$ PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d}}\right), \quad PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d}}\right) $$相对位置编码:不编码绝对位置,而是编码"两个词之间的距离”。例如 RoPE(Rotary Position Embedding)通过旋转矩阵将相对位置信息融入 Q 和 K 的点积中,让注意力分数自然地反映位置距离。这是现代大语言模型(如 LLaMA)的主流方案。
2.3 残差连接与层归一化
每一个 Transformer 子层(注意力层或 FFN 层)都被包装在残差连接和层归一化之中。原始 Transformer 采用 Post-Norm(后归一化):
$$ \text{output} = \text{LayerNorm}(x + \text{SubLayer}(x)) $$但现代大语言模型(GPT-2 以后、LLaMA 等)普遍采用 Pre-Norm(前归一化):
$$ \text{output} = x + \text{SubLayer}(\text{LayerNorm}(x)) $$Pre-Norm vs Post-Norm 的区别
- Post-Norm:先做子层变换和残差相加,再归一化。优点是最终输出范围严格受控;缺点是梯度需要穿过 LayerNorm 才能到达残差路径,深层网络训练不稳定。
- Pre-Norm:先归一化再做子层变换,残差路径上没有 LayerNorm 阻挡。梯度可以通过残差路径"无障碍"地传到最前面的层,训练更稳定,支持更深的网络。
类比:先检查还是后检查。Post-Norm 像是产品出厂后才做质检,如果不合格就要返工;Pre-Norm 像是原材料进厂前就做好质检,生产线上的每一步都用合格的材料,成品率更高。
残差连接(Residual Connection)
类比:高速公路的出口匝道。主干道(原始信号 $x$)直接通到终点,匝道(子层变换 $\text{SubLayer}(x)$)提供额外的信息增益。即使匝道暂时施工(梯度很小),主干道依然畅通,信息不会丢失。
残差连接的核心价值:
- 梯度高速公路:反向传播时,梯度可以通过恒等映射直接传到前面的层,缓解深层网络的梯度消失问题。
- 更容易学习:网络只需学习"增量修改"($\text{SubLayer}(x)$),而不是从头重新表示整个输入。
层归一化(LayerNorm)
对同一个样本的所有特征维度做归一化:
$$ \text{LayerNorm}(x) = \gamma \cdot \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} + \beta $$其中 $\mu$ 和 $\sigma^2$ 是在特征维度上计算的均值和方差,$\gamma$ 和 $\beta$ 是可学习的缩放和偏移参数。
LayerNorm 的作用是将每一层的激活值稳定在合理的范围内,防止数值在深层网络中逐层放大或缩小,从而加速训练收敛。
3. 前馈网络(FFN)——升维与降维
3.1 FFN 的"升维→激活→降维"结构
每个 Transformer 层除了注意力子层之外,还有一个前馈网络(FFN):
$$ \text{FFN}(x) = W_2 \cdot \text{ReLU}(W_1 x + b_1) + b_2 $$其中 $W_1$ 将维度从 $d_{\text{model}}$ 映射到 $d_{\text{ff}}$(通常是 $4 \times d_{\text{model}}$),$W_2$ 再映射回 $d_{\text{model}}$。
这就是典型的升维→激活→降维结构:
- 升维($W_1$):将输入投影到更高维的空间,增加模型的表达能力。在高维空间中,原本纠缠在一起的特征更容易被线性分离。
- 激活(ReLU):引入非线性,让模型能够学习复杂的决策边界。
- 降维($W_2$):压缩回原始维度,保留关键信息。
类比:搅拌机原理。把水果(输入)放入大容量搅拌机(升维空间),充分搅拌(非线性激活),再倒回杯子(降维)。大容量搅拌机能让果汁混合得更均匀。
3.2 现代 FFN 变体:SwiGLU
原始 Transformer 使用 ReLU 作为激活函数,但现代大语言模型(如 LLaMA、PaLM)普遍采用 SwiGLU 激活,其公式为:
$$ \text{FFN}_{\text{SwiGLU}}(x) = W_2 \left[ \text{Swish}(W_1 x) \odot (W_3 x) \right] $$其中 $\text{Swish}(x) = x \cdot \sigma(x)$,$\sigma$ 是 Sigmoid 函数,$\odot$ 表示逐元素相乘(门控机制)。
与原始 FFN 的区别
- 引入了门控机制(第三个矩阵 $W_3$),让模型可以动态地"选择"哪些特征通道应该被激活。
- Swish 是一种"平滑的 ReLU",在零点附近没有突变,梯度更平滑。
- 为了保持参数量不变,中间维度从 $4d_{\text{model}}$ 缩减为 $\frac{8}{3}d_{\text{model}}$(约 2.67 倍)。
为什么 SwiGLU 效果更好? 门控机制相当于让 FFN 有了"选择性注意力"——不是所有中间特征都一视同仁地被激活,而是根据输入动态调节。这提升了 FFN 的表达能力和参数效率。
3.3 FFN 作为键值存储器
近年来的研究提出了一个有趣的假说:FFN 的两层权重矩阵可以看作一个键值存储器(Key-Value Memory)。
- 第一层权重 $W_1$ 的每一行是一个"键"(key),模式类似于"当输入匹配某种语义模式时激活"。
- 第二层权重 $W_2$ 的每一列是对应的"值"(value),存储了该模式对应的输出知识。
FFN 本质上存储了大量"如果遇到 X 模式,就输出 Y"的规则。这解释了为什么增大 FFN 的中间维度(即增加存储容量)能显著提升模型的知识存储能力。
3.4 澄清:加权操作不等于升维
需要注意的是,注意力机制中的加权求和操作虽然涉及多个向量的组合,但它不是升维。加权求和的结果维度和单个 Value 向量相同:
$$ \text{output} = \sum_i \alpha_i V_i \in \mathbb{R}^{d_v} $$这是一种同维度的混合,不会增加表示的维度。真正的升维是通过线性变换(如 FFN 中的 $W_1$)将特征投影到更高维的空间。
4. Transformer 相比 RNN 的优势
在 Transformer 出现之前,循环神经网络(RNN)及其变体(LSTM、GRU)是序列建模的主流方案。Transformer 相比 RNN 有以下关键优势:
4.1 长距离依赖
RNN 的信息必须逐步传递——第 100 个词的信息要经过 99 步才能到达第 1 个词的位置,即使有 LSTM 的门控机制,信息仍然会逐步衰减。
Transformer 的注意力机制是直接连接——第 100 个位置可以直接关注第 1 个位置,路径长度为 $O(1)$,不存在信息衰减问题。
类比:电话 vs 传话游戏。RNN 像传话游戏,信息在传递过程中逐渐失真;Transformer 像电话,任意两人可以直接通话。
4.2 并行计算
RNN 的计算是串行的:必须先计算 $h_1$,才能计算 $h_2$,依此类推。对于长度为 $n$ 的序列,需要 $O(n)$ 步顺序计算。
Transformer 的注意力计算是完全并行的:所有位置的 Q、K、V 可以同时计算,注意力矩阵可以一次性得出。在训练时(处理已知的完整序列),这可以充分利用 GPU 的并行计算能力,大幅加速训练。
4.3 梯度传播稳定性
RNN 的梯度需要通过时间步逐步反向传播,链式法则的连乘效应导致梯度容易消失或爆炸(梯度消失/爆炸问题)。
Transformer 的注意力是"一步到位"的矩阵运算,配合残差连接,梯度可以通过捷径直接传播,稳定性远优于 RNN。
4.4 KV Cache 推理加速
在自回归生成(逐词生成)时,Transformer 有一个巧妙的优化:KV Cache。
生成第 $t$ 个词时,注意力需要用到所有前 $t-1$ 个位置的 K 和 V。但这些值在之前生成时已经计算过了,不需要重复计算。KV Cache 将已计算的 K 和 V 缓存起来,每生成一个新词只需计算新位置的 Q、K、V,然后与缓存拼接,将推理复杂度从 $O(t^2)$ 降低到 $O(t)$。
4.5 Flash Attention:内存效率的革命
标准注意力计算需要将完整的注意力矩阵 $QK^T \in \mathbb{R}^{n \times n}$ 存储在 GPU 的 HBM(高带宽内存)中,内存复杂度为 $O(n^2)$。当序列长度 $n$ 很大时(如 8192 或更长),这成为严重的内存瓶颈。
Flash Attention(Dao et al., 2022)通过分块计算(tiling) 和在线 Softmax 技术,避免了完整注意力矩阵的物化:
- 将 Q、K、V 分成小块,每次只在 SRAM(片上缓存,速度快但容量小)中计算一块的注意力。
- 通过在线算法,在不存储完整 $QK^T$ 矩阵的情况下,逐步计算出正确的 Softmax 输出。
- 内存复杂度从 $O(n^2)$ 降到 $O(n)$,同时利用了 SRAM 的高速特性,实际速度反而更快。
类比:流水线作业。标准注意力像是一次性把所有食材铺满整个厨房台面再开始做菜;Flash Attention 像是流水线——每次只处理一小批食材,用完就清理台面,腾出空间处理下一批。台面(内存)占用大大减少,效率反而更高。
Flash Attention 已成为现代 LLM 训练和推理的事实标准,几乎所有主流框架(HuggingFace、vLLM)都已集成。
5. 训练基础组件
5.1 权重、损失函数、梯度——下山比喻
训练神经网络就像在大雾中下山:
- 权重(Weights):你在山上的位置坐标。你的目标是找到海拔最低的山谷(最优解)。
- 损失函数(Loss):海拔高度。它衡量你当前的"错误程度"——位置越差,海拔越高。
- 梯度(Gradient):脚下的坡度方向。它告诉你往哪个方向走能最快降低海拔。
- 学习率(Learning Rate):每一步的步幅大小。步幅太大可能跨过山谷(发散),步幅太小则下山太慢。
5.2 学习率与梯度下降
梯度下降的更新公式:
$$ w_{t+1} = w_t - \eta \cdot \nabla_w L(w_t) $$其中 $\eta$ 是学习率,$\nabla_w L(w_t)$ 是损失函数对权重 $w$ 的梯度。
直观理解:沿着梯度的反方向(即损失下降最快的方向)移动一步。学习率 $\eta$ 控制步幅。
学习率调度:实践中,学习率通常不是固定的。最常用的策略是 Warmup + Cosine Decay:
- Warmup 阶段(前 1%~5% 步数):学习率从 0 线性增长到目标峰值 $\eta_{\text{max}}$。原因是在训练初期,模型参数几乎是随机的,梯度方向很不稳定。如果一开始就用大学习率,参数可能被"甩飞"。Warmup 给优化器(尤其是 Adam 的移动平均统计量)一个"热身"时间。
- Cosine Decay 阶段:学习率按余弦函数缓慢衰减,公式为:
这种衰减方式在训练中后期比线性衰减更"柔和",让模型有更多时间在最优解附近精细搜索。
梯度裁剪(Gradient Clipping):另一个保障训练稳定性的重要技术。当梯度的范数超过阈值 $\tau$ 时,对梯度进行等比缩放:
$$ g \leftarrow \frac{\tau}{\|g\|} \cdot g \quad \text{if } \|g\| > \tau $$类比:安全绳。梯度裁剪就像登山时的安全绳——正常行走时不受影响,但当某一步突然踩空(梯度爆炸)时,安全绳会拉住你,防止坠崖。典型的裁剪阈值为 1.0,这对几乎所有大语言模型训练都是标配。
5.3 优化器的演进
SGD(随机梯度下降)
最基本的优化器,直接用当前梯度更新权重:
$$ w_{t+1} = w_t - \eta \cdot g_t $$其中 $g_t = \nabla_w L(w_t)$ 是当前 mini-batch 的梯度。
问题:梯度方向在不同 batch 之间可能剧烈波动,导致更新路径呈"之字形"震荡,收敛慢。
Momentum(动量)
引入"速度"的概念,让更新具有惯性:
$$ v_t = \beta \cdot v_{t-1} + g_t $$$$ w_{t+1} = w_t - \eta \cdot v_t $$其中 $\beta$ 是动量系数(通常取 0.9)。
类比:球滚下山坡。SGD 像一个没有惯性的点,每一步都直接转向当前最陡的方向;Momentum 像一个有质量的球,它会保持之前的速度方向,遇到小的凹凸不会轻易改变方向,在一个方向上持续加速。
Adam(Adaptive Moment Estimation)
Adam 结合了 Momentum 和 RMSprop 的思想,维护两个移动平均:
$$ m_t = \beta_1 m_{t-1} + (1 - \beta_1) g_t \quad \text{(一阶矩:梯度的均值)} $$$$ v_t = \beta_2 v_{t-1} + (1 - \beta_2) g_t^2 \quad \text{(二阶矩:梯度的方差)} $$偏差修正后:
$$ \hat{m}_t = \frac{m_t}{1 - \beta_1^t}, \quad \hat{v}_t = \frac{v_t}{1 - \beta_2^t} $$更新规则:
$$ w_{t+1} = w_t - \eta \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} $$核心思想:每个参数有自己的自适应学习率。梯度变化剧烈的参数($\hat{v}_t$ 大)自动降低学习率,梯度变化平稳的参数($\hat{v}_t$ 小)保持较大学习率。
三种优化器对比
| 特性 | SGD | Momentum | Adam |
|---|---|---|---|
| 更新方向 | 当前梯度 | 梯度的移动平均 | 梯度均值 / 梯度标准差 |
| 自适应学习率 | 无 | 无 | 有(每个参数不同) |
| 收敛速度 | 慢 | 中等 | 快 |
| 超参数敏感度 | 高(需精调学习率) | 中等 | 低(默认参数通常可用) |
| 泛化性能 | 最好(有时) | 较好 | 略差(需配合权重衰减) |
6. 损失函数的数学本质——最大似然估计
6.1 MLE 的哲学
训练神经网络的损失函数,其根源是最大似然估计(Maximum Likelihood Estimation, MLE)。MLE 的哲学朴素而深刻:
给定观测到的训练数据,找到一组模型参数,使得模型生成这些数据的概率最大。
数学表述:假设训练数据为 $\{x_1, x_2, \ldots, x_N\}$,模型参数为 $\theta$,则 MLE 的目标是:
$$ \theta^* = \arg\max_\theta \prod_{i=1}^{N} p_\theta(x_i) = \arg\max_\theta \sum_{i=1}^{N} \log p_\theta(x_i) $$取对数将连乘变为连和(对数似然),最大化对数似然等价于最小化负对数似然(NLL)。
6.2 负对数似然(NLL)——通用损失框架
$$ \mathcal{L}_{\text{NLL}} = -\frac{1}{N}\sum_{i=1}^{N} \log p_\theta(x_i) $$NLL 是几乎所有损失函数的统一框架。接下来我们看它在不同假设下如何推导出具体的损失函数。
6.3 假设误差服从正态分布 → 推导出 MSE
对于回归任务,假设模型输出 $f_\theta(x)$ 与真实值 $y$ 之间的误差服从正态分布:
$$ p(y \mid x; \theta) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left(-\frac{(y - f_\theta(x))^2}{2\sigma^2}\right) $$取负对数似然:
$$ -\log p(y \mid x; \theta) = \frac{(y - f_\theta(x))^2}{2\sigma^2} + \frac{1}{2}\log(2\pi\sigma^2) $$忽略常数项,对所有样本求平均,就得到均方误差(MSE):
$$ \mathcal{L}_{\text{MSE}} = \frac{1}{N}\sum_{i=1}^{N}(y_i - f_\theta(x_i))^2 $$直观理解假设误差是正态分布的,那么"最可能的参数"就是让预测值和真实值的差距平方和最小的那些参数。
6.4 假设类别服从多项分布 → 推导出交叉熵损失
对于分类任务,假设输出类别服从多项分布。模型输出 logits $z$,经过 Softmax 转化为概率:
$$ p(y = k \mid x; \theta) = \text{softmax}(z_k) = \frac{e^{z_k}}{\sum_{j} e^{z_j}} $$负对数似然为:
$$ -\log p(y = k \mid x; \theta) = -\log \frac{e^{z_k}}{\sum_{j} e^{z_j}} = -z_k + \log \sum_{j} e^{z_j} $$这就是交叉熵损失(Cross-Entropy Loss)。对于 $N$ 个样本:
$$ \mathcal{L}_{\text{CE}} = -\frac{1}{N}\sum_{i=1}^{N} \log \frac{e^{z_{i,y_i}}}{\sum_{j} e^{z_{i,j}}} $$其中 $z_{i,y_i}$ 是第 $i$ 个样本在正确类别上的 logit 值。
6.5 Softmax 的作用
Softmax 将原始的 logits(可以是任意实数)转化为一个概率分布:
$$ \text{softmax}(z_k) = \frac{e^{z_k}}{\sum_{j} e^{z_j}} \in (0, 1), \quad \sum_k \text{softmax}(z_k) = 1 $$两个关键性质
- 归一化:输出之和为 1,符合概率的定义。
- 突出最大值:指数函数放大了大值和小值之间的差距。如果 logits 是 $[2, 1, 0.1]$,Softmax 输出约为 $[0.659, 0.242, 0.099]$,最大的值获得了最大的概率。
6.6 交叉熵、KL 散度、负对数似然的等价关系
这三个概念在分类问题中是等价的,但它们的直觉不同。
KL 散度(Kullback-Leibler Divergence):衡量两个概率分布 $p$(真实分布)和 $q$(模型分布)之间的"距离":
$$ D_{\text{KL}}(p \| q) = \sum_{k} p_k \log \frac{p_k}{q_k} $$展开:
$$ D_{\text{KL}}(p \| q) = \underbrace{-\sum_{k} p_k \log q_k}_{\text{交叉熵 } H(p, q)} - \underbrace{\left(-\sum_{k} p_k \log p_k\right)}_{\text{熵 } H(p)} $$即:
$$ D_{\text{KL}}(p \| q) = H(p, q) - H(p) $$对于分类问题,真实分布 $p$ 是 one-hot 向量(如 $[0, 0, 1, 0]$),其熵 $H(p) = 0$。因此:
$$ D_{\text{KL}}(p \| q) = H(p, q) = -\log q_{\text{correct}} $$这就是负对数似然!也就是说,在 one-hot 标签的分类问题中:
交叉熵 = KL 散度 = 负对数似然
直观理解:
- NLL 的视角:最大化模型生成正确标签的概率。
- 交叉熵 的视角:用模型分布 $q$ 编码来自真实分布 $p$ 的信息,所需的平均比特数越小越好。
- KL 散度 的视角:让模型分布 $q$ 尽量接近真实分布 $p$。
6.7 为什么分类任务不用 MSE?
从梯度的角度可以给出清晰的解释。
假设使用 MSE 损失 $\mathcal{L} = \frac{1}{2}(y - \hat{y})^2$,其中 $\hat{y} = \sigma(z)$ 是 Sigmoid 输出。对 logit $z$ 求梯度:
$$ \frac{\partial \mathcal{L}_{\text{MSE}}}{\partial z} = (\hat{y} - y) \cdot \sigma'(z) $$而交叉熵损失的梯度是:
$$ \frac{\partial \mathcal{L}_{\text{CE}}}{\partial z} = \hat{y} - y $$关键区别:MSE 的梯度多了一个 $\sigma'(z)$ 因子。当 $\sigma(z)$ 接近 0 或 1 时(Sigmoid 的饱和区),$\sigma'(z) \approx 0$,导致梯度消失。即使模型的预测完全错误($\hat{y} \approx 0$ 但 $y = 1$),梯度也接近零,模型无法学习。
而交叉熵的梯度 $\hat{y} - y$ 不受 Sigmoid 导数的影响,即使在饱和区也能提供足够大的梯度,让模型快速修正错误。
类比:报警系统。MSE 像一个在极端情况下失灵的报警器——当错误最严重时反而不响了;交叉熵像一个始终可靠的报警器——错误越大,警报越响。
7. 语言模型特有的评估与技巧
7.1 困惑度(Perplexity)
困惑度是语言模型最常用的评估指标,定义为:
$$ \text{PPL} = \exp\left(-\frac{1}{N}\sum_{i=1}^{N} \log p_\theta(x_i \mid x_{\lt i})\right) = \exp(\mathcal{L}_{\text{NLL}}) $$直观意义:困惑度可以理解为模型在每个位置的"有效选择数"。
- PPL = 1:模型完全确定下一个词是什么(完美预测)。
- PPL = 100:模型相当于在 100 个候选词之间犹豫不决。
- PPL = V(词表大小):模型等于在做均匀随机猜测,完全没有学到规律。
类比:考试中的困惑。PPL = 1 意味着你每道题都确定答案;PPL = 100 意味着每道题你都在 100 个选项中纠结;PPL = 50000 意味着你对每个空都完全没有头绪。
困惑度越低,语言模型越好。现代大语言模型的困惑度可以降到很低的水平,这也是它们能够生成流畅文本的原因。
7.2 标签平滑(Label Smoothing)
标准的 one-hot 标签是一种"极端自信"的表示:正确类别的概率是 1,其他都是 0。这会导致模型过度自信,logit 值趋向无穷大。
标签平滑将 one-hot 标签"软化":
$$ y_{\text{smooth}} = (1 - \epsilon) \cdot y_{\text{one-hot}} + \epsilon \cdot \frac{1}{K} $$其中 $\epsilon$ 是平滑系数(通常取 0.1),$K$ 是类别数。
例如,对于 4 分类,原本的 $[0, 0, 1, 0]$ 变为 $[0.025, 0.025, 0.925, 0.025]$。
正则化效果:标签平滑防止模型对自己的预测过于自信,迫使 logit 值保持在合理范围内。这等价于在标准交叉熵基础上引入了一个 KL 散度惩罚项,鼓励模型输出分布不要太偏离均匀分布。
类比:谦虚的学习者。标签平滑像是在告诉模型:“你认为答案是 C,但也要给 A、B、D 一点可能性,不要那么绝对。“这种"谦虚"的态度让模型对未见过的数据更加鲁棒。
8. 过拟合与泛化
8.1 训练 Loss 最小 ≠ 模型最好
一个关键的认知:训练损失(Training Loss)低不代表模型好。模型可能只是"记住"了训练数据的所有细节(包括噪声),而不是学到了真正的规律。这就像一个学生把所有习题的答案都背下来了,但遇到新题就束手无策。
验证损失(Validation Loss)才是黄金标准。它衡量模型在未见过的数据上的表现,反映的是模型的泛化能力。
当出现以下情况时,就是过拟合的信号:
- 训练 Loss 持续下降,但验证 Loss 开始上升
- 两个 Loss 之间出现"剪刀差”
8.2 早停(Early Stopping)
早停是最简单直接的过拟合应对策略:在训练过程中持续监控验证 Loss,当验证 Loss 不再下降(甚至开始上升)时,提前终止训练。
类比:适可而止的练习。练钢琴时,刚开始你的演奏水平不断提升,但练到某个点后开始越弹越差(手指疲劳、过度适应某个版本)。聪明的做法是在最佳状态时停下来。
8.3 Dropout
Dropout 是一种简单而有效的正则化技术:在训练时,以概率 $p$(通常为 0.1 到 0.5)随机将某些神经元的输出置为 0。
$$ \text{Dropout}(h_i) = \begin{cases} 0 & \text{with probability } p \\ \frac{h_i}{1-p} & \text{with probability } 1-p \end{cases} $$注意除以 $(1-p)$ 是为了保持期望值不变(期望值缩放),这样推理时就不需要做任何特殊处理。
为什么 Dropout 有效?
- 打破共适应:阻止神经元之间形成固定的"联盟"关系,迫使每个神经元独立地学习有用的特征。
- 隐式集成:每次 Dropout 相当于训练一个不同的子网络。推理时相当于对所有子网络做集成平均,类似于随机森林的思路。
- 增加噪声:为训练过程注入随机性,防止模型过度依赖某些特定的特征路径。
9. 正则化的深入剖析——L1 与 L2
9.1 损失函数加惩罚项
正则化的核心思想是:在原始损失函数上添加一个惩罚项,限制模型的复杂度。
$$ \mathcal{L}_{\text{total}} = \mathcal{L}_{\text{data}} + \lambda \cdot R(w) $$其中 $\mathcal{L}_{\text{data}}$ 是数据损失(如交叉熵),$R(w)$ 是正则化项,$\lambda$ 是正则化强度系数。
9.2 L2 正则化
L2 公式
$$ R_{L2}(w) = \frac{1}{2}\sum_{i} w_i^2 = \frac{1}{2}\|w\|_2^2 $$(加 $\frac{1}{2}$ 是为了求导方便。)
L2 梯度
$$ \frac{\partial R_{L2}}{\partial w_i} = w_i $$加上系数 $\lambda$ 后,L2 正则化对总损失的梯度贡献为 $2\lambda w$(有些实现中省略了 2)。注意,这个力的大小与权重成正比。
类比:弹簧力。L2 正则化就像在每个权重上绑了一根弹簧,把它们拉向零。权重越大,弹簧拉力越大。这意味着:
- 大权重受到很强的惩罚,会被快速拉小。
- 但弹簧力永远不为零,所以权重会趋于零但不会精确为零——它们只是变得很小很小。
权重更新公式(SGD + L2)
$$ w_{t+1} = w_t - \eta \cdot (\nabla_w \mathcal{L}_{\text{data}} + 2\lambda w_t) = (1 - 2\eta\lambda)w_t - \eta \cdot \nabla_w \mathcal{L}_{\text{data}} $$注意到 $(1 - 2\eta\lambda) < 1$,这意味着每一步更新都会让权重先"衰减"一小部分,然后再减去数据梯度。这就是权重衰减(Weight Decay) 这个名字的来源。
9.3 L1 正则化
L1 公式
$$ R_{L1}(w) = \sum_{i} |w_i| = \|w\|_1 $$L1 梯度(次梯度)
$$ \frac{\partial R_{L1}}{\partial w_i} = \text{sign}(w_i) = \begin{cases} +1 & \text{if } w_i > 0 \\ -1 & \text{if } w_i < 0 \end{cases} $$关键区别:L1 的梯度大小是恒定的($\pm \lambda$),与权重的大小无关。
类比:恒定摩擦力。L1 正则化像一个恒定大小的摩擦力——不管物体(权重)在什么位置,摩擦力的大小都一样。这意味着:
- 小权重受到的"相对惩罚"很大(对于 $w = 0.001$,惩罚梯度 $1$ 比数据梯度大得多),会被直接推到零。
- 大权重受到的"相对惩罚"很小,可以保留。
- 因此 L1 正则化倾向于产生精确的零权重(稀疏解),相当于自动进行特征选择。
9.4 几何直觉:等高线与约束区
另一种理解 L1 和 L2 正则化的方式是从约束优化的角度。将正则化问题等价地看作:
$$ \min_w \mathcal{L}_{\text{data}}(w) \quad \text{subject to} \quad R(w) \leq t $$为什么损失函数的等高线是椭圆?
在最优解附近,对损失函数做二阶泰勒展开:
$$ \mathcal{L}(w) \approx \mathcal{L}(w^*) + \frac{1}{2}(w - w^*)^T H (w - w^*) $$其中 $H$ 是 Hessian 矩阵(二阶导数矩阵),它是正定的。令这个二次型等于常数,就得到一个椭圆的方程——椭圆的形状由 Hessian 的特征值决定。
L2 的约束区:$|w|_2^2 \leq t$ 是一个圆形(二维)或超球面。圆形与椭圆等高线的切点通常不在坐标轴上,所以解的各个分量都不为零——没有稀疏性。
L1 的约束区:$|w|_1 \leq t$ 是一个菱形(二维)或超正方体。菱形的"尖角"恰好在坐标轴上。由于椭圆等高线在扩张时最容易与菱形的尖角接触,所以切点往往在坐标轴上——对应某些分量恰好为零,即稀疏解。
类比:气球膨胀碰到障碍物。损失函数的等高线像一个不断膨胀的气球。L2 的约束区是圆柱,气球碰到的是圆滑的表面,接触点不在特殊位置;L1 的约束区是钻石形,气球最容易碰到尖角——尖角恰好对应零权重。
9.5 权重衰减与 L2 正则化的关系
在 SGD 下,L2 正则化和权重衰减是等价的。但当使用自适应学习率优化器(如 Adam)时,两者不再等价。
L2 正则化:将 $2\lambda w$ 加入梯度,然后经过 Adam 的自适应缩放:
$$ w_{t+1} = w_t - \eta \cdot \frac{\hat{m}_t + 2\lambda w_t}{\sqrt{\hat{v}_t} + \epsilon} $$权重衰减:直接在更新步骤中衰减权重,不经过自适应缩放:
$$ w_{t+1} = (1 - \lambda)w_t - \eta \cdot \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} $$关键区别:在 L2 正则化 + Adam 中,正则化梯度 $2\lambda w$ 也被自适应学习率 $\frac{1}{\sqrt{\hat{v}_t}}$ 缩放了。对于梯度变化剧烈的参数($\hat{v}_t$ 大),正则化效果会被削弱,导致这些参数的权重衰减不够充分。
AdamW(Decoupled Weight Decay)正是为了修正这个问题而提出的:将权重衰减从梯度计算中解耦出来,直接作用于权重更新,恢复了权重衰减应有的正则化效果。AdamW 是现代大语言模型训练的标准优化器。
10. 训练工程实践
以上讨论的都是"理论层面"的机制。在实际训练大语言模型时,还需要一些工程技巧来应对计算资源和训练稳定性的问题。
10.1 混合精度训练
标准的神经网络训练使用 FP32(32 位浮点数)存储参数、梯度和激活值。但现代 GPU 的 Tensor Core 对 FP16/BF16(16 位浮点数)有专门的加速支持,吞吐量可以翻倍甚至更多。
混合精度训练的核心思路:用低精度(FP16 或 BF16)做前向和反向传播以加速计算,同时保留一份 FP32 的"主权重副本"用于更新,以避免精度损失。
具体流程:
- 维护一份 FP32 的主权重。
- 每次迭代时,将主权重转为 FP16/BF16,执行前向和反向传播。
- 得到 FP16/BF16 的梯度后,转回 FP32 来更新主权重。
FP16 vs BF16 的选择
| 特性 | FP16 | BF16 |
|---|---|---|
| 指数位 | 5 位 | 8 位 |
| 尾数位 | 10 位 | 7 位 |
| 动态范围 | 较小(容易溢出) | 与 FP32 相同 |
| 精度 | 较高 | 较低 |
| 是否需要 Loss Scaling | 是 | 通常不需要 |
BF16(Brain Floating Point)是 Google 专门为深度学习设计的格式,牺牲了一些精度但保留了和 FP32 相同的动态范围,避免了梯度上溢/下溢问题,因此在大语言模型训练中更受欢迎。
10.2 Scaling Laws——缩放定律
Kaplan 等人(2020)和 Hoffmann 等人(2022,Chinchilla 论文)发现了一个令人惊叹的规律:大语言模型的性能(以交叉熵损失衡量)与三个因素之间存在幂律关系:
$$ L(N, D) = \frac{A}{N^{\alpha}} + \frac{B}{D^{\beta}} + L_{\infty} $$其中:
- $N$ 是模型参数量
- $D$ 是训练数据量(token 数)
- $L_{\infty}$ 是不可约减的损失下限(语言本身的熵)
核心洞察
- 参数量和数据量应该同步增长。Chinchilla 论文指出,最优配比大约是 1 个参数对应 20 个训练 token。
- 更大的模型不一定更好:如果数据量不够,一个大模型可能还不如一个在更多数据上训练的小模型(Chinchilla 70B 优于 Gopher 280B)。
- 计算预算的最优分配:给定固定的 GPU 算力预算,应该在模型大小和数据量之间找到最优平衡点,而不是一味地增大模型。
延伸阅读:关于模型规模与泛化能力之间的深层关系(包括双重下降现象),详见本站文章 深度学习中的双下降现象(Double Descent)与缩放定律(Scaling Law)。
类比:厨师与食材。模型参数就像厨师的技艺(越多"手法"越好),训练数据就像食材的种类和数量。一个技艺超群的厨师如果只见过几种食材,做出的菜品也不会太丰富;反过来,食材再多但厨师技艺粗糙,也做不出好菜。最好的办法是两者匹配增长。
11. 全文总结与知识图谱
让我们回顾本文的逻辑主线:
flowchart TD
T0["Tokenization(BPE)"] --> T1["词嵌入 + 权重共享"]
T1 --> A["因果注意力(架构核心)"]
A --> B["Q/K/V + 缩放点积"]
B --> C["下三角掩码(自回归)"]
A --> D["多头注意力(多角度学习)"]
A --> E["位置编码(RoPE / 正弦)"]
D --> F["残差连接 + LayerNorm"]
E --> F
F --> G["FFN(升维-激活-降维 / SwiGLU)"]
G --> H["Transformer Block"]
H --> I["训练目标:最大似然估计"]
I --> J["NLL → 交叉熵 / MSE"]
J --> K["Softmax 转概率分布"]
I --> L["困惑度(PPL)评估"]
L --> M["标签平滑(正则化)"]
H --> N["优化器:SGD → Momentum → AdamW"]
N --> O["Warmup + Cosine Decay"]
N --> P["梯度裁剪"]
H --> Q["泛化控制"]
Q --> R["过拟合 vs 欠拟合"]
R --> S["早停 / Dropout"]
R --> V["L1 正则化(稀疏)"]
R --> W["L2 正则化(平滑)"]
H --> X["混合精度训练(BF16/FP16)"]
H --> Y["Scaling Laws(参数-数据配比)"]
架构设计层面:Tokenization(BPE)→ 词嵌入(权重共享)→ 因果注意力 + 多头机制 + 位置编码 + 残差/LayerNorm + FFN(SwiGLU)构成了 Transformer 的完整骨架,解决了 RNN 的长距离依赖和并行化难题。
优化目标层面:最大似然估计(MLE)是损失函数的数学根基,NLL 是统一框架,交叉熵和 MSE 是其在不同假设下的特例。Softmax 将 logits 转化为概率分布,困惑度提供直觉化的评估指标。
学习算法层面:从 SGD 到 Momentum 再到 AdamW,优化器通过引入动量和自适应学习率加速收敛。Warmup + Cosine Decay 学习率调度确保训练稳定启动并精细收尾。梯度裁剪为训练过程提供安全保障。
泛化控制层面:Dropout、标签平滑、L1/L2 正则化、早停等技术从不同角度防止过拟合。理解 L1(恒力→稀疏)和 L2(变力→平滑)的力学直觉,以及 AdamW 的设计动机,是正确使用正则化的关键。
工程实践层面:混合精度训练利用 BF16/FP16 加速计算,Scaling Laws 指导模型大小与数据量的最优配比。
系列导航:
- 第一篇(本文):从因果注意力到正则化——架构设计、损失函数、优化器、正则化
- 第二篇:工程实践核心技术——预训练、SFT/RLHF/DPO、分布式训练、混合精度
- 第三篇:高效推理与轻量部署——量化、KV Cache 优化、投机解码、推理框架