CS221 · 人工智能:原理与技术
Lecture 17 · 语言模型
源文件:lecture-17.md
Lecture 17 · 语言模型
CS221: Artificial Intelligence — Principles and Techniques · Stanford · Autumn 2025
📅 Nov 17 · 💻language_models.pdf(不可执行讲义)· 讲者 Ken Liu
承上启下
过去几讲(逻辑 Lecture 15 · 逻辑 I:命题逻辑–Lecture 16 · 逻辑 II:一阶逻辑 / 贝叶斯网络 Lecture 12 · 贝叶斯网络 I:建模与推断–L14):
- 我们手工写下知识(命题/一阶逻辑公式)或结构(贝叶斯网络的图与条件分布),再让机器在其上做推理。表达力一讲比一讲强,但有一个始终绕不开的瓶颈:「知识从哪来」这一步永远要人来给——逻辑公式要人写,网络结构要人画。
本讲(语言模型,language model):
- 换一个极端思路——不写规则、不画图,只让模型读海量文本、预测下一个 token。知识不再由人显式录入,而是从数据里自己长出来。
- 结果出人意料:同一个模型不做任何专门化就能翻译、摘要、写码、对话——这也是本课所有技术线索最终汇合的地方。
说明
本讲把前面几乎每个模块都重新召唤了一遍:
- n-gram 的马尔可夫假设呼应贝叶斯网络(L12–14)——n-gram 语言模型本质上就是一条链式贝叶斯网络;
- 张量视角接上 L1 的张量运算与 Lecture 4 · 深度学习 的神经网络;
- 语言模型就是一个策略(policy)、RLHF ≈ 策略梯度,直接回到 MDP/RL(Lecture 7 · 马尔可夫决策过程–L9);
- 分词 BPE 是 Lecture 3 · 线性分类 的老朋友;「任务本身即语言建模」的编码思想又与一阶逻辑(L16)遥相呼应——都是把问题翻译成机器可处理的形式语言,只不过这次的形式语言就是自然语言本身。
下一讲 Lecture 18 · AI 与社会 则讨论这样的模型进入社会后的影响。
0. 开场:语言模型已经工业化
在讲原理之前,先感受一下规模——今天的语言模型早已不是实验室玩具,而是动辄数千万美元、上百人协作的工业项目:
| 事实 | 数字 |
|---|---|
| Qwen-3 训练数据 | 36T tokens ≈ 3 亿本书 |
| Llama 3 (405B) 训练数据 | ≈ 15.6T tokens(讲义取整为 16T) |
| Llama 3 参数量 | 405B 参数 |
| 训练计算量(6ND 估算) | ≈ 3.8 × 10²⁵ FLOPs(与 Meta 实报的 3.8 × 10²⁵ 一致) |
| 折算 GPU 时 | ≈ 88 万 H100·天(≈ 你的 MacBook M2 跑 65 万年) |
| 单次预训练成本 | ≈ \$42M**(按 \$2 / H100·小时,且假设中途不失败) |
| 论文作者 | **150+ 人** |
说明 训练一个稠密模型所需的总浮点运算量约为 说明 H100 的 bf16 峰值算力约 $10^{15}$ FLOP/s,实际训练的硬件利用率(MFU)通常只有 40%–50%。按一半峰值算:$3.8 \times 10^{25} \div (5 \times 10^{14}) \approx 7.6 \times 10^{10}$ 秒 ≈ 88 万天。Meta 实际报告用了约 3080 万 GPU·小时(≈ 128 万 GPU·天),比理想估算更多——真实训练总有额外开销与失败重启。 四问")):::root R --> Q1["1 · 什么是 语言模型?"]:::blue R --> Q2["2 · 为什么给语言建模 是个好主意?"]:::blue R --> Q3["3 · 是什么让 语言模型奏效?"]:::blue R --> Q4["4 · 我们现在 走到哪了?"]:::blue classDef root fill:#ffe0b2,stroke:#e65100 classDef blue fill:#e1f5fe,stroke:#0277bd ``` --- ## 1. 什么是语言模型? ### 1.1 「语言」= 有结构的字符序列 语言模型(language model, LM)顾名思义就是**语言的模型**。那什么是语言? 说明 语言 = 有结构的字符序列。结构来自两样东西:词表(vocabulary)——允许出现的字符/词的集合;语法(grammar)——它们如何合法地组合。「语言的模型」就是对这类序列的概率分布建模:哪些序列常见、哪些罕见、哪些几乎不可能。 提示 要让模型偏好 crashed and investors"] -->|LM| B["logits (V,)"] B -->|argmax / 采样| C["panicked"] C -.拼回序列.-> D["...investors panicked"] D -->|LM| E["logits (V,)"] E --> F["下一个 token ..."] style C fill:#c8e6c9,stroke:#2e7d32 style B fill:#e1f5fe,stroke:#0277bd style E fill:#e1f5fe,stroke:#0277bd ``` 说明 真正训练时会把多句话堆成一批,形状变成 $(B, T)$ → 嵌入 $(B, T, D)$ → logits $(B, T, V)$。$B$ 是 batch 大小,和 L4 的 mini-batch SGD 是同一件事——一次前向同时处理多条序列,摊薄计算开销。 提示 关键领悟:要给整句建模,你只需要一个会「给定上文、预测下一个 token」的模型——链式法则保证这些条件分布拼起来就是完整的联合分布。自回归模型 = 链式法则的直接实现。张量视角里的 $\text{logits} \in \mathbb{R}^{T \times V}$ 逐位置经过 softmax,就是这一串条件概率: 说明 训练与评估都围绕负对数似然:$\mathcal{L}(\theta) = -\frac{1}{T}\sum_{i=1}^{T} \log P_\theta(x_i \mid x_{<i})$。它的指数 $\text{PPL} = e^{\mathcal{L}}$ 叫困惑度(perplexity),直觉是「模型平均在多少个候选词之间犹豫」——PPL = 1 表示完美预测,PPL = V 表示纯瞎猜。缩放定律里「loss 持续下降」指的就是这条曲线。 说明 NTP 之所以最终胜出,是因为它天然支持生成:从左到右采样即可产出文本;MLM 只会填空,做生成要额外的技巧。生成能力正是后面「任务本身即语言建模」(§2.1)的前提。 提示 马尔可夫假设:每个词只依赖前 $n-1$ 个词。这正是贝叶斯网络那几讲(L12–14)的核心思想——用局部条件独立换取可计算性。讲者原话:「the Markov assumption but for n instead of 1; recall Bayesian lectures.」n-gram LM 其实就是一条链式贝叶斯网络:短串在语料里大量重复,计数不再归零;代价是超出窗口的信息全部丢失。 注意 n-gram 并没有根治稀疏问题,只是缓解:$n$ 稍一增大,可能的 n-gram 组合数以 $O(V^n)$ 爆炸,绝大多数组合又数不到了。补救是平滑(smoothing)——比如 Lecture 14 · 贝叶斯网络 III:参数学习 的 Laplace 平滑 $\hat P(w \mid c) = \frac{\operatorname{count}(c,w) + \lambda}{\operatorname{count}(c) + \lambda V}$,给每个未见组合留一点概率质量。但平滑治标不治本:n-gram 模型永远无法理解「stocks 和 shares 是近义词」这类语义相似性。 提示 神经网络凭什么能泛化到没见过的组合?因为嵌入把词放进了连续空间:如果训练中见过「investors panicked」,而 traders 的嵌入向量与 investors 相近,那么模型对「traders panicked」也会给出合理概率——n-gram 的离散计数永远做不到这一点。这就是「以参数化模型换泛化」的老主题(L2–L4)在语言上的重演。 提示 只要把任务表述成文本续写,一个语言模型就能干——不需要为每个任务单独设计模型和损失函数。这与 Lecture 16 · 逻辑 II:一阶逻辑 的精神相通:HW7 里我们用一阶逻辑把「谁是谁的 TA」这类问题编码成可推理的形式;这里则是把同类问题编码成自然语言的续写,交给 LM 处理。区别在于:逻辑的编码要人工设计谓词和公式,而「一切皆文本」的编码几乎零成本——这正是 T5 论文「text-to-text」框架的核心主张。 说明 不为任何任务专门训练,仅靠在网页文本(WebText)上做 NTP,就在翻译、摘要、问答上展现出「零样本(zero-shot)」能力——任务不是被教的,是被「读」出来的。论文标题本身就是宣言:Language Models are Unsupervised Multitask Learners。 更多数据 D 更多参数 N"] --> B["测试 loss 持续下降"] B --> C["能力涌现 翻译/写码/对话/摘要"] style A fill:#e1f5fe,stroke:#0277bd style B fill:#ffe0b2,stroke:#e65100 style C fill:#c8e6c9,stroke:#2e7d32 ``` 两篇奠基性工作给出了「该怎么变大」的定量答案: | | **Kaplan 缩放定律**(OpenAI, 2020) | **Chinchilla 缩放定律**(DeepMind, 2022) | | :--- | :--- | :--- | | 核心结论 | loss 随 $N$、$D$、$C$ 呈**幂律**下降 | 给定算力,$N$ 与 $D$ 应**等比例**同增 | | 实践含义 | 「把模型做大」 | 「模型和数据一起做大」——此前的大模型**训练不足** | | 经验法则 | 偏向堆参数 | 约 $D^ \approx 20N$:每个参数配约 20 个 token | 注意 Kaplan 一度让大家拼命堆参数、轻视数据;Chinchilla 纠偏:在固定算力 $C \approx 6ND$ 下重新拟合,最优解是 $N^ \propto C^{1/2}$、$D^ \propto C^{1/2}$——很多「巨无霸」其实是数据饿死的。实证:70B 参数的 Chinchilla 用 1.4T token 训练,打败了 280B 的 Gopher 和 175B 的 GPT-3。这也解释了开场为什么 Llama 3 的 405B 参数要配约 15.6T token(≈ 38 token/参数,比 Chinchilla 比例还高——因为 Meta 还要优化推理成本,宁可「过度训练」小一点的模型)。缩放定律的完整推导见 CS336 的 Lecture 9 · 缩放定律 I:基础(未找到对应页面)。 处理序列"] --> B["① 参数量 O(D·V·T²) 随 T、V 爆炸"]:::red A --> C["② 权重固定 无动态权重"]:::red A --> D["③ 对位置无偏好 不懂词序"]:::red B --> E["需要一种机制: 按内容动态决定 '看哪里'"]:::blue C --> E D --> E E --> F["注意力 attention 创造动态权重"]:::green F --> G["Transformer"]:::orange classDef red fill:#ffcdd2,stroke:#c62828 classDef blue fill:#e1f5fe,stroke:#0277bd classDef green fill:#c8e6c9,stroke:#2e7d32 classDef orange fill:#ffe0b2,stroke:#e65100 ``` 逐条展开这三个缺陷: - **① 参数爆炸**:拍平后的输入维度是 $T \cdot D$,要为 $T$ 个位置各输出 $V$ 维 logits,全连接权重规模按 $O(T^2 \cdot D \cdot V)$ 增长——上下文一长就完全不可行,而且换一个序列长度就得换一个网络。 - **② 权重静态**:MLP 的权重训练完就冻住,对所有输入一视同仁。但语言需要**按内容决定看哪里**——「it」指代谁,取决于这句话说了什么,不能用一套固定权重应付所有句子。 - **③ 不懂词序**:对拍平的向量来说,位置只是下标,模型对「谁在前谁在后」没有恰当的归纳偏置。 提示 注意力(attention)的本质:让每个 token 根据当前内容临时算出「该关注序列里哪些位置」的权重——即动态权重(dynamic weights)。标准形式是: 对所有输入相同"] end subgraph ATT["注意力:动态权重"] Q["query·key → 按内容算出权重"] --> V2["加权聚合 value"] end style W fill:#ffcdd2,stroke:#c62828 style Q fill:#c8e6c9,stroke:#2e7d32 style V2 fill:#e1f5fe,stroke:#0277bd ``` 说明 两点补充:其一,做 NTP 时注意力要加因果掩码(causal mask)——位置 $i$ 只能看 $\le i$ 的位置,否则「预测下一个词」就泄题了。其二,Transformer 的完整构造(多头注意力、位置编码、残差、LayerNorm)本课不展开,留给 CS224n;但你已具备全部前置知识——它就是 L4 的「线性层 + 非线性 + 残差 + LayerNorm」再加上注意力这一块积木,工程细节可见 CS336 的 Lecture 3 · 架构与超参数(未找到对应页面)。 (OLMo / AI2)"] --> B["预训练 目标:下一 token 预测"] B --> C["基座模型 会补全,但不'听话'"] C --> D["后训练"] D --> E["SFT 指令微调"] E --> F["RLHF 对齐"] F --> G["会聊天的助手"] style B fill:#e1f5fe,stroke:#0277bd style C fill:#ffe0b2,stroke:#e65100 style F fill:#f3e5f5,stroke:#7b1fa2 style G fill:#c8e6c9,stroke:#2e7d32 ``` | | **预训练(pre-training)** | **后训练(post-training)** | | :--- | :--- | :--- | | 目标 | 简单目标:下一 token 预测 | 让模型「听话」、有用、无害 | | 数据 | 海量、相对干净的通用文本(如 [OLMo](https://allenai.org/olmo) / AI2) | 少量高质量的指令 / 人类偏好数据 | | 产物 | **基座模型**:会补全但不懂「跟你对话」 | **对齐后的助手** | | 关键现象 | **上下文学习(in-context learning)** | 学会遵循指令、拒绝有害请求 | 例子 基座模型有一个训练时没人明确教过的本领:只要在 prompt 里给几个示例,它就临场学会这个任务,参数一动不动。例如:
模型会续写 提示
换句话说,RLHF 把「聊天」变成了一个 MDP,把「对齐」变成了策略优化。工程细节见 CS336 的 Lecture 15 · 对齐 I:SFT 与 RLHF(未找到对应页面)。 = 人类偏好"] R -->|策略梯度 推高高奖励回答| S style S fill:#e1f5fe,stroke:#0277bd style A2 fill:#c8e6c9,stroke:#2e7d32 style R fill:#ffe0b2,stroke:#e65100 ``` 注意 后训练教会的「拒绝有害请求」并不是牢固的边界,攻击者不断找绕过安全训练的漏洞:
这些攻击奏效的深层原因:安全行为只是训练分布上的统计倾向,不是逻辑规则(对比 L15–16:逻辑系统的约束是硬的,学出来的约束是软的)。防御方与攻击方持续拉锯。 提示 解法是折中:子词分词(subword tokenization),即 Lecture 3 · 线性分类 讲过的 BPE(Byte-Pair Encoding,字节对编码)。从「1 token = 1 字符」出发,按频率反复合并最常见的相邻 token 对,长出一套子词单元——常见词(the、and)最终合并成单个 token,稀有词则拆成若干已知子词的拼接。这样任何字符串都能被编码(不会有 out-of-vocabulary),常见内容又编码得很紧凑。分词算法的完整实现见 CS336 的 Lecture 1 · 概览与分词(未找到对应页面)。 例子 用 Adam 做混合精度训练,每个参数大约要存 16 字节:bf16 权重 2 B + bf16 梯度 2 B + fp32 主权重 4 B + Adam 一阶矩 4 B + 二阶矩 4 B。于是 $70 \times 10^9 \times 16\,\text{B} \approx 1.12\,\text{TB}$——单是训练状态就需要至少 14 张 H100 才装得下,还没算激活值。这就是为什么大模型训练必然是多卡工程。 H100 仅 80GB 训练状态 1.12TB"]:::red P --> M["显存不够"]:::orange P --> S["速度太慢"]:::orange M --> M1["① 量化 2-bit → 省 16×"]:::blue M --> M2["② 并行 & 分片 数据/模型/流水/张量"]:::blue S --> S1["③ 硬件感知 算子融合"]:::blue S --> S2["④ KV cache 缓存 + 批处理"]:::blue classDef red fill:#ffcdd2,stroke:#c62828 classDef orange fill:#ffe0b2,stroke:#e65100 classDef blue fill:#e1f5fe,stroke:#0277bd ``` 说明 只要把图像、音频、甚至机器人动作也编码成 token 序列,同一套 Transformer + NTP 就能吞下它们。「token 是图像、是语言……甚至是机器人的动作!」——语言建模的框架远不止于文字:序列建模是通用接口,「语言」只是它的第一个杀手级应用。 说明 这是一门仍在剧烈变化的领域——你们学到的原理(张量、概率、马尔可夫、策略、优化)正是看懂它的钥匙。「祝考试顺利。」 题目 句子空间随长度指数增长($V^T$ 种),任何稍长的精确串在语料里几乎从不重复,频率估计对绝大多数句子给出 0。n-gram 用马尔可夫假设 $P(x_i \mid x_{<i}) \approx P(x_i \mid x_{i-n+1:i-1})$ 把整句计数换成大量重复出现的短串计数。代价:超出窗口的长程依赖全部丢失;且 $n$ 增大时组合数以 $O(V^n)$ 爆炸、重新变稀疏,需要平滑,也永远学不到词与词的语义相似性。 题目 $P(x_1, \dots, x_T) = \prod_{i=1}^{T} P(x_i \mid x_{<i})$,对任意分布恒成立、无近似。每个因子恰好就是模型在位置 $i$ 输出的 softmax 条件分布,所以把各位置的 $\log P(x_i \mid x_{<i})$ 相加(即负的训练损失)就得到整句的对数概率——自回归模型是链式法则的直接实现。 题目 $C \approx 6 \times 8 \times 10^9 \times 15 \times 10^{12} = 7.2 \times 10^{23}$ FLOPs。除以 $5 \times 10^{14}$ FLOP/s 得 $1.44 \times 10^9$ 秒 ≈ 16,700 H100·天——比如 1000 张 H100 跑约 17 天。顺带检验 Chinchilla 比例:$D/N = 15 \times 10^{12} / (8 \times 10^9) \approx 1875$ token/参数,远超 Chinchilla 的约 20——这正是 Llama 3 8B 那类刻意「过度训练」小模型以降低推理成本的典型配置。 题目 MLP 的权重训练完即冻结,对所有输入用同一套;注意力则由当前输入现场算出关注权重——$\operatorname{softmax}(QK^\top/\sqrt{d_k})$ 依赖于输入本身,故称「动态」。MLP 的三个缺陷:参数量随序列长度按 $O(T^2 \cdot D \cdot V)$ 爆炸;权重静态、无法按内容决定「看哪里」;对词序缺乏合适的归纳偏置。注意力用「按内容打分再加权聚合」同时化解三者。 题目 状态 = 已生成的上文(含 prompt);行动 = 选出下一个 token;策略 = 语言模型的条件分布 $\pi_\theta(x_i \mid x_{<i})$;奖励 = 奖励模型(由人类偏好比较数据训练)对完整回答的打分,在序列末端才给出(稀疏奖励)。更新式 $\nabla_\theta J = \mathbb{E}{y \sim \pi\theta}[R(x,y) \nabla_\theta \log \pi_\theta(y \mid x)]$ 正是 REINFORCE:对高奖励的回答推高其对数概率,对低奖励的压低——「对齐」由此变成 L7–9 意义上的策略优化问题。 |
参考资料
- 💻 language_models.pdf(本讲讲义)
- 📄 Attention Is All You Need (Vaswani et al., 2017) — Transformer 与注意力机制
- 📄 Language Models are Unsupervised Multitask Learners / GPT-2 (Radford et al., 2019) — 零样本多任务能力
- 📄 Language Models are Few-Shot Learners / GPT-3 (Brown et al., 2020) — 上下文学习与规模化
- 📄 Scaling Laws for Neural Language Models / Kaplan (OpenAI, 2020) — 幂律缩放定律
- 📄 Training Compute-Optimal LLMs / Chinchilla (Hoffmann et al., 2022) — 模型与数据等比例同增
- 📄 Training LMs to Follow Instructions with Human Feedback / InstructGPT (Ouyang et al., 2022) — SFT + RLHF 对齐
- 📄 Exploring the Limits of Transfer Learning / T5 (Raffel et al., 2020) — 「一切皆文本到文本」
- 📄 The Llama 3 Herd of Models (Grattafiori et al., 2024) — 开场规模数字的官方来源
- 📖 OLMo:完全开放的语言模型(AI2 / Allen Institute for AI)
- 🔗 Tiktokenizer 在线分词体验
- 🌐 CS221 Autumn 2025 课程主页