Lec6 预训练

基本思想

预训练的基础模型将适应下游任务。

image-20260130130847510

迁移学习:从一个任务中获取“知识”并应用于另一个任务

更少的任务数据:使用更少的数据达到给定的性能水平

更好的任务性能:达到比从头开始训练更高的性能

一个模型,多种任务:方便,摊薄成本,许多用途的起点,…

主要因素

每个模型受以下四个主要因素的影响:

架构: 神经网络架构

任务: 模型预测的内容(例如,下一个标记)

数据: 用于训练模型的数据

超参数:例如,学习率,批量大小

掩码语言建模

掩码语言建模(MLM)训练语言模型以根据剩余可见上下文预测掩码标记。这个目标在双向模型(如BERT)中被广泛使用。

MLM损失定义为:

\[ \mathcal{L}_{\text{MLM}}(\theta; D) = -\frac{1}{|D|} \sum_{x \in D} \;\mathbb{E}_{M \sim \text{corrupt}(x)} \sum_{t \in M} \log p_\theta(x_t \mid x_{-M}) \]

  • \(x \in D\):来自数据集的输入序列(句子)

  • \(M\):随机抽样的掩码标记位置集合

  • \(\text{corrupt}(x)\):应用于\(x\)的掩码(损坏)过程

  • \(x_{-M}\):序列中所有未掩码的标记

  • \(x_t\):位置\(t\)的真实标记

  • \(p_\theta(x_t \mid x_{-M})\):给定可见上下文预测\(x_t\)的模型概率

  • 去噪视角:MLM可以被视为去噪自编码器:输入通过掩码标记被损坏,模型学习重建原始序列。

  • 伪似然目标:MLM最大化给定序列其余部分的掩码标记的条件对数概率之和,而不是建模序列的完整联合似然。这对应于最大化伪似然而不是真实的联合似然。

自回归语言建模

给定所有先前的标记\(x_{<t}\)预测下一个标记\(x_t\)。 [ {}(; D) = - {x D} {t=1}^{|x|} p(x_t x_{<t}) ] 关键特性 - 最大化训练数据的似然
- 拟合真实数据分布\(p_*\)
- 等价于具有单热目标分布的交叉熵
- 可以解释为学习压缩\(p_*\)生成的数据

image-20260130140511145

评估模型

  • 损失(训练、验证、测试)
    • 诊断训练轨迹,比较同一家族的模型
  • 少量提示
  • 微调

数据

  • 数量:我有多少数据?
  • 质量:对训练是否有益?(提取、过滤、去重)
  • 覆盖率:数据是否覆盖我关心的领域,并且比例正确?
    • 我们可以训练一个分类器过滤,以帮助我们检测内容

Lec7 规模法则与上下文学习

规模法则

训练 = 花费计算

在固定的预训练预算下,我们应该如何分配预算以实现最佳模型?

image-20260206232739205

变压器LM的核心近似(Kaplan et al. 2020): \[ C \approx 6ND \]

  • N = 参数数量,D = 标记数量,C = FLOPs
  • 示例:Llama 2 7B在2T标记上 → C ≈ 8.4 × 10²² FLOPs

核心问题:在固定的C下,如何在N和D之间进行拆分?

幂律

\[ L = a \cdot x^{b} \quad \Rightarrow \quad \log L = \log a + b \cdot \log x \]

将x加倍 → L变为L · 2ᵇ。当b = −0.095时,加倍数据仅减少损失约6.4%。收益递减非常严重——线性损失改善需要指数级更多资源。

image-20260206233531669

数据规模

\[ L = (D / D_c)^{-b} \]

  • 三个区域:小数据 → 幂律区域 → 不可减少的误差(受数据熵限制)
  • 重复数据:4个周期≈新数据;40个周期→毫无价值(Muennighoff+ 2025)
  • 不同领域(维基百科、书籍、公共抓取)具有不同的规模曲线

image-20260206233726326

模型大小规模

\[ L = (N / N_c)^{-b} \]

  • 更大的模型更样本高效(用更少的标记达到更低的损失)
  • 变压器的扩展性显著优于LSTM
image-20260206233840078

计算最优训练

论文 N_opt D_opt 含义
Kaplan et al. 2020 ∝ C⁰·⁷³ ∝ C⁰·²⁷ 优先考虑更大的模型
Chinchilla (Hoffmann et al. 2022) ∝ C⁰·⁵ ∝ C⁰·⁵ N和D同等扩展

∝表示成比例

image-20260206234520100

Chinchilla的洞察:许多现有的LLM(例如,Gopher 280B)被训练不足。这直接影响了LLaMA的设计——较小的模型在更多数据上进行训练。

进行小规模实验 → 适应规模法则 → 推断目标运行的最佳超参数(模型大小、标记、批量大小、学习率)。

