查看全课大纲(第 53 / 69 节)
- 1.NLP 的研究领域、应用与学习路径
- 2.自然语言的基本术语
- 3.信息论基础:信息熵与交叉熵
- 4.语言的进化与语义变迁
- 5.主观概率、客观概率与条件概率
- 6.贝叶斯原理与推理
- 7.随机变量:二项式、期望方差与联合概率
- 8.常见概率分布
- 9.辛普森悖论与贝叶斯解题实例
- 10.语言模型:语言概率与词袋模型
- 11.n-gram 语言模型(二元 / 三元 / N-Gram)
- 12.语言模型评价:交叉熵、困惑度与插值
- 13.朴素贝叶斯文本分类:垃圾邮件
- 14.拼写检查
- 15.中文分词:构词法、最大匹配、最优路径与 Jieba
- 16.词表示问题与语义相似度
- 17.TF-IDF 权重处理
- 18.One-Hot 表达与词表示的局限
- 19.Word2Vec 核心思想
- 20.Word2Vec 训练过程
- 21.Skip-gram 模型详解
- 22.词性标注任务与标注方法(规则 + N-Gram)
- 23.EM 算法与混合模型
- 24.高斯混合模型 GMM
- 25.从混合模型到隐马尔可夫模型
- 26.隐马尔可夫模型(HMM)推导与维特比解码
- 27.线性链条件随机场 CRF
- 28.贝叶斯网络与图模型
- 29.隐马尔可夫链与 HMM 推导
- 30.PLSA 主题模型
- 31.LSI 与 SVD 向量表达
- 32.LDA 与狄利克雷分布
- 33.主题模型实验复现(困惑度 / 分类 / 相似度 / 延展)
- 34.上下文无关文法(CFG)与句法分析
- 35.概率上下文无关文法 PCFG
- 36.统计机器翻译:词对齐与翻译模型
- 37.统计机器翻译中的对齐模型与参数估计
- 38.从统计机器翻译到神经机器翻译
- 39.神经元与反向传播速览(指向深度学习课)
- 40.CNN 原理及其在 NLP 中的应用
- 41.循环神经网络的基本原理与 Elman / Jordan 网络
- 42.LSTM:长短期记忆网络的核心思想与分步实现
- 43.Encoder-Decoder 框架
- 44.Seq2Seq 与早期注意力机制
- 45.注意力机制的背景与动机
- 46.注意力模型实现原理与匹配函数
- 47.记忆网络:组成与计算
- 48.注意力机制的应用与历史延展
- 49.Transformer 结构:Encoder-Decoder 栈与 Self-Attention
- 50.Multi-Head Attention、FFNN 与位置编码
- 51.层归一化、损失函数与 Universal Transformer 延展
- 52.预训练范式:从 ELMo 到 BERT
- 53.BERT 与掩码语言模型
- 54.BERT 下游任务微调与 GLUE 口径
- 55.GPT 与自回归语言建模
- 56.GPT-1 到 GPT-4 的演进
- 57.指令微调与 RLHF
- 58.分词器:BPE、WordPiece 与中文词表
- 59.上下文窗口与长文本处理
- 60.能力边界、成本与适用场景
- 61.文本分类实战:从朴素贝叶斯到逻辑回归
- 62.命名实体识别实战
- 63.文本生成与摘要实战
- 64.语义检索与向量库实战
- 65.RAG 知识库问答
- 66.NLP 评估指标:BLEU / ROUGE / BERTScore 与人工评估
- 67.幻觉与事实性问题
- 68.文本与知识结合(知识图谱压缩)
- 69.跨媒体信息检索与未来展望
BERT 与掩码语言模型
小象实战讲义 · 自然语言处理
在前面的章节里,我们已经掌握了词向量、RNN/LSTM、注意力机制与 Transformer 的基本结构。本节进入预训练模型这一主题,讨论一个具有代表性的 encoder 类模型——BERT。它要解决的核心问题是:如何从无标注文本中预训练出深层双向的上下文表示,使得下游任务只需要在预训练参数上加一个输出层做微调,就能迁移到分类、自然语言推断、问答等多种任务。本节先假定读者已掌握 Transformer 的自注意力结构,重点讲 BERT 的预训练机制与下游微调的基本口径;更细的微调实践与现代预训练模型的演进留到后续章节。
💡 核心导读
- 问题定位:静态词向量一词一向量,无法表达多义词在不同上下文中的含义;此前的上下文表示要么只拼接左右两个方向的 LSTM 特征,要么只能从左到右建模。
- 核心思路:BERT 以多层双向 Transformer encoder 为骨架,在所有层同时结合左右两侧上下文,联合预训练深度表示。
- 两个预训练任务:掩码语言模型(MLM)随机掩盖部分词元并预测原词;下一句预测(NSP)判断两句是否为真实相邻关系。
- 两种规格:论文给出 BERT-base 与 BERT-large 两档,层数、隐层维度、注意力头数与参数量均可对照论文表格复核。
- 迁移方式:预训练完成后,下游任务用预训练参数初始化,仅新增任务相关的输出层联合微调。
从上下文表示说起
静态词向量的局限
早期的词向量(如 Word2Vec)为每个词在词典中分配一个固定向量,同一个词在不同句子里共用同一个表示。这无法区分多义词:一个词的含义往往要由它两侧的上下文共同决定。
在 BERT 之前,已经出现过两类上下文表示方案:
- ELMo:分别训练从左到右和从右到左的两层 LSTM,再把两个方向的隐层特征拼接起来供下游使用,属于特征拼接式方法。
- OpenAI GPT:采用从左到右的 Transformer,每个词元只能注意其左侧上下文,适合生成式任务。
BERT 的不同之处在于:它用双向 Transformer encoder,在所有层同时结合左右两侧上下文来建模表示。这一架构选择基于 Vaswani et al. 2017 提出的 Transformer 结构(Attention Is All You Need,arXiv:1706.03762)。架构定位与三者对比,可对照 BERT 论文第 3 节的架构示意图(Devlin et al., 2018,arXiv:1810.04805,§3 Model Architecture)。
BERT 在流程中的两步
BERT 的框架分为两步:
- 预训练(Pre-training):在无标注语料上按预训练任务训练,得到通用的上下文表示与参数。
- 微调(Fine-tuning):用预训练参数初始化模型,再在下游任务的标注数据上联合微调全部参数;每个下游任务对应一个单独的微调模型。
预训练架构与下游架构差异很小,这也是 BERT 能较方便迁移到多种任务的原因之一(Devlin et al., 2018,arXiv:1810.04805,§3 BERT)。
模型架构与两种规格
记号与规模档位
BERT 是多层双向 Transformer encoder。论文用 L 表示 Transformer 块层数,H 表示隐层维度,A 表示自注意力头数;前馈网络维度统一取 4H。论文主要报告两种规模(Devlin et al., 2018,arXiv:1810.04805,§3 Model Architecture):
| 规格 | 层数 L | 隐层 H | 注意力头 A | 前馈维度 4H | 总参数量 |
|---|---|---|---|---|---|
| BERT-base | 12 | 768 | 12 | 3072 | 110M |
| BERT-large | 24 | 1024 | 16 | 4096 | 340M |
论文说明,base 档刻意取与 OpenAI GPT 相近的体量以便对照,二者架构上最关键的差异是注意力掩码方向:BERT 用双向自注意力,GPT 用只能看左侧的受限自注意力。
输入表示
BERT 的输入需要同时表示单句和句对。它使用 WordPiece 分词,词表规模为 30,000 token。每个词元的输入嵌入由三部分相加构成:词元嵌入、句段嵌入(区分句 A 与句 B)、位置嵌入(Devlin et al., 2018,arXiv:1810.04805,§3 Input/Output Representations)。
序列首词元固定为特殊分类符 [CLS],其最终隐层向量用作整句的聚合表示;句对用特殊分隔符 [SEP] 隔开,并为每个词元标注属于句 A 还是句 B。序列长度不超过 512 个 token。
# BERT 输入表示 = 词元嵌入 + 句段嵌入 + 位置嵌入(固定小向量演示求和结构,真实嵌入由预训练得到)
import numpy as np
token_emb = np.array([0.21, -0.35, 0.10])
segment_emb = np.array([0.05, 0.02, -0.03])
position_emb = np.array([-0.08, 0.11, 0.06])
input_emb = token_emb + segment_emb + position_emb
print(f"输入嵌入: {input_emb.round(4)}")输入嵌入: [ 0.18 -0.22 0.13]两个预训练任务
掩码语言模型(MLM)
双向建模如果直接让模型预测每个词,模型可以间接地看到自己要预测的词。MLM(Masked Language Model)的做法是:在每个序列中随机掩码 15% 的 WordPiece token,让模型根据左右上下文预测被掩盖位置的原词。
被选中的位置按三种方式处理(Devlin et al., 2018,arXiv:1810.04805,§3.1 Pre-training BERT):
- 80%:替换为
[MASK]; - 10%:替换为一个随机词元;
- 10%:保持原词不变。
这样做是为了缓解 [MASK] 这个符号在微调阶段不会出现的问题:保留一部分原词、替换一部分随机词,迫使模型对每个位置都保持上下文预测能力,而不是只依赖掩码符。
# MLM 掩码策略演示(固定小词典与固定选中位置;训练时 15% 抽取与替换由随机过程完成)
tokens = ["the", "man", "went", "to", "store", "and", "bought", "milk", "yesterday", "morning"]
# 预先选定被处理的位置(演示用固定下标;真实训练按 15% 随机抽取)
selected = {1, 4, 7}
# 三个分支的固定落点:80% -> [MASK];10% -> 随机替换词(此处手工给定一个替换词);10% -> 保持原词
replace = {1: "[MASK]", 4: "apple", 7: None}
masked = []
for i, tok in enumerate(tokens):
if i not in selected:
masked.append(tok)
elif replace[i] is None:
masked.append(tok)
else:
masked.append(replace[i])
print("原序列:", " ".join(tokens))
print("掩码后:", " ".join(masked))
print("被选位置:", sorted(selected))原序列: the man went to store and bought milk yesterday morning
掩码后: the [MASK] went to apple and bought milk yesterday morning
被选位置: [1, 4, 7]下一句预测(NSP)
仅靠 MLM 学习词级表示,还不足以建模句子之间的关系。NSP(Next Sentence Prediction)是一个二分类任务:构造句对时,50% 的情况下句 B 是句 A 的真实下一句(IsNext),50% 的情况下句 B 是语料中的随机句(NotNext)。模型借助 [CLS] 向量判断两句是否相邻,从而学习句子级的连贯关系(Devlin et al., 2018,arXiv:1810.04805,§3.1 Pre-training BERT 与 §A.2 Pre-training Procedure)。
预训练过程与下游微调
预训练口径
论文预训练语料为 BooksCorpus(8 亿词)与英文维基百科,合计约 33 亿词。训练 batch 为 256 个序列,每序列 512 token,即每个 batch 约 128,000 个 token;训练 1,000,000 步,约相当于在该语料上 40 个 epoch。优化器为 Adam,学习率 1e-4,β1=0.9、β2=0.999,L2 权重衰减 0.01,前 10,000 步学习率 warmup 后线性衰减;各层 dropout 取 0.1,激活函数为 GELU(Devlin et al., 2018,arXiv:1810.04805,§A.2 Pre-training Procedure)。
为节省算力,前 90% 的训练步使用序列长度 128,后 10% 的步使用长度 512,以学习位置嵌入。
下游微调口径
微调时用预训练参数初始化,再在标注数据上联合微调。对于分类类任务,取 [CLS] 对应的最终隐层向量 ,与分类权重 计算 softmax 交叉熵,新增的参数主要就是这一层分类权重。对于问答类任务,把问题与段落打包成一个序列,仅新增起点向量 与终点向量 ,用每个词元表示与二者的点积经 softmax 选出答案跨度(Devlin et al., 2018,arXiv:1810.04805,§3.2 Fine-tuning BERT 与 §4.1 GLUE)。
论文中 BERT-large 报告的结果为 2018 年当时的数值,仅作历史参照,不代表当前榜单,也不代表 base 档成绩:GLUE 80.5%、MultiNLI 86.7%、SQuAD v1.1 Test F1 93.2、SQuAD v2.0 Test F1 83.1(均为 large 档;Devlin et al., 2018,arXiv:1810.04805,摘要与 §4 各任务表)。
今天怎么做
BERT 之后,encoder 类预训练模型继续演进:例如 RoBERTa 去掉 NSP 任务、使用更大规模数据与更长训练;DeBERTa 改进注意力中内容与位置的解耦表示。再往后,线上主干逐步转向更大规模的预训练模型与 decoder 架构。本节只做历史定位与机制讲解,这些后续模型的细节不在本节展开。
延伸阅读
- Devlin, J., Chang, M.-W., Lee, K., Toutanova, K. (2018). BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. arXiv:1810.04805(NAACL 2019)。架构规格见 §3,输入表示见 §3 Input/Output Representations,MLM/NSP 见 §3.1,预训练超参见 §A.2,下游结果见 §4。
- Vaswani, A. et al. (2017). Attention Is All You Need. arXiv:1706.03762。BERT encoder 骨架所基于的 Transformer 原始结构。
📝 动手练一练
- 概念辨析:为什么 MLM 不把被选中位置全部替换成
[MASK],而要保留 10% 原词、替换 10% 随机词?这与微调阶段[MASK]不再出现有什么关系?
👉 点击查看参考答案
如果被选中位置全部替换为 [MASK],模型在预训练阶段学到的是「看到 [MASK] 就预测原词」的专门模式;但微调阶段的真实句子里并不存在 [MASK] 符号,模型在分布上会不适应。保留 10% 原词,迫使模型即使位置词没有被替换也要结合上下文判断其表示;替换 10% 随机词,则迫使模型不能只依赖当前词元本身,而要依靠上下文纠正错误词元。三者混合让预训练表示更贴近微调时的真实输入分布。
- 对照理解:BERT-base(L=12, H=768, A=12)与 BERT-large(L=24, H=1024, A=16)在层数、隐层维度、头数和参数量上有何差别?前馈维度 4H 分别是多少?
👉 点击查看参考答案
- base:12 层,隐层 768,12 个头,前馈维度 4×768=3072,总参数 110M。
- large:24 层,隐层 1024,16 个头,前馈维度 4×1024=4096,总参数 340M。
large 在深度、宽度和头数上都大于 base,论文在多个下游任务上观察到 large 稳定优于 base;实际选用时要结合任务数据规模与算力预算权衡。
本章小结
本节围绕 BERT 与掩码语言模型展开。BERT 以双向 Transformer encoder 为骨架,通过 MLM 与 NSP 两个任务在无标注语料上预训练深层双向上下文表示;输入由词元、句段、位置三种嵌入相加构成,词表为 30,000 WordPiece。论文给出 base 与 large 两档规格,下游任务用预训练参数初始化后只加一个输出层联合微调。需要强调,本节引用的成绩均为论文 2018 年报告值,用于理解方法由来,不能当作当前主流水平;更细的微调实践与现代预训练模型的演进留到后续章节。
📋 行动清单
- 说清 BERT 相比静态词向量、ELMo、GPT 在上下文建模方向上的差异。
- 复述 MLM 的 15% 掩码比例与 80/10/10 三种替换分支,以及 NSP 的二分类构造。
- 对照论文表格记住 base/large 的层数、隐层维度、头数、前馈维度与参数量。
- 理解下游微调只新增任务输出层、其余参数联合微调的基本口径。
—— 小象教研组