论文信息:
- 标题:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
- 作者:Jacob Devlin, Ming-Wei Chang, Kenton Lee, Kristina Toutanova(Google AI Language)
- 发表:NAACL 2019(2018年10月 arXiv 预印本)
- 论文链接:https://arxiv.org/abs/1810.04805
- 官方代码:https://github.com/google-research/bert
BERT(Bidirectional Encoder Representations from Transformers)是 Google 于 2018 年提出的语言表示模型,在自然语言处理领域具有里程碑意义。其核心贡献在于证明了深度双向预训练对于语言理解的关键作用,通过创新性地将 Transformer 编码器与掩码语言模型(MLM)训练目标结合,首次实现了真正意义上的双向上下文建模。
BERT 的出现标志着 NLP 领域进入"预训练+微调"(Pre-train + Fine-tune)范式的成熟期,在发布时刷新了 11 项 NLP 基准的最佳成绩,至今仍是 NLP 研究和应用的基石。
BERT 之前,预训练语言表示主要通过两种方式应用于下游任务:
1. 基于特征的方法(Feature-based)
使用预训练的词嵌入或上下文表示作为输入特征,在此基础上训练任务特定模型。代表性工作包括 ELMo(Peters et al., 2018)。
ELMo 的做法是训练独立的从左到右和从右到左的 LSTM,然后将两者的隐状态浅层拼接。这种方式虽然在一定程度上捕获了双向信息,但:
2. 基于微调的方法(Fine-tuning)
先在大规模无标注文本上预训练语言模型,然后在下游任务上微调所有参数。代表性工作为 OpenAI GPT(Radford et al., 2018)。GPT 使用 Transformer 解码器架构,但由于标准语言模型是从左到右单向预测下一个 token,每个位置只能关注其左侧的上下文,无法利用右侧信息。
传统语言模型的单向性在以下场景中尤为突出:
BERT 的关键洞察是:纯粹的语言模型预训练目标(next token prediction)天然是单向的,要获得真正双向的表示,必须引入非语言模型的预训练任务。
BERT 是一个多层双向 Transformer 编码器。论文定义了两个模型规格:
| 规格 | 层数 | 隐层维度 | 注意力头数 | 参数量 |
|---|---|---|---|---|
| BERT | 12 | 768 | 12 | 110M |
| BERT | 24 | 1024 | 16 | 340M |
BERT 的参数量级与 OpenAI GPT 相当(两者均为约 110M),使得后续的对比实验具有公平性。两者的核心架构差异在于:
BERT 继承自 Vaswani et al. (2017) 的 Transformer 架构。一个 Transformer 编码器块包含两个核心子层:
每个子层后接残差连接(Residual Connection)和层归一化(Layer Normalization):
| 维度 | BERT | OpenAI GPT |
|---|---|---|
| 架构类型 | Transformer 编码器 | Transformer 解码器 |
| 注意力方式 | 双向(全可见) | 单向(causal mask) |
| 预训练目标 | MLM + NSP | 从左到右语言模型 |
| 参数量(BASE) | 110M | 110M |
后来的研究中出现了更大的 BERT 变体:RoBERTa(Liu et al., 2019)通过更多数据、更长训练和动态掩码策略进一步优化了 BERT 训练过程;而在参数量上,后来的研究表明 BERT 架构可以扩展到更大的规模,如 ALBERT(Lan et al., 2019)通过参数共享将参数量缩减但仍保持良好性能。
BERT 的输入表示设计精巧,能灵活支持单句和句对两种场景。输入 token 序列由三部分嵌入相加构成:

1. Token 嵌入(Token Embeddings)
使用 30,000 token 的 WordPiece 词表。WordPiece 是一种子词分词方法,将罕见词分解为更常见的子词片段:
2. 段嵌入(Segment Embeddings)
区分句子 A 和句子 B。对于单句输入,所有 token 使用同一段嵌入。
3. 位置嵌入(Position Embeddings)
可学习的位置编码,而非 Transformer 原文中的正弦/余弦位置编码。最大序列长度为 512。
| Token | 含义 | 用途 |
|---|---|---|
[CLS] |
Classification | 每个序列的第一个 token,其最终隐状态作为整个序列的聚合表示,用于分类任务 |
[SEP] |
Separator | 分隔两个句子,也作为序列结束标记 |
[MASK] |
Mask | 在 MLM 预训练中替换被掩码的 token |
[PAD] |
Padding | 填充 token,用于将不同长度的序列对齐到同一长度 |
句对输入的格式:
[CLS] 我 喜 欢 这 部 电 影 [SEP] 故 事 非 常 精 彩 [SEP]
对应嵌入:
BERT 同时使用两种无监督预训练任务。
标准语言模型是单向的。为了解决"深度双向表示 vs. 语言模型单向性"的矛盾,BERT 借鉴 Cloze 任务的思想——随机 mask 掉输入中的部分 token,让模型根据双向上下文预测被 mask 的 token。
每一个训练序列中,随机选择 15% 的 token 参与 mask 过程。对于被选中的 token:
[MASK]:例如,my dog is hairy → my dog is [MASK]这样设计的目的是:
[MASK] 时才做预测,而忽略其他 token[MASK])与微调(无 [MASK])之间的不匹配| 方面 | 单向 LM(GPT) | 双向 MLM(BERT) |
|---|---|---|
| 每步预测的 token | 所有 token(从左到右) | 仅被 mask 的 15% token |
| 可用的上下文 | 仅左侧 | 左右两侧 |
| 训练效率(每步信息) | 高(所有位置都计算) | 较低(仅 15% 位置有监督信号) |
| 表示质量 | 单向 | 深度双向 |
理解要点:BERT 需要更多训练步数来达到同等效果,因为每步只有 15% 的 token 提供监督信号。但优点是这些 token 获得了来自两侧上下文的丰富信息。
许多重要的 NLP 任务(如问答、自然语言推理)需要理解两句话之间的关系。NSP 旨在让模型学习捕捉句子级别的关联信息。
对于每个训练样本,构造一个句对(A, B):
模型基于 [CLS] 位置的输出进行二分类预测。
输入 = [CLS] 我 今 天 去 了 公 园 [SEP] 看 到 了 一 群 鸭 子 [SEP]
标签 = IsNext
输入 = [CLS] 我 今 天 去 了 公 园 [SEP] 质 数 有 无 穷 多 个 [SEP]
标签 = NotNext
后续研究(如 RoBERTa)发现 NSP 的效果存在争议:
选择这两个数据源的原因是它们包含长连续文本片段,有利于模型学习长距离依赖关系。
微调过程相对轻量——在单个 Cloud TPU 上,大多数 GLUE 任务可在 1 小时内微调完成。