提示与上下文学习

三种提示策略

策略 格式 关键问题
无提示 原始文本补全 不可控
零-shot 指令 + 输入 输出格式不稳定;对措辞敏感
少量-shot (ICL) 指令 + K个示例 + 输入 示例定义格式和任务;无参数更新

ICL现象(Agarwal et al. 2024)

  • 任务检索:有时仅输入示例的效果与(输入,输出)对一样好——ICL部分“检索”预训练模式而不是学习新的映射

image-20260206235526522

  • 预训练偏差:默认标签需要少量示例;翻转/抽象标签需要更多示例以克服内置关联

    image-20260206235557572

  • 敏感性:示例顺序、标签平衡和标签覆盖率都会显著影响性能(Lu et al. 2021;Zhang et al. 2022)

    image-20260206235916474

  • 模型变异:从多次示例中受益的能力差异很大(Gemini 1.5 Pro在1024-shot时提升;GPT-4-Turbo早期达到饱和)

image-20260206235954906

聊天提示

消息格式为系统 / 用户 / 助手角色 → 分词器将其转换为带有特殊标记的字符串。系统提示定义模型行为(推理策略、安全规则、输出格式等)。

思维链(CoT)

  • 少量-shot CoT(Wei et al. 2022):在示例中包含推理步骤
  • 零-shot CoT(Kojima et al. 2022):附加“让我们一步一步思考”
  • 关键洞察:CoT为模型提供自适应计算时间——每个推理标记是额外的前向传递

提示链

顺序链多个LLM调用(使用不同的提示/外部工具):

1
输入 → LLM₁ → 中间结果 → LLM₂ → 中间结果 → ... → 输出

实现问题分解、工具使用(搜索、代码执行)和多步骤推理。


Lec8 微调

什么是微调?

在任务特定数据上继续基于梯度的训练预训练模型。给定预训练参数θ₀和数据集D = {(x, y)ₙ}: \[ \theta^* = \arg\min_\theta \mathbb{E}_{(x,y)\sim D} [\mathcal{L}(f_\theta(x), y)] \] 也称为监督微调(SFT)。使用正则化/丢弃以防止过拟合。

两种微调范式

分类微调:在最后的隐藏状态上添加线性头。 \[ p_\theta(y \mid x) = \text{softmax}(Wh + b), \quad W \in \mathbb{R}^{K \times d}, \; b \in \mathbb{R}^K \]

  • 损失:交叉熵 \(\mathcal{L} = -\log p_\theta(y \mid x)\)
  • 更新所有参数 \(\theta = (\theta_0, W, b)\)

语言模型微调:保持LM架构,在(输入,输出)对上训练。

保持LM架构,在(输入,输出)对上训练。连接为[start] x [sep] y [end],仅对输出标记计算损失:

\[ \mathcal{L}_{\text{MLE}} = -\sum_{t=1}^{T} \log p_\theta(y_t \mid x, y_{<t}) \] 不需要额外的头——使用现有的LM头。

更新哪些参数?

选项 更新内容 成本 权衡
仅头部 \(K \times d + K\)参数 最便宜 假设预训练表示已经是线性可分的
完全微调 所有 \(\theta\) 可能导致过拟合
PEFT 小子集 \(\theta\) 可以改变表示

LoRA(低秩适应)[Hu et al. 2021]

关键思想:用低秩矩阵近似权重更新。

