Files
2026-05-16 17:16:51 +08:00

20 KiB
Raw Permalink Blame History

title, draft, tags
title draft tags
上下文化表示ELMo 与 BERT 的双向上下文建模 false
ELMo
BERT
上下文化表示
BiLSTM
双向语言模型

上下文化表示ELMo 与 BERT 的双向上下文建模


一、静态词向量的根本局限

1.1 一词多义问题

静态词向量的问题

使用 Word2Vec 或 GloVe 学习到的词向量是静态的——同一个词无论在什么上下文中,都对应同一个向量。

具体问题

上下文 正确语义 静态向量会混淆
"bank" river ___ 河岸 无法区分
"bank" ___ robbery 银行 无法区分
"run" ___ a marathon 跑步(动词) 无法区分
"run" salmon ___ 溪流(名词) 无法区分

数学表示

对于同一词 w 在不同上下文 c_1c_2 中,静态词向量满足 $\mathbf{v}_w^{(c_1)} = \mathbf{v}_w^{(c_2)} = \mathbf{v}_w$。这忽略了语义的可变性。

1.2 解决方案的演进

方案演进

静态词向量Word2Vec/GloVe
    ↓ 解决一词多义
多义词向量(未广泛使用)
    ↓ 上下文感知
上下文向量ELMo, 2018
    ↓ 大规模预训练 + 深 Transformer
BERT2018

核心思想

每个词的表示应该依赖于其上下文。相同的词在不同的句子中应该有不同的向量。


二、ELMo深度上下文化词表示

2.1 ELMo 的核心思想

ELMoEmbeddings from Language Models, Peters et al., 2018的全称是"从语言模型提取的嵌入"。

核心洞察

使用双向 LSTM 语言模型BiLSTM LM的内部状态作为词的上下文相关表示。

关键创新

  1. 字符卷积嵌入ELMo 使用字符级卷积网络CNN生成词嵌入天生具备极强的 OOV未登录词处理能力远超 Word2Vec/GloVe 等基于词的静态嵌入
  2. 双向:同时考虑左上下文和右上下文
  3. 深层:使用多层 LSTM 的不同层捕捉不同粒度的信息
  4. 预训练 + fine-tune:在大语料上预训练,可以微调到下游任务

2.2 双向语言模型的数学定义

前向语言模型

给定词序列 $w_1, w_2, \ldots, w_T$,前向 LM 计算:

P(w_t | w_1, \ldots, w_{t-1}) = \text{softmax}(\mathbf{h}_t^{\rightarrow} \mathbf{W}_o) \tag{2.1}

其中 \mathbf{h}_t^{\rightarrow} 是前向 LSTM 在位置 t 的隐藏状态。

后向语言模型

P(w_t | w_{t+1}, \ldots, w_T) = \text{softmax}(\mathbf{h}_t^{\leftarrow} \mathbf{W}_o) \tag{2.2}

其中 \mathbf{h}_t^{\leftarrow} 是后向 LSTM 在位置 t 的隐藏状态。

双向 LM 目标

\mathcal{L} = \sum_{t=1}^T \left[ \log P(w_t | w_1, \ldots, w_{t-1}) + \log P(w_t | w_{t+1}, \ldots, w_T) \right] \tag{2.3}

这使得每个位置 t 的表示同时包含左右两边的信息。

2.3 ELMo 的架构

双层双向 LSTM

Token:  w_1   w_2   w_3   ...  w_T
         ↓     ↓     ↓        ↓
Char Emb  →    →    →    →    →
         ↓     ↓     ↓        ↓
      ┌───────────────────────┐
      │   Forward LSTM Layer 1  │
      └───────────────────────┘
         ↓     ↓     ↓        ↓
      ┌───────────────────────┐
      │  Backward LSTM Layer 1  │
      └───────────────────────┘
         ↓     ↓     ↓        ↓
      ┌───────────────────────┐
      │   Forward LSTM Layer 2  │
      └───────────────────────┘
         ↓     ↓     ↓        ↓
      ┌───────────────────────┐
      │  Backward LSTM Layer 2  │
      └───────────────────────┘
         ↓     ↓     ↓        ↓
       h_1    h_2   h_3  ...  h_T

每层输出

每个位置 t 有两个 LSTM 层的输出:

  • \mathbf{h}_t^{\rightarrow, 1}, $\mathbf{h}_t^{\rightarrow, 2}$前向层1和层2
  • \mathbf{h}_t^{\leftarrow, 1}, $\mathbf{h}_t^{\leftarrow, 2}$后向层1和层2

