Skip to content

第二十章:BERT

BERT(Bidirectional Encoder Representations from Transformers)由 Google 于 2018 年 10 月提出,是 NLP 历史上最具影响力的预训练模型之一。它首次在 11 个 NLP 任务上取得了最先进的结果。


BERT 的核心创新

与 GPT 的区别

特性GPTBERT
架构Transformer 解码器(单向)Transformer 编码器(双向)
预训练任务自回归语言模型掩码语言模型 + 下一句预测
注意力方向只能看到前文可以看到前后文
适用任务生成任务理解任务

为什么双向很重要?

考虑句子:"我去银行存了钱" vs "我在河边的银行散步"

GPT(单向)处理"银行"时:

  • "我去银行" → 只能看到"我去",无法确定"银行"的含义

BERT(双向)处理"银行"时:

  • "我去银行存了钱" → 可以同时看到"存钱",确定是金融机构
  • "我在河边的银行散步" → 可以同时看到"河边",确定是河岸

BERT 的架构

模型结构

BERT 使用 Transformer 的编码器部分:

输入:[CLS] 我 爱 自然 语言 处理 [SEP]

Token 嵌入 + 段落嵌入 + 位置嵌入

┌─────────────────────────────┐
│  多头自注意力(双向)          │
│  前馈网络                     │
│  残差连接 + LayerNorm         │
│         × 12 层(BERT-Base) │
└─────────────────────────────┘

输出:每个位置的上下文相关表示

三种嵌入

BERT 的输入由三种嵌入相加而成:

1. Token 嵌入:词的语义表示

2. 段落嵌入(Segment Embedding):区分句子对中的两个句子

[CLS] 今天天气很好 [SEP] 我们去公园吧 [SEP]
  A    A   A  A  A   A    B  B  B  B  B   B

3. 位置嵌入:可学习的位置编码(不是正弦编码)

模型规模

版本层数隐藏维度注意力头数参数量
BERT-Base1276812110M
BERT-Large24102416340M

预训练任务

任务 1:掩码语言模型(Masked Language Model, MLM)

核心思想:随机遮盖输入中的一些词,让模型预测被遮盖的词。

输入:我 爱 [MASK] 语言 处理
标签:        自然

掩码策略

对于被选中的 15% 的 token:

  • 80% 的概率替换为 [MASK]
  • 10% 的概率替换为随机词
  • 10% 的概率保持不变

为什么不是全部替换为 [MASK]?

如果总是用 [MASK] 替换,模型会学到"看到 [MASK] 就预测"的模式,但在实际使用时没有 [MASK]。通过随机替换和保持不变,模型被迫学习每个位置的真实语义。

任务 2:下一句预测(Next Sentence Prediction, NSP)

核心思想:预测两个句子是否是连续的。

正例(IsNext):
  [CLS] 今天天气很好 [SEP] 我们去公园吧 [SEP]
  标签:1

负例(NotNext):
  [CLS] 今天天气很好 [SEP] 我喜欢吃苹果 [SEP]
  标签:0

NSP 的争议

后续研究(如 RoBERTa)发现 NSP 任务对模型性能的贡献不大,甚至可能有害。因此很多后续模型取消了 NSP。


BERT 的输入输出

输入格式

单句输入:  [CLS] 句子 [SEP]
句子对输入:[CLS] 句子A [SEP] 句子B [SEP]

输出

BERT 为每个输入 token 输出一个向量:

输入:  [CLS] 我  爱  自然 语言 处理 [SEP]
输出:  h_CLS h₁  h₂  h₃   h₄   h₅   h_SEP
维度:  768  768 768 768  768  768   768
  • h_CLS:整个序列的聚合表示,用于分类任务
  • h₁, ..., h₅:每个 token 的上下文相关表示,用于序列标注

微调 BERT

BERT 可以通过添加一个简单的输出层来微调各种下游任务:

文本分类

[CLS] 这个电影很好看 [SEP]

BERT

h_CLS → 线性层 → Softmax → 正面/负面

命名实体识别(NER)

[CLS] 张三在北京大学读书 [SEP]

BERT

h₁ h₂ h₃ h₄ h₅ h₆ h₇ h₈
 ↓  ↓  ↓  ↓  ↓  ↓  ↓  ↓
线性层 → Softmax → B-PER I-PER O B-ORG I-ORG O O O

问答

[CLS] 问题 [SEP] 文章 [SEP]

BERT

预测答案的起始和结束位置

代码实现

加载 BERT

python
from transformers import BertTokenizer, BertModel

# 加载分词器和模型
tokenizer = BertTokenizer.from_pretrained("bert-base-chinese")
model = BertModel.from_pretrained("bert-base-chinese")

# 编码
text = "我爱自然语言处理"
inputs = tokenizer(text, return_tensors="pt")

# 前向传播
outputs = model(**inputs)

# 输出
last_hidden_state = outputs.last_hidden_state  # (1, seq_len, 768)
pooler_output = outputs.pooler_output            # (1, 768)

文本分类微调

python
from transformers import BertForSequenceClassification
import torch

# 加载分类模型
model = BertForSequenceClassification.from_pretrained(
    "bert-base-chinese",
    num_labels=2
)

# 准备数据
texts = ["这个电影很好看", "这个电影很难看"]
labels = torch.tensor([1, 0])  # 1=正面, 0=负面

inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")

# 前向传播
outputs = model(**inputs, labels=labels)
loss = outputs.loss
logits = outputs.logits  # (2, 2)

# 预测
predictions = torch.argmax(logits, dim=1)

BERT 的影响

BERT 的出现带来了深远的影响:

  1. 范式转变:确立了"预训练 + 微调"的标准范式
  2. 性能突破:在 11 个 NLP 任务上取得最先进结果
  3. 开源影响:推动了预训练模型的开源文化
  4. 后续工作:催生了 RoBERTa、ALBERT、DistilBERT 等大量变体

小结

概念说明
双向编码器同时利用前文和后文信息
掩码语言模型随机遮盖词并预测,实现双向训练
下一句预测预测两个句子是否连续
三种嵌入Token + 段落 + 位置
微调添加简单输出层适配下游任务

BERT 的成功证明了:双向上下文信息对于语言理解至关重要。它与 GPT 代表了两种不同的预训练范式,共同推动了 NLP 的发展。

AI 知识体系 — 从机器学习到大语言模型