Basics
判别式 vs. 生成式模型
三种模型类型:
判别式模型(Discriminative Model) 学习 p(y|x),即给定数据x,预测标签y的概率。比如给一张猫的图片,模型输出”猫”的概率高于”狗”。所有可能的标签在概率空间中相互竞争。缺陷很明显:因为输入x本身不参与竞争,模型无法拒绝不合理的输入——比如给它一张猴子图片(不在训练标签中),它仍然会强行给出”猫”或”狗”的概率,因为它根本不知道这张图”不太可能出现”。
生成式模型(Generative Model) 学习 p(x),即学习训练数据中每种输入的出现概率。所有可能的输入互相竞争概率质量。优点是可以拒绝不合理输入(直接给它赋极低概率),但代价是需要对数据有极深的理解——比如”猫坐在篮子里”的概率,应该高于”猴子在办公室”。
条件生成式模型(Conditional Generative Model) 学习 p(x|y),在给定标签y的条件下生成数据x。例如,给定”猫”这个标签,生成一张猫的图片。每个标签都会在自己的概率空间内引发竞争。
Bayes’ Rule的桥梁作用: 三种模型通过贝叶斯公式相互关联:
其中p(x|y)是条件生成模型,p(y|x)是判别模型,p(x)是生成模型,p(y)是标签先验。在理论上它们可以互推,但现代深度学习通常直接通过训练近似这些关系,而非手动组合。
定义语言模型
传统NLP的局限: 过去的NLP系统通常只针对单一任务优化——比如情感分析、垃圾邮件检测、文本分类。这些大多是判别式任务,模型只学习 p(y|x),在特定任务上表现很好,但超出该任务范围就束手无策,也不需要真正”理解”语言结构。
LLM的核心:下一个token预测
从单步来看,预测下一个词是判别式的:给定上下文x,在词表中所有词语之间分配概率,选出最可能的下一个词。例如 p(“quick” | “The”)。
但从整体来看,LLM是生成式的。它通过自回归(autoregressive)方式逐步生成整个序列,每一步都依赖前面所有已生成的token:
这其实是在学习一个关于整个文本序列的联合概率分布,本质上是生成式模型。
条件生成才是实际使用方式: 在实践中,我们不会让模型凭空生成文本,而是给它一个prompt(提示词)作为条件,模型在此基础上继续生成:
这里prompt y充当了”标签”的角色。这也意味着,通过巧妙设计prompt,我们甚至可以用这个条件生成模型来完成判别式任务(比如情感分析)。
什么叫”Large”? 这个定义并不精确,而是随时代演变的共识:
- 最初指大到无法放入单张消费级GPU
- 后来指出现了”涌现能力”(emergent behaviors)的规模
- 现在”大”既指参数量,也指训练数据量(万亿级token)
LLM发展的关键里程碑
1. Few-Shot Learning(2020) 以GPT-3为代表,发现无需更新模型权重,只需在context window中提供任务描述和示例,模型就能完成新任务。分为零样本(zero-shot)、单样本(one-shot)和少样本(few-shot)三种形式。这一发现虽然如今已是基础常识,但它奠定了RAG等现代技术的基础。
2. 指令微调与对齐(2021/2022) 原始预训练模型只是”自动补全引擎”,并不能按照人类意图工作。通过RLHF(人类反馈强化学习)等技术进行指令微调,以InstructGPT、FLAN、ChatGPT为代表,使模型真正能够理解并执行自然语言指令,成为今天人机交互的标准范式。
3. 多模态与多语言(2022/2023) 模型能力从纯英文文本扩展到图像、音频等多种模态。早期方案是为文本模型附加独立的视觉/音频编码器,而”原生多模态”方案则让单一模型直接将图像像素和音频波形作为token处理。GPT-4V、早期Gemini、Flamingo是代表性工作。如今前沿模型默认就是全模态(omni-modal)的。
4. RAG检索增强生成(2023) 解决LLM知识陈旧和幻觉问题:在生成答案前先从外部数据库检索相关内容作为上下文。如今已是绝大多数工业应用的标准方案,并带动了向量数据库、OCR等周边技术的发展,也推动LLM训练重心从”记忆更多知识”转向”长上下文处理能力”。
5. AI Agent与工具调用(2024) 让模型不仅能”说”,还能”做”——调用API、执行代码、浏览网页等。核心是”感知→推理→行动→反思”的智能体循环。早期的热炒是全自主循环,现在行业更关注可靠的、确定性的函数调用,是B2B AI应用的主要商业驱动力。
6. 推理模型(2025) 发现在正式回答前生成大量”思考token”可以大幅提升复杂任务表现(chain-of-thought)。代表性实现是在prompt后插入<think>标签,模型在</think>之前自由生成推理过程,最终答案才展示给用户。这是目前的技术前沿,推动了”推理时计算扩展”的范式转变。
The Standard Transformer
Tokenization & Embeddings(分词与嵌入)
为什么需要Tokenization?
机器无法直接处理文字,需要把文本切成离散的基本单位(token)。切法有三种粒度:字符级(最细,序列最长)、词级(最粗,序列最短)、子词级(折中,现代LLM普遍使用)。
从token到向量:Embedding矩阵
切好的每个token都有一个唯一的整数ID,通过查表从一个大矩阵(Embedding Matrix)中取出对应的向量。这个矩阵的尺寸是词表大小 × 嵌入维度,是模型训练的参数之一。关键在于,这些向量不是随机的——训练后相近语义的词会自动聚拢在向量空间中。经典例子就是 King - Man + Woman ≈ Queen,语义关系被几何关系编码了进去。
词表大小的权衡
词表越大,每个词被表示为更少的token,处理效率更高;但词表矩阵本身就更大,占用更多参数。对于小模型来说,嵌入矩阵可能占总参数的10%以上,所以有时会共享输入嵌入和输出层的参数(embedding sharing)来节省。大模型通常不需要这么做。
BPE(Byte-Pair Encoding)算法
现代最常用的分词算法。核心思想:从字符级出发,反复把最高频的相邻字符对合并成一个新token,直到达到目标词表大小。结果是高频词通常是整词,低频或罕见词则被拆成有意义的子词。这使得模型能处理训练时没见过的词,而不是完全不认识。
多语言问题
一个在英文语料上训练的tokenizer,遇到阿拉伯语时会非常低效——同样一段文字,英文可能20个token,阿拉伯语可能120个token。这直接导致非英语语言的模型处理成本更高、能力更弱。解决办法是用多语言数据训练专用tokenizer,但这又面临鸡生蛋的问题:好的tokenizer需要好的数据配比,但找到最优数据配比又需要好的tokenizer。
Positional Encodings(位置编码)
为什么需要位置编码?
Transformer的核心运算(注意力)本质上是无序的——它把所有token的embedding加权求和,跟顺序无关。”阿根廷打败了法国”和”法国打败了阿根廷”会产生完全相同的输入表示!所以必须额外告诉模型每个token的位置。
绝对位置编码(APE,Absolute Position Embeddings)
最简单的方法:每个位置(1, 2, 3…)对应一个学习到的向量,直接加到token embedding上。缺点很明显:训练时见过的最大长度是上限,超过就无法泛化。
旋转位置编码(RoPE,Relative Positional Embeddings)
更现代的方案,大多数当前主流模型使用。核心思想:与其直接给每个位置一个向量,不如把位置信息编码成旋转角度,直接注入到注意力计算中。这样模型关注的是两个token之间的相对距离,而不是绝对位置编号。比如token5和token8之间永远相差3,无论它们出现在序列的什么位置。
实践中,标准RoPE的旋转频率是固定的,训练时序列短,推理时序列长就会出问题。解决方案包括:调整基础频率(ABF,Adjusted Base Frequency,让旋转变慢,能看更远)、YaRN(不同维度用不同缩放比例)等。
DRoPE:结合两者优点
有趣的新方案:先用普通RoPE训练(收敛快),训练完之后把位置编码丢掉,再做一个短暂的微调。让模型在训练时享受位置编码的便利,推理时依靠内部学到的结构来处理任意长度。实验显示比RoPE+YaRN在超长上下文中表现更好。
Layer Normalization(层归一化)
为什么需要归一化?
深层网络训练时,激活值容易出现数值不稳定——有的层数值爆炸,有的梯度消失,模型根本无法收敛。归一化的作用就是把每一层的输出拉回正常范围。
BatchNorm vs. LayerNorm
图像模型常用BatchNorm(跨batch内同位置的样本做归一化),但文本序列长度不固定,padding会污染统计量,所以序列模型改用LayerNorm——对每个token自己的embedding维度做归一化,完全独立,跟batch里其他样本无关。
Pre-LN vs. Post-LN
归一化放在残差块的前面还是后面影响很大。原始Transformer用Post-LN(先做注意力/FFN,再归一化再加残差),但深层网络训练时梯度容易消失。现代LLM普遍用Pre-LN(先归一化,再做计算,直接加到残差流上),梯度更稳定,可以训练更深的网络。
RMSNorm
LayerNorm的简化版,去掉了均值中心化步骤,只按向量的均方根来缩放。计算更快,实验表明效果相当甚至更好。Llama系列等主流模型都在使用。
Self-Attention & Masking(自注意力与掩码)
注意力机制的核心公式:
其中
按行向量计算。
三个矩阵Q(Query)、K(Key)、V(Value)都从同一个输入X变换而来(自注意力的”自”就在这里)。
如何理解:每个token用Q问”我关心什么”,用K说”我能提供什么”,Q和K的点积衡量相关性,然后按相关性对V加权求和,得到该token整合了全局上下文后的新表示。除以$\sqrt{d_k}$是为了防止点积数值太大导致softmax饱和。
Multi-Head Attention(多头注意力)
单头注意力就是一次QKV计算:给定输入X,算出Q、K、V三个矩阵,然后:
Attention(Q, K, V) = softmax(QKᵀ / √dₖ) · V
这个操作的结果是:每个token综合了序列中所有其他token的信息,得到一个新的表示向量。
问题在于,这一次计算只能捕捉一种类型的关系。比如对于句子”The cat sat on the mat because it was tired”,”it”这个词既需要理解它指代的是”cat”(语义关系),也需要理解它在句子中的语法位置,还可能需要理解”tired”和”cat”之间的因果关系。一个注意力头同时要学这么多不同性质的关系,能力有限。
Multi-Head Attention的解决方案非常直观:并行跑多个注意力头,每个头独立学习不同类型的关系,最后把结果合并。
具体做法:假设模型维度是 d_model = 512,用 h = 8 个头,那么每个头的维度是 d_k = 512 / 8 = 64。每个头 i 有自己独立的参数矩阵 W^Q_i、W^K_i、W^V_i,把输入X投影到64维空间,然后各自独立做注意力计算,得到各自的输出 Z_i。8个头的输出全部拼接成一个$[n \times 512]$的矩阵,再经过一个输出投影矩阵 W^O 变换回 d_model 维度。
不同的头在学什么?
研究者通过可视化注意力权重发现,不同头确实自发地学会了不同的模式。有的头专门关注相邻词(局部语法结构),有的头专门追踪代词指代(”it”→”cat”),有的头关注动词和其主语之间的关系,有的头甚至学会了某种长距离依存关系。这些都是自发涌现的,没有人明确告诉某个头去学什么。
参数量的变化
多头注意力和单头注意力的参数量实际上是相同的。因为虽然分成了8个头,但每个头的维度缩小了8倍,总的矩阵大小不变。多头的意义不在于增加参数,而在于让这些参数能够并行学习多种不同的特征。
不同的”头”可以关注不同类型的关系(比如一个头关注语法,另一个头关注语义)。实现上就是把嵌入维度分成h份,每份独立做注意力,最后拼起来。
因果掩码(Causal Masking)
LLM生成文本时,当前token不能”看到”未来的token(否则训练时相当于作弊)。实现方法是在注意力分数矩阵中,把右上角(未来位置)设为负无穷,softmax之后这些位置的权重就变成0,等于完全屏蔽。
长上下文的注意力优化
全注意力的计算量是$O(n^2)$,序列翻倍计算量翻四倍,代价极高。PPT介绍了几种近似方案:分块注意力(把序列切段,段内做注意力,O(m·k²))、滑动窗口注意力(每个token只看最近N个token)、双块注意力DCA(结合块内和跨块,兼顾局部和一定范围的全局)。还有一个有趣的发现叫Attention Sink——模型会对最开头的几个token给出异常高的注意力权重,作为”锚点”,这是模型自发涌现的行为,不是设计出来的。
Feed-Forward Layers(前馈层)
在Transformer的每一层中,注意力之后紧跟着一个FFN。这两个组件分工明确:
- 注意力:在token之间传递信息(”我要聚合哪些其他位置的信息”)
- FFN:在每个token内部做特征变换(”我要对聚合来的信息做什么处理”)
FFN对每个token独立处理,不同token之间不互相影响。这和注意力的”全局交互”形成了互补。
FFN的结构
标准两层结构:
其中 W₁ 把维度从 d_model 扩展到 d_ff(通常是4倍,比如512→2048),σ是非线性激活函数,W₂ 再压缩回 d_model。
为什么要先扩展再压缩?这个”瓶颈”结构让模型有机会在高维空间中做复杂的特征组合,然后再提炼回有用的表示。有研究认为FFN实际上充当了一种”知识存储”的角色,模型记忆的事实性知识(比如”巴黎是法国的首都”)很大程度上就存储在FFN的权重里。
激活函数的演变
早期用ReLU,现在主流是GELU或SiLU,它们的输出更平滑,梯度也更好传导。还有一种叫GLU(门控线性单元)的变体,用两条并行路径相乘来控制信息流,Llama等模型在用。
MoE的动机
标准FFN有个问题:不管输入是什么,所有参数都参与计算。处理一个简单的标点符号和处理一个复杂的技术术语,调动的计算量完全一样,非常浪费。
这就引出了Mixture of Experts(MoE):把一个大FFN替换成N个小型FFN(专家),每次只激活其中k个。对于简单token,路由器可以选择能力刚好够用的专家;对于复杂token,选择更专业的专家。总参数量增大了(更强的表达能力),但每次实际计算量不变(只激活少数专家)。
主要挑战是负载均衡:如果路由器总是把大部分token发给同几个专家,其他专家闲置,计算资源浪费,而且被过度使用的专家也容易过拟合。解决方案包括辅助损失(在训练目标中加入让流量均匀分布的惩罚项)和bias-based无损平衡(动态调整每个专家的分数偏置,用得少的加分,用得多的减分)。
标准Transformer架构总结
所有组件组合起来就是完整的Transformer。
主要有两种变体:
Encoder-Decoder架构(原始论文,Attention is All You Need):编码器处理输入序列(双向注意力),解码器生成输出序列(因果注意力+cross-attention连接编码器),适合翻译、摘要等任务。
Decoder-Only架构(GPT系列,ChatGPT,现代主流LLM):去掉编码器,只保留解码器,输入和输出都走同一条路。流程是:输入tokens → 加位置编码 → N个解码器块(每块:LayerNorm → Masked Self-Attention → 残差 → LayerNorm → FFN → 残差)→ 线性层 → Softmax → 输出下一个token的概率分布。
最后:Temperature与采样
模型输出的是词表上的概率分布,如何从中采样决定了输出风格。Temperature参数T控制分布的”锐利程度”:T<1使分布更集中(更确定、更保守);T>1使分布更平坦(更随机、更有创意);T=0等价于argmax,每次选概率最高的词——但有趣的是,即使T=0,生成结果也可能不完全确定,
Encoder-Decoder 架构
Encoder用双向注意力——每个token可以同时看到序列中所有其他token,包括它左边的和右边的。
设计背景
原始Transformer是为机器翻译设计的,任务结构是:给定源语言句子,生成目标语言句子。这个任务有一个天然的特点——输入和输出是两个独立的序列,有明确的”理解阶段”和”生成阶段”之分。Encoder-Decoder架构就是为这种结构量身设计的。
Encoder的工作
Encoder的任务是充分理解输入。它使用双向自注意力——每个token可以同时看到序列中所有其他token,包括它前面的和后面的。比如翻译”I love Paris”时,”love”这个词可以同时看到”I”和”Paris”,从而建立完整的语义表示。
Encoder由N层相同结构的块堆叠而成,每层包含:多头自注意力 + 残差 + LayerNorm + FFN + 残差 + LayerNorm。最终输出是一组向量,每个向量代表对应输入token在整个上下文中的深层语义表示。
Decoder的工作
Decoder的任务是逐步生成输出,同时利用Encoder的理解结果。它的结构比Encoder多了一个组件,每层有三个子模块:
第一个是Masked Self-Attention:Decoder只能看到它已经生成的token,不能看到未来的目标token(因果掩码)。这保证了生成时的自回归性质。
第二个是Cross-Attention:这是Encoder和Decoder的连接桥梁,也是这个架构最关键的部分。Query来自Decoder当前的状态,Key和Value来自Encoder的输出。这让Decoder在生成每个词时,可以”回头看”整个源序列,动态决定当前最需要关注源语言的哪个部分。
第三个是FFN:跟Encoder一样,在token内部做特征变换。
一个具体的翻译例子
翻译”I love Paris”为”我爱巴黎”时:
- Encoder处理”I love Paris”,得到三个上下文向量
- Decoder先看到特殊的起始token,通过Cross-Attention决定生成”我”(主要关注Encoder中”I”的位置)
- 然后看到”我”,生成”爱”(主要关注”love”)
- 然后看到”我爱”,生成”巴黎”(主要关注”Paris”)
- 最后生成结束符,停止
适合什么任务
任何有明确”输入序列→输出序列”映射的任务都适合,包括机器翻译、文本摘要、问答、图片描述生成等。代表模型有T5、BART、早期的谷歌翻译模型。
Decoder-Only 架构
Decoder用单向注意力——每个token只能看到它之前的token(因果掩码)。
为什么可以去掉Encoder?
这是一个非常深刻的洞察。既然LLM本质上是条件生成模型 p(x|y),prompt就是条件y,生成的回答就是x,那能不能把prompt直接当作”已经生成的前缀”,让Decoder自己完成理解和生成?
答案是可以的。Decoder-Only模型把prompt和回答拼接成一个序列,统一用因果自注意力处理。Decoder足够深的时候,它自己完全有能力理解输入——不需要一个专门的Encoder来做这件事。
结构
每个Decoder块的结构(Pre-LN版本,现代主流):
1 | 输入 x |
注意这里没有Cross-Attention,因为没有Encoder,也就不需要连接两个序列。整个模型就是N个这样的块叠起来,输入输出都是同一条残差流。
训练方式
训练时,输入是整个序列(prompt + 回答),靠因果掩码让每个位置只看到它之前的内容,然后对每个位置预测下一个token。这意味着一次前向传播就能对序列中所有位置同时计算损失,训练效率很高。
推理方式
推理时,先输入整个prompt,得到下一个token的概率分布,采样一个token;然后把这个token拼到序列末尾,再次前向传播;重复这个过程直到生成结束符。这就是所谓的自回归生成,每次生成一个token,之前生成的内容都作为下一步的上下文。
KV Cache优化
纯粹的自回归生成很慢,因为每步都要重新计算所有之前token的Key和Value。实际工程中会把每层的K和V缓存下来,新token来时只需要计算新token自己的Q,然后和缓存的K、V做注意力即可。这是让LLM推理变得可用的关键工程优化。
高级注意力机制(Advanced Attention Mechanisms)
注意力机制的瓶颈 (The Attention Bottleneck)
标准 Transformer 强大的原因在于它能让每个 Token 与其他所有 Token 产生关联,但这引发了严重的计算和内存问题。
- 复杂度高: 全局注意力的计算复杂度为 $O(n^{2}d_{k})$,内存复杂度为 $O(n^{2})$。对于超长上下文模型,即便是无限算力,仅存储这些矩阵也会耗尽 VRAM。
- 训练 vs. 推理的差异:
- 训练阶段是并行的(一次性处理整个句子),主要瓶颈在于 VRAM 容量,因为反向传播需要存储大量中间激活值。
- 推理阶段是串行的(逐词生成),主要瓶颈在于内存带宽,即每次生成一个词都需要将庞大的权重和数据从内存搬运到计算单元。
- KV Cache 困境: 为了加速推理,系统会缓存历史 Token 的 Key (K) 和 Value (V) 向量以避免重复计算。但缓存大小随上下文长度线性增长,例如对于处理 128k 上下文的 70B 模型,KV Cache 的体积甚至会超过模型权重本身。
KV 共享与压缩 (KV-Sharing & Compression)
为了缓解 KV Cache 带来的内存压力,PPT 介绍了三种主流的方法:
- MQA (Multi-Query Attention): 所有注意力头(Heads)共享同一组 K 和 V,极大地减少了内存带宽消耗,但可能会导致模型容量下降和训练不稳定。
- GQA (Grouped-Query Attention): 工业界目前最常用的折中方案。将注意力头分成若干组(通常为 2、4 或 8),组内共享 KV。它在显著压缩缓存的同时,保留了表征的多样性。
- MLA (Multi-Latent Attention): 不减少 KV 头的数量,而是将庞大的 KV 张量压缩成一个小维度的潜在向量(Latent vector),并在运行时进行解压。它通过巧妙的矩阵结合,在潜在空间内完成大部分计算,从而大幅节省内存带宽。
硬件高效与结构化注意力 (Hardware-Efficient & Structured Attention)
这一部分重点探讨了如何通过优化底层硬件的内存访问机制或改变数学结构来提升效率。
- PagedAttention (vLLM): 借鉴了操作系统的分页内存管理,将 KV Cache 划分为固定大小的“页”进行非连续存储。这消除了内存碎片,使批处理大小提升了 2-5倍。
- FlashAttention 系列: 它的核心思想在于优化内存 IO 而不是单纯减少计算量。通过将矩阵分块并加载到速度极快的 GPU SRAM 中进行计算,避免了频繁读写较慢的全局显存(HBM),这带来了约 7.6倍 的实际加速,并大幅降低了内存占用。FlashAttention2 进一步优化了序列维度的并行化,解决了计算瓶颈。
- 线性与混合注意力:
- Linear Transformer 移除了传统的 Softmax 操作,使用核函数映射,将复杂度降为 $O(nd)$,但牺牲了部分精度。
- Lightning Attention 和 Gated DeltaNet 等模型则采用了“块内并行 + 块间循环(RNN式状态更新)”的混合架构,在长上下文中既保证了高效计算又具备较强的状态追踪能力。
稀疏注意力 (Sparse Attention)
由于自然语言往往具有局部依赖性,并非所有词都需要进行全局关联,稀疏注意力应运而生。
- 块稀疏 (Block Sparse):
- Longformer 采用滑动窗口(关注邻近词)加少量全局 Token 的策略,将复杂度降至 $O(n(w+g)d)$。
- BigBird 在此基础上加入了少量的随机连接,从图论角度看,这使它成为了理论上的通用近似器。
- 动态稀疏 (Dynamic Sparse): 例如 Routing Transformer,它使用局部敏感哈希(LSH)将语义相似的 Token 聚类,仅在簇内计算注意力。但 PPT 提到,其实时聚类的开销往往抵消了稀疏性带来的速度提升。
- 原生稀疏注意力 (Native Sparse Attention, NSA): 通过将 Token 块压缩成摘要向量,来全局评估哪些块最重要,强制所有注意力头共享这些重要块的内存加载。NSA 结合了压缩掩码、选择掩码和滑动窗口掩码,实现了硬件友好的稀疏计算。
- DeepSeek Sparse Attention: 专为 MLA 架构设计,通过学习独立的代理向量(Proxy vectors)来进行检索评分,无需完全解压特征即可找到相关上下文块,以极低的额外开销支持了超长上下文的检索。
数据与评估(Data & Evaluation)
训练课程设计 (Training Curricula)
神经网络并不是静态的数据库,它们具有“可塑性”,往往对最后看到的数据记忆最深。因此,现代大模型不再是一锅端地训练,而是分阶段“上课”:
- 预训练 (Pre-Training): 目标是“压缩”人类语言和世界知识的统计结构,数据量极大(万亿级 Token),质量相对嘈杂。这一阶段赋予了模型智能的潜力,但行为通常不受控。
- 中期训练 (Mid-Training): 在基础模型建立后,注入高质量、信息丰富的数据(如教科书、StackOverflow、合成推理链),并进行长上下文扩展训练。模型在这里获得独特的个性和推理能力。
- 后训练 (Post-Training): 通过监督微调 (SFT) 和强化学习 (RL) 将原始智能转化为特定工具,教导模型遵循格式要求和安全目标。对于主打“推理”的模型,后训练的算力成本甚至可能与预训练相当。
训练框架 (Training Frameworks)
为了在集群上训练庞大的模型,研究人员依赖于不同的分布式训练框架:
- Megatron-LM (NVIDIA): 专为英伟达硬件打造,首创了 3D 并行(张量、流水线和数据并行)。性能极其强大,但配置和调试的难度很高。
- DeepSpeed (Microsoft): 侧重于显存优化,通过 ZeRO 优化器对状态和梯度进行分片,甚至支持将内存卸载到 CPU RAM,使得在普通硬件上训练大模型成为可能。
- Torch Titan (PyTorch): 原生的 PyTorch 分布式训练参考实现,API 具有组合性,代码可读性高,是目前业界追求简洁研究代码库的趋势。
数据策展与配比 (Data Curation)
数据质量直接决定模型上限,现代实验室的核心工作往往不是“找数据”,而是“删数据”。
- 各类数据的价值:
- 英文网页数据: 通用 LLM 的核心,目前极度依赖过滤(去除 SEO 垃圾信息)来提升质量。
- 数学数据: 并非为了让模型变成计算器,而是通过数学证明的纯粹逻辑依赖关系来教授多步推理。
- 代码数据: 代码具有严格的语法和长程依赖,大规模代码训练能显著提升模型在标准测试中的推理表现。
- 如何科学地配比数据? 人工猜测配比效率极低,PPT 介绍了三种自动化寻找最佳数据比例的方法:
- DoReMix: 通过训练一个小模型找出其“苦手”的领域,然后据此调整全量数据的权重。
- RHO-LOSS: 在样本级别进行过滤,剔除完全学不会的噪音和太简单的样本,只保留具有学习价值的中间地带。
- RegMix: 用随机配比训练多个小模型,再用回归模型预测出能达到最低损失的最佳配比。
基准测试与评估 (Benchmarks & Evaluation)
随着模型能力的爆发,如何准确“打分”成了一个巨大的挑战。
- 好评估的标准:
- 单调性 (Monotonicity): 随着模型训练步数的增加,分数应该稳定上升,而不是上下剧烈波动。
- 高信噪比 (SNR): 分数的变化应该真实反映能力的提升,而不是随机误差。
- 同时需要警惕数据污染(测试题不小心被混入训练集)和饱和(测试题太简单,模型轻易拿满分)。
- 自由生成文本的评分方法:
- 传统自动评分: BLEU、ROUGE 等基于词汇重合度的方法,速度快但难以理解语义。
- 采样统计: 在复杂的推理/数学任务中,通过多次生成取多数决 (maj@n) 或计算通过率 (pass@k) 会更稳健。
- 功能性评分: 测试模型是否严格遵守了格式约束(例如“包含确切的3个项目符号”)。
- 人类与 LLM 裁判 (LLM-as-a-Judge): 灵活性高但容易带入偏见(比如更偏好冗长的回答、语气自信的错误回答,或特定位置的选项)。
预训练(Pre-Training)
权重初始化 (Weight Initialization)
权重初始化决定了网络能否有效地开始学习,适当的方差能防止梯度消失或爆炸。
Xavier 初始化:早期的经典方法,通过公式
确保层与层之间的激活和梯度方差保持恒定。
截断正态分布 (Truncated Normal):从正态分布(如 $W_{i,j}\sim\mathcal{N}(0,0.02)$)中采样,但强制截断偏离均值太远(如 $\pm2\sigma$)的离群值。这能减少早期训练中的极端方差,至今仍被 OpenAI、Meta 和 DeepSeek 广泛使用。
muP 初始化:一种参数化的初始化方法,使得不同深度和宽度的模型在扩展时具有等效的学习动态(向前传播时乘以 $1/\sqrt{n}$ 因子)。
损失函数 (Loss Functions)
- 交叉熵损失 (CE Loss):语言模型最标准的损失函数,用于最大化预测正确下一个词的概率,公式为 $\mathcal{L}_{CE}=-\Sigma_{t=1}^{T}y~log(x)$。但它对频率极高的词很敏感,且由于评分过于刚性,容易导致模型输出“过度自信”。
- Z-Loss:为了防止模型在计算时产生极大的 Logit(这会导致数值不稳定),引入辅助惩罚项 $\mathcal{L}_{z}=\epsilon\cdot log^{2}(\Sigma~e^{x_{i}})$ 将 Logit 压向零。这在低精度训练中极为关键。
- 随机目标损失 (Stochastic Target Loss):通过向目标分布中加入均匀噪声(类似标签平滑),防止模型在模棱两可的选择上过度拟合或表现得绝对自信。
优化器 (Optimizers)
优化器决定了模型权重如何根据梯度进行更新。
- AdamW:深度学习目前的绝对霸主。它是一种自适应动量估计的一阶优化器,核心贡献在于将权重衰减 (Weight Decay)与梯度更新动量解耦,使得正则化更加独立和有效。
- Muon:一种被前沿实验室采用的二阶优化器。它将权重矩阵作为一个整体(利用 SVD 和 Newton Schulz 步骤提取特征),丢弃了单纯的幅度信息而专注于方向,这使得它对大批量 (Batch size) 训练具有更高的耐受度,弥补了其较高的计算成本。
正则化 (Regularizers)
用于防止过拟合并提高模型的泛化与稳定能力。
- 常见的手段包括权重衰减、梯度裁剪(限制梯度的最大上限)以及单轮训练法则(由于拥有万亿级别的 Token,模型通常对每条数据只看一遍,天然防止过拟合)。
- QK-Norm:在计算注意力得分前,对 Query 和 Key 应用 LayerNorm。这能压制过大的注意力对数,但缺点是可能会损失幅度信息,导致注意力从关键的“针”分散到了无关的上下文中,有时会损害长文本理解能力。
学习率调度器 (Schedulers)
学习率在训练过程中的变化曲线极大地影响了模型的收敛效果。
- 余弦衰减 (Cosine Decay):预热后呈余弦曲线平滑下降。效果好,但非常僵化——你必须在训练开始前就精准设定总步数,且很难在中间暂停或追加训练。
- WSD (Warmup-Stable-Decay):现代大模型最常用的策略。预热后,模型维持一个极长的高学习率“稳定期”,仅在训练的最后 10% 到 20% 的阶段才发生断崖式衰减。这使得研究人员可以随时给模型“加餐”延长训练,方便保存 Checkpoint。
- DeepSeekV3 调度器:采用混合策略,交替使用常数平稳期和余弦衰减期,最后再进行一次急剧下降。
缩放定律 (Scaling Laws)
这是大语言模型时代的“物理学定律”,探讨算力、数据和参数规模之间的数学关系。
- 苦涩的教训 (The Bitter Lesson):哲学的基石,即人类手工设计的精巧架构,最终都会在“大规模算力 + 大规模数据”的通用方法面前败下阵来。
- 早期缩放定律 (OpenAI, 2020):发现损失函数 $L(N)\approx N^{-\alpha}$ 呈幂律下降。但这导致了一个误区:大家以为只要把模型参数做得极大就能赢,结果造出了一批“训练不足”的庞然大物。
- 计算最优缩放 (Chinchilla, DeepMind 2022):纠正了上述误区,提出在给定算力下,参数量和数据量必须同比例增加。经验法则是:每一个模型参数,大约需要搭配 20 个 Token 的训练数据。
- 数据瓶颈:Anthropic 的研究指出,如果像以前那样让模型对同一批文本循环训练(多 Epochs),性能会迅速退化(哪怕只重复 0.1% 的数据)。因此,高质量的人类独特文本成了一种“稀缺资源”。
- 打破定律 (数据筛选):DeepMind 后续发现,如果剔除太简单的废话和太难的噪声,仅用高质量数据训练,可以击败传统的幂律曲线,以更少的数据达到更低的 Loss。
- 推理最优 (Inference Optimality):现在的趋势不再仅仅关注训练时的 Loss,而是关注部署成本。例如 Llama3 8B 故意“过度训练”(使用了远超 Chinchilla 比例的数据),以及采用 MoE 架构,都是为了在保持小模型低推理成本的同时榨干其能力。
后训练(Post-Training)
中期训练 (Mid-Training)
这是一个介于预训练和监督微调 (SFT) 之间的步骤。
- 核心逻辑:当你希望模型掌握某种特定核心技能(如写代码、深度推理)时,可以在预训练后,继续用海量特定领域的数据对其进行“加餐”。
- 推理模型的关键:现代顶尖推理模型经常在这一步使用由更大“教师模型”生成的“蒸馏推理 Token”来进行训练,这能在较小模型上产生惊人的效果。
监督微调 (Supervised Fine-Tuning, SFT)
无论后续的强化学习多么复杂,SFT 始终是所有后训练流程的基础起点。
- 高性价比:相比强化学习,SFT 算力成本低廉且训练稳定,它通过标准的交叉熵损失函数 $\mathcal{L}=-\Sigma~log~P(y_{t}|x,y_{<t})$ 来学习输入与输出的映射。
- 训练优化技巧:
- 序列打包 (Sequence Packing):因为指令数据的长度参差不齐,为了不浪费 GPU 算力,会将多个短问答拼接到一个长序列中,并通过特定的“块对角矩阵掩码”确保不同的问题之间不会互相产生注意力。
- 系统提示词条件化 (System Prompt Conditioning):在训练数据中加入“系统提示词”,让模型学会在同一个问题下,根据不同的人设或格式要求(如“保持简短”或“详细解释”)给出不同的回答。
强化学习基础 (Reinforcement Learning, RL)
RL 将大语言模型视为一个“智能体 (Agent)”,它通过不断生成 Token(采取行动)来最大化最终的“奖励 (Reward)”。
- 同策略 (On-policy) vs. 异策略 (Off-policy):
- 同策略:模型自己实时生成回答,并立刻接受评分(成本高,但对症下药)。
- 异策略:模型利用静态的、别人整理好的数据集进行学习(成本低,但可能学不到点子上)。
- 策略型 vs. 价值型:
- 基于策略 (Policy-Based):直接优化模型参数,如果一个回答得了高分,就强化产生这个回答的神经通路。
- 基于价值 (Value-Based):训练一个独立的模型(如 Critic)来评估当前状态有多好,以此来辅助主模型。
偏好优化 (Preference Optimization)
这是为了让模型“比数据的平均水平更好”,教它分辨什么是“好答案”,什么是“坏答案”。
- DPO (直接偏好优化):这是一个重大突破。它不需要额外训练一个奖励模型,而是将 LLM 本身视为隐式的奖励模型,直接最大化“好答案”和“坏答案”之间的对数几率差。核心公式为:$\mathcal{L}_{DPO}=-log~\sigma(\beta~log\frac{\pi_{\theta}(y_{w}|x)}{\pi_{ref}(y_{w}|x)}-\beta~log\frac{\pi_{\theta}(y_{1}|x)}{\pi_{ref}(y_{1}|x)})$。
- KTO (卡尼曼-特沃斯基优化):借鉴了行为经济学中的“损失厌恶”理论。DPO 必须要有成对的“好 vs 坏”数据,而 KTO 允许模型从单条(不成对的)点赞或踩的数据中学习。
- ORPO & APO:为了防止模型在追求偏好时“用力过猛”而遗忘了 SFT 阶段学到的基础知识,这些算法在损失函数中引入了“锚点”或“几率比惩罚”来进行制衡。
强化微调 (Reinforcement Fine-Tuning, RFT)
这是目前“推理大模型”(如解决数学、代码问题)最火热的训练方式,因为这些领域有着极其明确的“客观对错”(可验证的奖励)。
- PPO (近端策略优化):GPT-4 和 Llama 2 的黄金标准。它在显存中同时挂载 4 个模型(当前策略、旧策略、价值模型、参考模型),并通过“裁剪 (Clipping)”机制限制模型单次更新的幅度,防止模型“学崩”。
- GRPO (群组相对策略优化):DeepSeek-R1 的核心技术。由于 PPO 太占显存,GRPO 彻底抛弃了“价值模型 (Critic)”。它针对同一个问题生成一组(比如 64 个)答案,计算平均分,然后看每个答案相对平均分是更好还是更差:$A_{i}=\frac{R_{i}-Mean(R_{group})}{StdDev(R_{group})}$。这极大节省了内存,同时保证了训练效果。
- GDPO (群组奖励解耦归一化策略优化):GRPO 的进阶版。当任务同时要求“逻辑正确”、“格式遵守”和“语气安全”时,直接把奖励相加会导致模型“挑软柿子捏”(只做好容易的指标)。GDPO 将不同类型的奖励独立进行归一化处理,确保模型在所有维度上都能均衡进化。
硬件基础 (Hardware Fundamentals)
计算生态:为什么是 GPU? (The Compute Landscape)
- CPU vs. GPU 的核心差异:
- CPU 拥有少量极其强大的核心和复杂的控制单元(如分支预测),专为处理串行任务和复杂逻辑(If/Else)设计,追求极低延迟。
- GPU 则拥有成千上万个简单的小核心,专为高并发的吞吐量设计。因为深度学习本质上就是海量的矩阵乘法(线性代数),可以被拆分成无数独立的小任务并行处理,所以 GPU 这种“人多力量大”的宽架构比 CPU 快几个数量级。
- SIMD 架构:即“单指令多数据流”。GPU 可以在一个时钟周期内,用同一条指令同时处理多个数据点(省去了传统的 for 循环)。但它很脆弱,一旦遇到复杂的 if 分支导致不同的线程走向不同的路径(Warp Divergence),并行效率就会断崖式下跌。
- 异构芯片:除了通用的 NVIDIA GPU(靠 CUDA 软件生态统治市场),还有专为张量运算设计的 ASIC(如 Google 的 TPU,让数据像心跳一样在芯片内流动的脉动阵列),以及彻底抛弃 HBM、把所有内存都做到极其昂贵的片上 SRAM 里的 Groq/Cerebras LPU(追求极致的推理延迟)。
解剖 GPU 内部 (Inside a GPU)
- 层级结构:GPU > 流式多处理器 (SM) > 核心 (Cores)。为了让 GPU 满载,我们必须分配足够多的任务让所有 SM 保持活跃。
- CUDA Core vs. Tensor Core:
- CUDA Core 是通用工人,每次只能做一个乘加运算 $(A+B)$,精确但步骤多。
- Tensor Core 是专业技工,硬件层面直接连线,能在一个时钟周期内完成整个小矩阵的乘加运算 ($D=A\times B+C$)。注意,如果你用 FP32 精度训练,往往就无法调用 Tensor Core,必须降级到 FP16/BF16 才能起飞。
- 算子融合 (Kernel Fusion):向全局显存 (HBM) 读写数据是最耗时的操作。算子融合(比如著名的 FlashAttention)就是让数据留在速度极快的 SRAM 缓存中,一次性把好几个数学步骤算完再写回 HBM,从而成倍减少内存 IO。
内存与数据搬运 (Memory & Data Movement)
在大模型中,真正的瓶颈往往不是算数慢,而是搬数据慢。
- 内存金字塔:
- SRAM (L1 Cache):几纳秒级延迟,极快但极小 (KB/MB 级)。
- HBM (VRAM 显存):百纳秒级延迟,存放模型权重的主阵地 (GB 级)。
- DRAM (CPU 内存):上万纳秒延迟,极慢但容量巨大。
- 算术强度 (Arithmetic Intensity):指每搬运一字节数据,能执行多少次数学运算。
- Prefill 阶段 (处理用户 Prompt):矩阵对矩阵乘法,算术强度高,属于算力瓶颈 (Compute-bound)。
- Decoding 阶段 (逐字生成回答):矩阵对向量乘法,为了算一个词要把整个模型的权重搬一遍,算术强度极低,属于内存带宽瓶颈 (Memory-bound)。这也是为什么大模型“出第一个字很快,但后续蹦字很慢”的物理原因。
并行、优化与指标 (Performance & Optimization)
当你无法把一个千亿参数模型塞进单张显卡时,就需要分布式策略:
- 张量并行 (Tensor Parallelism):把一个大矩阵“横切”,分给多张显卡同时算,最后再汇总。这需要极高的卡间通信速度,所以非常依赖 NVLink(比 PCIe 快十倍以上的专用通道)。
- 流水线并行 (Pipeline Parallelism):把模型“竖切”,GPU 1 算前 10 层,算完把结果传给 GPU 2 算中间 10 层。
- 核心评估指标:
- TTFT (首 Token 延迟):由算力决定。
- TPOT (每输出 Token 延迟):由显存带宽决定。
- MFU (模型 FLOPs 利用率):衡量你榨干了 GPU 多少理论算力(通常推理时 MFU 不到 50%,因为都在等内存加载)。
计算玄学 (Computational Quirks)
PPT 的最后揭示了大模型底层计算的一些反直觉“玄学”现象:
- 非确定性 (Non-Determinism):在传统软件中,同样的输入必然有同样的输出。但在大模型推理中,即使把温度设为 0 (Temperature=0),多次运行也可能得到不同的回答。原因是浮点数加法不满足结合律:$(0.0001+1000.0)+0.0002$ 和 $(0.0001+0.0002)+1000.0$ 的结果在极低精度下是不同的。GPU 内部线程完成的先后顺序受微观温度、时钟波动影响,导致累加顺序随机,进而引起细微的误差累积,最终在最后一层“翻转”了预测的 Token。
- 波级量化 (Wave Quantization) & 矩阵平铺 (Tiling):矩阵运算的效率并不是线性增长的。如果矩阵的维度是 2 的幂(如 128, 256),它能完美填满 SM 核心;但如果维度哪怕多出 1(比如 257),GPU 就不得不为这溢出的一点点数据额外启动一整波 (Wave) 全新的计算指令,导致效率骤降。
效率与优化 (Efficiency & Optimization)
量化 (Quantization)
量化是指将模型中高精度的浮点数(如 FP32 或 FP16)强制压缩成低精度的离散值(如 INT8 甚至更低)。这不仅能缩小模型体积,更能极大加快从 VRAM 搬运数据到计算单元的速度(缓解带宽瓶颈)。
仿射量化 (Affine Quantization):通过一个“缩放因子 (Scale, S)”和一个“零点 (Zero point, Z)”来进行映射。公式为
- 对称 vs. 非对称:对称量化强制把 Z 设为 0,这让计算更快,通常用于分布均匀的权重;非对称量化则保留 Z,精度更高,通常用于分布倾斜的激活值。
离群值难题 (The Outlier Problem):在超过 6B 参数的大模型中,往往会出现极大的离群值。如果全局使用同一个缩放因子 S,这些离群值会导致正常的细微数值在量化后全变成 0。因此,现代方法(如 QLoRA 用的块级量化)会把张量切成小块,给每个小块单独算一个 S。
校准 (Calibration):分为动态(运行时临时算 min/max,开销大)和静态(提前用一批数据跑一遍,把 S 和 Z 固化下来,即 PTQ 训练后量化)。
前沿技术:
- GPTQ:不只是简单四舍五入,而是根据海森矩阵(Hessian)计算出的权重敏感度,逐列量化并动态调整剩余权重来补偿误差。
- AWQ:发现那些与大激活值相乘的权重最重要。量化前先成倍放大这些“关键权重”,并在计算时缩小激活值,从而在 INT8 空间内保留更高的分辨率。
- QAT (量化感知训练):如果模型卡在一个极其狭窄的局部最优解,微小的量化误差就会让 Loss 爆炸。QAT 在训练时就故意加入“量化-反量化”的噪声,逼迫模型寻找更平缓、更抗干扰的极小值点。
- BitNet (1-bit LLM):极限压缩,权重只取 -1, 0, 1(约 1.58 bits)。0 允许模型过滤特征。这种模型甚至不需要乘法器,全是加减法,在规模足够大时能追平 16 位模型的表现。
参数高效微调 (Parameter-Efficient Fine-Tuning, PEFT)
为了让一个通用大模型适应新任务,我们不需要重新训练它的几百亿个参数。
- Adapter:在 Transformer 的层与层之间插入小型的“降维->非线性->升维”瓶颈网络。缺点是增加了模型的物理深度,拖慢了推理速度。
- LoRA (Low-Rank Adaptation):假设微调时权重的变化矩阵 $\Delta W$ 是低秩的。它冻结原模型,只训练两个小矩阵 $A$ 和 $B$(例如 $W_{new}=W+B\times A$)。
- 在推理时,由于线性代数的特性,我们可以直接把 $B\times A$ 的结果加到原权重里(即合并 Merge),实现零延迟惩罚。
- QLoRA:把原本巨大的 Base 模型压成 4-bit (NF4 格式) 塞进显存,然后用高精度的 LoRA 层进行微调,甚至把优化器状态卸载到 CPU 内存里,使得在消费级显卡上微调大模型成为可能。
模型压缩与蒸馏 (Model Compression & Distillation)
- 模型剪枝 (Model Pruning):把接近 0 的权重直接删掉。但 GPU 很讨厌不规则的稀疏矩阵(会导致内存寻址变慢),因此目前只有结构化剪枝(如 N:M,每 4 个数里必须有 2 个是 0)能在 Tensor Core 上真正加速。
- 知识蒸馏 (Knowledge Distillation):让一个小模型 (Student) 去模仿一个大模型 (Teacher)。
- 白盒蒸馏 (Dark Knowledge):教师模型输出的不仅仅是正确答案(1.0),还有对其他错误答案的概率评估(比如 0.09, 0.01)。这些分布细节包含了概念间的关系(暗知识),学生模型通过最小化 KL 散度来学习这种分布(通常还会用温度系数 T 展平概率分布)。
- 黑盒蒸馏:如果拿不到教师模型的底层概率,就让教师生成大量带有推理过程(Chain-of-thought)的合成数据,用这些数据对学生模型做 SFT。
算法级加速 (Algorithmic Speedups)
- 连续批处理 (Continuous Batching):传统的批处理中,短请求必须等长请求生成完才能一起出图。连续批处理在“Token 级别”进行调度,只要有请求输出了
[EOS],立刻把它踢掉并塞入新请求,极大提升了服务器吞吐量。 - 投机解码 (Speculative Decoding):针对“逐字生成”时的显存带宽瓶颈。用一个小模型快速“瞎猜” N 个词,然后让大模型一次性并行验证这 N 个词。由于并行验证在显存利用率上非常划算,只要小模型猜得准,就能在不损失精度的情况下实现 2-3 倍加速。
- 梯度检查点 (Gradient Checkpointing):为了省下训练时存放激活值的巨大内存,前向传播时只保存部分层的数据。反向传播到了缺失的地方,再重新跑一遍前向计算补回来。用时间(慢 20-30%)换空间,从而能跑更大的 Batch Size 或更长的上下文。
- DualPath:针对当下 Agent 多轮对话导致 KV-Cache 暴增的存储读取瓶颈。传统架构中,读取硬盘里 KV-Cache 的重担全压在 Prefill(预填充)节点的网卡上,导致严重拥堵。DualPath 让空闲的 Decode(解码)节点也帮忙从硬盘读数据,再通过高速内部网络传给 Prefill 节点,实现了网络带宽的全局负载均衡。