2.4 ELMo 表示的聚合

原始 ELMo 向量

对于每个位置 $t$,拼接所有层的隐藏状态:

\mathbf{H}_t = [\mathbf{h}_t^{\rightarrow, 1}; \mathbf{h}_t^{\rightarrow, 2}; \mathbf{h}_t^{\leftarrow, 1}; \mathbf{h}_t^{\leftarrow, 2}] \in \mathbb{R}^{4d} \tag{2.4}

其中 d 是每层 LSTM 的隐藏维度。

加权聚合ELMo 改进版)

不是简单拼接,而是学习加权平均:

\mathbf{v}_t = \gamma \sum_{j=1}^L s_j \mathbf{h}_t^j \tag{2.5}

其中:

  • L 是层数(这里 $L=2$
  • s_j 是可学习的 softmax 权重,经 softmax 归一化后 $\sum_j s_j = 1$,自适应选取各层信息
  • \gamma 是可学习的全局缩放系数,平衡整体向量幅值

为什么加权

不同层捕获不同类型的信息:

  • 底层Layer 1更关注语法/词形信息(词性、词缀)
  • 高层Layer 2更关注语义/意义信息(命名实体、语义角色)

2.5 ELMo 在下游任务的使用

固定特征提取器模式

  1. 冻结 BiLSTM LM 的权重
  2. 在下游任务上添加 task-specific 层
  3. 只微调新增层的权重

数学表示

设下游任务的输入是句子 $s = (w_1, \ldots, w_T)$ELMo 向量为 $\mathbf{v}_t$。

下游任务的表示为:

\mathbf{x}_t^{\text{down}} = [\mathbf{x}_t^{\text{base}}; \mathbf{v}_t] \tag{2.6}

其中 \mathbf{x}_t^{\text{base}} 是原始词向量,\mathbf{v}_t 是 ELMo 上下文嵌入。

组合方式

  • Concatenation:拼接原始词向量和 ELMo 向量
  • Weighted:直接用 \mathbf{v}_t 替换原始向量

ELMo 两种使用模式

  • 特征冻结模式:仅微调下游任务层(添加 Task-specific 层),适合小数据集
  • 全量微调模式:整体更新 BiLSTM 权重,适合大数据场景

2.6 ELMo 的局限性

局限 描述
架构限制 BiLSTM 无法捕获长距离依赖(最长约 100-200 tokens
并行性差 LSTM 训练是序列性的,无法充分利用 GPU 并行
表示能力 BiLSTM 的 hidden states 是线性组合,表达能力有限
参数量 相对较少的参数限制了表示能力

这促使了 Transformer 架构的引入


三、BERT深度双向预训练

3.1 BERT 的核心思想

BERTBidirectional Encoder Representations from Transformers, Devlin et al., 2018的核心贡献是

使用 Masked Language ModelMLM 目标,实现真正的双向上下文表示

关键创新

  1. 真正的双向上下文:不是像 ELMo 那样简单拼接前后向(伪双向,时序依赖无法突破),而是通过掩码机制同时看到左右上下文,实现原生全局双向建模
  2. Transformer 架构:用 Self-Attention 替代 LSTM解决长距离依赖和并行问题
  3. 大规模预训练在大规模语料Wikipedia + BookCorpus上预训练

3.2 Masked Language Model 的数学推导

核心问题:双向条件下,语言模型的似然 P(w_t | w_1, \ldots, w_{t-1}, w_{t+1}, \ldots, w_T) 会产生"信息泄漏"——当前词可能直接从输入中"看到自己"。

解决方案:掩码机制

在输入中随机遮盖 15% 的 token

  • 被遮盖的 token 以 [MASK] 替换
  • 模型需要根据双向上下文预测被遮盖的词

MLM 目标

\mathcal{L}_{\text{MLM}} = -\sum_{t \in \mathcal{M}} \log P(w_t | w_{\setminus t}) \tag{3.1}

其中 \mathcal{M} 是被掩码的位置集合。

这实现了同时利用左右上下文信息!

3.3 BERT 的输入表示

BERT 的输入是三部分之和

\boldsymbol{e}_t = \boldsymbol{e}_{\text{tok},t} + \boldsymbol{e}_{\text{pos},t} + \boldsymbol{e}_{\text{seg},t} \tag{3.2}

其中:

  • $\boldsymbol{e}_{\text{tok},t}$词嵌入Token Embedding
  • $\boldsymbol{e}_{\text{pos},t}$绝对位置嵌入Position Embedding
  • $\boldsymbol{e}_{\text{seg},t}$句子分段嵌入Segment Embedding用于区分句子 A 和 B

3.4 预训练任务详解

任务 1Masked Language ModelMLM

BERT 随机选择 15% 的 token 进行掩码:

  • 80% 替换为 [MASK]
  • 10% 替换为随机 token增加鲁棒性
  • 10% 保持不变(减少 [MASK] 在微调时的影响)

掩码策略设计动机:缓解「预训练存在 [MASK]、微调无 [MASK]」的分布偏移问题。若全部使用 [MASK],则预训练时模型看到 MASK token 但微调时看不到,造成不一致。随机词和保留原词让模型被迫学习更鲁棒的表示。

数学表示

w_t 是被选中的 token

  • 80%w_t \rightarrow \text{[MASK]}
  • 10%w_t \rightarrow w_{\text{random}}
  • 10%$w_t \rightarrow w_t$(不变)

任务 2Next Sentence PredictionNSP

判断句子 B 是否是句子 A 的下一句:

P(\text{IsNext} | \text{sentence } A, \text{ sentence } B) \tag{3.3}

正样本B 确实是 A 的下一句 负样本B 是随机采样的句子

NSP 的核心缺陷NSP 偏向主题匹配(判断两句是否属于同一话题),无法学习深层语义连贯关系。这也是 RoBERTa 直接剔除 NSP 任务的根本原因。

NSP 目标

\mathcal{L}_{\text{NSP}} = -\log P(\text{IsNext} | A, B) \tag{3.4}

3.5 BERT 的 Transformer 架构

标准 Transformer Encoder

BERT-base 使用 12 层 Transformer Encoder

Input: [CLS] token_1 [SEP] token_2 [SEP]
        ↓       ↓        ↓       ↓
     Token + Pos + Seg Embeddings
        ↓
     Transformer Encoder × 12
        ↓
     Output: [CLS] h_{T+1} ...

每层 Transformer Block

  1. Multi-Head Self-Attention
  2. Add & LayerNorm
  3. Feed-Forward Network
  4. Add & LayerNorm

3.6 BERT 的输出表示

定义(最后一层表示)

\mathbf{H}_t^{(L)} \in \mathbb{R}^d \tag{3.5}

这是第 L最后一层Transformer 的输出。

对于分类任务(如情感分析):

  • 使用 [CLS] token 的表示:\mathbf{H}_0^{(L)}
  • 通过 softmax 分类:
P(y | \mathbf{H}_0^{(L)}) = \text{softmax}(\mathbf{H}_0^{(L)} \mathbf{W}_o) \tag{3.6}

对于序列标注任务(如 NER

  • 每个 token 的表示:\mathbf{H}_t^{(L)}
  • 通过 CRF 层或 softmax 分类(工业界 NER 主流用法是 BERT + CRF

BERT 架构定位BERT 是纯 Encoder-only 架构,无解码器结构,天生不支持自回归文本生成,仅适合理解类任务。

3.7 BERT 与 ELMo 的对比

维度 ELMo BERT
架构 BiLSTM Transformer Encoder
双向上下文 拼接前后向 通过 MLM 同时利用
表示方式 加权层拼接 最后一层 + attention
并行性 LSTM 序列性) Transformer 并行)
长距离依赖 弱(< 200 tokens 512 tokens
掩码机制 MLM
预训练任务 语言模型 MLM + NSP

四、BERT 的数学细节

4.1 Self-Attention 的矩阵形式

定义Query, Key, Value

对于输入序列 $\mathbf{H} \in \mathbb{R}^{T \times d}$

\mathbf{Q} = \mathbf{H} \mathbf{W}_Q, \quad \mathbf{K} = \mathbf{H} \mathbf{W}_K, \quad \mathbf{V} = \mathbf{H} \mathbf{W}_V \tag{4.1}

注意力分数

\mathbf{A} = \text{softmax}\left(\frac{\mathbf{Q} \mathbf{K}^\top}{\sqrt{d_k}}\right) \tag{4.2}

除以 \sqrt{d_k} 的作用:防止高维下内积数值过大,导致 softmax 梯度饱和、训练停滞。

输出

\mathbf{O} = \mathbf{A} \mathbf{V} \tag{4.3}

4.2 多头注意力

定义(多头输出)

\text{MultiHead}(\mathbf{H}) = \text{Concat}(\text{head}_1, \ldots, \text{head}_h) \mathbf{W}_O \tag{4.4} \text{head}_i = \text{Attention}(\mathbf{H} \mathbf{W}_Q^i, \mathbf{H} \mathbf{W}_K^i, \mathbf{H} \mathbf{W}_V^i) \tag{4.5}

维度关系

如果 $d_{\text{model}} = 768$$h = 12$,则每头的维度 $d_k = d_v = 64$。

输出投影层:拼接多头结果后必须经过输出投影层 $\mathbf{W}O \in \mathbb{R}^{d_v \times d{\text{model}}}$,将多头注意力输出映射回原始维度,保持模型一致性。

4.3 BERT 的训练目标

总损失函数

\mathcal{L} = \mathcal{L}_{\text{MLM}} + \mathcal{L}_{\text{NSP}} \tag{4.6}

MLM 损失

\mathcal{L}_{\text{MLM}} = -\sum_{t \in \mathcal{M}} \log \frac{\exp(\mathbf{H}_t^{(L)} \mathbf{w}_{w_t})}{\sum_{w \in V} \exp(\mathbf{H}_t^{(L)} \mathbf{w}_w)} \tag{4.7}

NSP 损失

\mathcal{L}_{\text{NSP}} = -\left[ y \log P(\text{IsNext}) + (1-y) \log (1-P(\text{IsNext})) \right] \tag{4.8}

4.4 位置编码与长度外推

BERT 的位置编码

使用可学习的绝对位置编码 $\mathbf{E}{\text{pos}} \in \mathbb{R}^{512 \times d{\text{model}}}$。

问题:零外推性

BERT 原生仅支持 512 序列长度,无外推能力。当序列长度超过 512 时,无法查表。

后续改进

方法 描述
RoPE 旋转位置编码通过复数乘法实现相对位置编码GPT、LLAMA 等使用)
ALiBi 在注意力分数上加线性偏置
RoPE 解决长序列外推问题

五、BERT 的 Fine-tuning

5.1 预训练 + Fine-tuning 范式

核心思想

  1. 在大规模语料上预训练:学习通用语言表示
  2. 在下游任务上微调:添加任务特定层,调整所有权重

数学表示

预训练目标:

\theta^* = \arg\max_\theta \sum_{(w_1, \ldots, w_T)} \mathcal{L}_{\text{MLM}}(\theta) + \mathcal{L}_{\text{NSP}}(\theta) \tag{5.1}

Fine-tuning 目标:

\theta^* = \arg\max_{\theta'} \sum_{(x, y) \in \mathcal{D}_{\text{task}}} \mathcal{L}_{\text{task}}(\theta'; \theta^*) \tag{5.2}

5.2 不同任务的 Fine-tuning 方式

分类任务

[CLS] → FC + softmax → 类别

序列标注任务NER

token_1 → FC → tag_1
token_2 → FC → tag_2
...

问答任务SQuAD

[CLS] question [SEP] context [SEP]
  ↓
预测答案范围的 start 和 end

文本生成任务

BERT 本身不是生成模型,但可以通过添加解码器实现(如 BERT2BERT


六、训练中的问题与解决方案

6.1 BERT 训练的问题

问题 1[MASK] token 在微调时不出现

预训练时使用 [MASK],但微调时没有掩码。这导致预训练和微调的不一致。

BERT 的解决方案(随机替换)

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

后续改进ERNIE 等)

引入了实体级掩码、 phrase 级掩码等更复杂的掩码策略。

问题 2NSP 任务太简单

NSP 是一个二分类任务,学习太容易,没有学到足够的语义信息。

解决方案

RoBERTa 去掉了 NSP 任务,使用动态掩码,取得了更好的效果。

6.2 训练不收敛

问题表现

  • Loss 爆炸或 NaN
  • 梯度消失

解决方案

  1. 使用 AdamW 优化器(权重衰减解耦,适配预训练模型)
  2. 学习率 warmup预热步数为总步数的 1%~2%
  3. 梯度裁剪
  4. 使用适当的权重衰减
  5. 混合精度 BF16 训练(适配大模型,防止溢出)

6.3 BERT 微调通用超参(实战刚需)

  • 基础学习率2 \times 10^{-5} \sim 5 \times 10^{-5}
  • 预热步数:总步数的 1%~2%
  • 优化器:优先 AdamW权重衰减解耦
  • 批大小16~32根据显存调整
  • 训练轮数2~4小数据集避免过拟合

6.3 内存与计算效率

BERT-base 的资源需求

资源 需求
参数 110M
FP32 权重 ~440MB
FP16 权重 ~220MB
训练 batch size 32单卡或更大多卡

Gradient Checkpointing

通过在前向传播时不保存所有中间激活,而是在反向传播时重新计算,降低内存占用。


七、BERT 家族与后续发展

7.1 主要变体

模型 参数量 主要改进
BERT-base 110M 12层, 768维, 12头
BERT-large 340M 24层, 1024维, 16头
RoBERTa 125M 去掉 NSP动态掩码更多数据
ALBERT 12M 参数共享,减少内存
ELECTRA 110M 替换 token 检测替代 MLM
DeBERTa 134M 分离注意力,解码增强

7.2 ELECTRA 的替换 token 检测

核心思想

不是掩码,而是让一个小型的"生成器"替换某些 token然后让"判别器"判断每个 token 是否被替换。

数学表示

\mathcal{L}_{\text{Generator}} = -\sum_{t} \log P(w_t | w_t^{\text{corrupt}}) \quad \text{(生成器)} \tag{7.1} \mathcal{L}_{\text{Discriminator}} = -\sum_{t} \log \mathbf{1}_{w_t = w_t^{\text{original}}} \quad \text{(判别器)} \tag{7.2}

优势:每个 token 位置都参与训练(而不只是 15% 的掩码位置),更高效。

7.3 从 BERT 到 GPT 的演进

演进路径

BERT: Encoder-only (双向上下文, MLM)
  ↓
GPT-2: Decoder-only (单向, CLM)
  ↓
GPT-3: 更大规模 + Few-shot
  ↓
GPT-4: 多模态 + 更强推理

核心差异

模型 架构 训练目标 上下文
BERT Encoder MLM + NSP 双向
GPT-2/3 Decoder CLM 单向

八、数学公式速查

8.1 ELMo 公式

前向 LM 概率

P(w_t | w_1, \ldots, w_{t-1}) = \text{softmax}(\mathbf{h}_t^{\rightarrow} \mathbf{W}_o) \tag{8.1}

双向 LM 损失

\mathcal{L} = \sum_{t=1}^T \left[ \log P(w_t | w_{<t}) + \log P(w_t | w_{>t}) \right] \tag{8.2}

ELMo 表示

\mathbf{v}_t = \gamma \sum_{j=1}^L s_j \mathbf{h}_t^j \tag{8.3}

8.2 BERT 公式

MLM 损失

\mathcal{L}_{\text{MLM}} = -\sum_{t \in \mathcal{M}} \log P(w_t | w_{\setminus t}) \tag{8.4}

NSP 损失

\mathcal{L}_{\text{NSP}} = -\log P(\text{IsNext} | A, B) \tag{8.5}

总损失

\mathcal{L} = \mathcal{L}_{\text{MLM}} + \mathcal{L}_{\text{NSP}} \tag{8.6}

8.3 注意力公式

缩放点积注意力

\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^\top}{\sqrt{d_k}}\right) V \tag{8.7}

