共计 1674 个字符,预计需要花费 5 分钟才能阅读完成。
背景痛点
在自然语言处理(NLP)领域,传统词向量模型(如 Word2Vec、GloVe)存在两个主要缺陷:
- 歧义消解能力弱 :同一个词在不同上下文中的含义无法区分(例如 ”bank” 在 ”river bank” 和 ”bank account” 中的不同含义)。
- 长距离依赖处理差 :基于窗口的模型难以捕捉超过 5 - 7 个词以外的语义关系。
预训练 + 微调(Pre-train + Fine-tune)范式通过在大规模语料上学习通用语言表示,再针对特定任务进行微调,有效解决了这些问题。
技术对比
| 特性 | BERT | GPT | ELMo |
|---|---|---|---|
| 编码方向 | 双向 | 单向(从左到右) | 双向(独立编码) |
| 核心机制 | Transformer Encoder | Transformer Decoder | BiLSTM |
| 自注意力计算复杂度 | O(n²d) | O(n²d) | 不适用 |
| 位置处理 | 绝对位置编码 | 绝对位置编码 | 无显式编码 |
| 典型应用 | 分类 / 序列标注 | 文本生成 | 特征提取 |
核心实现
加载 BERT-base 模型
import torch
from transformers import BertModel, BertTokenizer
# 初始化 tokenizer 和 model
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')
# 输入样例(batch_size=1)inputs = tokenizer("Hello world!", return_tensors="pt") # 输出: {'input_ids': tensor(...), 'attention_mask': tensor(...)}
outputs = model(**inputs) # 输出包含 last_hidden_state 和 pooler_output
特殊 Token 作用
[CLS]:位于序列开头,用于分类任务的聚合表示[SEP]:分隔两个句子(如问答任务)[PAD]:填充 token 保证 batch 内长度一致

LayerNorm 与残差连接
- Layer Normalization:对每个样本的特征维度进行归一化(区别于 BatchNorm)
- 残差连接 :解决深层网络梯度消失问题,公式为:
$$\text{Output} = \text{LayerNorm}(x + \text{Sublayer}(x))$$
生产优化
混合精度训练
from apex import amp
model, optimizer = amp.initialize(model, optimizer, opt_level="O1")
with amp.scale_loss(loss, optimizer) as scaled_loss:
scaled_loss.backward()
知识蒸馏技巧
- 保持 Student 和 Teacher 的 tokenizer 一致
- 对齐隐藏层维度(如 BERT-base→TinyBERT 需添加适配层)
- 联合优化 KL 散度损失和任务损失:
$$\mathcal{L}{total} = \alpha \mathcal{L}$$} + (1-\alpha) \mathcal{L}_{KL
避坑指南
学习率设置
- 初始学习率建议:
2e-5~5e-5 - Warmup 步数:总训练步数的 10%(例如 1000 步训练则 warmup=100 步)
OOV 处理策略
- WordPiece 分词 :将未登录词拆分为子词(如 ”unhappiness”→”un”, “##happiness”)
- 动态 masking:预训练时对 15% 的 token 随机 mask
延伸思考
- 稀疏注意力 :如何平衡计算效率和长序列建模能力?
- 模型量化 :INT8 量化在保持 99% 准确率时的最优策略是什么?
- 多语言适配 :低资源语言如何有效迁移英语 BERT 的知识?
参考文献
- BERT 原始论文:Devlin et al., 2018 (arXiv:1810.04805)
- HuggingFace 文档:https://huggingface.co/transformers/
- Apex 混合精度:https://nvidia.github.io/apex/
正文完
