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

620 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: 上下文化表示ELMo 与 BERT 的双向上下文建模
draft: false
tags:
- ELMo
- BERT
- 上下文化表示
- BiLSTM
- 双向语言模型
---
# 上下文化表示ELMo 与 BERT 的双向上下文建模
---
## 一、静态词向量的根本局限
### 1.1 一词多义问题
**静态词向量的问题**
使用 Word2Vec 或 GloVe 学习到的词向量是**静态的**——同一个词无论在什么上下文中,都对应同一个向量。
**具体问题**
| 词 | 上下文 | 正确语义 | 静态向量会混淆 |
|----|-------|---------|--------------|
| "bank" | river ___ | 河岸 | 无法区分 |
| "bank" | ___ robbery | 银行 | 无法区分 |
| "run" | ___ a marathon | 跑步(动词) | 无法区分 |
| "run" | salmon ___ | 溪流(名词) | 无法区分 |
**数学表示**
对于同一词 $w$ 在不同上下文 $c_1$ 和 $c_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 的核心思想
**ELMo**Embeddings 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 的核心思想
**BERT**Bidirectional 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 的加权层拼接
- **BERT**Masked 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)