多头注意力

\text{MultiHead}(H) = \text{Concat}(\text{head}_1, \ldots, \text{head}_h) W_O \tag{8.8}

九、总结

ELMo 与 BERT 的核心贡献

模型 核心贡献 局限性
ELMo 双向 LSTM LM + 上下文表示 架构限制,无法长依赖
BERT Transformer + MLM + NSP 仍是 Encoder不是生成模型

为什么需要 BERT

  1. 解决一词多义:上下文相关表示自动区分不同语义
  2. 捕获长距离依赖Transformer attention 覆盖全部上下文
  3. 预训练 + 微调范式:在大规模无标注数据上预训练,在小规模标注数据上微调

BERT 对 NLP 的影响

BERT 开启了"预训练 + 微调"的 NLP 新时代。在此之前,每个任务都需要从头训练;在此之后,所有任务都可以基于预训练模型微调。

核心公式

  • ELMo:双向 LSTM 的加权层拼接
  • BERTMasked LM 实现真正的双向上下文
  • Fine-tuning:预训练参数初始化 + 任务特定层

延伸阅读

  1. Peters et al., "Deep Contextualized Word Representations" (NAACL 2018) — ELMo
  2. Devlin et al., "BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding" (NAACL 2019)
  3. Radford et al., "GPT: Improving Language Understanding by Generative Pre-Training" (2018)
  4. Liu et al., "RoBERTa: A Robustly Optimized BERT Pretraining Approach" (2019)
  5. Clark et al., "ELECTRA: Pre-training Text Encoders as Discriminators Rather Than Generators" (ICLR 2020)