查看全课大纲(第 52 / 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.跨媒体信息检索与未来展望
预训练范式:从 ELMo 到 BERT
小象实战讲义 · 自然语言处理
在掌握了词向量、序列模型和注意力机制等基础工具后,我们来到了自然语言处理发展的一个关键分水岭:预训练范式。静态词向量虽然奠定了表示学习的基础,但其“一词一向量”的固有缺陷在复杂的语言现象面前捉襟见肘。本节将带你深入理解,研究者们如何从静态表示走向上下文相关的动态表示,并最终确立了“预训练-微调”这一主导至今的范式。我们将重点剖析 ELMo 和 BERT 这两篇里程碑式的工作,理清它们各自的核心思想、技术路线及其承前启后的历史地位。
💡 核心导读
- 静态词向量的三大局限:无法处理一词多义、表示与上下文无关、难以应对未登录词。
- ELMo 的突破:系统性提出并推广「上下文相关词表示」,通过双向 LSTM 语言模型预训练,并加权融合不同层特征,为不同下游任务提供动态向量。
- BERT 的范式确立:采用双向 Transformer 编码器,通过掩码语言模型和下一句预测任务进行预训练,推广并确立了“预训练+全参微调”的迁移范式。
- 两种范式的对照:理解“基于特征”(feature-based)与“微调”(fine-tuning)这两种预训练模型使用方式的根本区别。
- 演进脉络:从静态向量到上下文向量,再到深层双向表示;从特征提取到参数微调。
静态词向量的局限与上下文表示的兴起
在 Word2Vec 和 GloVe 等静态词向量模型中,每个词被映射为一个固定的向量。无论「苹果」出现在「我吃了一个苹果」还是「苹果昨天发布了新手机」,拿到的都是同一个向量。这带来了三个根本性的问题:
- 一词多义无法区分:同一个词在不同语境下可能有完全不同的含义(「苹果」指水果或公司、「包袱」指布包或心理负担),静态向量无法捕捉这种差异。
- 表示与上下文无关:词向量在训练完成后即被冻结,无法融入当前句子的搭配信息、句法角色或指代关系。
- 未登录词(OOV)处理生硬:对于训练时未出现的词或形态变化,只能依靠子词切分或回退到特殊标记等策略,缺乏灵活性。
因此,NLP 社区迫切需要一种能够根据上下文动态调整词表示的模型。核心诉求是:同一个词在不同的句子里,应该得到不同的向量表示。这就是 上下文相关表示(contextualized representation)的概念。ELMo 是这条技术路线上第一个具有广泛影响力的代表作。
ELMo:深度上下文词表示
Deep contextualized word representations(Peters et al., 2018, arXiv:1802.05365) 这篇论文提出了 ELMo(Embeddings from Language Models)模型,其核心思想是利用一个深层双向语言模型来生成上下文相关的词表示。
双向语言模型预训练
ELMo 的预训练任务是一个双向语言模型(biLM)。它由两个独立训练但共享词向量层的 LSTM 语言模型组成:
- 前向 LSTM:从左到右阅读句子,根据前文预测下一个词的概率。
- 后向 LSTM:从右到左阅读句子,根据后文预测上一个词的概率。
对于一个包含 N 个词符(token)的序列 ,前向语言模型计算序列概率: 类似地,后向语言模型计算:
模型的目标是最大化前向和后向对数似然之和。
上下文表征的定义与加权求和
ELMo 的关键创新在于,它并不是简单地取语言模型最后一层的隐藏状态作为词表示。对于一个 L 层的双向语言模型,论文为每个词符 描述了一组 2L+1 个表示(注意是「个数」,不是向量维度):
- 第 0 层:词向量层输出 。
- 对于第 层:前向 LSTM 隐状态 与后向 LSTM 隐状态 各算一个(这就是 2L 的来源)。
真正代入加权求和时,把同一层的前后向拼接成一个向量,记 ,于是求和里是 项:
- 下限 是词向量层, 是各层双向拼接状态。
ELMo 将所有这些层的表示进行一个可学习的加权求和,作为该词符最终的上下文相关表示。原始论文(§3.2 式 (1))中的公式为: 其中:
- 是经过 softmax 归一化的层权重(可学习参数),表示不同层对下游任务的贡献。
- 是一个标量缩放系数(可学习参数),允许任务模型整体缩放 ELMo 向量的幅度。
层权重为什么重要?下面这个小例子把同一组层输出喂给两种不同的权重,看最终向量怎么变( 分别用三个基向量代替,便于肉眼核对):
import numpy as np
h = np.array([[1.0, 0.0, 0.0], # h_0 词向量层
[0.0, 1.0, 0.0], # h_1 第 1 层双向拼接
[0.0, 0.0, 1.0]]) # h_2 第 2 层双向拼接
gamma = 2.0
for name, s in [("句法型任务", [0.5, 0.4, 0.1]), ("语义型任务", [0.1, 0.3, 0.6])]:
elmo = gamma * (s @ h)
print(f"{name}: s={s} -> ELMo={elmo.round(4)}")句法型任务: s=[0.5, 0.4, 0.1] -> ELMo=[1. 0.8 0.2]
语义型任务: s=[0.1, 0.3, 0.6] -> ELMo=[0.2 0.6 1.2]同一组层输出,权重全压在下层时结果偏向第一维,压在上层时偏向第三维——这就是「一个 ELMo,各任务各取所需」在数值上的样子。
特征式使用与层权重的意义
ELMo 的使用方式是 基于特征(feature-based)的。预训练完成后,ELMo 模型的参数被冻结。对于下游任务(如文本分类、命名实体识别),我们将输入句子送入 ELMo 模型,得到每个词的 ELMo 向量,然后将这些向量作为额外的特征,与传统的词向量(如 GloVe)拼接后,输入到下游任务特定的模型(如 BiLSTM-CRF)中。
可学习的层权重 设计具有深刻含义。研究发现,不同 NLP 任务会倾向于使用不同层的表示:
- 底层表示(靠近输入层)往往捕获了更多的句法信息(如词性、句法结构)。因此,像词性标注这类任务会赋予底层表示更高的权重。
- 高层表示(靠近输出层)则更多地编码了语义信息。因此,像情感分析、问答这类任务会更依赖高层表示。
这种“按需分配”层权重的机制,使得 ELMo 能够灵活地为各种任务提供最相关的特征,这是其设计成功的重要经验依据。
BERT:双向 Transformer 的预训练与微调
ELMo 证明了上下文相关表示的巨大威力,但其基于 LSTM 和特征式使用的设计,在效率和性能上仍有提升空间。BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding(Devlin et al., NAACL 2019;预印本 arXiv:1810.04805 于 2018-10 发布) 的提出,标志着预训练范式进入了一个新时代。
模型结构:双向 Transformer 编码器
BERT 完全放弃了 RNN/LSTM 结构,转而使用 Transformer 编码器(Transformer Encoder)作为其核心架构。Transformer 的自注意力(Self-Attention)机制允许模型在计算每个位置的表示时,同时关注输入序列中的所有位置,从而实现真正意义上的深度双向上下文建模。这与 ELMo 中两个独立单向 LSTM 的简单拼接有本质区别。
预训练任务:掩码语言模型与下一句预测
BERT 设计了两个新颖的无监督预训练任务:
- 掩码语言模型:随机遮盖输入序列中 15% 的词符(token),让模型根据上下文预测被遮盖的原始词。这迫使模型必须深度融合双向信息才能完成预测。
- 下一句预测:给定两个句子 A 和 B,让模型判断 B 是否是 A 在原文中的真实下一句。这个任务帮助模型理解句子间关系,对问答、自然语言推理等任务至关重要。
(注:关于 MLM 和 NSP 任务更具体的实施细节,如遮盖策略、训练数据比例等,将在下一节 nlp_10_2 中详细展开。)
微调式使用
BERT 在使用方式上沿用并推广了全参微调(fine-tuning):需要说明,全参微调并非 BERT 首创,此前的 GPT 已采用这种在预训练模型上更新全部参数的迁移方式;BERT 的贡献是把“预训练+全参微调”做成了被广泛复用的标准流程。对于下游任务,我们会在预训练好的 BERT 模型基础上,添加一个简单的任务特定输出层(例如一个分类层)。然后,将 BERT 模型的所有参数与新增的输出层参数一起,在任务数据上进行端到端的训练。
这种做法的好处是显而易见的:下游任务可以直接、充分地利用预训练模型学到的强大语言知识,并通过微调过程使其适配特定任务,实现了预训练与下游应用的深度整合。
两种迁移策略的界定
BERT 论文在引言(§1)中明确区分了两种迁移学习策略,这也是理解本节演进脉络的关键:
- 基于特征的迁移:如 ELMo。预训练模型产生上下文相关的特征表示,这些特征被输入到一个独立的下游架构中。预训练模型的参数在适应下游任务时是冻结的。
- 微调式迁移:如 GPT、BERT。引入少量任务特定参数,在下游任务上通过简单地微调所有预训练参数来适应。预训练模型的参数是可更新的。
BERT 的成功,使得“预训练 + 微调”成为 NLP 任务事实上的标准流程。
范式演进与对照
为了更清晰地理解从静态词向量到 ELMo,再到 BERT 的演变,我们可以从以下几个维度进行对比:
| 维度 | 静态词向量(Word2Vec/GloVe) | ELMo(feature-based) | BERT(fine-tuning) |
|---|---|---|---|
| 是否上下文相关 | 否,一词一向量 | 是,按句计算 | 是,按句计算 |
| 预训练任务 | 无监督共现统计/词预测 | 双向 LSTM 语言模型 | MLM + NSP |
| 下游使用方式 | 直接取用固定向量 | 冻结参数,作为特征拼接到下游模型 | 全参微调,端到端训练 |
| 核心架构 | 浅层神经网络/矩阵分解 | 双向多层 LSTM | 双向多层 Transformer Encoder |
| 主要贡献/思想 | 将词映射到稠密向量空间 | 首次实现深度上下文相关表示;按任务学习层权重 | 确立“预训练-微调”范式;深度双向上下文建模 |
| 历史局限 | 无法处理一词多义、OOV | 特征与任务模型分离,训练和推理链路较长 | 预训练计算成本极高;判别式预训练目标不完全适配纯生成任务 |
从 ELMo 到 BERT 的演进,清晰地勾勒出三条主线:
- 表示层演进:静态向量 → 上下文向量(ELMo)→ 深层双向上下文表示(BERT)。
- 使用方式演进:作为固定特征(feature-based)→ 参与参数更新(fine-tuning)。
- 训练目标演进:单向语言模型(如 GPT)→ 双向掩码还原(BERT)。这条线与后续将讲到的 GPT 系列模型形成鲜明对照。
今天怎么做
时至今日,ELMo 作为一个具体的模型架构已基本退出历史舞台,但其核心思想——上下文相关表示和为不同任务适配不同层次的表示——已被深度融入现代预训练模型的设计中。
“大规模预训练 + 轻量适配”已成为 NLP 乃至多模态领域的默认范式。我们不再争论是否需要预训练,而是更多地讨论如何更高效、更灵活地使用这些大模型:
- 全参微调:传统但成本高昂的方式。
- 参数高效微调:如 LoRA(Low-Rank Adaptation)、Prefix-Tuning 等,只更新极少量参数来适配新任务。
- 提示学习:通过设计自然语言提示(Prompt),直接激发模型的内部知识,有时甚至不需要更新参数。
今天的讨论焦点,已经从“如何构建一个像 ELMo 那样的上下文编码器”,转向了“如何以最佳方式利用像 BERT 这样的强大基础模型”。
📝 动手练一练
- 概念辨析:请简述“基于特征的迁移”(feature-based)和“微调式迁移”(fine-tuning)两种策略的核心区别,并各举一个模型例子。
👉 点击查看参考答案
- 基于特征的迁移:预训练模型的参数在应用于下游任务时被冻结,不参与更新。模型输出的表示被用作下游任务模型的输入特征。下游任务模型拥有独立的、需要从头训练的架构和参数。
- 例子:ELMo。预训练好的双向 LSTM 参数固定,其输出的词向量被拼接到下游 BiLSTM-CRF 模型的输入中。
- 微调式迁移:预训练模型的参数在应用于下游任务时是可更新的。通常只需在预训练模型顶部添加一个简单的任务层(如分类头),然后整个模型(预训练部分+任务层)一起在下游任务数据上进行端到端训练。
- 例子:BERT。在预训练好的 BERT 模型后加一个分类层,然后在 GLUE 任务数据上同时更新 BERT 和分类层的参数。
- 公式理解:假设一个 2 层的 ELMo 模型(L=2),对于某个词符,我们得到以下向量(为简化,假设每个向量维度为 3):
- 词向量层输出:
h_0 = [1, 0, 0] - 第一层双向状态:
h_1 = [0, 1, 0] - 第二层双向状态:
h_2 = [0, 0, 1]若当前下游任务学到的层权重为s = [0.2, 0.3, 0.5](已 softmax),缩放系数γ = 2。请计算该词符最终的 ELMo 向量。
- 词向量层输出:
👉 点击查看参考答案
根据 ELMo 公式:
计算加权和:
乘以缩放系数 γ:
因此,该词符的最终 ELMo 向量为 [0.4, 0.6, 1.0]。
本章小结
本节我们深入探讨了 NLP 预训练范式的起源与确立。我们首先指出了静态词向量在表示能力上的根本局限,从而引出了对上下文相关表示的迫切需求。ELMo 作为先行者,通过双向 LSTM 语言模型和可学习的层加权求和,首次实现了深度上下文词表示,并采用了基于特征的使用方式。随后,BERT 以双向 Transformer 编码器为核心,通过掩码语言模型和下一句预测任务进行预训练,并推广、确立了“预训练+全参微调”的使用范式(全参微调本身由 GPT 等先行者引入),一举奠定了现代大模型发展的基础。理解 ELMo 与 BERT 在架构、预训练目标和使用方式上的差异,是把握预训练技术演进脉络的关键。
📋 行动清单
- 理清核心概念:能够清晰解释“上下文相关表示”、“基于特征迁移”和“微调式迁移”的含义与区别。
- 掌握演进脉络:在白板上画出从静态词向量到 ELMo 再到 BERT 的技术演进图,标注出每个阶段的核心创新与局限。
- 思考现代应用:了解除了全参微调,当前还有哪些主流的预训练模型适配方式(如 LoRA、提示学习),并思考它们各自适用于什么场景。
延伸阅读
- Peters, M. E., Neumann, M., Iyyer, M., Gardner, M., Clark, C., Lee, K., & Zettlemoyer, L. (2018). Deep contextualized word representations. arXiv preprint arXiv:1802.05365. (NAACL 2018) 重点阅读 §3 ELMo: Embeddings from Language Models。
- Devlin, J., Chang, M. W., Lee, K., & Toutanova, K. (2019). BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. NAACL 2019(预印本 arXiv:1810.04805)。重点阅读 §1 Introduction 和 §3 BERT。
—— 小象教研组