08 BERT 论文精读:双向 Transformer 如何学习语言表示?

在上一篇文章中,我们精读了 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 那样对话,而在于它定义了一个强大的双向语言理解范式。

相关推荐
星恒随风9 小时前
从零开始理解 ResNet(上):为什么 CNN 需要“残差连接”?
人工智能·笔记·神经网络·学习·cnn
shuaiqinke9 小时前
【分享】医维度解剖 3D人体模型 解剖学习超直观
学习·3d
星秀日9 小时前
rust学习入门
开发语言·学习·rust
库奇噜啦呼10 小时前
【iOS】源码学习-类的加载
学习·ios·cocoa
Engineer邓祥浩10 小时前
宏观认知(1):AI 是什么——吴恩达《AI for Everyone》Week1 学习笔记
人工智能·笔记·学习
小程故事多_8010 小时前
深入解析FlashAttention,大模型长序列训练的底层优化核心技术
人工智能·transformer
暴躁小师兄数据学院10 小时前
【AI大模型应用开发工程师特训笔记】第04讲(第五章):条件判断与流程控制
大数据·人工智能·python·学习
3DVisionary10 小时前
混凝土裂纹如何全自动识别?DIC技术在结构裂缝重构的应用
人工智能·学习·dic技术·混凝土裂缝监测·全场应变分析·三维位移测量·实验力学
魔法阵维护师11 小时前
从零开发游戏需要学习的c#模块,第二十八章(血条显示 —— 敌人与玩家生命可视化)
学习·游戏·c#