1. 句子对分类任务(如 NLI, 文本蕴含)
[CLS] A [SEP] B [SEP][CLS] 的最终隐状态 ,输入一个 softmax 分类层2. 单句分类任务(如情感分析, 主题分类)
[CLS] A [SEP][CLS] 的输出3. 阅读理解(SQuAD)
[CLS] 问题 [SEP] 段落文本 [SEP]4. 命名实体识别(NER)
5. 序列标注任务(如 POS tagging)
论文推荐的微调超参数范围:
| 参数 | 建议值 |
|---|---|
| Batch size | 16 - 32 |
| Learning rate (Adam) | 2e-5 - 5e-5 |
| Training epochs | 3 - 4 |
| Warmup proportion | 0.1 |
| Weight decay | 0.01 |
关键经验:微调 BERT 的学习率远小于从头训练的典型值(通常为 5e-5 量级)。过大的学习率会导致预训练学到的语言知识被迅速破坏。
GLUE(General Language Understanding Evaluation)包含 9 个自然语言理解任务。BERT 在 GLUE 基准上获得了当时的最优成绩:
| 任务 | 描述 | BERT | BERT | Prior SOTA |
|---|---|---|---|---|
| MNLI | 蕴含关系判定 | 84.6 | 86.7 | 80.6 (OpenAI GPT) |
| QQP | 问题对等价性 | 89.3 | 89.4 | 87.7 (OpenAI GPT) |
| QNLI | 问答自然语言推理 | 90.5 | 91.1 | 82.3 (OpenAI GPT) |
| SST-2 | 情感分类 | 93.5 | 94.9 | 91.3 (OpenAI GPT) |
| CoLA | 语言可接受性 | 52.1 | 60.6 | 35.0 (OpenAI GPT) |
| STS-B | 语义文本相似度 | 85.8 | 86.5 | 80.9 (OpenAI GPT) |
| MRPC | 文本对语义等价 | 88.9 | 89.3 | 82.3 (OpenAI GPT) |
| RTE | 文本蕴含识别 | 66.4 | 70.1 | 56.0 (OpenAI GPT) |
| WNLI | Winograd 模式 | 65.1 | 72.0 | 65.1 (OpenAI GPT) |
BERT 在所有 GLUE 任务上均超过此前最优水平,平均提升幅度超过 7%。
| 指标 | BERT | BERT | Prior SOTA |
|---|---|---|---|
| SQuAD v1.1 F1 | 88.5 | 93.2 | 89.0 (Human) |
| SQuAD v1.1 EM | - | 81.8 | 74.2 |
| SQuAD v2.0 F1 | 76.3 | 83.5 | 73.4 |
BERT 在 SQuAD v1.1 上的 F1 得分首次超过人类表现(89.0),标志着机器阅读理解能力达到新的高度。
SWAG(Situations With Adversarial Generations)数据集测试模型的常识推理能力:
1. 使用不同层次的特征
论文发现,使用最后四层隐状态拼接(feature-based 方式)的效果与完整微调差距极小(仅 0.3 F1),说明 BERT 的各层表示均有丰富的语义信息。
2. 双向训练的优势
通过对比实验,BERT 等同参数的双向模型相对单向模型在多个任务上有显著优势:
这表明双向上下文对于需要句子间推理的任务尤为重要。
| 变体 | 描述 | MNLI 准确率 | QNLI F1 | SQuAD 1.1 F1 |
|---|---|---|---|---|
| BERT 完整 | MLM + NSP | 84.6 | 90.5 | 88.5 |
| 去除 NSP | 仅使用 MLM | 84.0 (-0.6) | 88.4 (-2.1) | 87.4 (-1.1) |
| 去除 NSP + LTR & BiLSTM | 单向 + BiLSTM | 80.0 (-4.6) | 84.9 (-5.6) | 84.2 (-4.3) |
| LTR + BiLSTM | 使用标准语言模型 | 78.8 (-5.8) | 83.9 (-6.6) | 82.1 (-6.4) |
关键发现:
实验显示,随着模型参数量增加,BERT 在多个任务上的持续改进:
| 参数量 | 层数 | MNLI | SQuAD |
|---|---|---|---|
| ~35M(4层) | 4 | 77.8 | 84.4 |
| ~65M(8层) | 8 | 81.7 | 86.7 |
| 110M(12层) | 12 | 84.6 | 88.5 |
| 340M(24层) | 24 | 86.7 | 93.2 |
这说明更大的模型在语言理解任务上持续受益,为后续 ScaledLM 的研究方向提供了实证支持。
| 模型 | 年份 | 改进点 | 影响 |
|---|---|---|---|
| RoBERTa | 2019 | 更多数据、动态掩码、更大 batch、去除 NSP、更长训练 | 在 GLUE 上超越 BERT |
| ALBERT | 2019 | 跨层参数共享、分解嵌入矩阵、SOP 任务 | 大幅减少参数量,保持性能 |
| DistilBERT | 2019 | 知识蒸馏 | 参数量减少 40%,保留 97% 性能 |
| SpanBERT | 2020 | 掩码连续 span、改进的 Span 预测目标 | 在 QA 任务上超越 BERT |
| ELECTRA | 2020 | 判别器与生成器对抗训练 | 更高效的预训练 |
| ERNIE (百度) | 2019 | 增加知识图谱信息、实体级掩码 | 在知识密集型任务中更优 |
对 BERT 的深入研究形成了被称为 "BERTology" 的研究方向,主要发现包括:
from transformers import BertTokenizer, BertModel
# 加载预训练模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
model = BertModel.from_pretrained('bert-base-chinese')
# 文本编码
text = "BERT 模型在自然语言处理领域具有里程碑意义。"
encoded = tokenizer(text, return_tensors='pt', padding=True, truncation=True)
# 前向传播
outputs = model(**encoded)
last_hidden = outputs.last_hidden_state # [batch, seq_len, 768]
pooler_output = outputs.pooler_output # [batch, 768] 对应 [CLS] token
from transformers import BertForSequenceClassification, Trainer, TrainingArguments
# 加载带分类头的 BERT
model = BertForSequenceClassification.from_pretrained(
'bert-base-chinese',
num_labels=2 # 二分类
)
# 配置训练参数
training_args = TrainingArguments(
output_dir='./results',
learning_rate=2e-5,
per_device_train_batch_size=16,
num_train_epochs=3,
weight_decay=0.01,
)
# 创建 Trainer 并微调
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
)
trainer.train()
bert-base-chinese 基于单字),无需额外分词工具。但部分变体(如哈工大 RoBERTa-wwm-ext)使用全词掩码(Whole Word Masking),在中文上掩码整个词而非单字MLM 在预训练时大量使用 [MASK] token,但在微调阶段完全没有 mask token。这种分布偏移(discrepancy)导致模型在微调时的输入分布与预训练时不一致。后续的 ELECTRA 试图通过判别式训练来解决这个问题。
BERT 在 64 个 TPU 芯片上需要 4 天完成预训练,对大多数研究者和团队来说门槛较高。后续工作如 RoBERTa 在更大数据上训练,进一步推高了计算需求。
512 token 的最大序列长度在处理长文档、法律文本、科学论文时成为瓶颈。后续 Longformer(Beltagy et al., 2020)和 BigBird(Zaheer et al., 2020)等通过稀疏注意力机制扩展了上下文窗口。
BERT 是编码器模型,天生不适合文本生成任务。虽然可以用于填空式生成,但在自回归生成任务上远不如 GPT 等解码器模型。这代表着"编码器 vs 解码器"的功能分化,而非缺陷。
BERT 的知识完全来自训练数据(BooksCorpus + Wikipedia),这导致:
BERT 是 NLP 领域的分水岭工作,其影响体现在多个层面:
虽然当前主流大语言模型(GPT-4、Claude、LLaMA 等)以自回归式解码器架构为主,但 BERT 的核心思想——双向上下文理解、预训练-微调范式——仍然深刻影响着现代 NLP 的发展。许多现代 LLM 的能力评估仍会参考 BERT 时代的基准框架。
BERT 证明了深度双向预训练表示的价值,这一洞见为后来 MASK-Predict Decoding 等混合架构提供了理论基础。在需要深度语义理解的场景(搜索、问答、分类、排序)中,BERT 及其变体仍然是实践中的黄金标准。
本文档为 AI 知识体系 的一部分,内容持续更新中。