来源:notes/books/BERT/01_详细解读.md

BERT 详细解读

核心结论

BERT 的核心贡献是把 Transformer encoder 变成了通用语言理解底座。它通过 masked language modeling 让模型在每一层同时利用左、右上下文,从而获得深度双向表示;再通过统一的 fine-tuning 流程,把同一个预训练模型迁移到分类、句对匹配、序列标注和抽取式问答等任务上。

它改变 NLP 工作流的地方不只是“模型效果更好”,而是把大量任务从“为每个任务设计复杂结构”推进到“预训练模型 + 少量任务头 + 全参数微调”。这就是后来预训练语言模型范式的关键起点之一。

论文信息

  • 标题:BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
  • 作者:Jacob Devlin, Ming-Wei Chang, Kenton Lee, Kristina Toutanova
  • 机构:Google AI Language
  • arXiv:1810.04805
  • 版本:v2, 2019-05-24
  • 本地 PDF:source_materials/bert.pdf
  • 全文转换:source_materials/pdf_full_text.md

背景问题

BERT 之前,语言表示预训练已经有效,但主流路线有两个限制。

第一,feature-based 方法如 ELMo 通常把预训练表示作为额外特征接入下游模型,下游任务仍然需要较多任务结构设计。

第二,fine-tuning 方法如 OpenAI GPT 使用 left-to-right language model。它适合生成,但对理解任务有天然限制:每个 token 在预训练时只能看左侧上下文,不能同时利用右侧信息。对自然语言推理、句对关系和抽取式问答这类任务,单向上下文是不充分的。

BERT 的判断是:语言理解任务需要双向上下文,而且这种双向性应该发生在 Transformer 的所有层,而不是简单拼接一个左到右模型和一个右到左模型。

方法拆解

1. 架构:Transformer Encoder

BERT 使用多层双向 Transformer encoder。论文报告两个主要规模:

  • BERTBASE:12 层,hidden size 768,12 个 attention heads,约 110M 参数。
  • BERTLARGE:24 层,hidden size 1024,16 个 attention heads,约 340M 参数。

这里的关键不是 Transformer 本身,而是 attention mask。GPT 的 decoder 使用因果 mask,当前位置只能看左侧;BERT encoder 不使用因果 mask,序列中每个 token 可以关注左右两侧所有 token。

2. 输入表示:三类 embedding 相加

BERT 的输入由三部分相加:

  • Token embedding:WordPiece token 表示。
  • Segment embedding:区分句子 A / 句子 B。
  • Position embedding:位置表示。

特殊 token:

  • [CLS]:放在序列开头,其最终 hidden state 用于分类任务。
  • [SEP]:分隔两个句子或标记句子结束。

这个设计让单句任务、句对任务、问答任务都能装进同一个输入格式。

3. 预训练任务一:Masked Language Modeling

MLM 是 BERT 的核心。训练时随机选择 15% 的 WordPiece token 作为预测目标。为减少预训练和微调之间的 [MASK] 不一致,选中的 token 会按规则处理:

  • 80% 替换成 [MASK]
  • 10% 替换成随机 token。
  • 10% 保持原 token 不变。

模型只预测被选中的 token,而不是重建整句。这个目标允许模型同时利用左右上下文,因此可以训练深度双向表示。

MLM 的优点是解决单向语言模型的限制;缺点是预训练阶段出现 [MASK],但下游微调和真实输入没有这个 token,存在分布不一致。

4. 预训练任务二:Next Sentence Prediction

NSP 用于学习句子间关系。训练样本中,一半是连续句子对,一半是随机配对句子。模型根据 [CLS] 表示判断句子 B 是否是句子 A 的下一句。

论文认为 NSP 对问答和自然语言推理等句对任务有帮助。后续研究对 NSP 的必要性有争议,RoBERTa 等工作移除了 NSP 并获得更强结果。因此应把 NSP 理解为 BERT 原始方案的一部分,而不是预训练语言模型的永久标准。

Fine-tuning 范式

BERT 的迁移方式非常统一:下游任务直接加载预训练参数,再加一个很小的任务输出层,然后全参数微调。

典型任务适配:

  • 句子分类:用 [CLS] 的 final hidden state 接分类器。
  • 句对分类:输入 [CLS] sentence A [SEP] sentence B [SEP],用 segment embedding 区分两句。
  • 序列标注:对每个 token 的 final hidden state 做标签预测。
  • 抽取式问答:对每个 token 预测 start/end span。

