在上一篇文章中,我们精读了 GPT-1。
GPT-1 的核心思想是:先使用 Transformer Decoder 在大规模无标注文本上进行生成式预训练,然后再把预训练模型迁移到下游 NLP 任务中进行微调。它走的是 从左到右的自回归语言模型路线。
但是 GPT-1 有一个天然限制:
它只能根据左侧上下文预测后面的 token,不能同时利用左右两侧上下文。
例如句子:
我今天去 [MASK] 上课。
如果模型要预测 [MASK] 位置的词,只看左边"我今天去"是不够的;右边的"上课"也非常关键。
如果模型能够同时看到左右上下文,就更容易判断 [MASK] 位置应该是:
学校
教室
培训班
BERT 正是为了解决这个问题而提出的。BERT 对应的论文是:
BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
BERT 的全称是:
Bidirectional Encoder Representations from Transformers
也就是:
来自 Transformer 的双向编码器表示
这篇论文由 Google 在 2018 年提出,是预训练语言模型时代最重要的论文之一。它的核心思想是:
使用 Transformer Encoder 在大规模无标注文本上进行双向语言表示预训练,然后在各种下游理解任务上进行微调。
如果说 GPT-1 代表了生成式预训练路线,那么 BERT 就代表了双向理解式预训练路线。
一、BERT 想解决什么问题?
在 BERT 之前,预训练语言模型已经出现了一些重要工作,例如 ELMo、GPT-1 等。这些方法都证明了一个方向:
先在大规模无标注文本上学习语言表示,再迁移到下游任务,比从零开始训练模型更有效。
但是这些方法仍然存在一些问题。ELMo 虽然可以利用双向信息,但它本质上是两个单向语言模型的拼接:一个从左到右读文本,一个从右到左读文本。它不是在同一个深层模型中同时融合左右上下文。
GPT-1 使用 Transformer Decoder 做自回归语言建模。它的预训练目标是:
给定前面的 token,预测下一个 token
也就是说,GPT-1 在预测当前位置时只能看到左侧上下文。例如:
我 今天 去 学校
GPT-1 的建模方式是:
P(我)
P(今天 | 我)
P(去 | 我, 今天)
P(学校 | 我, 今天, 去)
这种方式非常适合文本生成,但对于很多理解任务来说,双向上下文更重要。例如:
这个苹果手机很好用。
这里的"苹果"表示 Apple 公司。而在:
这个苹果很好吃。
这里的"苹果"表示水果。要判断词义,通常需要同时看左边和右边的上下文。BERT 要解决的问题就是:
如何让 Transformer 在预训练阶段就学习深层双向语言表示?
这也是 BERT 和 GPT-1 最大的区别。
二、BERT 的核心思想:Encoder-only + 双向预训练
BERT 使用的是 Transformer Encoder,而不是 Transformer Decoder。
这点非常关键。
Transformer Encoder 的 Self-Attention 是双向的。也就是说,每个 token 可以同时关注句子中左边和右边的 token。
例如句子:
我 今天 去 学校 上课
在 BERT 中,"学校"这个 token 可以同时关注:
左边:我 今天 去
右边:上课
这和 GPT 不同。GPT 使用 causal mask,每个位置只能看到自己左边的 token,不能看到未来 token。可以这样对比:
| 模型 | 架构 | Attention 方向 | 预训练目标 | 更适合 |
|---|---|---|---|---|
| GPT-1 | Transformer Decoder | 单向,从左到右 | 预测下一个 token | 生成任务 |
| BERT | Transformer Encoder | 双向,左右上下文都可见 | 预测被 mask 的 token | 理解任务 |
BERT 的模型结构可以简化为:
输入文本
↓
Tokenizer
↓
Token Embedding + Segment Embedding + Position Embedding
↓
Transformer Encoder × N
↓
任务输出层
BERT 的核心不是生成文本,而是学习每个 token 的上下文表示。也就是说,BERT 关注的是:
给定完整句子,如何为每个 token 生成融合左右上下文的表示?
这种表示非常适合下游理解任务,例如:
文本分类
自然语言推理
语义相似度
命名实体识别
阅读理解
三、BERT 的输入表示:Token、Segment 和 Position 三种 Embedding
BERT 的输入不是单一 embedding,而是三种 embedding 相加:
Input Embedding
=
Token Embedding
+
Segment Embedding
+
Position Embedding
可以写成:
其中:
-
表示第i个 token 的词向量;
-
表示该 token 属于句子 A 还是句子 B;
-
表示该 token 在序列中的位置。
1. Token Embedding
Token Embedding 是最基础的词向量。BERT 使用 WordPiece tokenizer,把文本切分成子词 token。例如:
playing
可能被切成:
play / ##ing
其中 ##ing 表示这是接在前面 token 后面的子词片段。这样做可以缓解未登录词问题,同时避免词表过大。
2. Segment Embedding
BERT 很多任务都涉及句子对。例如自然语言推理:
句子 A:一个人在弹吉他。
句子 B:一个人在演奏乐器。
模型需要判断句子 B 是否能由句子 A 推出。为了让模型区分两个句子,BERT 引入 Segment Embedding。通常:
句子 A 的 token 加上 Segment A Embedding
句子 B 的 token 加上 Segment B Embedding
输入格式一般是:
[CLS] 句子A [SEP] 句子B [SEP]
其中:
-
[CLS]放在序列开头,用于聚合整个输入的表示; -
[SEP]用于分隔句子。
3. Position Embedding
Transformer 本身没有顺序结构,因此需要位置编码。BERT 使用可学习的位置 embedding,让模型知道每个 token 在序列中的位置。例如:
我 / 今天 / 去 / 学校
模型不仅要知道这些 token 是什么,还要知道它们的顺序。所以,BERT 的输入可以理解为:
这个 token 是什么?
它属于哪个句子?
它位于序列的哪个位置?
三种信息相加后,才进入 Transformer Encoder。
四、BERT 的预训练任务一:Masked Language Modeling
如果 BERT 使用普通双向 Self-Attention,每个 token 都能看到左右上下文。这会带来一个问题:
如果直接让模型预测当前 token,它会在输入中直接看到答案。
例如输入:
我 今天 去 学校 上课
如果让模型预测"学校",但"学校"本身就在输入里,那任务就没有意义了。因此,BERT 设计了 Masked Language Modeling,简称 MLM。
MLM 的做法是:
随机遮住输入中的一部分 token,让模型根据左右上下文预测被遮住的 token。
例如:
我 今天 去 [MASK] 上课
模型需要预测:
学校
这样,BERT 就可以在双向上下文条件下学习语言表示。MLM 的训练目标可以写成:
其中:
-
表示被 mask 的位置集合;
-
是第 i个位置的真实 token;
-
表示被遮挡后的输入序列;
-
模型只在被 mask 的位置上计算损失。
MLM 的具体遮挡策略
BERT 并不是把所有选中的 token 都替换成 [MASK]。论文中的做法是:随机选择 15% 的 token 作为预测目标。对于这些被选中的 token:
80% 的情况:替换成 [MASK]
10% 的情况:替换成随机 token
10% 的情况:保持原 token 不变
例如原句是:
我 今天 去 学校 上课
可能变成:
我 今天 去 [MASK] 上课
也可能变成:
我 今天 去 苹果 上课
或者保持:
我 今天 去 学校 上课
为什么不全部替换成 [MASK]?因为下游微调时,真实输入中通常不会出现 [MASK]。如果预训练时模型总是看到 [MASK],预训练和微调之间会产生不一致。所以 BERT 使用 80/10/10 的策略,让模型既能学习预测被遮住 token,又不会过度依赖 [MASK] 这个特殊符号。
MLM 的意义
MLM 让 BERT 可以学习真正的双向表示。GPT 的自回归目标是:
只看左边,预测右边
BERT 的 MLM 目标是:
同时看左边和右边,预测中间被遮住的 token
这使 BERT 更适合理解任务。
例如:
这个苹果很好吃。
这个苹果手机很好用。
BERT 可以根据右侧上下文判断"苹果"的语义。
五、BERT 的预训练任务二:Next Sentence Prediction
除了 MLM,BERT 还设计了第二个预训练任务:Next Sentence Prediction,简称 NSP。NSP 的目标是:
判断两个句子是否是连续的上下文关系。
输入是两个句子 A 和 B:
[CLS] 句子A [SEP] 句子B [SEP]
模型需要预测:
B 是否是 A 的下一句?
构造数据时:
50% 的样本中,B 是 A 的真实下一句
50% 的样本中,B 是从语料中随机抽取的句子
例如正样本:
句子 A:小明今天去学校上课。
句子 B:老师讲解了 Transformer 的基本原理。
标签:IsNext
负样本:
句子 A:小明今天去学校上课。
句子 B:这家餐厅的牛肉面很好吃。
标签:NotNext
NSP 的分类通常使用 [CLS] 位置的输出表示。设 [CLS] 对应的最终隐藏状态为:
则 NSP 的预测概率可以写成:
其中:
-
y表示 IsNext 或 NotNext;
-
是 NSP 分类层参数。
为什么需要 NSP?
BERT 面向很多句子对任务,例如:
自然语言推理
问答匹配
语义相似度
阅读理解
这些任务不只需要理解单个句子,还需要理解两个句子之间的关系。NSP 就是为了让模型在预训练阶段学习句子级关系。不过需要注意,NSP 后来受到了一些质疑。后续 RoBERTa 等工作发现,去掉 NSP 并使用更大数据和更充分训练,也可以取得更好效果。所以 NSP 是 BERT 原论文中的重要设计,但并不是后来所有 BERT 类模型都会保留的组件。
六、BERT 的整体预训练目标
BERT 的预训练目标由 MLM 和 NSP 两部分组成。
可以写成:
其中:
-
负责 token 级别的语言表示学习;
-
负责句子对关系建模。
训练流程可以概括为:
大规模无标注文本
↓
构造 [CLS] 句子A [SEP] 句子B [SEP]
↓
随机 mask 15% token
↓
输入 Transformer Encoder
↓
预测被 mask 的 token
↓
判断句子B是否是句子A的下一句
这就是 BERT 的预训练过程。
与 GPT-1 相比,BERT 的最大不同在于:
GPT-1:生成式预训练,单向语言模型
BERT:掩码式预训练,双向语言表示
七、BERT 的模型规模:BERT-Base 和 BERT-Large
BERT 原论文主要给出了两个模型版本:
BERT-Base
BERT-Large
它们的配置如下:
| 模型 | 层数 | Hidden Size | Attention Heads | 参数量 |
|---|---|---|---|---|
| BERT-Base | 12 | 768 | 12 | 约 110M |
| BERT-Large | 24 | 1024 | 16 | 约 340M |
BERT-Base 的规模与 GPT-1 接近,方便进行对比。BERT-Large 则更深、更宽,性能也更强。可以这样理解:
BERT-Base:标准版本,训练和使用成本相对较低
BERT-Large:更大版本,性能更强,但计算成本更高
BERT 的预训练语料包括 BooksCorpus 和 English Wikipedia。BooksCorpus 提供长文本和连续语境,Wikipedia 提供百科知识和较规范的语言表达。两者结合,使 BERT 能够学习比较丰富的语言表示。
八、BERT 如何适配下游任务?
BERT 的使用方式非常统一:
在预训练好的 BERT 上添加一个很小的任务层,然后对整个模型进行微调。
这和 GPT-1 的"预训练 + 微调"思想类似,但 BERT 更强调通过统一的 Encoder 表示适配各种理解任务。
1. 文本分类
例如情感分类:
[CLS] 这部电影非常精彩 [SEP]
BERT 输出每个 token 的隐藏状态。通常取 [CLS] 位置的最终表示:
接一个线性分类层:
用于预测类别。
2. 句子对分类
例如自然语言推理:
[CLS] 一个男孩在踢足球 [SEP] 一个孩子在运动 [SEP]
模型通过 Segment Embedding 区分句子 A 和句子 B。然后仍然使用 [CLS] 表示进行分类,判断二者关系是:
entailment
neutral
contradiction
3. 命名实体识别
命名实体识别是 token-level 任务。例如:
小明 在 北京 上学
模型需要预测每个 token 的标签:
小明 → PERSON
北京 → LOCATION
这类任务不使用 [CLS] 做整体分类,而是对每个 token 的输出隐藏状态接分类层。也就是说:
每个 token 输出一个标签
4. 阅读理解
以抽取式问答为例,输入格式通常是:
[CLS] 问题 [SEP] 文章 [SEP]
BERT 需要从文章中找出答案片段。做法是预测答案的开始位置和结束位置。
设第i个 token 的隐藏状态为:
模型分别计算每个位置作为答案起点和终点的概率:
最终选择概率最高的起点和终点作为答案范围。例如文章中有一句:
BERT 是由 Google 提出的预训练语言模型。
问题是:
BERT 是谁提出的?
模型应该预测答案 span:
Google
这说明 BERT 不只是做分类,也可以通过 token-level 输出完成阅读理解。
九、BERT 与 GPT-1 的核心区别
GPT-1 和 BERT 都是 Transformer 预训练模型,但它们代表了两条不同路线。
| 对比维度 | GPT-1 | BERT |
|---|---|---|
| 架构 | Transformer Decoder | Transformer Encoder |
| Attention 方向 | 单向,只看左侧上下文 | 双向,同时看左右上下文 |
| 预训练目标 | 自回归语言建模 | MLM + NSP |
| 输入形式 | 连续文本序列 | [CLS] A [SEP] B [SEP] |
| 下游适配 | 输入转换 + 微调 | 加任务头 + 微调 |
| 更适合 | 文本生成 | 文本理解 |
| 后续发展 | GPT-2、GPT-3、ChatGPT | RoBERTa、ALBERT、ELECTRA |
可以用一句话概括:
GPT-1 学的是"如何从左到右生成文本",BERT 学的是"如何利用左右上下文理解文本"。
这也是为什么后来的大语言模型主流选择 GPT 路线,而很多理解任务、检索任务、文本编码任务仍然大量使用 BERT 类模型。
十、BERT 的贡献与局限
BERT 的贡献主要有三点。
第一,它提出了深层双向 Transformer 预训练语言表示。
BERT 不是简单把左向语言模型和右向语言模型拼接,而是在同一个 Transformer Encoder 中通过 MLM 学习深层双向上下文表示。
第二,它建立了"预训练 + 微调"的强大范式。
BERT 可以通过一个统一的预训练模型迁移到文本分类、句子对判断、命名实体识别、阅读理解等任务中。
第三,它显著推动了 NLP 进入预训练模型时代。
在 BERT 之后,RoBERTa、ALBERT、ELECTRA、ERNIE、DeBERTa 等大量模型都在 BERT 的基础上改进。
当然,BERT 也有局限。
第一,BERT 不适合直接生成长文本。
它是 Encoder-only 架构,不是自回归生成模型。
第二,MLM 存在预训练和微调不一致问题。
预训练时输入中有 [MASK],但下游任务中通常没有 [MASK]。
第三,NSP 的有效性后来受到质疑。
RoBERTa 等后续工作发现,去掉 NSP 并改进训练数据和训练策略,也可以取得更强效果。
第四,BERT 的上下文长度有限。
原始 BERT 通常使用 512 token 的最大长度,难以直接处理很长文档。
因此,BERT 是理解型预训练模型的重要起点,但并不是现代大语言模型的最终形态。
十一、BERT 在大语言模型发展中的位置
从今天的大语言模型视角回看,BERT 的意义非常特殊。
它不是 ChatGPT 这类对话模型的直接前身,因为 ChatGPT 主要继承的是 GPT 的 decoder-only 自回归生成路线。
但 BERT 对整个预训练语言模型的发展影响巨大。
它证明了:
大规模无标注文本预训练
+
Transformer
+
下游任务微调
可以显著提升 NLP 任务表现。
如果把预训练语言模型时代的主线简化,可以得到:
GPT-1:生成式预训练路线
BERT:双向理解式预训练路线
T5:Text-to-Text 统一路线
这三条路线共同奠定了后续大语言模型的发展基础。
GPT 路线最终走向了 ChatGPT、LLaMA、Qwen、DeepSeek 等生成式大模型。
BERT 路线则长期影响文本理解、检索、排序、语义匹配和编码器表示学习。
T5 路线则进一步把各种 NLP 任务统一成文本到文本的格式。
所以,BERT 的价值不在于它能不能像 ChatGPT 那样对话,而在于它定义了一个强大的双向语言理解范式。