数学基础:最小必要子集
LLM 用到的数学并不神秘,核心就四块:线性代数(数据如何表示与变换)、概率与信息论(模型在优化什么)、微积分(梯度如何流动)、优化(参数如何更新)。本篇只讲"够理解 LLM"的那部分,每个概念都配 PyTorch 代码。
说明:本站未启用 KaTeX,公式以代码块形式书写,例如
y = Wx + b。
一、线性代数:数据的语言
1. 向量、矩阵与张量
LLM 里一切都在张量(tensor)上运算:
标量 (scalar):一个数 shape = ()
向量 (vector):一维,词表 logits shape = (vocab_size,)
矩阵 (matrix):二维,权重 shape = (d_out, d_in)
张量 (tensor):任意维,一批隐状态 shape = (batch, seq_len, d_model)
一个典型的隐状态形状 (B, T, C):B 个样本、每个 T 个 token、每个 token 是 C 维向量。
import torch
x = torch.randn(2, 8, 64) # batch=2, seq=8, d_model=64
W = torch.randn(64, 128) # 线性层权重
y = x @ W # 矩阵乘法 → shape (2, 8, 128)
@ 对高维张量做的是批量矩阵乘:对每个 (T, C) 切片分别乘 W。这是 LLM 中最高频的操作,没有之一。
2. 线性变换的直觉
y = Wx 的几何意义是对向量做旋转 + 缩放。神经网络堆叠很多线性层,再配合非线性激活,就能表达任意复杂的映射。注意力里的 Q/K/V、FFN 的升降维,本质都是线性变换。
3. 内积与相似度
两个向量的内积 q·k = Σᵢ qᵢkᵢ = |q||k|cosθ 度量方向的一致性。注意力分数就是 query 与 key 的内积——语义越相关,内积越大。余弦相似度把它归一化到 [-1, 1]:
q = torch.randn(64); k = torch.randn(64)
cos = q @ k / (q.norm() * k.norm())
词嵌入(embedding)之所以"意思近的词距离近",就是因为训练让内积/余弦相似度编码了语义。
4. 转置与广播
注意力分数矩阵是 QK^T:(T,C) @ (C,T) → (T,T),第 (i,j) 个元素就是第 i 个 token 对第 j 个 token 的关注强度。PyTorch 的**广播(broadcasting)**规则让 (B,T,C) 与 (C,) 直接相加——理解广播是读懂所有 LLM 代码的前提。
二、概率:模型到底在算什么
1. 条件概率与链式法则
语言模型把一句话的概率分解为:
P(x₁..xₙ) = P(x₁) · P(x₂|x₁) · P(x₃|x₁,x₂) ··· · P(xₙ|x₁..xₙ₋₁)
每个因子都由神经网络给出。这就是"自回归(autoregressive)"的含义:逐个预测,每个预测都依赖前面所有 token。
2. Softmax:把任意实数变成概率分布
模型最后一层输出 vocab_size 个任意实数(logits),softmax 将其归一化:
softmax(zᵢ) = exp(zᵢ) / Σⱼ exp(zⱼ)
logits = torch.tensor([2.0, 1.0, 0.1])
p = torch.softmax(logits, dim=-1) # [0.659, 0.242, 0.099]
工程上一定要先减最大值再 exp(z - max(z)),否则 exp 会溢出——torch.softmax 内部已处理。
3. 交叉熵损失:训练的唯一目标
给定正确 token 的 one-hot 分布,交叉熵衡量预测分布与它的差距:
L = -log P(正确token)
整条序列的损失是所有位置交叉熵的平均。预训练的全部工作就是把这一个数降下去。
logits = torch.randn(4, 100) # (seq_len, vocab)
targets = torch.randint(0, 100, (4,))
loss = torch.nn.functional.cross_entropy(logits, targets)
注意 cross_entropy 期望 logits 形状为 (N, C),所以 LLM 代码里常见 logits.view(-1, vocab) 的 reshape。
4. KL 散度与困惑度
- KL 散度
D_KL(p‖q) = Σ p log(p/q)度量两个分布的差异,交叉熵 = 真实分布熵 + KL。RLHF 里用 KL 惩罚防止微调后的模型偏离基座太远。 - 困惑度(Perplexity, PPL)
= exp(平均交叉熵),直觉是"模型在每一步平均犹豫于多少个候选"。PPL 越低越好,是评估基座模型的标准指标。
三、信息论:理解数据与损失
- 熵
H(p) = -Σ p log p:分布的不确定性。自然语言的熵决定了语言模型 loss 的理论下限——数据本身的不可预测性。 - 交叉熵 ≥ 熵:模型 loss 不可能低于数据本身的熵,loss 降不下去不一定是模型不行,可能是数据本身噪声大。
- 压缩观:好的语言模型 = 好的压缩器。交叉熵损失就是在学对文本的最优编码长度,这也是"预测即智能"视角的来源。
四、微积分:梯度如何流动
1. 链式法则 = 反向传播
对复合函数 L = f(g(x)),有 dL/dx = (dL/dg)·(dg/dx)。反向传播就是从 loss 出发,沿计算图逐层把梯度乘回去。你不需要手写它——PyTorch 的 autograd 帮你做——但要知道:
- 每层 forward 时保存中间结果,backward 时用它们算梯度;
- 这就是为什么显存与激活值大小强相关,也是 gradient checkpointing(用重算换显存)的原理。
2. 梯度消失与爆炸
深层网络里梯度是连乘:连乘一堆 <1 的数→趋近 0(消失);连乘 >1 的数→爆炸。现代 LLM 用三个手段压制它:
- 残差连接:
y = x + F(x),梯度有一条"高速公路"直接回传; - 归一化(LayerNorm/RMSNorm):把每层输入拉回稳定分布;
- 合适的初始化:如
N(0, 0.02),让前向/反向信号方差保持稳定。
五、优化:参数如何变好
1. 梯度下降家族
SGD: θ ← θ - η·∇L
Momentum: 引入速度项,积累历史梯度方向
Adam: 每个参数自适应学习率 = 梯度一阶矩 / 二阶矩开根号
AdamW: Adam + 权重衰减与梯度解耦(LLM 训练的事实标准)
optimizer = torch.optim.AdamW(model.parameters(), lr=3e-4,
betas=(0.9, 0.95), weight_decay=0.1)
LLM 常用 β₂=0.95(而非默认 0.999),让二阶矩估计更快响应梯度变化,大 batch 训练更稳。
2. 学习率调度:Warmup + 衰减
- Warmup:开头几千步把 lr 从 0 线性升到峰值。冷启动时梯度方向混乱,大 lr 会直接训崩。
- 衰减:余弦衰减到峰值的 ~10%,或线性衰减。末期小 lr 让模型"精细收敛"。
lr(t) = t/W·lr_max (t < W,warmup)
lr(t) = lr_min + ½(lr_max-lr_min)(1+cos(π·(t-W)/(T-W))) (之后,cosine)
3. Scaling Law(经验公式)
Kaplan 与 Chinchilla 的实验结论:
L(N, D) = A/N^α + B/D^β + E α≈0.34, β≈0.28, E≈1.69(不可约损失)
Chinchilla 最优:算力预算固定时,参数量 N 与数据量 D 应等比扩张,经验比例约 每参数 20 个 token(70B 模型 ≈ 1.4T token)。这直接指导了现代 LLM 的"该训多大、喂多少数据"。
小结:一页速查
| 数学概念 | 在 LLM 中的角色 |
|---|---|
| 矩阵乘法 | 所有线性层、注意力 QK^T |
| 内积/余弦相似度 | 注意力分数、嵌入语义 |
| 条件概率链式法则 | 自回归建模 |
| Softmax | logits → 概率分布 |
| 交叉熵 | 训练损失 |
| 困惑度 | 基座评估指标 |
| KL 散度 | RLHF 中的偏离惩罚 |
| 链式法则 | 反向传播 |
| 残差 + 归一化 | 抑制梯度消失/爆炸 |
| AdamW + cosine lr | 训练标配优化方案 |
| Scaling Law | 算力/参数/数据的配比指南 |
掌握这些,下一篇 分词器 就可以纯看代码了。