预训练革命
在 2018 年之前,NLP 的标准流程是这样的:
- 拿到一个具体任务(情感分类、命名实体识别、机器翻译……)
- 手工设计特征(词袋、TF-IDF、n-gram、依存句法树……)
- 训练一个监督模型(SVM、CRF、浅层 LSTM……)
每换一个任务,特征要重新设计,模型要从零训练。标注数据永远不够用——人工标 10 万条已经是大工程,但语言的复杂度远不止 10 万条能覆盖的。
2018 年,两篇论文几乎同时给出了另一种范式:
先在海量无标注文本上"自学"语言规律(预训练),再用少量标注数据适配具体任务(微调)。
这两篇论文就是 GPT(OpenAI,2018 年 6 月)和 BERT(Google,2018 年 10 月)。它们用的底层架构都是 Transformer,但训练目标截然不同——一个从左往右预测,一个双向填空。
预训练的核心洞察很简单:语言本身就是监督信号。你不需要人工标注"这句话是正面还是负面",只要让模型预测下一个词(或者还原被遮住的词),它就必须理解语法、语义、常识、甚至逻辑推理。几十 GB 的互联网文本免费提供了数十亿个这样的"自监督"训练样本。
这个范式转变的影响是颠覆性的:
- 特征工程消失了 —— 预训练模型自己学出了特征表示
- 小数据任务不再绝望 —— 微调只需要几百到几千条标注
- 一个模型通吃多任务 —— 同一个预训练模型微调一下就能做分类、问答、摘要
- 规模带来质变 —— 模型越大、数据越多,下游任务表现越好(后来被总结为 Scaling Laws)
语言模型基础
在讲 GPT 和 BERT 之前,需要搞清一个核心概念:语言模型(Language Model)。
语言模型的任务很朴素——给定一个词序列,估计它出现的概率:
用链式法则展开:
每一步都在回答同一个问题:给定前面所有的词,下一个词是什么? 这就是"预测下一个 token"。
注意这里说的是 token 而不是"词"。现代语言模型用 子词分词(BPE / SentencePiece)把文本切成比词更细的单元。比如 "unhappiness" 可能被切成 "un" + "happi" + "ness"。这样做的好处是:词表大小可控(通常 32K-128K),同时能处理任何新词——没见过的词总能被拆成见过的子词。
语言模型的训练不需要任何标注——原始文本本身就包含了所有监督信号。每一个 token 的"标签"就是它自己,而"输入"就是它前面的所有 token。这就是自监督学习(self-supervised learning):数据自己提供标签。
为什么"预测下一个词"能学到这么多?
因为要准确预测下一个词,模型被迫理解越来越深层的东西:
- 预测 "北京是中国的___" → 需要事实知识(首都)
- 预测 "他虽然很累,___还是坚持跑完" → 需要语法(但/却)
- 预测 "如果 A > B 且 B > C,那么 A ___ C" → 需要逻辑推理(>)
- 预测 "她说完这句话,转身就走了。他愣在原地,___" → 需要情感理解
预测任务看似简单,但要做好它,模型必须内化语言的几乎所有层面。这就是预训练的力量。
GPT:单向 Transformer
GPT(Generative Pre-trained Transformer) 的核心思想极其简单:拿一个 Transformer 的 decoder 做语言模型。
架构:Decoder-Only
GPT 使用 decoder-only 架构——去掉了原始 Transformer 的 encoder,只保留 decoder 的堆叠。如果你读过 Transformer 篇,你已经知道这个结构的核心:
- 每个 block 包含 因果自注意力(causal self-attention) + FFN
- 因果注意力用一个下三角掩码确保每个 token 只能看到自己和之前的 token
- 这让模型天然适合自回归生成:从左到右,一个一个 token 地预测
因果掩码的数学表达:
其中 当 (允许看), 当 (禁止看)。加上 后 softmax 输出为 0——未来的信息被完全屏蔽。
训练目标:因果语言模型(CLM)
给定一段文本 ,GPT 最大化:
每个位置 的输出向量经过线性层 + softmax 变成词表上的概率分布,和真实 token 做交叉熵损失。整个训练过程可以完全并行——虽然推理是自回归的,但训练时所有位置的损失可以一次算出来(因为 causal mask 保证了每个位置看不到后面的答案)。
从 GPT-1 到 GPT-4
| 模型 | 年份 | 参数量 | 层数 | 关键突破 |
|---|---|---|---|---|
| GPT-1 | 2018 | 117M | 12 | 证明"预训练 + 微调"可行 |
| GPT-2 | 2019 | 1.5B | 48 | 不微调也能做任务(zero-shot) |
| GPT-3 | 2020 | 175B | 96 | In-context learning,few-shot 范式 |
| GPT-4 | 2023 | 未公开(传 ~1.8T MoE) | 未公开 | 多模态,推理能力质变 |
GPT-1 的贡献是验证了预训练范式——在 BookCorpus 上预训练一个 12 层 Transformer,然后微调,在 9/12 个 NLP 基准上拿了最好成绩。
GPT-2 发现了一件有趣的事:模型够大就不需要微调了。直接给 prompt "TL;DR:" 它就能做摘要,给 "Translate English to French:" 就能翻译。虽然效果还不够好,但这暗示了模型在预训练中"附带"学会了很多任务。
GPT-3 把这个发现推到极致——175B 参数,用 in-context learning 取代微调:只需要在 prompt 里给几个例子(few-shot),模型就能做新任务。不改权重,不算梯度,纯靠推理时的"模式匹配"。这彻底改变了 NLP 的使用方式。
BERT:双向理解
BERT(Bidirectional Encoder Representations from Transformers) 走了一条完全不同的路:它用的是 Transformer 的 encoder,而且双向看。
架构:Encoder-Only
BERT 使用标准的 Transformer encoder——和 decoder 的唯一区别是没有因果掩码。每个 token 的 注意力 可以看到序列中所有位置(包括后面的 token)。
这意味着当模型处理"机器学习很有趣"时,"学"这个 token 不仅能看到前面的"机器",也能看到后面的"习很有趣"。完整的上下文信息让 BERT 在理解任务上有天然优势。
训练目标 1:掩码语言模型(MLM)
但双向带来一个问题:你不能让模型"预测下一个词"了——因为它能看到答案!
BERT 的解决方案巧妙:随机遮住一些 token,让模型猜被遮住的是什么。这就是 Masked Language Model(MLM):
- 随机选择输入中 15% 的 token
- 其中 80% 替换为特殊标记
[MASK] - 其中 10% 替换为随机 token
- 其中 10% 保持不变
- 模型要预测这 15% 位置的原始 token
其中 是被 mask 的位置集合。注意和 GPT 的关键区别:GPT 的条件是 (只有前文),BERT 的条件是 (除了被 mask 的位置,前后文都能看到)。
为什么不全部替换为 [MASK]?因为微调时输入里没有 [MASK] 标记——如果预训练时模型只学会了处理 [MASK],在真实文本上就会失效。混入随机替换和保持不变,让模型对每个位置都保持"警惕"。
训练目标 2:下一句预测(NSP)
BERT 还有第二个预训练任务——Next Sentence Prediction:给模型两个句子 A 和 B,预测 B 是不是 A 的真实下一句。
- 50% 的情况下,B 是 A 的真实下一句(正例)
- 50% 的情况下,B 是随机抽取的句子(负例)
NSP 的初衷是让模型理解句子间的关系,帮助问答、推理等任务。不过后来的研究(RoBERTa, 2019)发现 NSP 帮助不大甚至有害——去掉它效果反而更好。原因可能是随机抽的负例太容易区分,模型学会了走捷径(比如只看话题是否相关)。
为什么双向很重要
用一个例子感受差异。考虑句子:"他在银行存了一笔钱"和"河的两岸有很多银行"。
- GPT(单向):处理到"银行"时,只能看到前面的"他在"或"河的两岸有很多"——第一句话里看到"他在",很难判断是金融还是河岸;第二句看到"河的两岸"才能判断
- BERT(双向):处理"银行"时同时看到前后文——第一句的"存了一笔钱"和第二句的"河的两岸"都能用上,消歧义更准确
对于理解型任务(分类、问答、NER),双向信息至关重要。但双向也有代价——BERT 不能做生成。因为它看过了整个序列,没法自回归地一个个生成 token。
下面的交互组件直观对比了两种预训练方式的注意力模式。切换 GPT / BERT,悬停某个 token 看它能"看到"哪些位置:
因果注意力:每个 token 只能看到自己和左边的 token。悬停某行查看它的注意力范围。
GPT vs BERT 对比
把两种范式放在一起看:
| GPT | BERT | |
|---|---|---|
| 架构 | Decoder-only (Transformer decoder 堆叠) | Encoder-only (Transformer encoder 堆叠) |
| 注意力方向 | 单向(因果掩码,只看左边) | 双向(无掩码,看所有位置) |
| 训练目标 | 因果语言模型 CLM:预测下一个 token | 掩码语言模型 MLM:还原被 mask 的 token |
| 数学形式 | ||
| 训练效率 | 每个 token 都参与损失计算 | 只有 15% 被 mask 的 token 参与损失 |
| 擅长任务 | 文本生成、对话、代码生成 | 文本分类、问答、命名实体识别 |
| 是否能生成 | 天然支持自回归生成 | 不能直接生成(可以填空) |
| 代表模型 | GPT 系列、LLaMA、Claude | BERT、RoBERTa、ALBERT、DeBERTa |
| 当前地位 | 大模型的主流路线 | 中小规模理解任务仍在广泛使用 |
一个常被忽略的区别是训练效率。GPT 的每个 token 都贡献一个损失项(预测下一个 token),BERT 只有被 mask 的 15% 贡献损失。这意味着同样多的训练数据,GPT 从每个 token 都学到了信息,BERT 浪费了 85%。这个效率差异在数据量达到万亿 token 时变得很关键。
还有一个架构层面的差异:BERT 的双向注意力无法使用 KV cache 优化。decoder-only 的推理可以把之前 token 的 key/value 缓存下来(参见 Transformer 篇),每一步只需要计算新 token。BERT 的每个 token 都要和所有 token 做注意力,缓存无法复用。当序列长度很长时,这个差距是数量级的。
微调与 Prompt
预训练给了我们一个"懂语言"的基础模型。但它不知道你想让它做什么——分类?问答?翻译?有两种方式告诉它。
方式一:微调(Fine-tuning)
这是 BERT 时代的标准做法:
- 拿预训练好的模型
- 在最后一层后面加一个任务特定的头(比如分类就加一个线性层)
- 用标注数据更新所有参数
- 每个任务都得到一个独立的模型
微调的好处是效果好——几百条标注数据就能在特定任务上达到很高的准确率。坏处是每个任务需要单独一个模型。如果你有 100 个任务,就需要部署 100 个 BERT。
方式二:In-Context Learning(上下文学习)
GPT-3 开创了一种完全不同的范式——不改权重,用 prompt 定义任务:
将以下句子翻译成英文:
句子:机器学习很有趣
翻译:Machine learning is fun
句子:今天天气真好
翻译:
模型看到了两个"示例",然后自然地续写出翻译结果。这就是 few-shot in-context learning:通过在 prompt 中给出几个示例,让模型理解任务格式并执行。
| 微调(Fine-tuning) | In-Context Learning | |
|---|---|---|
| 是否改权重 | 改(全部或部分) | 不改 |
| 需要多少数据 | 几百到几千条标注 | 0(zero-shot)到几十条(few-shot) |
| 计算成本 | 训练:高;推理:低 | 训练:零;推理:高(长 prompt) |
| 部署 | 每个任务一个模型 | 一个模型服务所有任务 |
| 效果 | 特定任务上更好 | 通用但不极致 |
为什么 GPT 路线最终胜出
2018-2020 年,BERT 在各种 NLP 排行榜上碾压 GPT——因为理解任务正是它的强项,而且微调后效果极好。BERT 一度看起来是更好的范式。
但从 2020 年的 GPT-3 开始,风向变了。几个关键因素让 decoder-only + 自回归生成成为大模型的主流选择:
- 生成能力是刚需 —— ChatGPT 证明了"对话"是 AI 最自然的交互方式,而 BERT 不能生成
- 规模效应更好 —— GPT 架构的训练效率更高(每个 token 都学),scaling law 显示 decoder-only 在大规模下收益更大
- 一个模型做所有事 —— in-context learning 消除了"每个任务一个模型"的部署噩梦
- 简洁性 —— decoder-only 只有一种 block,encoder-decoder 的复杂度在大规模下没有带来对应的收益
- 后训练的突破 —— RLHF(基于人类反馈的强化学习)让自回归模型学会了"听指令",弥补了 GPT 架构在理解任务上的劣势
今天,最强的大模型——GPT-4、Claude、Gemini、LLaMA、DeepSeek——全部都是 decoder-only 架构。BERT 并没有消失——它仍然是中小规模理解任务(搜索排序、文档分类、NER)的最佳选择,因为它小、快、微调效果好。但在"通向通用智能"这条路上,GPT 的路线赢了。