对于权重\(W_0 \in \mathbb{R}^{d \times d'}\),将更新分解为:

\[ \Delta W = BA, \quad B \in \mathbb{R}^{d \times r}, \; A \in \mathbb{R}^{r \times d'}, \; r \ll \min(d, d') \]

  • 冻结\(W_0\),仅训练\(A\)\(B\)
  • 最终权重:\(W = W_0 + \frac{\alpha}{r} \cdot BA\)
  • 通常应用于注意力层中的\(W_q\)\(W_v\)
  • 训练后,将\(\Delta W\)合并到\(W_0\)中 → 没有额外的推理成本

image-20260207002605984

微调的效果

数据效率:预训练模型在比从头开始训练少得多的示例下达到良好性能(Howard & Ruder 2018 — ULMFiT)。

分布收敛:微调最小化\(D_{\text{KL}}(p_{\text{finetune}} \| p_\theta)\)而不是\(D_{\text{KL}}(p_{\text{data}} \| p_\theta)\)。模型的分布变得更窄且专业化。

副作用

  • 摘要模型在翻译时失败(失去了通用性)
  • 模型变得依赖于训练期间使用的确切提示格式
  • 微调后少量学习能力可能下降

指令微调

在多个任务上对(指令 + 输入,输出)对进行微调,使其学习通用地遵循指令。

image-20260207002839337

聊天微调

聊天只是具有对话格式的指令微调:

  • 系统提示 + [用户,助手,用户,助手,…]
  • 特殊标记标记角色边界(例如,<|start_header_id|>user<|end_header_id|>
  • 指令 + 输入隐式嵌入在对话中

数据来源:OpenOrca(16个手写系统提示,GPT-4输出,2.9M示例),LMSys-1M(来自在线LLM服务的真实用户对话)

image-20260207002950797

知识蒸馏

使用强大的教师模型训练一个较小的学生模型。两种方法都最小化教师\(q\)与学生\(p_\theta\)之间的\(D_{\text{KL}}(q \| p_\theta)\)

标记级蒸馏 [Hinton et al. 2015]

学生在每个标记位置模仿教师的完整概率分布

\[ \mathcal{L}_{\text{distill}} = -\sum_{y_t \in V} q(y_t \mid y_{<t}, x) \cdot \log p_\theta(y_t \mid y_{<t}, x) \]

  • 使用软标签(教师的分布)而不是硬的单热标签
  • 需要访问教师的logits
  • 比标准交叉熵提供更丰富的信号(仅使用正确的标记)

image-20260207003122001

序列级蒸馏 [Kim & Rush 2016]

教师生成完整输出;学生在其上进行微调:

\[ \mathcal{L}_{\text{seq}} = \mathbb{E}_{y \sim q(y|x)} \left[-\log p_\theta(y \mid x)\right] \]

  • 只需要教师生成的文本,而不是logits(黑箱友好)
  • 示例:DeepSeek-R1-Distill-Qwen-7B = 在DeepSeek-R1的输出上微调的Qwen-7B
  • 数学上也最小化\(D_{\text{KL}}(q \| p_\theta)\),只是使用蒙特卡洛近似

image-20260207003300579

增强教师 [West et al. 2022]

教师可以是一个增强的LLM:

\[ q \propto p_{\text{LLM}}(y \mid x) \cdot A(x, y) \] 其中\(A\)是分类器/验证器。如果增强的教师优于单独的\(p_{\text{LLM}}\),则蒸馏的学生可以超越\(p_{\text{LLM}}\)——学生通过过滤/验证的数据变得比其基础教师更好。

Lec9 解码算法

基本设置

自回归语言模型

\[ p_\theta(y_{1:T} | x) = \prod_{t=1}^{T} p_\theta(y_t | y_{<t}, x) \]

下一个标记分布

每个项\(p_\theta(y_t | y_{<t}, x)\)为下一个标记提供概率分布。

解码:选择下一个标记,以便我们最终得到输出\(y_{1:T}\)


解码作为优化

目标:MAP解码

找到最可能的输出: \[ \hat{y} = \arg\max_{y \in \mathcal{Y}} p_\theta(y | x) \]

  • 也称为模式寻求最大后验(MAP)
  • 关键挑战:输出空间\(\mathcal{Y}\)非常大

image-20260210155455010

方法1:贪婪解码

对于\(t = 1 \ldots \text{结束}\)\[ \hat{y}_t = \arg\max_{y_t \in V} p_\theta(y_t | \hat{y}_{<t}, x) \]

局限性:不保证最可能的序列。

image-20260210155537243

方法2:束搜索

  • 宽度限制的广度优先搜索
  • 在每一步保持\(B\)个可能路径
  • \(B = 1\):贪婪解码
  • \(B = |V|^{T_{\max}}\):精确MAP(不可处理)
  • 实际上:\(B = 16\)(超参数)

image-20260210155609745

HuggingFace接口

1
2
3
4
5
# 贪婪
model.generate(do_sample=False, num_beams=1)

# 束搜索
model.generate(do_sample=False, num_beams=16)

MAP解码的陷阱

1. 退化 - 重复陷阱:模型对重复循环分配高概率 - 短序列:最高概率序列可能为空 - 补救:长度归一化

2. 非典型性 - 最可能的结果 ≠ 典型结果 - 示例:偏置硬币\(\Pr[H] = 0.6\),100次翻转的最可能结果是全是正面(非典型!)

3. 概率分布 - 当存在多种方式表达相同事物时,概率在变体之间分散 - 最高概率输出可能不是“最佳”

image-20260210160105078


采样

祖先采样

对于\(t = 1 \ldots \text{结束}\)\[ \hat{y}_t \sim p_\theta(y_t | \hat{y}_{<t}, x) \]

  • 等同于序列采样:\(y_{1:T} \sim p_\theta(y_{1:T} | x)\)
  • 通过分类采样实现(PyTorch等)

HuggingFace接口

1
model.generate(do_sample=True)

祖先采样的问题

重尾问题

  • 即使每个坏标记的概率很小,坏标记的总和也具有非平凡的概率
  • 导致不连贯

复合错误: - 采样没有坏标记的概率:\((1 - \epsilon)^T\) - 示例:\(\epsilon = 0.01, T = 128 \Rightarrow p(\text{没有坏标记}) = 0.276\)

解决方法:截断尾部

Top-k采样:仅从\(k\)个最可能的标记中采样 \[ \hat{y}_t \sim \begin{cases} p_\theta(y_t | y_{<t}, x) / Z_t & \text{如果 } y_t \text{ 在 top-}k \\ 0 & \text{否则} \end{cases} \]

Top-p采样:仅从前\(p\)概率质量中采样

温度采样:使分布更加尖锐 \[ \text{softmax}(x, \tau) = \frac{\exp(x/\tau)}{\sum_i \exp(x_i/\tau)} \]

温度 参数 优点 缺点
\(\tau \geq 1\) 多样化 不连贯
\(\tau < 1\) 连贯 重复

image-20260210161335068

HuggingFace接口

1
2
3
4
5
6
7
8
# Top-k
model.generate(do_sample=True, top_k=20)

# Top-p
model.generate(do_sample=True, top_p=0.9)

# 温度
model.generate(do_sample=True, temperature=0.7)

其他截断策略

方法 阈值策略
Top-\(k\) \(k\)个最可能的中采样
Top-\(p\) 累计概率最多为\(p\)
\(\epsilon\) 概率至少为\(\epsilon\)
\(\eta\) 最小概率与熵成比例
Min-\(p\) 概率至少为\(p_{\min}\),按最大标记概率缩放

加速解码

为什么解码慢?

时间瓶颈\[ \text{时间} = \max\left(\frac{\text{操作FLOPs}}{\text{设备FLOP/s}}, \frac{\text{传输数据(GB)}}{\text{内存带宽(GB/s)}}\right) \]

  • 计算限制:例如,\(A = BC\)(矩阵乘法)
  • 内存限制:例如,\(a = Bx\)(矩阵-向量乘法)
  • 解码一个标记通常是内存限制

指标

延迟:用户等待多久? - 第一个标记的时间,每个请求的时间

吞吐量:每秒完成多少请求? - 每秒标记数,每秒请求数

键值缓存

问题:没有缓存,计算注意力需要\(O(T^2)\)的重新计算。

解决方案:存储先前计算的键和值。

在解码的第\(t\)步(1层,1头): \[ \begin{align} q_t &= h_t W_q \in \mathbb{R}^{1 \times d_k} \\ k_t &= h_t W_K \in \mathbb{R}^{1 \times d_k} \\ v_t &= h_t W_V \in \mathbb{R}^{1 \times d_v} \end{align} \]

缓存:\(K_{1:t-1} \in \mathbb{R}^{(t-1) \times d_k}\)\(V_{1:t-1} \in \mathbb{R}^{(t-1) \times d_v}\)

\(k_t\)附加到\(K_{1:t-1}\),将\(v_t\)附加到\(V_{1:t-1}\)\[ z_t = \text{softmax}\left(\frac{q_t K_{1:t}^T}{\sqrt{d_k}}\right) V_{1:t} \]

加速:将\(O(T^2)\)减少到\(O(T)\)计算。

加速单个标记

目标 策略 示例
减少内存带宽 量化、蒸馏、架构 GPTQ、AWQ、GQA/MQA
增加FLOP/s 在硬件上优化操作 FlashAttention、torch.compile
减少FLOPs 在架构中减少FLOPs 专家混合、Mamba

加速完整序列

策略 思路 示例
在时间上并行化 便宜地草拟标记,进行并行验证 投机解码
在时间上并行化 并行生成多个标记 非自回归模型

投机解码: 1. 使用小型草拟模型\(q\)提前生成标记 2. 大模型\(p\)并行处理草拟的标记 3. 以概率接受:\(\alpha_i = \min\left(1, \frac{p(\text{标记} | \ldots)}{q(\text{标记} | \ldots)}\right)\)

加速多个序列

策略 思路 示例
状态重用 共享前缀\(\Rightarrow\)共享KV缓存 PagedAttention、RadixAttention
改进批处理 更好的调度 连续批处理
程序级优化 优化完整生成图 SGLang、DSPy

总结

  1. 解码作为优化:贪婪、束搜索、MAP(固定路线最大化概率)
    • 陷阱:退化、非典型性、概率分布
  2. 采样:祖先、top-k、top-p、温度。(改变后续采样的概率分布)
    • 解决尾部概率和多样性问题
  3. 高效推理:KV缓存、投机解码、批处理
    • 对于大规模部署至关重要

一个关键的收获是,束搜索或贪婪是基于搜索的,它希望获得一个固定的优化输出,但采样引入了多样性或变异,以生成更具创造性的答案,并可能得到不同的答案。