这个范式显著降低了任务工程成本。以前很多 NLP 系统依赖任务特定结构,BERT 则把大部分能力前置到预训练阶段。

实验结论

论文在 11 个 NLP 任务上报告了强结果,包括 GLUE、MultiNLI、SQuAD v1.1、SQuAD v2.0 等。

关键实验意义:

  • BERTLARGE 通常显著强于 BERTBASE,说明规模有作用。
  • 去掉 NSP 或改成单向/浅双向表示会影响部分任务表现。
  • 使用预训练参数初始化并全量微调,是性能提升的核心流程。
  • BERT 对 token-level 任务如问答尤其有价值,因为这些任务需要左右上下文共同定位答案。

与 GPT 的区别

维度 BERT GPT/GPT-2
架构 encoder-only decoder-only
注意力 双向 self-attention 因果 self-attention
训练目标 MLM + NSP next-token prediction
强项 理解、分类、抽取、句对关系 生成、补全、开放式任务
下游方式 微调任务头 prompt / 微调 / 指令对齐
典型输出 表示或标签 文本序列

BERT 更像“理解型底座”,GPT 更像“生成型接口”。今天很多 embedding、reranker、分类器、抽取系统仍然沿用 BERT 系 encoder 模型;而聊天和生成系统主要沿用 GPT 系 decoder-only 模型。

与 ELMo 的区别

ELMo 也利用左右上下文,但它是分别训练左到右和右到左语言模型,再把表示拼接起来。BERT 的双向性发生在每一层 self-attention 中,token 的表示从底层开始就能融合左右上下文。这是“浅双向”和“深双向”的差异。

工程启发

1. 当任务是理解,不一定要用生成模型

如果任务是分类、相似度、抽取、检索、重排,BERT 系 encoder 往往更直接、成本更低、延迟更可控。不要把所有 NLP 问题都默认交给 decoder-only LLM。

2. 输入格式统一可以降低系统复杂度

BERT 用 [CLS][SEP]、segment embedding 统一单句和句对任务。这个思想在今天仍然重要:系统层面最好先把任务接口标准化,再考虑模型。

3. 预训练目标决定能力边界

MLM 适合理解,不适合原生长文本生成。next-token prediction 适合生成,但对双向 token-level 理解不如 encoder 自然。选模型时要看预训练目标是否贴合任务。

4. 微调不是只训练最后一层

BERT 的标准 fine-tuning 是全参数微调。只冻结 BERT 并训练分类头可能能跑,但通常不是论文里的最强设置。

局限与后续发展

  • [MASK] token 导致预训练和下游输入不一致。
  • NSP 是否必要存在争议。
  • 最大序列长度有限,长文档任务需要切片、滑窗或长上下文变体。
  • encoder-only 不适合自然生成。
  • BERT 原始训练数据和规模后来被 RoBERTa、ALBERT、DeBERTa 等改进。

后续重要方向:

  • RoBERTa:更强训练策略,移除 NSP。
  • ALBERT:参数共享与句子顺序预测。
  • DistilBERT:蒸馏压缩。
  • DeBERTa:解耦注意力和增强位置表示。
  • Sentence-BERT:把 BERT 改造成句向量检索/相似度模型。

阅读重点

如果只精读部分章节,建议按这个顺序:

  1. Abstract 和 Introduction:理解论文要解决什么问题。
  2. Section 3.1:模型架构和输入表示。
  3. Section 3.2:MLM 和 NSP。
  4. Section 4:fine-tuning 到不同任务的方式。
  5. Ablation:理解双向预训练、规模、NSP 的影响。

可执行学习任务

  1. 手写一张 BERT 输入结构图:[CLS] sentence A [SEP] sentence B [SEP],标出 token/segment/position embeddings。
  2. 用自己的话解释为什么 BERT 不能直接用普通 left-to-right LM 目标训练。
  3. 对比 BERT 和 GPT-2:写出架构、目标、任务适配方式的三项差异。
  4. 找一个抽取式问答样例,说明 BERT 如何预测 start token 和 end token。
  5. 如果做工程实践,用 Hugging Face 跑一次 bert-base-uncased 文本分类微调或 embedding 抽取。

下一步动作

  • 补一张 02_方法卡片.md,把 BERT 的模型选择、微调、输入构造和适用任务变成工程检查清单。
  • 继续单独处理 GPT-2 或 T5,形成 encoder-only、decoder-only、encoder-decoder 三类架构的对照笔记。