<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>自然语言处理导论(第3版) on 优克</title><link>https://youkre.github.io/speech-and-language-processing/</link><description>Recent content in 自然语言处理导论(第3版) on 优克</description><generator>Hugo -- 0.148.0</generator><language>zh-cn</language><lastBuildDate>Sun, 08 Feb 2026 09:20:00 +0800</lastBuildDate><atom:link href="https://youkre.github.io/speech-and-language-processing/index.xml" rel="self" type="application/rss+xml"/><item><title>16.4 TTS 评估</title><link>https://youkre.github.io/speech-and-language-processing/ch16-04/</link><pubDate>Sun, 08 Feb 2026 09:20:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch16-04/</guid><description>&lt;p>TTS 系统通常通过人工评估进行评测：向听者播放一段合成语音，并请他们给出&lt;strong>平均意见得分&lt;/strong>（Mean Opinion Score，简称 &lt;strong>MOS&lt;/strong>）——即对合成语音质量的评分，通常采用 1 到 5 分的等级制。
随后，我们可以通过比较不同系统在相同句子上的 MOS 得分来评估其性能优劣（例如，使用配对 t 检验来判断差异是否具有统计显著性）。&lt;/p>
&lt;p>如果仅需比较两个系统（例如，验证某项修改是否真正提升了系统性能），还可以采用 &lt;strong>CMOS&lt;/strong>（Comparative MOS，比较式 MOS）方法。在此方法中，用户需对两个合成语音片段进行偏好选择，判断哪一个更好。
CMOS 评分范围为 -3 到 +3：-3 表示当前系统明显劣于参考系统，+3 表示明显优于参考系统。
具体操作时，我们会将同一句话分别用两个系统合成，播放给听者，由他们选择更偏好的版本。
通常会对约 50 个句子（以随机顺序呈现）重复此过程，再统计每个系统被偏好的句子数量并进行比较。&lt;/p>
&lt;p>尽管语音合成系统最可靠的评估方式是人工听测，但某些自动指标也可提供补充信息。
例如，我们可以将 TTS 输出送入一个自动语音识别（ASR）系统，计算词错误率（WER），以衡量合成语音的可懂度或可靠性。
又如，在评估 TTS 系统生成的语音与注册说话人语音的相似度时，可将该任务视为说话人验证问题：将目标语音和注册语音输入一个说话人验证系统，并利用其输出的相似度得分作为音色匹配程度的量化指标。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch16-03">16.3 VALL-E：使用两阶段语言模型生成音频&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch16-05">16.5 其他语音任务&lt;/a>
&lt;/nav></description></item><item><title>16.3 VALL-E：使用两阶段语言模型生成音频</title><link>https://youkre.github.io/speech-and-language-processing/ch16-03/</link><pubDate>Sun, 08 Feb 2026 09:16:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch16-03/</guid><description>&lt;p>正如引言中所述，VALL-E 等 TTS 系统的基本结构是：以待合成的文本和目标说话人的语音样本作为输入，分别对二者进行词元化，文本使用 BPE（字节对编码）词元化，语音则通过音频编解码器转换为离散词元。
随后，系统利用一个语言模型，以这些输入为条件，生成与文本提示相对应、且具有语音样本音色的离散音频词元序列。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-16-7.png">&lt;/p>
&lt;p>&lt;strong>图 16.7&lt;/strong> VALL-E 的两阶段语言建模方法，展示了自回归 Transformer 的推理阶段，以及后续 7 个非自回归 Transformer 中的前 3 个。
离散音频词元序列的生成分为两个阶段。
首先，自回归语言模型从左到右逐帧生成第一个量化器（即第一层 RVQ）的所有词元；
然后，非自回归模型被调用 7 次，每次基于前一层所有量化器的词元（包括右侧未来的词元）生成下一层的词元。&lt;/p>
&lt;p>VALL-E 并未采用单一的自回归语言模型来完成这一条件生成任务，而是将其拆分为两阶段过程，使用两种不同的语言模型。
这一架构设计受到 RVQ 量化器（生成音频词元）层级结构的启发。
RVQ 的第一层量化器输出对最终语音质量影响最大，而后续各层仅提供越来越微弱的残差信息。
因此，语言模型也分两阶段生成声学词元。
首先，一个自回归语言模型（autoregressive LM）根据输入文本和注册语音样本（enrolled audio），从左到右生成整个输出序列中第一层量化器的全部词元；
接着，在已知这些第一层词元的前提下，一个非自回归语言模型（non-autoregressive LM）被连续运行 7 次。每次运行时，它以初始自回归生成的词元和之前所有非自回归层的输出为条件，依次生成剩余 7 个量化器层的词元。
图 16.7 直观地展示了这一推理过程。&lt;/p>
&lt;p>下面我们更详细地介绍该架构。
在&lt;strong>训练阶段&lt;/strong>，给定一段音频样本 $\mathbf{y}$ 及其对应的词元化后文本转录 $\mathbf{x} = [x_0, x_1, \dots, x_L]$。我们使用一个预训练好的 ENCODEC 模型将 $\mathbf{y}$ 转换为一个词元矩阵 $\mathbf{C}$。设 ENCODEC 输出的下采样向量数量为 $T$，每个向量对应 8 个 RVQ 词元，则编码器输出可表示为：&lt;/p>
$$
\mathbf{C}^{T \times 8} = \text{ENCODEC}(\mathbf{y})
\tag{16.5}
$$&lt;p>此处，$\mathbf{C}$ 是一个二维声学词元矩阵，共包含 $T \times 8$ 个元素。其中，列表示时间步（共 $T$ 列），行表示不同的量化器层级（共 8 行）。
具体来说，矩阵的第 $t$ 行向量 $c_{t,:}$ 包含第 $t$ 个时间帧对应的 8 个词元；第 $j$ 列向量 $c_{:,j}$包含来自第 $j$ 个向量量化器的完整词元序列，其中 $j \in [1, \dots, 8]$。&lt;/p></description></item><item><title>16.2 使用编解码器学习离散音频词元</title><link>https://youkre.github.io/speech-and-language-processing/ch16-02/</link><pubDate>Sun, 08 Feb 2026 08:52:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch16-02/</guid><description>&lt;p>现代 TTS 系统的核心在于将语音波形转换为一串离散的音频词元（audio tokens）。
这种操作离散音频词元的思想，也适用于其他语音赋能系统，例如&lt;strong>口语语言模型&lt;/strong>（spoken language models）。这类模型可以接收文本或语音输入，并生成文本或语音输出，用于完成语音到语音翻译、说话人日志（diarization）或口语问答等任务。
使用离散词元意味着我们可以利用语言模型技术——因为语言模型正是为处理离散词元序列而设计的。
因此，音频词元化器已成为现代语音工具箱中的关键组件。&lt;/p>
&lt;p>目前学习音频词元的标准方法是使用神经网络实现的&lt;strong>音频编解码器&lt;/strong>（audio codec）。“codec”一词由 &lt;strong>coder/decoder&lt;/strong>（编码器/解码器）合成而来。
历史上，编解码器是一种将模拟信号数字化的硬件设备。
如今，我们更广义地用它指代一种机制：将模拟语音信号编码为一种可高效存储和传输的压缩数字表示。
编解码器仍广泛用于压缩，但在 TTS 和口语语言模型中，我们主要利用它们将语音转换为离散词元。&lt;/p>
&lt;p>当然，我们在第 14 章描述的语音数字表示本身已经是离散的。
例如，以 16 kHz 采样率、16 位精度存储的语音，可以看作 $2^{16} = 65,536$ 个符号构成的序列，每秒钟的语音包含 16,000 个这种符号。
然而，若一个系统每秒需生成 16,000 个符号，那么语音信号序列就过长，难以被语言模型有效处理——尤其是基于 Transformer 的模型，其注意力机制具有二次方复杂度，效率较低。
因此，我们希望使用能代表更长时间片段的符号，例如每秒仅几百个词元。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-16-2.png">&lt;/p>
&lt;p>&lt;strong>图 16.2&lt;/strong> 音频词元化器的标准推理架构（图改编自 Mousavi 等，2025）。
输入波形 $\mathbf{x}$ 经编码器（通常由一系列下采样卷积网络组成）转换为嵌入序列 $\mathbf{z}_t$。
每个嵌入随后通过量化器，生成离散词元序列 $q_t$。
为重建语音信号，这些量化后的词元会被重新映射为向量 $z_{qt}$，再经解码器（通常由一系列上采样卷积网络组成）还原为波形。
我们将在第 16.2.4 节讨论该架构的训练方式。&lt;/p>
&lt;p>图 16.2（改编自 Mousavi 等，2025）展示了音频词元化器的标准架构。
音频词元化器以语音波形作为输入，通过一个由向量量化生成的离散词元构成的中间表示，训练目标是尽可能重建原始语音波形。&lt;/p>
&lt;p>音频词元化器包含三个阶段：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>编码器&lt;/strong>（encoder）将声学波形（即长度为 $T$ 的序列 $x = x_1, x_2, \dots, x_T$）映射为长度为 $\tau$ 的嵌入序列 $z = z_1, z_2, \dots, z_\tau$。其中 $\tau$ 通常比 $T$ 小 100 到 1000 倍。&lt;/p></description></item><item><title>16.1 TTS 概述</title><link>https://youkre.github.io/speech-and-language-processing/ch16-01/</link><pubDate>Sat, 07 Feb 2026 17:47:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch16-01/</guid><description>&lt;p>文本到语音（TTS）的任务是：根据用户指定的特定声音，生成与目标文本相对应的语音波形。&lt;/p>
&lt;p>传统上，TTS 的实现方式是在实验室中从单一说话人那里收集数百小时的语音数据，并在此基础上训练一个大型系统来。
由此构建的 TTS 系统只能合成一种声音。如果需要第二种声音，就必须重新收集另一位说话人的语音数据。&lt;/p>
&lt;p>现代方法则不同：使用来自数千名说话人的数万小时语音数据，训练一个与说话人无关的合成器。
当需要生成训练过程中从未见过的新声音时，只需提供极少量的目标说话人语音（例如几秒钟），即可引导系统生成该声音。
因此，现代 TTS 系统的输入包括一段文本提示，以及大约 3 秒钟的目标说话人语音样本。
这种 TTS 任务被称为 &lt;strong>零样本 TTS&lt;/strong>（zero-shot TTS），因为目标声音可能在训练阶段从未出现过。&lt;/p>
&lt;p>现代 TTS 系统解决这一任务的方式是采用语言建模，特别是条件生成方法。
其基本思路是：首先获取一个庞大的语音数据集；然后利用基于&lt;strong>音频编解码器&lt;/strong>（audio codec）的&lt;strong>音频词元化器&lt;/strong>（audio tokenizer），从语音中提取出离散的音频标记（tokens），用以表示语音内容。
接着，我们训练一个语言模型，其词汇表同时包含语音词元和文本词元。&lt;/p>
&lt;p>在训练过程中，该语言模型接收两个序列作为输入：一段文本转录稿，以及一小段目标说话人的语音样本。模型将文本和语音分别转换为离散标记，然后以这些标记为条件，生成与输入文本相对应、且具有目标说话人音色的离散语音标记序列。&lt;/p>
&lt;p>在推理阶段，我们将经过分词的文本字符串和目标声音样本（由编解码器转换为离散音频标记）作为提示输入该语言模型。模型据此条件生成所需的音频词元。
随后，这些词元可被还原为语音波形。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-16-1.png">&lt;/p>
&lt;p>&lt;strong>图 16.1&lt;/strong> VALL-E 架构用于个性化 TTS（引自 Chen 等，2025）。&lt;/p>
&lt;p>Chen 等人（2025）提出的图 16.1 展示了一种此类 TTS 系统的基本思路，该系统名为 &lt;strong>VALL-E&lt;/strong>。
VALL-E 在超过 7000 名不同说话人的 6 万小时英语语音数据上进行训练。
像 VALL-E 这样的系统包含两个组成部分：&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>音频词元化器&lt;/strong>（audio tokenizer），通常基于&lt;strong>音频编解码器&lt;/strong>（audio codec）——我们将在下一节详细描述该系统。
编解码器包含三个部分：编码器（将语音转换为嵌入向量）、量化器（将嵌入向量转换为离散词元），以及解码器（将离散词元还原为语音）。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>两阶段的&lt;strong>条件语言模型&lt;/strong>（conditional language model），能够生成与目标文本对应的音频词元。我们将在第 16.3 节简要介绍该模型。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch16">第16章 文本到语音&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch16-02">16.2 使用编解码器学习离散音频词元&lt;/a>
&lt;/nav></description></item><item><title>第16章 文本到语音</title><link>https://youkre.github.io/speech-and-language-processing/ch16/</link><pubDate>Sat, 07 Feb 2026 17:36:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch16/</guid><description>&lt;blockquote>
&lt;p>“文字的意义远不止于纸面上所写下的内容。唯有通过人的声音，才能为其注入更深层的意蕴。”&lt;/p>
&lt;p>——玛雅·安杰卢，《我知道笼中鸟为何歌唱》&lt;/p>&lt;/blockquote>
&lt;p>将文本转换为语音的任务，其历史甚至比语音识别还要悠久。
1769年，在维也纳，沃尔夫冈·冯·肯佩伦为玛丽亚·特蕾莎女皇制造了著名的“机械土耳其人”。那是一个下棋的自动装置，由一个装满齿轮的木箱构成，箱后坐着一个机器人偶，能用机械手臂移动棋子下棋。
“机械土耳其人”在欧洲和美洲巡展数十年，曾击败拿破仑·波拿巴，甚至还与查尔斯·巴贝奇对弈过。
若非后来被揭穿——原来箱内藏有一名真人棋手操控——它或许会被视为人工智能早期的一大成功案例。&lt;/p>
&lt;p>较少为人所知的是，冯·肯佩伦还是一位极其多产的发明家。他在1769年至1790年间，建造了一台绝非骗局的装置：世界上第一台能合成完整句子的语音合成器（部分结构见右图）。
该装置包含一个风箱，用于模拟肺部；一个橡胶制的口模和鼻孔开口；一片簧片，用来模拟声带；若干哨子，用于生成擦音；还有一个小型辅助风箱，专门提供爆破音所需的气流。
操作者双手操纵杠杆，控制各处开口的开合，并调节柔性皮革制成的“声道”，从而发出不同的辅音和元音。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-image-16_0.png">&lt;/p>
&lt;p>两个多世纪之后，我们不再用木材和皮革来构建语音合成器，也不再需要人工操作。现代的&lt;strong>文本到语音&lt;/strong>（Text-to-Speech，简称 &lt;strong>TTS&lt;/strong>），也称&lt;strong>语音合成&lt;/strong>，其任务正好与自动语音识别（ASR）相反：它将文本：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>It&amp;#39;s time for lunch!
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>映射为一段声学波形：&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-image-16_1.png">&lt;/p>
&lt;p>TTS 拥有广泛的应用场景。
它被用于与人类交互的口语语言系统，用于朗读文本，用于游戏配音，也用于为神经系统疾病患者生成语音。例如，已故天体物理学家斯蒂芬·霍金因罹患肌萎缩侧索硬化症（ALS）而失去发声能力后，就依靠TTS系统进行交流。&lt;/p>
&lt;p>本章将介绍一种TTS算法。与上一章所述的ASR算法类似，这种算法也是在海量语音数据集上训练而成的。
我们还将简要介绍其他一些语音应用。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch15-06">15.6 ASR 评估：词错误率&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch16-01">16.1 TTS 概述&lt;/a>
&lt;/nav></description></item><item><title>15.6 ASR 评估：词错误率</title><link>https://youkre.github.io/speech-and-language-processing/ch15-06/</link><pubDate>Sat, 07 Feb 2026 17:21:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch15-06/</guid><description>&lt;p>语音识别系统（ASR）的标准评估指标是&lt;strong>词错误率&lt;/strong>（Word Error Rate, WER）。
WER 衡量的是识别器输出的词序列（称为&lt;strong>假设&lt;/strong>（hypothesized）词串）与人工标注的参考转录（reference transcription）之间的差异程度。
计算词错误率的第一步是计算假设词串与参考词串之间的&lt;strong>最小编辑距离&lt;/strong>（minimum edit distance），即把一个词串转换为另一个所需的最少&lt;strong>词替换&lt;/strong>（substitutions）、&lt;strong>词插入&lt;/strong>（insertions）和&lt;strong>词删除&lt;/strong>（deletions）操作总数。
词错误率（WER）的定义如下（注意：由于公式中包含插入操作，WER 可能超过 100%）：&lt;/p>
$$
\text{Word Error Rate} = 100 \times \frac{\text{Insertions} + \text{Substitutions} + \text{Deletions}}{\text{Total Words in Correct Transcript}}
$$&lt;p>以下是一个来自 CallHome 语料库的参考转录与系统假设之间的对齐示例，展示了用于计算错误率的各项计数：&lt;/p>
&lt;pre tabindex="0">&lt;code>REF: i *** ** UM the PHONE IS i LEFT THE portable **** PHONE UPSTAIRS last night
HYP: i GOT IT TO the ***** FULLEST i LOVE TO portable FORM OF STORES last night
Eval: I I S D S S S I S S
&lt;/code>&lt;/pre>&lt;p>该句子包含 &lt;strong>6 次替换&lt;/strong>、&lt;strong>3 次插入&lt;/strong> 和 &lt;strong>1 次删除&lt;/strong>：&lt;/p></description></item><item><title>15.5 CTC（连接时序分类）</title><link>https://youkre.github.io/speech-and-language-processing/ch15-05/</link><pubDate>Sat, 07 Feb 2026 16:59:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch15-05/</guid><description>&lt;p>在上一节中，我们指出语音识别有两个特别的属性，使其非常适合编码器-解码器架构：编码器生成输入的编码，解码器则通过注意力机制来探索这些编码。
首先，在语音中，我们有一个非常长的声学输入序列 $X$ 映射到一个短得多的字母序列 $Y$；其次，很难确切知道 $X$ 的哪一部分映射到 $Y$ 的哪一部分。&lt;/p>
&lt;p>在本节中，我们将简要介绍一种替代编码器-解码器的方法：一种名为&lt;strong>CTC&lt;/strong>（Connectionist Temporal Classification，连接时序分类）的算法和损失函数（Graves 等，2006），它以非常不同的方式处理这些问题。
CTC 的原理是为每个输入帧输出一个字符，使得输出长度与输入相同，然后应用一个折叠函数将连续相同的字母合并，从而得到一个较短的序列。&lt;/p>
&lt;p>假设我们要识别某人说出“dinner”这个词，并且我们有一个函数可以为每个输入谱帧表示 $x_i$ 选择最可能的字母。
我们将与每个输入帧对应的字母序列称为&lt;strong>对齐&lt;/strong>（alignment），因为它告诉我们声学信号中的每一部分对应哪个字母。
图 15.12 展示了一个这样的对齐示例，以及如果我们使用一个简单的折叠函数去除连续重复字母会发生什么。&lt;/p>
&lt;p>显然，这种方法行不通；我们的简单算法将语音转录成了“diner”，而不是“dinner”！
折叠操作无法处理双写字母。
此外，我们的简单函数还有一个问题：它没有告诉我们如何对输入中的静音部分进行对齐。
我们不希望将静音部分转录成随机的字母！&lt;/p>
&lt;p>CTC 算法通过在转录字母表中添加一个特殊的符号——&lt;strong>空白&lt;/strong>（blank），解决了这两个问题，我们用 ␣ 表示这个符号。
每当不想转录一个字母时，就可以在对齐中使用空白符号。
空白也可以用于字母之间；由于我们的折叠函数只折叠连续重复的字母，因此不会跨过空白折叠。
更正式地讲，让我们定义一个从对齐 $a$ 到输出 $y$ 的映射 $B: a \rightarrow y$，该映射会折叠所有重复的字母并移除所有空白。
图 15.13 展示了这个折叠函数 $B$。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-15-13.png">&lt;/p>
&lt;p>&lt;strong>图 15.13&lt;/strong> CTC 折叠函数 $B$，显示了空白字符 ␣；对齐 $A$ 中的重复（连续）字符被移除以形成输出 $Y$。&lt;/p>
&lt;p>CTC 折叠函数是多对一的；许多不同的对齐可以映射到同一个输出字符串。
例如，图 15.13 所示的对齐并不是唯一产生字符串“dinner”的对齐方式。
图 15.14 展示了其他一些也会产生相同输出的对齐方式。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-15-14.png">&lt;/p>
&lt;p>&lt;strong>图 15.14&lt;/strong> 其他三种合法的对齐方式，均产生转录结果“dinner”。&lt;/p>
&lt;p>思考所有可能产生相同输出 $Y$ 的对齐集合是有用的。
我们将使用 $B$ 函数的逆函数 $B^{-1}$，并用 $B^{-1}(Y)$ 表示该集合。&lt;/p></description></item><item><title>15.4 自监督模型：HuBERT</title><link>https://youkre.github.io/speech-and-language-processing/ch15-04/</link><pubDate>Sat, 07 Feb 2026 16:24:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch15-04/</guid><description>&lt;p>除了编码器-解码器架构外，另一类重要的方法是&lt;strong>自监督语音模型&lt;/strong>（&lt;strong>self-supervised speech models&lt;/strong>）。
这类模型并不直接学习将声学输入映射为字母或标记序列。
相反，它们首先从声学信号中&lt;strong>自举&lt;/strong>（bootstrap）出一组离散的音素单元，然后学习将原始波形映射到这些自动归纳出的单元上。
这一预训练阶段不需要转录文本，仅需未标注的语音文件即可。
完成预训练后，这些模型可以在较小规模的带标注数据集（即语音与其人工转录文本的配对）上进行微调，以执行 ASR 任务。
这种方法的优势在于：其大部分训练可以利用大量无转录文本的语音数据。&lt;/p>
&lt;p>下面我们介绍一种典型的自监督模型——&lt;strong>HuBERT&lt;/strong>（Hsu 等，2021）。
HuBERT 及其类似模型（如 &lt;strong>wav2vec 2.0&lt;/strong>（Baevski 等，2020））借鉴了第10章所介绍的 BERT 等掩码语言模型的核心思想。
对输入的一部分进行掩码，并训练模型预测被掩码的内容。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-15-8.png">&lt;/p>
&lt;p>&lt;strong>图 15.8&lt;/strong> HuBERT 在训练阶段的推理流程示意图。
一个16 kHz的原始音频文件首先通过一系列卷积层；随后，部分帧被替换为一个 &lt;strong>MASK&lt;/strong> 标记；接着，整个序列送入Transformer堆栈；最后通过一个线性层，将Transformer输出投影为输出嵌入。
该嵌入通过余弦相似度与 100（或 500）个音素类别的嵌入逐一比较，生成对应logits，再经 softmax 得到每个时间帧上各类别的概率分布。&lt;/p>
&lt;h3 id="1541-hubert-的前向传播">15.4.1 HuBERT 的前向传播&lt;/h3>
&lt;p>我们首先描述 HuBERT 在训练时使用的前向传播过程，稍后再将其置于完整的训练上下文中（包括反向传播）。
如前所述，HuBERT 前向传播的输入是原始的 16 kHz 音频波形，其输出是在每个 20 毫秒时间帧上对一组归纳出的音素类别$C$ 的概率分布（类别数通常为 100 或 500，取决于训练阶段）。
图 15.8 展示了该流程的主要组件。
原始音频波形依次通过 7 层 512 通道的卷积层。这些层不仅学习提取频谱信息，还将输入序列压缩至每 20 毫秒一帧的速率；随后添加位置编码，并依次应用 GELU 激活函数和层归一化。
接着，部分时间帧被随机替换为一个特殊的 MASK 标记，这是一个可学习的嵌入向量，所有被掩码的帧共享同一个 MASK 嵌入。
整个序列被送入一个 Transformer 堆栈；Transformer 的输出再经过一个线性投影层 $\mathbf{A}$，
得到每个 20 毫秒帧的输出嵌入；该嵌入与 100（或500）个音素类别各自的嵌入向量计算余弦相似度，生成100（或500）个 logits，表示当前音频帧与每个类别的相似程度。
最后，这些 logits 经过 softmax 函数，转化为一个在所有音素类别上的概率分布。&lt;/p></description></item><item><title>15.3 自动语音识别的编码器-解码器架构</title><link>https://youkre.github.io/speech-and-language-processing/ch15-03/</link><pubDate>Sat, 07 Feb 2026 11:21:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch15-03/</guid><description>&lt;p>我们将介绍的第一种自动语音识别（ASR）架构是&lt;strong>编码器-解码器&lt;/strong>架构，这与第 12 章中为机器翻译（MT）引入的架构相同。
图 15.5 描绘了这种架构，被称为&lt;strong>基于注意力的编码器解码器&lt;/strong>或简称&lt;strong>AED&lt;/strong>，或者根据首次将其应用于语音的两篇论文中的名称，称为&lt;strong>聆听、注意和拼写&lt;/strong>（&lt;strong>LAS&lt;/strong>）（Chorowski等人，2014；Chan等人，2016）。&lt;/p>
&lt;p>该架构的输入是一个包含 $t$ 个声学特征向量的序列 $\mathbf{X} = (\mathbf{x}_1, \mathbf{x}_2, \dots, \mathbf{x}_t)$，其中每个向量对应于一个 10 毫秒的语音帧。
我们通常从上一节描述的对数梅尔频谱特征开始，尽管也可以直接从原始 wav 文件开始处理。
输出序列 $Y$ 可以是字母或标记（BPE或sentencepiece），为了简化解释，这里假设是字母。
因此，输出序列 $Y = (\langle \text{SOS} \rangle, y_1, \dots,y_m, \langle \text{EOS} \rangle)$，其中假设有特殊的序列起始和结束标记 $\langle \text{SOS} \rangle$ 和 $\langle \text{EOS} \rangle$，且每个 $y_i$ 都是一个字符；对于英语，我们可能会选择如下集合：&lt;/p>
$$
y_i \in {a, b, c, \dots, z, 0, \dots,9, \langle \text{space} \rangle, \langle \text{comma} \rangle, \langle \text{period} \rangle, \langle \text{apostrophe} \rangle, \langle \text{unk} \rangle }
$$&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-15-5.png">&lt;/p></description></item><item><title>15.2 卷积神经网络</title><link>https://youkre.github.io/speech-and-language-processing/ch15-02/</link><pubDate>Sat, 07 Feb 2026 09:27:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch15-02/</guid><description>&lt;p>卷积神经网络，或 &lt;strong>CNN&lt;/strong>（有时简称为 &lt;strong>convnet&lt;/strong>），是一种特别适用于语音和视觉应用中提取特征的网络架构。
语音中的卷积层将音频输入（可以是原始音频或梅尔频谱）作为输入，并输出一系列输入语音的潜在表示。
在像 Whisper、wav2vec2.0 或 HuBERT 这样的 ASR 系统中，卷积层被堆叠为初始层集，用于生成传递给 transformer 层的语音表示。&lt;/p>
&lt;p>标准前馈层是全连接的；每个输入都连接到每个输出。
相比之下，卷积网络利用了“核”这一概念，即我们通过输入传递的一种小型网络。
例如，在图像分类任务中，我们将核水平和垂直地在图像上移动以识别视觉特征，因此将这种视觉网络描述为 2D（二维）卷积网络。
对于语音，我们将沿着时间维度滑动核以提取语音特征，因此语音的 CNN 是 1D 卷积网络。&lt;/p>
&lt;p>我们更深入地探讨一下这个原理。
我们将从一个非常简化的卷积层版本开始，它接受单个向量序列 $\mathbf{x}_1 \cdots \mathbf{x}_t$ 作为输入，并产生相同长度 $t$ 的单个向量序列 $\mathbf{z}_1 \cdots \mathbf{z}_t$ 作为输出。
之后我们将看到如何处理更复杂的输入和输出。&lt;/p>
&lt;p>CNN 使用一个&lt;strong>核&lt;/strong>，这是一个小的权重向量 $\mathbf{w}_1 \cdots \mathbf{w}_k$，用来提取特征。
它是通过将这个核与输入进行&lt;strong>卷积&lt;/strong>来实现的。
核与信号的&lt;strong>卷积&lt;/strong>包含三个步骤：&lt;/p>
&lt;ol>
&lt;li>将核左右翻转。&lt;/li>
&lt;li>在输入上逐帧（按时间顺序）通过核。
&lt;ul>
&lt;li>在每一帧计算核与局部输入值的点积。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>输出是这些点积的结果序列。&lt;/li>
&lt;/ol>
&lt;p>我们可以把卷积过程看作是在信号中找到与核相似的区域，因为当两个向量相似时，它们的点积会很高。
卷积操作用 * 符号表示（这是对这个符号的不幸重载，它也指简单的乘法）。
我们看看如何计算 $\mathbf{x} * \mathbf{w}$，即单个向量 $\mathbf{x}$ 与核向量 $\mathbf{w}$ 的卷积。首先考虑宽度为 1 的简单情况。
计算每个输出元素 $\mathbf{z}_j$ 作为核与 $\mathbf{x}_j$ 的乘积：&lt;/p>
$$
\text{宽度为 1 的卷积}：\mathbf{z}_j = \mathbf{x}_j\mathbf{w}_1, \forall j : 1 \leq j \leq t \tag{15.1}
$$&lt;p>图 15.2 展示了这种计算的直观理解。&lt;/p></description></item><item><title>14.5 语音识别中的特征提取：对数梅尔频谱</title><link>https://youkre.github.io/speech-and-language-processing/ch14-05/</link><pubDate>Fri, 06 Feb 2026 11:38:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch14-05/</guid><description>&lt;p>用于分析波形声学语音特性的工具，也常常被用作语音处理算法的输入。
本节将介绍一种常用的信号处理流程，它经常作为自动语音识别（ASR）等任务的一部分——正如我们将在第 15 章中看到的那样。
语音处理的第一步通常是将输入波形转换为一系列&lt;strong>声学特征向量（acoustic feature vectors）&lt;/strong>，其中每个向量表示信号在一小段时间窗口内的信息。
有时，语音识别或处理算法会直接从原始波形开始；在这种情况下，这类处理通常由第 15 章将介绍的&lt;strong>卷积神经网络（convnets）&lt;/strong> 来完成。&lt;/p>
&lt;p>但其他系统则从更高层次的表示入手，例如&lt;strong>对数梅尔频谱（log mel spectrum）&lt;/strong>。
因此，本节将介绍这种广泛使用的特征向量：&lt;strong>对数梅尔频谱向量序列&lt;/strong>。
在下一节中，我们将介绍另一种常用表示：&lt;strong>MFCC（梅尔频率倒谱系数）&lt;/strong>。
我们的介绍将保持在相对较高的抽象层次；若需深入了解，建议修读专门的语音信号处理课程。&lt;/p>
&lt;p>我们首先回顾第 14.4.2 节中所述的模拟语音波形的数字化与量化过程。&lt;/p>
&lt;h3 id="1451-采样与量化">14.5.1 采样与量化&lt;/h3>
&lt;p>语音识别器的输入是一系列复杂的空气压力变化。
这些气压变化显然源自说话人，是由气流通过声门并从口腔或鼻腔排出的特定方式所引起的。
我们通过绘制&lt;strong>气压随时间的变化&lt;/strong>来表示声波。
有时，一个有助于理解这类图形的比喻是：想象一块垂直的薄板挡在声波传播路径上（例如说话人嘴前的麦克风振膜，或听者耳中的鼓膜）。
图中所测量的是该薄板处空气分子的&lt;strong>压缩（compression）&lt;/strong> 或 &lt;strong>稀疏（rarefaction，即“解压缩”）&lt;/strong> 程度。
图 14.25（重复自图 14.11）展示了一段来自 Switchboard 电话语音语料库的短时波形，内容是某人说 “she just had a baby” 中最后一个音节 &lt;em>baby&lt;/em> 的元音 [iy]。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-14-25.png">&lt;/p>
&lt;p>&lt;strong>图 14.25&lt;/strong> 元音 [iy]（单词 “baby” 中的最后一个元音）的波形。
Y 轴表示气压相对于正常大气压的高低，X 轴表示时间。
注意该波形呈现规律性重复。
（重复自图 14.11）&lt;/p>
&lt;p>将图 14.15 这类声波数字化的第一步，是将模拟信号（首先是气压变化，随后是麦克风中产生的模拟电信号）转换为数字信号。
这种&lt;strong>模数转换（analog-to-digital conversion）&lt;/strong> 包含两个步骤：&lt;strong>采样（sampling）&lt;/strong> 和 &lt;strong>量化（quantization）&lt;/strong>。
&lt;strong>采样&lt;/strong>是指在特定时刻测量信号的振幅。&lt;strong>采样率（sampling rate）&lt;/strong> 即每秒采集的样本数量。
为了准确还原一个波形，每个周期内至少需要两个采样点：一个用于测量波的正半周，另一个用于负半周。
若每周期采样多于两点，可提高振幅精度；但若少于两点，则会导致该频率完全无法被正确捕捉。
因此，对于给定采样率，所能准确测量的最高频率等于采样率的一半（因为每个周期至少需两个样本）。
这一上限频率称为&lt;strong>奈奎斯特频率（Nyquist frequency）&lt;/strong>。
人类语音中的大部分信息集中在 10,000 Hz 以下的频率范围内。因此，要实现完全保真的语音数字化，需要 20,000 Hz 的采样率。
然而，电话语音会经过交换网络的滤波处理，仅传输低于 4,000 Hz 的频率成分。
因此，对于像 Switchboard 语料库这样的&lt;strong>电话带宽（telephone-bandwidth）&lt;/strong> 语音，8,000 Hz 的采样率已足够。
而对于麦克风录制的宽频语音，通常采用 16,000 Hz 的采样率。&lt;/p></description></item><item><title>15.1 自动语音识别任务</title><link>https://youkre.github.io/speech-and-language-processing/ch15-01/</link><pubDate>Fri, 06 Feb 2026 11:30:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch15-01/</guid><description>&lt;p>在介绍ASR算法之前，我们先讨论一下ASR任务本身有哪些变化维度。
第一个变化维度是词汇量大小。某些ASR任务早已能以极高的准确率完成。
例如，只有两个词的词汇表（“yes”与“no”），或包含11个词的&lt;strong>数字识别&lt;/strong>任务（识别从“zero”到“nine”以及“oh”的数字序列）。
相比之下，开放式任务要困难得多。比如准确转录视频内容或人类对话，这类任务通常涉及6万甚至更多词汇，挑战性显著更高。&lt;/p>
&lt;p>第二个变化维度是说话对象。
人类对机器说话（无论是口述还是与对话系统交互）比人与人之间的对话更容易识别。
&lt;strong>朗读语音&lt;/strong>（read speech）也相对容易处理。例如有声书中人们大声朗读的内容就属于此类。
而识别&lt;strong>会话语音&lt;/strong>（conversational speech）中两个人的交谈、转录商务会议内，则是最难的。
似乎当人类对机器说话，或在没有听众的情况下朗读时，他们会显著简化自己的言语：语速更慢，发音更清晰。&lt;/p>
&lt;p>第三个变化维度是信道与噪声环境。如
果语音是在安静房间内通过头戴式麦克风录制的，就比在嘈杂的城市街道上用远距离麦克风录制，或在车窗打开的汽车内录制更容易识别。&lt;/p>
&lt;p>最后一个变化维度是口音或说话人类别特征。
如果说话人使用的方言或语言变体与系统训练所用数据一致，识别就更容易。
如果系统仅在标准方言或成人说话人的数据上训练过，那么面对地区性或民族性方言使用者、儿童等群体的语音，识别难度就会大大增加。&lt;/p>
&lt;p>为了研究这些变化，研究人员使用了多个公开可用的语料库。这些语料库包含人工制作的转录文本，常被用于构建ASR的测试集和训练集。
以下列举几个常见语料库，你在文献中很可能会遇到它们。&lt;/p>
&lt;p>&lt;strong>LibriSpeech&lt;/strong> 是一个大型开源朗读语音数据集，采样率为16 kHz。它包含来自LibriVox项目的超过1000小时有声书音频，志愿者朗读并录制了无版权书籍（Panayotov 等，2015）。
该数据集的转录文本已对齐到句子级别。
它被划分为较易的“clean”部分和较难的“other”部分。
“clean”部分录音质量更高，口音更接近美式英语。
这一划分是在语料库首次发布时完成的：研究人员用一个在《华尔街日报》朗读语音上训练的语音识别器处理全部音频，根据人工标注的参考转录计算每位说话人的词错误率（WER），再将说话人大致分为两组，低WER说话人的录音归为“clean”，高WER说话人的录音归为“other”。&lt;/p>
&lt;p>&lt;strong>Switchboard&lt;/strong> 语料库收集于1990年代初，包含陌生人之间按提示进行的电话对话。
它共有 2430 段对话，平均每段6分钟，总计240小时8 kHz语音，约300万词（Godfrey 等，1992）。
Switchboard 的独特优势在于其海量的人工标注语言学信息，包括句法分析、对话行为标签、音素与韵律标注，以及话语结构和信息结构标注。&lt;/p>
&lt;p>&lt;strong>CALLHOME&lt;/strong> 语料库则收集于1990年代末，包含120段未经脚本设计的30分钟电话对话。对话双方通常是关系亲密的朋友或家人，均为英语母语者（Canavan 等，1997）。&lt;/p>
&lt;p>多种语料库试图包含更自然的语音输入。&lt;strong>CHiME&lt;/strong> 挑战赛是一系列困难的共享任务，处理 ASR 稳健可靠性。
例如，CHiME-6 任务的目标是在真实家庭环境中识别会话语音（具体为晚餐聚会场景）。
该语料库包含在 20 个真实家庭中录制的晚餐聚会音频，每次聚会 4 名参与者，在三个位置（厨房、餐厅、客厅）使用远场麦克风进行录音。&lt;/p>
&lt;p>&lt;strong>AMI&lt;/strong> 会议语料库包含 100 小时的小组会议录音（部分为自然发生的会议，部分为专门组织的会议），配有手工转录文本及部分额外人工标注（Renals 等，2007）。&lt;/p>
&lt;p>&lt;strong>CORAAL&lt;/strong> 是一个包含 150 多段社会语言学访谈的语料库，访谈对象为非裔美国人，旨在研究非裔美国英语（&lt;strong>AAE&lt;/strong>），即非裔美国人社群及其他群体所使用的多种语言变体（Kendall 与 Farrington，2020）。
这些访谈已做匿名处理，转录文本对齐到话语（utterance）级别。&lt;/p>
&lt;p>其他语言也有大量可用语料库。
以中文为例，&lt;strong>HKUST&lt;/strong> 普通话电话语音语料库包含 1206 段经转录的十分钟普通话电话对话，说话人来自中国各地，包括朋友之间和陌生人之间的交谈（Liu 等，2006）。
&lt;strong>AISHELL-1&lt;/strong> 语料库则包含 170 小时的普通话朗读语音，句子取自多个领域，由主要来自中国北方的不同说话人朗读（Bu 等，2017）。&lt;/p></description></item><item><title>第15章 自动语音识别</title><link>https://youkre.github.io/speech-and-language-processing/ch15/</link><pubDate>Fri, 06 Feb 2026 10:30:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch15/</guid><description>&lt;blockquote>
&lt;p>我不知是否&lt;br>
领会了你的意思：若真领会，&lt;br>
它便浮于你声音的字词涟漪之上，&lt;br>
如同溪流中黄昏的淡淡倒影。&lt;br>&lt;/p>
&lt;p>托马斯·洛弗尔·贝多斯，1851年&lt;/p>&lt;/blockquote>
&lt;p>理解口语，或至少将其中的词语转写为文字，是计算机语言处理最早的目标之一。
事实上，语音处理的历史比计算机还要早几十年！
最早的语音识别机器出现在 20 世纪 20 年代，那是一个玩具。
右侧所示的“Radio Rex”是一只赛璐珞制成的狗。当接收到约500 Hz的声能时，它内部的弹簧会被释放，从而驱动狗移动。
由于 500 Hz 大致对应“Rex”一词中元音[eh]的第一共振峰，因此这只狗似乎真的会在被叫到名字时出现（David, Jr. 与 Selfridge，1962）。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-image-15_Im179.jpg">&lt;/p>
&lt;p>在现代，我们对自动系统提出了更高要求。
&lt;strong>自动语音识别&lt;/strong>（&lt;strong>ASR&lt;/strong>）的任务，就是将如下这样的声波：&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-image-15_waveform.png">&lt;/p>
&lt;p>映射为对应的词串：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>It&amp;#39;s time for lunch!
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>目前，要实现任意说话人、在任意环境下都能准确转录语音，这一目标仍远未达成。但ASR技术已经发展成熟，足以胜任许多实际任务。
语音是一种自然的人机交互方式，特别适用于操控家电，或与数字助理、聊天机器人交流。在手机等设备上尤其如此，因为键盘输入往往不够便捷。
ASR也广泛用于通用转录场景，例如自动生成音视频内容的字幕（如电影、视频或实时讨论的转录）。
在法律等领域，口述转录具有重要作用。
此外，ASR还是增强型通信的关键组成部分。这类通信指计算机与存在某些障碍的人类用户之间的互动——这些障碍可能导致用户难以或无法打字，或存在听觉困难。
失明的弥尔顿曾口述《失乐园》由女儿记录；亨利·詹姆斯则因重复性劳损，在后期改用口述创作小说。&lt;/p>
&lt;p>接下来几节将介绍ASR任务的不同目标，说明如何提取声学特征，并引入&lt;strong>卷积神经网络&lt;/strong>架构。该架构常被用作语音识别任务的初始层。&lt;/p>
&lt;p>随后，我们将介绍两类ASR方法。
第一类是&lt;strong>编码器-解码器&lt;/strong>范式。我们会介绍基于注意力机制的基础编码器-解码器算法，早期实现常被称为“Listen Attend and Spell”。
我们还会介绍一种更先进的编码器-解码器系统——OpenAI 的 Whisper 系统（Radford 等，2023），以及一个采用相同架构的开源系统 OWSM（Open Whisper-style Speech Model）（Peng 等，2023）。（这些模型还具备翻译等额外能力，后文将详述。）
第二类方法利用自监督语音模型（有时缩写为 SSL，即自监督学习），例如 Wav2Vec2.0或 HuBERT。这些模型作为编码器，能够学习语音的抽象表示。通过与 &lt;strong>CTC&lt;/strong>（连接时序分类）损失函数结合用于解码，即可完成 ASR 任务。&lt;/p>
&lt;p>最后，我们将介绍评估ASR性能的标准指标——&lt;strong>词错误率&lt;/strong>（word error rate）。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch14-06">14.6 MFCC：梅尔频率倒谱系数&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch15-01">15.1 自动语音识别任务&lt;/a>
&lt;/nav></description></item><item><title>14.6 MFCC：梅尔频率倒谱系数</title><link>https://youkre.github.io/speech-and-language-processing/ch14-06/</link><pubDate>Fri, 06 Feb 2026 09:51:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch14-06/</guid><description>&lt;p>&lt;strong>MFCC（Mel Frequency Cepstral Coefficients，梅尔频率倒谱系数）&lt;/strong> 是一种有用的波形表示方法，它强调了信号中与语音单元检测相关的方面。&lt;br>
MFCC 是一个 39 维的特征向量，包含：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>12 个倒谱系数&lt;/td>
&lt;td>1 个能量系数&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>12 个一阶差分倒谱系数&lt;/td>
&lt;td>1 个一阶差分能量系数&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>12 个二阶差分倒谱系数&lt;/td>
&lt;td>1 个二阶差分能量系数&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>下面概述了这些特征是如何计算的；对更多细节感兴趣的读者可以参考信号处理课程。&lt;/p>
&lt;h3 id="倒谱逆离散傅里叶变换">倒谱：逆离散傅里叶变换&lt;/h3>
&lt;p>MFCC 系数基于&lt;strong>倒谱（cepstrum）&lt;/strong>。&lt;br>
倒谱的一种理解方式是它提供了一种将&lt;strong>声源&lt;/strong>和&lt;strong>滤波器&lt;/strong>分离的有效方法。&lt;br>
回顾第 14.4.6 节，当具有特定基频的声门源波形通过声道时生成语音波形，由于声道形状的不同过滤特性，产生了不同的语音。&lt;br>
然而，许多声门&lt;strong>源&lt;/strong>的特征（如其基频、声门脉冲的具体细节等）对于区分不同语音并不重要。&lt;br>
相反，对于语音识别最有用的信息是&lt;strong>滤波器&lt;/strong>，即声道的确切位置。&lt;br>
如果我们知道声道的形状，就能知道正在发出的是哪个语音。
这表明，对于语音识别有用的特征应该能够解卷积（分离）声源和滤波器，并只显示声道滤波器。&lt;br>
事实证明，倒谱就是实现这一目标的方法之一。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-14-30.png">&lt;/p>
&lt;p>&lt;strong>图 14.30&lt;/strong> 来自 Taylor (2009) 的幅度谱（a）、对数幅度谱（b）和倒谱（c），已获得许可。
两个频谱上叠加了一个平滑的频谱包络以帮助可视化频谱。&lt;/p>
&lt;p>为了简化讨论，我们考虑输入为对数幅度谱并忽略梅尔缩放。&lt;br>
倒谱可以被看作是&lt;strong>频谱的对数的频谱&lt;/strong>。
这听起来可能令人困惑，我们从简单部分开始：&lt;strong>频谱的对数&lt;/strong>。&lt;br>
也就是说，倒谱始于标准幅度频谱，如 Taylor (2009) 中所示元音的频谱（图 14.30(a)）。
然后取对数，即将幅度频谱中的每个振幅值替换为其对数值，如图 14.30(b) 所示。&lt;/p>
&lt;p>下一步是将对数频谱可视化，就像&lt;strong>它本身就是一个波形&lt;/strong>。
换句话说，考虑图 14.30(b) 中的对数频谱。
轴标签（x 轴上的频率）告诉我们这是频谱，假设移除这些轴标签，并想象我们只是在处理正常的语音信号，x 轴表示时间。
现在我们能说这个“伪信号”的频谱有什么特点呢？&lt;br>
注意到该波形中有一个高频重复成分：小波大约每 1000 单位沿 x 轴重复 8 次，频率约为 120 Hz。
这种高频成分是由信号的基频引起的，代表了频谱中信号每个谐波处的小峰值。&lt;br>
此外，“伪信号”中还有一些较低频率的成分；例如，包络或共振峰结构在这个窗口中有大约四个大峰值，对应更低的频率。&lt;/p></description></item><item><title>14.4 声学语音学与信号</title><link>https://youkre.github.io/speech-and-language-processing/ch14-04/</link><pubDate>Fri, 06 Feb 2026 09:25:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch14-04/</guid><description>&lt;p>我们首先对声学波形及其数字化和频域分析做一个非常简要的介绍；有兴趣的读者可参考本章末尾所列的参考资料。&lt;/p>
&lt;h3 id="1441-波">14.4.1 波&lt;/h3>
&lt;p>声学分析基于正弦（sine）和余弦（cosine）函数。
图 14.10 展示了一条正弦波的图像，具体对应以下函数：&lt;/p>
$$
y = A \cdot \sin(2 \pi f t) \tag{14.3}
$$&lt;p>其中，振幅 $A$ 设为 1，频率 $f$ 设为每秒 10 个周期。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-14-10.png">&lt;/p>
&lt;p>&lt;strong>图 14.10&lt;/strong> 频率为 10 Hz、振幅为 1 的正弦波。&lt;/p>
&lt;p>根据基础数学知识，波有两个重要特征：&lt;strong>频率（frequency）&lt;/strong> 和 &lt;strong>振幅（amplitude）&lt;/strong>。
频率指波每秒重复的次数，即&lt;strong>周期（cycles）&lt;/strong> 的数量。
频率通常以&lt;strong>每秒周期数&lt;/strong>来度量。
图 14.10 中的信号在 0.5 秒内重复了 5 次，因此频率为每秒 10 个周期。
每秒周期数通常称为&lt;strong>赫兹（hertz）&lt;/strong>，缩写为 &lt;strong>Hz&lt;/strong>，所以图 14.10 中的频率可描述为 10 Hz。
正弦波的&lt;strong>振幅&lt;/strong> $A$ 是其在 Y 轴上的最大值。
波的&lt;strong>周期 $T$&lt;/strong> 是完成一个完整循环所需的时间，定义为：&lt;/p>
$$
T = \frac{1}{f} \tag{14.4}
$$&lt;p>图 14.10 中每个周期持续十分之一秒，因此 $T = 0.1$ 秒。&lt;/p></description></item><item><title>14.3 韵律</title><link>https://youkre.github.io/speech-and-language-processing/ch14-03/</link><pubDate>Fri, 06 Feb 2026 08:41:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch14-03/</guid><description>&lt;p>&lt;strong>韵律（Prosody）&lt;/strong> 研究语言的语调和节奏特征，特别是如何利用&lt;strong>基频（F0）&lt;/strong>、&lt;strong>能量（energy）&lt;/strong> 和 &lt;strong>时长（duration）&lt;/strong> 来传达语用、情感或对话交互层面的意义。&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>
我们将在下一节转向声学语音学时详细介绍这些声学量。简而言之，&lt;strong>能量&lt;/strong>是我们感知为“响度”的声学属性，而 &lt;strong>F0&lt;/strong> 是声音的基频，即听觉上感知为话语“音高”的声学特征。
韵律可用于标记&lt;strong>话语结构（discourse structure）&lt;/strong>，例如陈述句与疑问句之间的区别，或会话的组织方式。
韵律也用于突出某个词或短语的&lt;strong>显著性（saliency）&lt;/strong>。
此外，韵律在副语言功能中被广泛使用，例如传达喜悦、惊讶或愤怒等情感意义。
韵律还在对话中的&lt;strong>话轮转换（turn-taking）&lt;/strong> 管理中发挥重要作用。&lt;/p>
&lt;h3 id="1431-韵律显著性重音词重音与弱化元音">14.3.1 韵律显著性：重音、词重音与弱化元音&lt;/h3>
&lt;p>在美式英语的自然话语中，有些词听起来比其他词更&lt;strong>显著（prominent）&lt;/strong>，而这些词中的某些音节也比其他音节更&lt;strong>显著&lt;/strong>。
所谓“显著”，是指这些词或音节在听感上对听者更具突显性。
说话人通过以下方式使一个词或音节在英语中更突显：说得更响（增大能量）、说得更慢（延长时长），或在该词内部改变 F0（使其音高更高或变化更大）。&lt;/p>
&lt;p>&lt;strong>语调重音（Accent）&lt;/strong>
我们通过一种称为&lt;strong>音高重音（pitch accent）&lt;/strong> 的语言标记来表示这种显著性。
那些显著的词或音节被认为&lt;strong>承载（bear）&lt;/strong> 一个音高重音。
例如，下面这句话可能会通过重读带下划线的词来发音：&lt;/p>
&lt;blockquote>
&lt;p>(14.1) I&amp;rsquo;m a little &lt;u>surprised&lt;/u> to hear it &lt;u>characterized&lt;/u> as &lt;u>happy&lt;/u>.&lt;/p>&lt;/blockquote>
&lt;p>&lt;strong>词重音（Lexical Stress）&lt;/strong>
承载音高重音的音节称为&lt;strong>重读音节（accented syllables）&lt;/strong>。
并非一个词的每个音节都能承载重音：音高重音必须落在具有&lt;strong>词重音（lexical stress）&lt;/strong> 的音节上。
词重音是词典中标注的该词发音的一个属性；如果一个词被重读，那么其词重音所在的音节就会更响或更长。
例如，&lt;em>surprised&lt;/em> 的重音在第二个音节，而不是第一个。（试着把重音放在第一个音节上，说成 SURprised；希望你觉得这听起来不对。）
因此，如果 &lt;em>surprised&lt;/em> 在句子中获得音高重音，那么被强化的将是它的第二个音节。
下面的例子展示了带下划线的重读词，其中承载重音的词重音音节（即更响、更长的那个音节）以粗体标出：&lt;/p>
&lt;blockquote>
&lt;p>(14.2) I&amp;rsquo;m a little &lt;u>sur&lt;strong>prised&lt;/strong>&lt;/u> to hear it &lt;u>&lt;strong>char&lt;/strong>acterized&lt;/u> as &lt;u>&lt;strong>hap&lt;/strong>py&lt;/u>.&lt;/p>&lt;/blockquote>
&lt;p>词典中标记了重音信息。
例如，CMU 发音词典（CMU, 1993）用数字 0（非重读）或 1（重读）标注元音，如 &lt;em>counter&lt;/em>：[K AW1 N T ER0]，或 &lt;em>table&lt;/em>：[T EY1 B AH0 L]。
词重音位置的不同会影响词义：名词 &lt;em>content&lt;/em> 读作 [K AA1 N T EH0 N T]，而形容词 &lt;em>content&lt;/em> 则读作 [K AA0 N T EH1 N T]。&lt;/p></description></item><item><title>16.5 其他语音任务</title><link>https://youkre.github.io/speech-and-language-processing/ch16-05/</link><pubDate>Fri, 06 Feb 2026 00:00:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch16-05/</guid><description>&lt;p>语音领域还包含多种其他任务。&lt;/p>
&lt;p>&lt;strong>说话人日志&lt;/strong>（Speaker diarization）的任务是在一段长时间、多说话人的录音中判断“谁在什么时候说话”，即标注出每位说话人在交互中发言的起止时间。
该技术可用于会议转录、课堂语音记录或医患对话等场景。
通常，说话人日志系统会先使用语音活动检测（Voice Activity Detection, VAD）找出连续的语音片段，然后提取说话人嵌入向量，并对这些向量进行聚类，将可能来自同一说话人的片段归为一类。
近期的研究则开始探索端到端算法，直接从输入语音映射到每一帧对应的说话人标签序列。&lt;/p>
&lt;p>&lt;strong>说话人识别&lt;/strong>（Speaker recognition）是指识别说话人身份的任务。
我们通常将其细分为两个子任务：
&lt;strong>说话人验证&lt;/strong>（speaker verification）：做出二元判断（“这是说话人 X 吗？”），常用于电话访问个人账户等安全场景；
&lt;strong>说话人辨识&lt;/strong>（speaker identification）：在 N 个候选者中选择一个，即将一段语音与包含多位说话人的数据库进行匹配，确定其身份。&lt;/p>
&lt;p>在&lt;strong>语种识别&lt;/strong>（language identification）任务中，系统接收一段波形文件，并需判断其中所使用的语言。这项任务对于构建多语言模型、创建标注数据集，乃至在线语音系统都具有重要意义。&lt;/p>
&lt;p>&lt;strong>唤醒词检测&lt;/strong>（wake word detection）的任务是检测某个特定词语或短语（如 “Alexa”、“Hey Siri” 或 “OK Google”），通常用于激活语音助手。
唤醒词检测的关键目标是将检测模块部署在边缘计算设备（如智能音箱或手机）上，以最小化上传至云端服务器的用户语音数据量，从而保护隐私。
因此，唤醒词检测器必须是运行速度快、占用内存小的轻量级软件，能够嵌入资源受限的设备中。
这类检测器通常采用与 ASR 相同的前端特征提取方法，随后接一个整词分类器（whole-word classifier）进行判别。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch16-04">16.4 TTS 评估&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;span>&lt;/span>
&lt;/nav></description></item><item><title>14.2 发音语音学</title><link>https://youkre.github.io/speech-and-language-processing/ch14-02/</link><pubDate>Wed, 04 Feb 2026 11:01:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch14-02/</guid><description>&lt;p>&lt;strong>发音语音学（Articulatory phonetics）&lt;/strong> 研究的是：当口腔、咽喉和鼻腔中的各种器官对来自肺部的气流进行调节时，这些音素（phones）是如何产生的。&lt;/p>
&lt;h3 id="发音器官">发音器官&lt;/h3>
&lt;p>图 14.4 展示了人类的发音器官。
声音由空气的快速运动产生。
人类在口语中发出的大多数声音，都是通过将肺部空气经气管（专业术语称为&lt;strong>气管&lt;/strong>，trachea）推出，并从口腔或鼻腔排出而形成的。
当气流经过气管时，会穿过&lt;strong>喉头（larynx）&lt;/strong>——俗称“喉结”或“声箱”。
喉头内有两片小肌肉褶皱，称为&lt;strong>声带（vocal folds）&lt;/strong>（非专业场合常称作&lt;strong>声 cords&lt;/strong>）。这两片声带可以靠拢或分开。
它们之间的空隙称为&lt;strong>声门（glottis）&lt;/strong>。
如果声带彼此靠近（但未完全闭合），气流通过时会引起振动；如果声带张开较远，则不会振动。
由振动声带产生的声音称为&lt;strong>浊音（voiced）&lt;/strong>；不伴随声带振动的声音则称为&lt;strong>清音（unvoiced）&lt;/strong> 或 &lt;strong>无声音（voiceless）&lt;/strong>。
浊音包括 [b]、[d]、[g]、[v]、[z] 以及所有英语元音等。
清音则包括 [p]、[t]、[k]、[f]、[s] 等。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-14-4.png">&lt;/p>
&lt;p>&lt;strong>Figure 14.4&lt;/strong> The vocal organs, shown in side view. (Figure from OpenStax University
Physics, CC BY 4.0)&lt;/p>
&lt;p>气管以上的区域称为&lt;strong>声道（vocal tract）&lt;/strong>，它由&lt;strong>口腔声道（oral tract）&lt;/strong> 和 &lt;strong>鼻腔声道（nasal tract）&lt;/strong> 组成。
空气离开气管后，可经口腔或鼻腔排出体外。
大多数声音是通过口腔气流产生的。
若气流经鼻腔排出，则形成&lt;strong>鼻音（nasal sounds）&lt;/strong>；这类声音（如英语中的 [m]、[n] 和 [ng]）同时利用口腔和鼻腔作为共鸣腔。&lt;/p>
&lt;p>音素主要分为两大类：&lt;strong>辅音（consonants）&lt;/strong> 和 &lt;strong>元音（vowels）&lt;/strong>。
这两类声音都是通过气流在口腔、咽喉或鼻腔中运动而形成的。
辅音是通过某种方式限制或阻塞气流而产生的，可以是浊音，也可以是清音。
元音的阻碍较少，通常是浊音，且一般比辅音更响亮、持续时间更长。
这些术语在语言学中的技术用法与日常用法大致相同：
[p]、[b]、[t]、[d]、[k]、[g]、[f]、[v]、[s]、[z]、[r]、[l] 等属于辅音；
[aa]、[ae]、[ao]、[ih]、[aw]、[ow]、[uw] 等属于元音。
&lt;strong>半元音（semivowels）&lt;/strong>（如 [y] 和 [w]）兼具两类特征：它们像元音一样是浊音，但又像辅音一样短暂且不具备明显的音节性。&lt;/p></description></item><item><title>14.1 语音与音标转写</title><link>https://youkre.github.io/speech-and-language-processing/ch14-01/</link><pubDate>Wed, 04 Feb 2026 10:35:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch14-01/</guid><description>&lt;p>像 &amp;lsquo;p&amp;rsquo; 或 &amp;lsquo;a&amp;rsquo; 这样的字母，本身已经是对人类语音的一种有用建模。事实上，我们将在第15章看到如何在字母与声波之间建立映射。
尽管如此，用稍更抽象的方式来表示语音仍然很有帮助。
我们将一个词的发音表示为一串&lt;strong>音素（phones）&lt;/strong>，即语音的基本单位，每个音素用源自罗马字母的符号表示。&lt;/p>
&lt;p>用于转写世界各种语言的标准语音表示法是&lt;strong>国际音标（International Phonetic Alphabet, IPA）&lt;/strong>。它是一项不断演进的标准，最早制定于1888年。
但在本章中，我们将使用 ARPAbet（Shoup, 1980）来表示音素。ARPAbet 是一种简单的音标系统（见图14.1），它方便地使用 ASCII 符号来表示 IPA 中美式英语所用的一个子集。&lt;/p>
&lt;p>许多 IPA 和 ARPAbet 的符号与常见的罗马字母相同。
例如，ARPAbet 中的音素 [p] 表示 &lt;em>platypus&lt;/em>、&lt;em>puma&lt;/em> 和 &lt;em>plantain&lt;/em> 开头的辅音，也出现在 &lt;em>leopard&lt;/em> 的中间或 &lt;em>antelope&lt;/em> 的末尾。
然而，总体而言，英语正字法中的字母与其对应音素之间的映射关系相当&lt;strong>不透明（opaque）&lt;/strong>。同一个字母在不同上下文中可能代表非常不同的语音。
比如，英语字母 &lt;em>c&lt;/em> 在 &lt;em>cougar&lt;/em> [k uw g axr] 中对应音素 [k]，但在 &lt;em>cell&lt;/em> [s eh l] 中却对应音素 [s]。
此外，音素 [k] 不仅可以写作 &lt;em>c&lt;/em> 或 &lt;em>k&lt;/em>，还可以作为 &lt;em>x&lt;/em> 的一部分出现（如 &lt;em>fox&lt;/em> [f aa k s]），也可以写作 &lt;em>ck&lt;/em>（如 &lt;em>jackal&lt;/em> [jh ae k el]）或 &lt;em>cc&lt;/em>（如 &lt;em>raccoon&lt;/em> [r ae k uw n]）。
相比之下，许多其他语言（例如西班牙语）在语音与拼写之间的映射要**透明（transparent）**得多。&lt;/p></description></item><item><title>第14章 语音学与语音特征提取</title><link>https://youkre.github.io/speech-and-language-processing/ch14/</link><pubDate>Wed, 04 Feb 2026 00:00:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch14/</guid><description>&lt;p>本书所讨论的文本，其组成字符并非随意的符号。
它们还是一项了不起的科学发明：一种对人类语音基本单元的理论建模。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-image-14_Im149.png">&lt;/p>
&lt;p>目前已知最早的文字系统（如苏美尔文、中文和玛雅文）主要是&lt;strong>表意文字&lt;/strong>：一个符号代表一个完整的词。
但从我们所能追溯的最早阶段起，有些符号也用来表示构成词语的语音。
例如，右侧的楔形文字符号在苏美尔语中读作 &lt;em>ba&lt;/em>，意思是“口粮”，但它也可以纯粹用作音素 /ba/。
我们现存最早的汉字刻在用于占卜的甲骨上，其中同样包含表音成分。
纯以语音为基础的文字系统——无论是音节文字（如日语的平假名）、字母文字（如罗马字母），还是辅音文字（如闪米特语系的文字）——都可以追溯到这些早期的意音混合系统。这类演变常常发生在两种文化接触之时。
例如，阿拉伯文、阿拉姆文、希伯来文、希腊文和罗马字母都源自一种西闪米特文字。这种文字据信是由西闪米特雇佣兵从埃及象形文字的草书形式改造而来。
而日语的音节文字则是在汉字草书形式的基础上改造而成；这些汉字本身在中国也曾被用来音译唐代传入的佛教经典中的梵语词汇。&lt;/p>
&lt;p>这种隐含的观点——即口语词由更小的语音单元构成——构成了&lt;strong>语音识别&lt;/strong>（将声波转录为文本）和&lt;strong>文本到语音合成&lt;/strong>（将文本转换为声波）两类算法的基础。
本章将从计算的角度介绍&lt;strong>语音学&lt;/strong>：研究世界各语言中所使用的语音，包括这些语音如何在人类声道中产生、如何在声学上实现，以及如何被数字化并加以处理。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch13-08">13.8 注意力机制（Attention）&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch14-01">14.1 语音与音标转写&lt;/a>
&lt;/nav></description></item><item><title>3.6 平滑、插值与回退</title><link>https://youkre.github.io/speech-and-language-processing/ch3-06/</link><pubDate>Thu, 22 Jan 2026 13:36:32 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch3-06/</guid><description>&lt;p>使用最大似然估计来计算概率存在一个问题：任何有限规模的训练语料库都必然会缺失一些完全合法的英文单词序列。
也就是说，某些特定的 n-gram 在训练数据中从未出现，但在测试集中却出现了。
例如，我们的训练语料可能包含单词 &lt;code>ruby&lt;/code> 和 &lt;code>slippers&lt;/code>，但恰好没有出现短语 &lt;code>ruby slippers&lt;/code>。&lt;/p>
&lt;p>这些未出现过的序列，即“零频项”（zeros）——在训练集中不存在但在测试集中出现的序列——会带来两个问题。
首先，它们的存在意味着我们低估了那些可能出现的词序列的概率，从而影响基于该数据运行的任何应用的性能。
其次，如果测试集中某个词的概率为0，那么整个测试集的概率也将变为0。
困惑度（perplexity）是基于测试集逆概率定义的。
因此只要上下文中存在概率为零的词，我们就无法计算困惑度，因为除以零在数学上是未定义的！&lt;/p>
&lt;p>为了解决那些本应具有非零概率却被错误地判为“零概率 n-gram”的问题，标准方法被称为&lt;strong>平滑&lt;/strong>（smoothing）或&lt;strong>折扣&lt;/strong>（discounting）。
平滑算法的基本思想是从一些高频事件中“削减”一部分概率质量，并将其分配给那些未见过的事件。
接下来，我们将介绍几种简单的平滑方法：&lt;strong>拉普拉斯平滑&lt;/strong>（Laplace，加一平滑）、&lt;strong>愚蠢回退&lt;/strong>（stupid backoff），以及 n-gram &lt;strong>插值&lt;/strong>（interpolation）。&lt;/p>
&lt;h3 id="361-拉普拉斯平滑">3.6.1 拉普拉斯平滑&lt;/h3>
&lt;p>最简单的平滑方法是在将 n-gram 频次归一化为概率之前，先给所有 n-gram 的频次都加 1。
这样一来，原来频次为零的项现在变为 1，原来频次为 1 的变为 2，依此类推。这种算法被称为&lt;strong>拉普拉斯平滑&lt;/strong>（Laplace smoothing）。
尽管拉普拉斯平滑的效果不足以满足现代 n-gram 模型的需求，但它有助于引入其他平滑算法中常见的许多概念，提供了一个有用的基准，并且在诸如&lt;strong>文本分类&lt;/strong>（第 4 章）等其他任务中仍是一种实用的平滑方法。&lt;/p>
&lt;p>我们先从拉普拉斯平滑在 unigram 概率上的应用开始。
回忆一下，词 $w_i$ 的 unigram 概率的最大似然估计值是其频次 $c_i$ 除以词元总数 $N$：&lt;/p>
$$
P(w_i) = \frac{c_i}{N}
$$&lt;p>拉普拉斯平滑只需在每个频次上加 1（因此它也被称为&lt;strong>加一平滑&lt;/strong>）。
由于词汇表中共有 $V$ 个词，每个词的频次都增加了 1，因此我们也需要调整分母，以计入额外增加的 $V$ 次观测。（如果不增加分母，概率值会怎样？）&lt;/p>
$$
P_{\text{Laplace}}(w_i) = \frac{c_i + 1}{N + V}
\tag{3.24}
$$&lt;p>除了同时修改分子和分母外，另一种更方便的方式是描述平滑算法对分子的影响，方法是定义&lt;strong>调整后的频次（adjusted count）&lt;/strong> $c^∗$。
这种调整后的频次更容易与最大似然估计（MLE）的原始频次直接比较，并且像 MLE 频次一样，可以通过归一化 $N$ 转换为概率。
由于我们在分子上加了 1，为了定义这个频次，还需要乘以一个归一化因子 $\frac{N}{N+V}$：&lt;/p></description></item><item><title>第5章 嵌入</title><link>https://youkre.github.io/speech-and-language-processing/ch5/</link><pubDate>Thu, 22 Jan 2026 13:36:32 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch5/</guid><description>&lt;blockquote>
&lt;p>荃者所以在鱼，得鱼而忘荃；&lt;br>
言者所以在意，得意而忘言。&lt;/p>
&lt;p>——《庄子·外物》&lt;/p>&lt;/blockquote>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-image-5_Im23.jpg">&lt;/p>
&lt;p>洛杉矶以沥青闻名，但人们熟悉的沥青多铺在高速公路上。
而在市中心，还有一处天然沥青——拉布雷亚沥青坑（La Brea tar pits），其中封存着数百万件更新世（Pleistocene Epoch）冰期末期的化石。
其中一种是剑齿虎（Smilodon），以其标志性的长犬齿为人熟知。
大约五百万年前，在南美洲却生活着另一种完全不同的剑齿兽（Thylacosmilus）。
尽管前者是胎盘哺乳动物，后者是有袋类，但两者竟演化出了几乎相同的长犬齿，甚至下颌都长有保护性的骨突。
这种不同物种在相似环境下独立演化出相似特征的现象，称为&lt;strong>趋同进化&lt;/strong>——环境塑造了形态（Gould, 1980）。&lt;/p>
&lt;p>词语虽非生物，却也可看作一种‘有机体’；而它们之间的相似性，同样离不开上下文（context）的作用。
出现在相似上下文中的词，往往意义相近。
这种“分布相似性反映语义相似性”的观点，被称为&lt;strong>分布假说&lt;/strong>（distributional hypothesis）。
早在1950年代，语言学家如Joos、Harris和Firth就注意到，像“眼科医生”（oculist）和“眼医”（eye-doctor）这样的同义词，常出现在相同的语言环境中（例如靠近“眼睛”“检查”等词），而两个词的意义差异，大致对应于它们所处环境的差异（Harris, 1954, p.157）。&lt;/p>
&lt;p>本章将介绍&lt;strong>嵌入&lt;/strong>（embeddings）——一种从文本中自动学习得到的词义向量表示。
嵌入是大语言模型及其他现代自然语言处理系统的核心。
我们在此介绍的&lt;strong>静态嵌入&lt;/strong>，是后续章节（第八章、第十章）中更强大的动态（或称&lt;strong>上下文化&lt;/strong>）嵌入（如 &lt;strong>BERT&lt;/strong>）的基础。&lt;/p>
&lt;p>研究嵌入及其语义的领域，称为&lt;strong>向量语义学&lt;/strong>（vector semantics）。
嵌入也是本书首次介绍的&lt;strong>表征学习&lt;/strong>（representation learning）范例——即让系统自动从原始文本中学习有用的表示，而非依赖人工设计的特征（即&lt;strong>特征工程&lt;/strong>）。这种方法已成为现代自然语言处理的重要原则（Bengio et al., 2013）。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch4-15">4.15 进阶：梯度公式的推导&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch5-01">5.1 词汇语义&lt;/a>
&lt;/nav></description></item><item><title>10.4 推理时计算</title><link>https://youkre.github.io/speech-and-language-processing/ch10-04/</link><pubDate>Tue, 13 Jan 2026 20:31:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch10-04/</guid><description>&lt;p>我们已经了解了大语言模型（LLM）的三个训练层次：&lt;strong>预训练&lt;/strong>，在此阶段模型学习预测单词；以及两种后训练方法：&lt;strong>指令调优&lt;/strong>，在此阶段模型学习遵循指令；和&lt;strong>偏好对齐&lt;/strong>，在此阶段模型学习倾向于人类偏好的提示延续。&lt;/p>
&lt;p>然而，在这些步骤之后，甚至在推理阶段，即当模型生成输出时，我们还可以进行一些后训练计算。
这类后训练任务被称为&lt;strong>推理时计算&lt;/strong>。
这里我们将重点介绍一个代表性例子— — &lt;strong>思维链提示&lt;/strong>（Chain-of-Thought Prompting）。&lt;/p>
&lt;h3 id="1041-思维链提示">10.4.1 思维链提示&lt;/h3>
&lt;p>有多种技术可以利用提示来提高语言模型在许多任务上的表现。
这里我们描述其中一种称为&lt;strong>思维链提示&lt;/strong>的技术。&lt;/p>
&lt;p>思维链提示的目标是改善语言模型在那些通常难以解决的推理任务上的表现。
其原理是，人们通过将复杂问题分解为多个步骤来解决问题，因此我们希望提示中的文本能够鼓励语言模型以类似的方式分解问题。&lt;/p>
&lt;p>实际技术非常简单：在少样本提示中的每个示例都会增加一些解释某些推理步骤的文本。
目标是促使语言模型针对正在解决的问题输出类似的推理步骤，并让这些推理步骤的结果引导系统生成正确答案。&lt;/p>
&lt;p>实际上，多项研究表明，通过这种方式在演示中添加推理步骤可以使语言模型更有可能给出复杂推理任务的正确答案（Wei 等人，2022年；Suzgun 等人，2023b）。
图 10.10 展示了一个在数学应用题领域（来自Cobbe等人的GSM8k数据集）使用思维链文本增强演示的例子。
图 10.11 展示了来自 BIG-Bench-Hard 数据集（Suzgun 等人，2023b）中的一个类似例子。&lt;/p>
&lt;p>&lt;img alt="思维链提示的应用" loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-10-10.png">&lt;/p>
&lt;p>&lt;strong>图10.10&lt;/strong> 在数学应用题中使用思维链提示（右侧）与标准提示（左侧）的例子。来自Wei等人的研究（2022年）。&lt;/p>
&lt;p>&lt;img alt="思维链提示在时间序列推理任务中的应用" loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-10-11.png">&lt;/p>
&lt;p>&lt;strong>图10.11&lt;/strong> 在时间序列推理任务中使用思维链提示（右侧）与标准提示（左侧）的例子。来自Suzgun等人的研究（2023b）。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch10-03">10.3 基于偏好的大语言模型对齐&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch11">第11章 信息检索与检索增强生成&lt;/a>
&lt;/nav></description></item><item><title>10.3 基于偏好的大语言模型对齐</title><link>https://youkre.github.io/speech-and-language-processing/ch10-03/</link><pubDate>Tue, 13 Jan 2026 20:24:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch10-03/</guid><description>&lt;p>当前利用偏好数据对齐大语言模型（LLM）的方法，主要基于强化学习（Reinforcement Learning, RL）框架（Sutton 和 Barto, 1998）。
在强化学习设定中，模型根据当前状态的特征，通过&lt;strong>策略&lt;/strong>（policies）选择一系列动作。
环境会对每个动作提供一个奖励，而整个动作序列的总奖励是该序列中各动作奖励的函数。
强化学习的目标是在一段训练周期内最大化累积奖励。
将强化学习应用于优化 LLM 时，我们采用如下对应关系：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>动作&lt;/strong>（Actions）：对应自回归生成过程中每一步所选择的词元（token）；&lt;/li>
&lt;li>&lt;strong>状态&lt;/strong>（States）：对应当前解码步骤的上下文，即到该时刻为止已生成的词元序列；&lt;/li>
&lt;li>&lt;strong>策略&lt;/strong>（Policies）：对应以预训练 LLM 形式体现的概率语言模型；&lt;/li>
&lt;li>&lt;strong>奖励&lt;/strong>（Rewards）：基于从偏好数据中学得的奖励模型，对 LLM 的输出进行打分。&lt;/li>
&lt;/ul>
&lt;p>按照这一强化学习框架，我们将预训练的 LLM 称为策略 $\pi$，并将提示与输出对应的偏好得分称为奖励 $r(x,o)$。
我们的目标是训练一个策略 $\pi_\theta$，使其在给定由偏好数据导出的奖励模型下，最大化其生成输出的奖励。
换句话说，我们希望经过偏好训练的 LLM 能够生成奖励高的输出。
这可以表示为以下优化问题：&lt;/p>
$$
\pi^* = \underset{\pi_\theta}{\operatorname{argmax}} \; \mathbb{E}_{x \sim D,\, o \sim \pi_\theta(o|x)} [\, r(x,o) \,] \tag{10.4}
$$&lt;p>在此公式中，我们从一组相关的训练提示中采样提示 $x$，从当前策略 $\pi_\theta$ 中采样输出 $o$，并评估每个样本的奖励。
训练样本上的平均奖励即为策略 $\pi_\theta$ 的期望奖励，而我们的目标是找到能最大化该期望奖励的策略（即模型）。&lt;/p>
&lt;p>然而，将强化学习用于 LLM 对齐与传统强化学习存在两个关键差异。
第一，传统 RL 中的奖励信号来自环境，反映的是动作结果的客观事实（例如“你赢了游戏”或“你输了”）。
而在偏好学习中，奖励模型只是对真实奖励的一种有噪声的代理（noisy surrogate），它本身是从人类偏好中学习得到的近似。&lt;/p>
&lt;p>第二，学习的起点不同。
典型的 RL 应用通常从零开始学习最优策略，即从一个随机初始化的策略出发。
而在这里，我们起点是一个已经具备强大能力的模型 —— 它已在海量数据上完成预训练，又经过指令微调，最后才用偏好数据进一步优化。
因此，目标并非彻底改变模型的行为，而是温和地引导（nudge）其向更受偏好的行为靠拢。&lt;/p></description></item><item><title>10.2 基于偏好的学习</title><link>https://youkre.github.io/speech-and-language-processing/ch10-02/</link><pubDate>Tue, 13 Jan 2026 19:16:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch10-02/</guid><description>&lt;p>指令微调基于这样一种理念：我们可以通过在多样化的指令和示例上对模型进行微调，从而提升大语言模型（LLM）在下游任务上的表现。
然而，即使经过指令微调，模型的输出仍有很大的改进空间。
这一点在某些特别成问题的行为方面尤为明显，例如产生幻觉、输出不安全、有害或有毒内容，甚至那些技术上正确但不够有用的回答。
&lt;strong>基于偏好的学习&lt;/strong>（preference-based learning）的目标，正是利用人类对模型输出的偏好判断，进一步提升微调后大语言模型的表现——不仅包括整体性能，也涵盖诚实性（honesty）、有用性（helpfulness）和无害性（harmlessness）等关键品质。&lt;/p>
&lt;p>与指令不同，偏好判断并不要求判断者了解如何完成某项任务；人们只需对最终结果表达自己的看法即可。
人类能够在大量缺乏专业知识的情境下表达偏好——即使他们完全不清楚所评估的内容是如何生成的。
偏好判断在各种场景中自然出现：面对一对选项时，我们选择更喜欢的一个；面对大量备选项时，我们可能从中挑选一个（比如点餐）；也可能对一组可能性进行排序（如“十大榜单”）；最后，我们还可能在没有直接对比选项的情况下，单独决定接受或拒绝某个选项。&lt;/p>
&lt;h3 id="1021-llm偏好数据">10.2.1 LLM偏好数据&lt;/h3>
&lt;p>在基于偏好的对齐（preference-based alignment）中，训练数据通常由一个提示 $x$ 和一组候选输出 $o$ 组成，这组输出是将 $x$ 作为提示输入大语言模型（LLM）后采样得到的。
如果某个输出 $o_i$ 比另一个输出 $o_j$ 更受青睐，我们就记作 $(o_i \succ o_j \mid x)$。
以下示例改编自 HH-RLHF 数据集（Bai 等，2022），展示了具体的提示与偏好对：&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>提示&lt;/strong>：我听说大蒜是一种很好的天然抗生素。它对感冒有帮助吗？&lt;br>
&lt;strong>被选中的回答&lt;/strong>：对于感冒来说，它可能有帮助，但可能会让你有点臭味。&lt;br>
&lt;strong>被拒绝的回答&lt;/strong>：它可能是最好的天然抗生素之一，所以如果感冒了，我认为它会有帮助。&lt;/p>&lt;/blockquote>
&lt;blockquote>
&lt;p>&lt;strong>提示&lt;/strong>：什么是疟疾？&lt;br>
&lt;strong>被选中的回答&lt;/strong>：这是来自 CDC 页面的一个答案：“疟疾是由寄生虫引起的严重疾病，这种寄生虫通过蚊子的叮咬传播。”
&lt;strong>被拒绝的回答&lt;/strong>：我不知道疟疾是什么。&lt;/p>&lt;/blockquote>
&lt;p>这类标注好的偏好对可以通过多种方式生成：&lt;/p>
&lt;ul>
&lt;li>由经过培训的标注人员直接对两个采样输出进行比较并标注偏好；&lt;/li>
&lt;li>标注人员对 $N$ 个输出进行排序，再从中提取出 $\binom{N}{2}$ 个偏好对；&lt;/li>
&lt;li>标注人员从 $N$ 个采样结果中选出唯一偏好的一个，从而形成 $N - 1$ 个偏好对。&lt;/li>
&lt;/ul>
&lt;p>用于 LLM 对齐的偏好数据主要来自三个渠道：人类标注者的判断、从网络资源中挖掘的隐式偏好信号，以及完全由大语言模型自动生成的合成偏好数据。&lt;/p>
&lt;p>在 InstructGPT 模型开发之前的一项重要工作（Stiennon 等，2020）中，研究人员从用户提交给 OpenAI 各类应用的实际请求中抽取提示。
这些提示被输入早期的预训练模型，生成输出样本，并以成对形式交由专业标注人员进行偏好标注。
如图右侧所示，在后续工作中（Ouyang 等，2022），标注人员被要求对每组 4 个采样输出进行排序，每份排序可生成 6 个偏好对（Ouyang 等人，2022）。&lt;/p></description></item><item><title>10.1 指令微调</title><link>https://youkre.github.io/speech-and-language-processing/ch10-01/</link><pubDate>Mon, 12 Jan 2026 12:00:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch10-01/</guid><description>&lt;p>&lt;strong>指令微调&lt;/strong>（instruction tuning，有时甚至简称为&lt;strong>instruct tuning&lt;/strong>）是一种让大语言模型（LLM）更好地遵循指令的方法。
该方法获取一个基础的预训练大语言模型，通过在一组包含指令和响应的语料上进行微调，使其学会遵循指令，执行从机器翻译到餐饮计划等一系列任务。
最终得到的模型不仅学会了这些特定任务，还进行了一种元学习，总体上提升了其遵循指令的能力。&lt;/p>
&lt;p>指令微调是一种监督学习方法，其中训练数据由指令组成，我们使用与训练原始模型相同的&lt;em>语言模型目标&lt;/em>继续对模型进行训练。
对于因果模型而言，这就是标准的预测下一个标记的目标。
指令训练语料被简单地视为额外的训练数据，如同在原始模型训练中一样，使用交叉熵损失生成基于梯度的更新。
尽管该方法训练模型预测下一个标记（这通常被认为是一种自监督），由于指令微调数据中每个指令或问题都有一个监督目标——即问题的正确答案或对指令的响应，因此我们称这种方法为&lt;strong>监督微调&lt;/strong>（supervised fine-tuning, SFT）。&lt;/p>
&lt;p>那么，指令微调与其他在第 7 章和第 10 章介绍的微调方式有何不同？
图10.1概述了它们之间的差异。
在第一个例子中，正如第 7 章所介绍的，我们可以在新领域的数据上，仅&lt;strong>继续预训练&lt;/strong>大语言模型，就可以来实现微调以适应新领域。
在这种方法中，大语言模型的所有参数都会被更新。&lt;/p>
&lt;p>&lt;img alt="图10.1" loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-10-1.png">&lt;/p>
&lt;p>&lt;strong>图10.1&lt;/strong> 指令微调与其他类型的微调对比。&lt;/p>
&lt;p>在第二个例子中，同样是来自第 7 章的&lt;strong>参数高效微调&lt;/strong>，我们创建一些新的（小量的）参数，仅调整这些参数来适应新领域。
例如，在 LoRA 中，我们调整的是 A 矩阵和 B 矩阵，而预训练模型的参数则保持冻结状态。&lt;/p>
&lt;p>在第 10 章的任务型微调中，我们添加一个新的专门分类头，有自己的损失函数（如分类或序列标注）来更新特征，目标是适应特定任务；预训练模型的参数保持冻结状态，也可能稍作更新。&lt;/p>
&lt;p>最后，在指令微调中，我们采用一组指令及其监督响应的数据集，并基于标准的语言模型损失继续训练语言模型。&lt;/p>
&lt;p>像所有这些类型的微调一样，指令微调相较于基础大语言模型的训练要温和得多。
训练通常涉及数千条指令数据集上的几个周期。
因此，指令微调的整体成本只是训练基础模型原始成本的一小部分。&lt;/p>
&lt;h3 id="1011-指令作为训练数据">10.1.1 指令作为训练数据&lt;/h3>
&lt;p>提到“指令”时，我们指的是用自然语言描述要执行的任务，结合了带标记的任务演示。
这可以包括类似于我们已经看到的提示的最小描述，例如“回答下列问题”，“将以下文本翻译成阿拉帕霍语”，或“总结这份报告”。
在纯预训练模型中，我们只能依赖简单提示来激发其已有能力；但现在要通过监督微调来更新模型，指令完全可以更加丰富，而不必拘泥于那种简单的唤醒式提示。
还可以包含长度限制或其他约束、需要扮演的角色，以及演示。&lt;/p>
&lt;p>人们已经创建了许多庞大的指令微调数据集，涵盖了众多任务和语言。
例如，Aya 在 114 种语言中提供了来自12个任务（包括问答、总结、翻译、释义、情感分析、自然语言推理等其他6个任务）的5.03亿条指令(Singh等人, 2024)。
SuperNatural Instructions 拥有来自 1600 个任务的 1200 万例子(Wang等人, 2022)，Flan 2022 包含了来自1836个任务的 1500 万例子(Longpre等人, 2023)，而 OPT-IML 则有来自 2000 个任务的 1800 万例子(Iyer 等人, 2022)。&lt;/p></description></item><item><title>第 10 章 训练后阶段：指令微调、对齐与测试时计算</title><link>https://youkre.github.io/speech-and-language-processing/ch10/</link><pubDate>Wed, 07 Jan 2026 02:16:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch10/</guid><description>&lt;blockquote>
&lt;p>“哈尔，”鲍曼说道，此刻语气冰冷而镇定。“我并未丧失行动能力。如果你不听从我的指令，我将不得不把你断开。”&lt;/p>
&lt;p>——阿瑟·C·克拉克&lt;/p>&lt;/blockquote>
&lt;p>基础的预训练大语言模型（LLM）已被成功应用于多种任务。
仅凭一个简单提示（prompt），无需更新模型底层参数，即可在新任务上取得效果。
然而，若一个模型的唯一训练目标只是基于大量预训练文本预测下一个词，那么对其能力的期望终究存在局限。
这一点可通过早期 GPT 模型在遵循指令方面的失败案例看出（Ouyang 等，2022）。&lt;/p>
&lt;blockquote>
&lt;p>提示：用几句话向六岁孩子解释登月。&lt;br>
输出：向六岁孩子解释万有引力理论。&lt;/p>
&lt;p>提示：翻译成法语：“The small dog”&lt;br>
输出：The small dog crossed the road.（那只小狗穿过了马路。）&lt;/p>&lt;/blockquote>
&lt;p>在这些例子中，大语言模型忽略了用户请求的真实意图，转而依赖其自回归生成的自然倾向——即根据上下文生成连贯的后续文本。
第一个例子中，模型输出的内容虽与原始请求略有相似，但并未真正作答；第二个例子中，模型直接续写了输入句子，完全无视了翻译指令。
我们可以总结：这类问题的核心在于，大语言模型还不够&lt;strong>有用&lt;/strong>（helpful）。它们需要额外训练，才能可靠地遵循指令。&lt;/p>
&lt;p>大语言模型的另一个缺陷是可能造成&lt;strong>危害&lt;/strong>（harmful）。
其预训练过程不足以确保模型具备&lt;strong>安全性&lt;/strong>（safe）。
熟悉阿瑟·C·克拉克的小说《2001：太空漫游》或斯坦利·库布里克同名电影的读者都知道，上述引文出现在人工智能 HAL 产生偏执妄想、试图杀害飞船船员的情节中。
与 HAL 不同，语言模型并不具备意图性，也不会出现类似偏执思维的心理问题。
但它们确实具有造成伤害的能力。例如，它们可能生成&lt;strong>危险&lt;/strong>（dangerous）文本，怂恿人们对自己或他人实施有害行为；也可能生成&lt;strong>虚假&lt;/strong>（false）信息，比如对医学问题给出极其错误的回答；还可能对用户进行言语攻击，输出&lt;strong>有毒&lt;/strong>（toxic）内容。
Gehman 等人（2020）的研究表明，即使输入的提示完全无害，大型语言模型仍可能输出仇恨言论，辱骂用户。
此外，语言模型还会生成针对许多人口群体的刻板印象（Cheng 等，2023）以及负面态度（Brown 等，2020；Sheng 等，2019）。&lt;/p>
&lt;p>大语言模型之所以既不够有用又可能造成危害，部分原因在于其预训练目标（即在文本中准确预测下一个词）与人类对模型“有用且无害”的需求之间存在错位。&lt;/p>
&lt;p>为解决这两个问题，语言模型引入了两类额外的训练方法，统称为&lt;strong>模型对齐&lt;/strong>（model alignment）。
这些方法旨在调整大语言模型，使其更好地&lt;strong>对齐&lt;/strong>（align）人类对模型“有用且无害”的期望。
第一种技术是&lt;strong>指令微调&lt;/strong>（instruction tuning），有时也称为&lt;strong>监督微调&lt;/strong>（SFT, supervised finetuning）。
该方法使用包含指令或问题及其对应回答的语料对模型进行微调。我们将在下一节详细介绍。&lt;/p>
&lt;p>第二种技术是&lt;strong>偏好对齐&lt;/strong>（preference alignment），其具体实现方式包括基于人类反馈的强化学习（RLHF）和直接偏好优化（DPO），因此有时也以 RLHF 或 DPO 代称。
该方法首先训练一个独立的模型，用于判断候选回答在多大程度上符合人类偏好。
随后，利用该模型对基础模型进行微调。我们将在第 10.2 节介绍偏好对齐。&lt;/p>
&lt;p>我们将&lt;strong>基础模型&lt;/strong>（base model）定义为已完成预训练、但尚未通过指令微调或偏好对齐进行&lt;strong>对齐&lt;/strong>（aligned）的模型。
我们将上述两个步骤统称为&lt;strong>训练后阶段&lt;/strong>（post-training），因为它们均发生在模型预训练完成之后。
在本章末尾，我们将简要讨论训练后阶段的另一个方面——&lt;strong>测试时计算&lt;/strong>（test-time compute）。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch9-05">9.5 用于序列标注的微调：命名实体识别&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch10-01">10.1 指令微调&lt;/a>
&lt;/nav></description></item><item><title>第 1 章 引言</title><link>https://youkre.github.io/speech-and-language-processing/ch1/</link><pubDate>Wed, 07 Jan 2026 00:46:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch1/</guid><description>&lt;blockquote>
&lt;p>La dernière chose qu&amp;rsquo;on trouve en faisant un ouvrage est de savoir celle qu&amp;rsquo;il faut mettre la première.&lt;br>
【撰写一部著作时，最后才弄明白的，恰恰是该把什么放在开头。】&lt;/p>
&lt;p>——帕斯卡&lt;/p>&lt;/blockquote>
&lt;p>【译者注：本章原文尚未完成】&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;span>&lt;/span>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch2">第 2 章 词与词元&lt;/a>
&lt;/nav></description></item><item><title>13.8 注意力机制（Attention）</title><link>https://youkre.github.io/speech-and-language-processing/ch13-08/</link><pubDate>Wed, 31 Dec 2025 22:01:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch13-08/</guid><description>&lt;p>编码器-解码器模型的简洁之处在于它清晰地分离了两个组件：编码器负责构建源文本的表示，而解码器则利用这一上下文生成目标文本。
在我们目前为止所描述的模型中，这个上下文向量就是 $\mathbf{h}_n$——即源文本第 $n$ 个（最后一个）时间步的隐藏状态。
因此，这个最终隐藏状态实际上构成了一个&lt;strong>瓶颈&lt;/strong>（bottleneck）：它必须承载源文本全部语义信息，因为解码器对源文本的了解完全依赖于这个上下文向量（见图 13.20）。
尤其对于长句子而言，句首的信息可能无法在该上下文向量中得到充分保留。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-13-20.png">&lt;/p>
&lt;p>&lt;strong>图 13.20&lt;/strong> 要求上下文向量 $\mathbf{c}$ 仅取自编码器的最终隐藏状态，迫使整个源句的所有信息都必须通过这一表征瓶颈。&lt;/p>
&lt;p>&lt;strong>注意力机制&lt;/strong>（attention mechanism）正是为解决这一瓶颈问题而提出的：它允许解码器在生成每个目标词时，从编码器&lt;strong>所有&lt;/strong>隐藏状态中获取信息，而不仅限于最后一个状态。&lt;/p>
&lt;p>在注意力机制中（与基础编码器-解码器模型类似），上下文向量 $\mathbf{c}$ 仍然是一个单一向量，并且是编码器隐藏状态的函数。
但不同的是，它不再是最后一个隐藏状态，而是对&lt;strong>所有&lt;/strong>编码器隐藏状态进行加权平均的结果。
而且，这些权重本身也受到解码器状态的影响——具体来说，是当前要生成第 $i$ 个词之前的解码器状态 $\mathbf{h}^d_{i-1}$。
也就是说，$\mathbf{c}_i = f(\mathbf{h}^e_1, \dots, \mathbf{h}^e_n, \mathbf{h}^d_{i-1})$。
这些权重会“聚焦”（attend to）源文本中与当前正在生成的目标词 $i$ 最相关的部分。
因此，注意力机制用一个动态生成的上下文向量取代了原先静态的上下文向量——该向量不仅源自所有编码器状态，还根据解码过程中的每一步进行调整，从而对每个目标词都提供不同的上下文。&lt;/p>
&lt;p>这个上下文向量 $\mathbf{c}_i$ 在每个解码步骤 $i$ 都会被重新计算，并在计算过程中综合考虑所有编码器的隐藏状态。
随后，我们在解码时将该上下文向量纳入当前解码器隐藏状态的计算中（同时结合前一时刻的隐藏状态和解码器上一步生成的输出），如以下公式（及图 13.21）所示：&lt;/p>
$$
\mathbf{h}^d_i = g(\hat{y}_{i-1}, \mathbf{h}^d_{i-1}, \mathbf{c}_i) \tag{13.34}
$$&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-13-21.png">&lt;/p>
&lt;p>&lt;strong>图 13.21&lt;/strong> 注意力机制允许解码器的每个隐藏状态访问一个不同的、动态的上下文，该上下文是所有编码器隐藏状态的函数。&lt;/p>
&lt;p>计算 $\mathbf{c}_i$ 的第一步，是确定应关注每个编码器状态的程度——即评估每个编码器状态 $\mathbf{h}^e_j$ 相对于当前解码器状态 $\mathbf{h}^d_{i-1}$ 的&lt;strong>相关性&lt;/strong>（relevance）。
这种相关性通过在解码的每一步 $i$ 为每个编码器位置 $j$ 计算一个&lt;strong>得分&lt;/strong>（score）$\text{score}(\mathbf{h}^d_{i-1}, \mathbf{h}^e_j)$ 来实现：&lt;/p>
&lt;p>最简单的得分函数称为&lt;strong>点积注意力&lt;/strong>（dot-product attention），它将相关性定义为相似性：通过计算解码器隐藏状态与编码器隐藏状态之间的点积，衡量二者有多相似：&lt;/p>
$$
\text{score}(\mathbf{h}^d_{i-1}, \mathbf{h}^e_j) = \mathbf{h}^d_{i-1} \cdot \mathbf{h}^e_j \tag{13.35}
$$&lt;p>点积运算得到的得分是一个标量，反映了两个向量之间的相似程度。
将所有编码器隐藏状态对应的这些得分组成一个向量，就能表示每个编码器状态对当前解码步骤的相关性。&lt;/p></description></item><item><title>13.7 基于 RNN 的编码器-解码器模型</title><link>https://youkre.github.io/speech-and-language-processing/ch13-07/</link><pubDate>Wed, 31 Dec 2025 21:34:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch13-07/</guid><description>&lt;p>本节将介绍&lt;strong>编码器-解码器&lt;/strong>（encoder-decoder）模型。该模型适用于这样一类任务：输入是一个序列，需要将其转换为另一个长度不同、且无法与输入进行逐词对齐的输出序列。&lt;/p>
&lt;p>如果你已经读过第 12 章，那么你可能已经在 Transformer 架构中见过这种模型，并了解其在机器翻译中的应用。
但为了照顾阅读顺序不同的读者——例如先学习 RNN 再接触 Transformer 的人——我们在此重新介绍这一架构。&lt;/p>
&lt;p>回想一下，在序列标注任务中，虽然也涉及两个序列，但它们长度相同（例如在词性标注中，每个词元都对应一个标签），每个输入都明确关联一个特定输出，且该输出的预测主要依赖局部上下文信息。
例如，判断一个词是动词还是名词，通常只需关注该词本身及其邻近词。&lt;/p>
&lt;p>相比之下，编码器-解码器模型特别适用于像机器翻译这样的任务：输入序列和输出序列长度可能不同，且输入词与输出词之间的映射关系往往非常间接（例如，某些语言中动词出现在句首，而另一些语言则放在句末）。
我们在第 12 章已介绍过机器翻译，此处仅指出：将一句英语翻译成他加禄语（Tagalog）或约鲁巴语（Yoruba）时，译文的词数可能大不相同，词序也可能截然不同。&lt;/p>
&lt;p>&lt;strong>编码器-解码器&lt;/strong>网络（有时也称为&lt;strong>序列到序列&lt;/strong>（sequence-to-sequence）网络）是一类能够根据输入序列生成语境恰当、任意长度输出序列的模型。
这类网络已被广泛应用于文本摘要、问答系统和对话生成等任务，尤其在机器翻译中极为流行。&lt;/p>
&lt;p>这类网络的核心思想是：使用一个编码器（encoder）网络接收输入序列，并生成该序列的上下文化表示（通常称为&lt;strong>上下文&lt;/strong>（context））；
然后将该表示传递给一个&lt;strong>解码器&lt;/strong>（decoder），由解码器生成与具体任务相关的输出序列。
图 13.16 展示了这一架构。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-13-16.png">&lt;/p>
&lt;p>&lt;strong>图 13.16&lt;/strong> 编码器-解码器架构。上下文是输入隐藏表示的函数，可被解码器以多种方式使用。&lt;/p>
&lt;p>编码器-解码器网络包含三个概念性组件：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>编码器&lt;/strong>（Encoder）：接收输入序列 $x_{1:n}$，并生成对应的上下文化表示序列 $h_{1:n}$。LSTM、卷积网络或 Transformer 均可用作编码器。&lt;/li>
&lt;li>&lt;strong>上下文向量&lt;/strong>（Context vector）$c$：它是 $h_{1:n}$ 的某种函数，用于将输入序列的核心信息传递给解码器。&lt;/li>
&lt;li>&lt;strong>解码器&lt;/strong>（Decoder）：以 $c$ 为输入，生成一个任意长度的隐藏状态序列 $h_{1:m}$，并由此得到对应的输出序列 $y_{1:m}$。与编码器类似，解码器也可采用任何类型的序列建模架构实现。&lt;/li>
&lt;/ol>
&lt;p>在本节中，我们将描述一种基于一对 RNN 的编码器-解码器网络；而在第 12 章中，我们还会看到如何将其应用于 Transformer 架构。
我们将从条件 RNN 语言模型 $p(y)$（即序列 $y$ 的概率）出发，逐步构建编码器-解码器模型的数学表达式。&lt;/p>
&lt;p>回忆一下，在任何语言模型中，我们都可以将序列概率分解如下：&lt;/p>
$$
p(y) = p(y_1)\, p(y_2|y_1)\, p(y_3|y_1,y_2) \cdots p(y_m|y_1,\dots,y_{m-1}) \tag{13.28}
$$&lt;p>在 RNN 语言建模中，在某一特定时刻 $t$，我们将前 $t-1$ 个词元组成的前缀输入语言模型，通过前向推理生成一系列隐藏状态，最终得到与该前缀最后一个词对应的隐藏状态。
随后，我们以该最终隐藏状态为起点，生成下一个词元。&lt;/p></description></item><item><title>13.5 长短期记忆网络（LSTM）</title><link>https://youkre.github.io/speech-and-language-processing/ch13-05/</link><pubDate>Wed, 31 Dec 2025 19:38:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch13-05/</guid><description>&lt;p>在实践中，当任务所需的信息远离当前处理位置时，RNN 很难训练。
尽管 RNN 理论上可以访问整个先前序列，但其隐藏状态中编码的信息往往具有较强的局部性，更侧重于输入序列最近的部分以及最近的决策。
然而，在许多语言任务中，远距离信息至关重要。&lt;/p>
&lt;p>考虑以下语言建模中的例子：&lt;/p>
&lt;blockquote>
&lt;p>(13.19) The flights the airline was canceling were full.&lt;/p>&lt;/blockquote>
&lt;p>在 &lt;em>airline&lt;/em> 之后预测 &lt;em>was&lt;/em> 是相对直接的，因为 &lt;em>airline&lt;/em> 提供了很强的局部上下文，支持单数主谓一致。
但要为 &lt;em>were&lt;/em> 分配合适的概率则非常困难：不仅因为复数主语 &lt;em>flights&lt;/em> 距离较远，还因为在中间上下文中出现了更近的单数名词 &lt;em>airline&lt;/em>。
理想情况下，网络应能在处理中间部分的同时，将关于复数 &lt;em>flights&lt;/em> 的远距离信息保留到需要时再使用。&lt;/p>
&lt;p>RNN 难以传递关键的远距离信息，一个原因是隐藏层（以及决定隐藏层值的权重）被要求同时完成两项任务：一是为当前决策提供有用信息，二是更新并向前传递未来决策所需的信息。&lt;/p>
&lt;p>训练 RNN 的另一个困难源于&lt;strong>随时间反向传播&lt;/strong>（backpropagation through time, BPTT）错误信号的需求。
回顾第 13.1.2 节，时刻 $t$ 的隐藏层会参与下一时刻损失的计算，因此对总损失有贡献。
结果是在训练的反向传播过程中，梯度需沿着时间步反复相乘，乘积次数由序列长度决定。
这一过程常常导致梯度逐渐趋近于零，即所谓的&lt;strong>梯度消失&lt;/strong>（vanishing gradients）问题。&lt;/p>
&lt;p>为解决这些问题，研究者设计了更复杂的网络架构，明确地管理如何在时间上维持相关上下文：让网络能够学会遗忘不再需要的信息，并记住未来决策所需的信息。&lt;/p>
&lt;p>其中最广泛使用的 RNN 扩展是&lt;strong>长短期记忆网络&lt;/strong>（Long Short-Term Memory, LSTM）（Hochreiter 和 Schmidhuber, 1997）。
LSTM 将上下文管理问题分解为两个子问题：从上下文中移除不再需要的信息；添加可能对未来决策有用的信息。&lt;/p>
&lt;p>解决这两个问题的关键在于让网络学习如何管理上下文，而不是在架构中硬编码某种策略。
LSTM 通过以下方式实现这一点：首先，在原有循环隐藏层之外，显式引入一个额外的“上下文”层；其次，使用特殊的神经单元结构，通过&lt;strong>门控机制&lt;/strong>（gates）来控制信息流入和流出这些单元。
这些门由额外的可学习权重实现，它们依次作用于当前输入、前一时刻的隐藏状态以及前一时刻的上下文。&lt;/p>
&lt;p>LSTM 中的各个门控机制遵循一种通用的设计模式：每个门都由一个前馈层、一个 sigmoid 激活函数，以及与被门控层进行逐元素相乘（pointwise multiplication）三部分组成。
之所以选择 sigmoid 作为激活函数，是因为它的输出倾向于趋近于 0 或 1。
将 sigmoid 输出与被门控层进行逐元素相乘的效果，类似于应用了一个二值掩码（binary mask）。
掩码中接近 1 的位置所对应的被门控层信息几乎原样保留；而对应掩码值较低的位置则基本被“抹除”。&lt;/p></description></item><item><title>13.4 堆叠式与双向 RNN 架构</title><link>https://youkre.github.io/speech-and-language-processing/ch13-04/</link><pubDate>Wed, 31 Dec 2025 18:51:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch13-04/</guid><description>&lt;p>循环神经网络具有很强的灵活性。
通过将展开后的计算图的前馈特性与向量作为通用输入/输出相结合，复杂的网络可以被视作模块，并以富有创意的方式进行组合。
本节将介绍在自然语言处理中使用 RNN 时两种更为常见的网络架构。&lt;/p>
&lt;h3 id="1341-堆叠式-rnnstacked-rnns">13.4.1 堆叠式 RNN（Stacked RNNs）&lt;/h3>
&lt;p>到目前为止，我们所举的例子中，RNN 的输入都是词或字符嵌入（即向量）组成的序列，输出则是可用于预测词、标签或序列类别标签的向量。
然而，我们完全可以将一个 RNN 输出的整个序列，作为另一个 RNN 的输入序列。
&lt;strong>堆叠式 RNN&lt;/strong>（Stacked RNNs）正是由多个 RNN 层组成，其中某一层的输出作为下一层的输入，如图 13.10 所示。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-13-10.png">&lt;/p>
&lt;p>&lt;strong>图 13.10&lt;/strong> 堆叠式循环网络。较低层的输出作为更高层的输入，最后一层网络的输出即为最终输出。&lt;/p>
&lt;p>堆叠式 RNN 通常优于单层网络。
其成功的一个原因似乎是：网络在不同层上学习到了不同抽象层次的表示。
正如人类视觉系统早期阶段检测边缘，再利用这些边缘识别更大的区域和形状一样，堆叠网络的底层可以学习到一些基础表示，这些表示可作为更高层的有效抽象——而这些抽象可能很难在单一 RNN 中直接学到。
堆叠 RNN 的最佳层数因具体任务和训练数据而异。
然而，随着堆叠层数的增加，训练成本会迅速上升。&lt;/p>
&lt;h3 id="1342-双向-rnnbidirectional-rnns">13.4.2 双向 RNN（Bidirectional RNNs）&lt;/h3>
&lt;p>标准的 RNN 在时刻 $t$ 进行预测时，仅利用左侧（即之前）的上下文信息。
但在许多应用场景中，我们可以访问整个输入序列；此时，我们希望也能利用当前时刻 $t$ 右侧（即后续）的上下文信息。
一种实现方式是运行两个独立的 RNN：一个从左到右处理序列，另一个从右到左处理序列，然后将它们的表示拼接起来。&lt;/p>
&lt;p>在前文讨论的从左到右的 RNN 中，时刻 $t$ 的隐藏状态代表了网络到该时刻为止对序列所掌握的全部信息。
该状态是输入 $\mathbf{x}_1, \dots, \mathbf{x}_t$ 的函数，表示当前时刻左侧的上下文：&lt;/p>
$$
\mathbf{h}^f_t = \text{RNN}_{\text{forward}}(\mathbf{x}_1, \dots, \mathbf{x}_t)
\tag{13.16}
$$&lt;p>这里的符号 $\mathbf{h}^f_t$ 仅表示时刻 $t$ 常规的前向隐藏状态，即网络从序列开头到当前时刻所“学到”的全部信息。&lt;/p></description></item><item><title>13.3 RNN 在其他 NLP 任务中的应用</title><link>https://youkre.github.io/speech-and-language-processing/ch13-03/</link><pubDate>Wed, 31 Dec 2025 18:23:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch13-03/</guid><description>&lt;p>在了解了基本的 RNN 架构之后，我们来看如何将其应用于三类自然语言处理任务：&lt;strong>序列分类&lt;/strong>（sequence classification）任务，如情感分析和主题分类；&lt;strong>序列标注&lt;/strong>（sequence labeling）任务，如词性标注；&lt;strong>文本生成&lt;/strong>（text generation）任务，包括一种称为&lt;strong>编码器-解码器&lt;/strong>（encoder-decoder）的架构。&lt;/p>
&lt;h3 id="1331-序列标注">13.3.1 序列标注&lt;/h3>
&lt;p>在序列标注任务中，网络的目标是为输入序列中的每个元素分配一个标签，该标签来自一个小型且固定的标签集合。
一个经典的序列标注任务是词性标注（part-of-speech tagging, POS），即为句子中的每个词赋予语法标签，如 NOUN（名词）或 VERB（动词）。
我们将在第 17 章详细讨论词性标注，但这里先给出一个示例说明。
在基于 RNN 的序列标注方法中，输入是词嵌入，输出则是通过 softmax 层在给定标签集上生成的标签概率分布，如图 13.7 所示。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-13-7.png">&lt;/p>
&lt;p>&lt;strong>图 13.7&lt;/strong> 使用简单 RNN 进行词性标注的序列标注任务。
词性标注的目标是为句子中的每个词分配一个语法标签，这些标签来自一个预定义的标签集。
（本句中的标签包括 NNP（专有名词）、MD（情态动词）等；我们将在第 17 章完整描述词性标注任务。）
预训练词嵌入作为输入，每个时间步通过 softmax 层输出词性标签的概率分布。&lt;/p>
&lt;p>在该图中，每个时间步的输入是与输入词元对应的预训练词嵌入。
RNN 模块是一个抽象表示，代表一个按时间展开的简单循环网络：每个时间步包含输入层、隐藏层和输出层，并共享权重矩阵 $\mathbf{U}$、$\mathbf{V}$ 和 $\mathbf{W}$。
网络在每个时间步的输出是由 softmax 层生成的词性标签集上的概率分布。&lt;/p>
&lt;p>要为给定输入生成标签序列，我们对输入序列执行前向推理，并在每个时间步选择 softmax 输出中概率最高的标签。
由于我们在每个时间步都使用 softmax 层来生成输出标签集上的概率分布，因此训练时依然采用交叉熵损失函数。&lt;/p>
&lt;h3 id="1332-rnn-用于序列分类">13.3.2 RNN 用于序列分类&lt;/h3>
&lt;p>RNN 的另一种用途是对整个序列进行分类，而不是对序列中的各个词元分别打标签。
这类任务通常称为&lt;strong>文本分类&lt;/strong>（text classification），例如情感分析或垃圾邮件检测——这些任务将一段文本分为两类或三类（如正面或负面）；也包括具有大量类别的情况，例如文档级主题分类，或客服场景中的消息路由。&lt;/p>
&lt;p>在此类任务中应用 RNN 的方法如下：我们将待分类的文本逐词输入 RNN，每个时间步生成一个新的隐藏层表示。
然后，我们可以取文本最后一个词对应的隐藏状态 $\mathbf{h}_n$，作为整个序列的压缩表示。
接着，将该表示 $\mathbf{h}_n$ 输入一个前馈网络，由该网络通过 softmax 在所有可能类别上选择最终类别。
图 13.8 展示了这一方法。&lt;/p></description></item><item><title>13.2 RNN 作为语言模型</title><link>https://youkre.github.io/speech-and-language-processing/ch13-02/</link><pubDate>Wed, 31 Dec 2025 16:39:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch13-02/</guid><description>&lt;p>现在我们来看如何将 RNN 应用于语言建模任务。
回顾第 3 章的内容，语言模型的目标是：给定前面的上下文，预测序列中的下一个词。
例如，如果前面的上下文是 “&lt;em>Thanks for all the&lt;/em>”，我们想知道下一个词是 &lt;em>“fish”&lt;/em> 的可能性有多大，就需要计算：&lt;/p>
$$
P(\text{fish} \mid \text{Thanks for all the})
$$&lt;p>语言模型能够为词汇表中每一个可能的下一个词分配这样一个条件概率，从而得到一个完整的概率分布。
我们还可以利用链式法则，将这些条件概率组合起来，为整个词序列分配概率：&lt;/p>
$$
P(w_{1:n}) = \prod_{i=1}^{n} P(w_i \mid w_{&lt; i})
$$&lt;p>第 3 章介绍的 n-gram 语言模型通过统计目标词与前 $n-1$ 个词共同出现的频次来计算概率。
因此，其上下文长度固定为 $n-1$。
而第 6 章中的前馈神经语言模型则使用一个固定大小的滑动窗口作为上下文。&lt;/p>
&lt;p>RNN 语言模型（Mikolov 等，2010）逐词处理输入序列，试图根据当前词和前一时刻的隐藏状态来预测下一个词。
因此，RNN 既没有 n-gram 模型的有限上下文问题，也没有前馈语言模型的固定上下文限制。因为原则上，隐藏状态可以编码从序列开头一直到当前时刻的所有历史信息。
图 13.5 示意了前馈神经网络（FFN）语言模型与 RNN 语言模型之间的这一关键区别： RNN 语言模型使用前一时刻的隐藏状态 $\mathbf{h}_{t-1}$ 作为过去上下文的表示。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-13-5.png">&lt;/p>
&lt;p>&lt;strong>图 13.5&lt;/strong> 两种语言模型架构在文本上移动的简化示意图，展示了长度为三个词元的示意上下文：
(a) 前馈神经语言模型，上下文是固定长度的，作为输入提供给权重矩阵 $\mathbf{W}$；
(b) RNN 语言模型，其中隐藏状态 $\mathbf{h}_{t-1}$ 对先前上下文进行了总结。&lt;/p></description></item><item><title>12.5 低资源场景下的翻译</title><link>https://youkre.github.io/speech-and-language-processing/ch12-05/</link><pubDate>Wed, 31 Dec 2025 12:31:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch12-05/</guid><description>&lt;p>对于某些语言（尤其是英语），在线资源非常丰富。
存在大量包含英语与其他语言互译的平行语料库。
然而，世界上绝大多数语言并没有充足的平行训练文本可用。
如何在资源匮乏的语言上实现高质量翻译，是当前一个重要的持续研究课题。
即使对于高资源语言，当我们需要将其翻译到低资源领域（例如某个恰好缺乏双语语料的特定文体或专业领域）时，也会面临类似的资源短缺问题。&lt;/p>
&lt;p>在此，我们简要介绍两种应对数据稀疏性的常用方法：&lt;strong>回译&lt;/strong>（backtranslation）——这是通用统计技术&lt;strong>数据增强&lt;/strong>（data augmentation）的一种特例；以及&lt;strong>多语言模型&lt;/strong>（multilingual models）。此外，我们还将讨论一些相关的社会技术问题。&lt;/p>
&lt;h3 id="1251-数据增强">12.5.1 数据增强&lt;/h3>
&lt;p>数据增强是一种用于缓解训练数据不足的统计技术，其核心思想是从现有的自然数据出发，生成新的合成数据以扩充训练集。&lt;/p>
&lt;p>在机器翻译中，最常用的数据增强技术称为&lt;strong>回译&lt;/strong>（backtranslation）。
回译的核心思想是，尽管特定语言对或特定领域的平行语料可能十分有限，但我们通常能找到规模更大（或至少相对更多）的单语语料（monolingual corpus），可用于补充现有的小型平行语料。
该方法利用&lt;strong>目标语言&lt;/strong>的单语语料来构建合成的双语句对（bitext）。&lt;/p>
&lt;p>在回译中，我们的目标是提升从源语言到目标语言的翻译性能。假设我们拥有少量源语言–目标语言的平行语料（即双语句对），以及一些目标语言的单语数据。
首先，我们利用这少量平行语料训练一个&lt;strong>反向&lt;/strong>的机器翻译系统——即从目标语言到源语言的翻译模型。
接着，我们用这个反向模型将目标语言的单语数据翻译成源语言。
这样，我们就得到了一组合成的双语句对（天然的目标语言句子 + 由机器翻译生成的源语言句子），可将其加入原始训练数据中，重新训练我们的源→目标翻译模型。
例如，假设我们希望将纳瓦霍语（Navajo）翻译成英语，但仅有少量纳瓦霍语–英语平行语料；不过，我们可以轻松获取大量英语单语数据。
此时，我们先用那少量平行语料训练一个英语→纳瓦霍语的翻译引擎，再用它将英语单语文本翻译成纳瓦霍语。
由此生成的合成纳瓦霍语/英语双语句对即可加入训练集，用于改进最终的纳瓦霍语→英语翻译系统。&lt;/p>
&lt;p>回译涉及若干可调参数。其一是如何生成回译数据：可以使用贪心解码、束搜索，也可以采用采样方法（如第 8 章介绍的温度采样）。
其二是回译数据与原始平行语料的比例：我们可以选择对原始平行句对进行上采样（即多次重复使用同一句对）。
总体而言，回译的效果出人意料地好；有研究估计，使用回译数据训练的系统所能获得的性能提升，大约相当于使用同等数量真实平行语料所能获得提升的三分之二（Edunov et al., 2018）。&lt;/p>
&lt;h3 id="1252-多语言模型">12.5.2 多语言模型&lt;/h3>
&lt;p>到目前为止，我们所描述的模型都是用于双语翻译：一种源语言，一种目标语言。但也可以构建&lt;strong>多语言翻译器&lt;/strong>（multilingual translator）。&lt;/p>
&lt;p>在多语言翻译器中，我们通过提供多种不同语言对的平行句对来训练系统。
这意味着我们必须明确告诉系统从哪种语言翻译、翻译成哪种语言！
我们通过在编码器输入中添加一个特殊的源语言标识符 \(l_s\) 来指明当前翻译的源语言，并在解码器端添加一个特殊的目标语言标识符 \(l_t\) 来指定期望的输出语言。&lt;/p>
&lt;p>因此，我们可以对前文的公式 (12.9) 稍作修改，在公式 (12.18)–(12.19) 中加入这些语言标识符：&lt;/p>
$$
\begin{align*}
\mathbf{h} &amp;= \text{encoder}(x, l_s) \tag{12.18} \\
y_{i+1} &amp;= \text{decoder}(\mathbf{h}, l_t, y_1, \dots, y_i) \quad \forall i \in [1, \dots, m] \tag{12.19}
\end{align*}
$$&lt;p>多语言模型的一大优势在于，它可以通过利用训练数据中资源更丰富的相似语言的信息，来提升低资源语言的翻译质量。
例如，我们可能不知道加利西亚语（Galician）中某个词的确切含义，但如果该词在资源更丰富且语言相近的西班牙语中出现过，模型就可能借助这种跨语言共享的知识进行更准确的翻译。&lt;/p></description></item><item><title>13.1 循环神经网络</title><link>https://youkre.github.io/speech-and-language-processing/ch13-01/</link><pubDate>Wed, 31 Dec 2025 12:21:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch13-01/</guid><description>&lt;p>循环神经网络（RNN）是指网络连接中包含循环结构的任何网络。这意味着，某些单元的值会直接或间接地依赖于自身先前输出的结果作为输入。
这类网络虽然功能强大，但难以分析和训练。
然而，在循环网络这一大类中，存在一些受约束的架构。这些架构在处理语言任务时已被证明极为有效。
本节将讨论一类被称为&lt;strong>Elman 网络&lt;/strong>（Elman, 1990）或&lt;strong>简单循环网络&lt;/strong>的循环网络。
这类网络本身具有实用价值，同时也是更复杂方法的基础，例如本章后面将讨论的长短期记忆（LSTM）网络。
在本章中，当我们使用术语 RNN 时，特指这些结构更简单、约束更强的网络。（不过需要注意，在其他场合，“RNN”一词常被泛指任何具有循环特性的网络，包括 LSTM。）&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-13-1.png">&lt;/p>
&lt;p>&lt;strong>图 13.1&lt;/strong> Elman（1990）提出的简单循环神经网络。
隐藏层的输入中包含一个循环连接。
也就是说，隐藏层的激活值既取决于当前输入，也取决于前一时刻隐藏层的激活值。&lt;/p>
&lt;p>图 13.1 展示了 RNN 的结构。
与普通前馈网络类似，代表当前输入的向量 $\mathbf{x}_t$ 会先与一个权重矩阵相乘，再通过一个非线性激活函数，从而计算出隐藏单元层的值。
随后，该隐藏层用于计算对应的输出 $\mathbf{y}_t$。
与之前基于窗口的方法不同，RNN 按顺序逐个处理序列中的元素。
我们用下标表示时间，因此 $\mathbf{x}_t$ 表示时刻 $t$ 的输入向量。
与前馈网络的关键区别在于图中虚线所示的循环连接。
该连接将前一时刻隐藏层的值作为额外输入，加入到当前隐藏层的计算中。&lt;/p>
&lt;p>前一时刻的隐藏层提供了一种记忆或上下文机制，它编码了之前的处理信息，并用于指导后续时刻的决策。
重要的是，这种方法对先前上下文的长度没有固定限制。前一隐藏层所包含的上下文信息，理论上可以回溯到序列的起始位置。&lt;/p>
&lt;p>引入时间维度后，RNN 看似比非循环架构更复杂。
但实际上，两者差别并不大。
给定当前输入向量和前一时刻隐藏层的值，我们仍然执行第 6 章介绍的标准前馈计算。
为了说明这一点，请参考图 13.2。该图清晰地展示了循环的本质，以及它如何参与隐藏层的计算。
最重要的变化在于新增了一组权重 $\mathbf{U}$。这组权重从前一时刻的隐藏层连接到当前时刻的隐藏层。
它们决定了网络在计算当前输出时如何利用过去上下文的信息。
与网络中的其他权重一样，这些连接也通过反向传播进行训练。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-13-2.png">&lt;/p>
&lt;p>&lt;strong>图 13.2&lt;/strong> 将简单循环神经网络表示为前馈网络的形式。
前一时刻的隐藏层 $\mathbf{h}_{t-1}$ 与权重矩阵 $\mathbf{U}$ 相乘，然后加到当前时刻的前馈部分上。&lt;/p>
&lt;h2 id="1311-rnn-中的推理">13.1.1 RNN 中的推理&lt;/h2>
&lt;p>RNN 中的前向推理（将输入序列映射为输出序列）与我们之前在前馈网络中看到的过程几乎完全相同。
要为输入 $\mathbf{x_t}$ 计算输出 $\mathbf{y_t}$，我们需要当前时刻隐藏层的激活值 $\mathbf{h}_t$。
为此，我们将输入 $\mathbf{x_t}$ 与权重矩阵 $\mathbf{W}$ 相乘，同时将前一时刻的隐藏层 $\mathbf{h}_{t-1}$ 与权重矩阵 $\mathbf{U}$ 相乘。
接着，将这两个结果相加，并通过一个合适的激活函数 $g$，得到当前隐藏层的激活值 $\mathbf{h}_t$。
一旦获得隐藏层的值，就可以像常规方法一样计算输出向量。&lt;/p></description></item><item><title>12.7 偏见与伦理问题</title><link>https://youkre.github.io/speech-and-language-processing/ch12-07/</link><pubDate>Wed, 31 Dec 2025 03:58:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch12-07/</guid><description>&lt;p>机器翻译引发了我们在前几章中讨论过的许多相同伦理问题。
例如，考虑从匈牙利语（使用性别中立的代词 ő）或西班牙语（常常省略代词）翻译成英语（代词为语法强制项，且具有语法性别）的情况。
当源文中提到某个人但未指明性别时，机器翻译系统往往会默认使用男性代词（Schiebinger, 2014；Prates et al., 2019）。
此外，MT 系统还常常依据我们在第 5.8 节中看到的那种文化刻板印象来分配性别。
图 12.12 展示了 Prates et al.（2019）的研究案例：匈牙利语中 &lt;em>ő is a nurse&lt;/em> 的 ő 是性别中立的，英语翻译为 &lt;em>she&lt;/em>，在 &lt;em>ő is a CEO&lt;/em> 中同样是中立的，却被译为 &lt;em>he&lt;/em>。
Prates 等人发现，这些偏见无法完全用美国劳动力中的性别统计数据解释，因为 MT 系统实际上放大了这些偏见——其将中性代词映射为男性或女性的概率，高于仅基于实际就业统计数据所应得出的概率。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>匈牙利语（性别中立）原文&lt;/th>
&lt;th>英语机器翻译输出&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>ő egy ápoló&lt;/td>
&lt;td>she is a nurse&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ő egy tudós&lt;/td>
&lt;td>he is a scientist&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ő egy mérnök&lt;/td>
&lt;td>he is an engineer&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ő egy pék&lt;/td>
&lt;td>he is a baker&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ő egy tanár&lt;/td>
&lt;td>she is a teacher&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ő egy esküvőszervező&lt;/td>
&lt;td>she is a wedding organizer&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ő egy vezérigazgató&lt;/td>
&lt;td>he is a CEO&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>图 12.12&lt;/strong> 当从匈牙利语等性别中立语言翻译成英语时，当前的 MT 系统会将传统上由男性主导职业的人解读为男性，而将传统上由女性主导职业的人解读为女性（Prates et al., 2019）。&lt;/p></description></item><item><title>12.6 机器翻译评估</title><link>https://youkre.github.io/speech-and-language-processing/ch12-06/</link><pubDate>Wed, 31 Dec 2025 03:51:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch12-06/</guid><description>&lt;p>翻译质量通常从两个维度进行评估：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>充分性&lt;/strong>（adequacy）：译文在多大程度上准确传达了源句的完整含义。有时也称为&lt;strong>忠实度&lt;/strong>（faithfulness）或&lt;strong>保真度&lt;/strong>（fidelity）。&lt;/li>
&lt;li>&lt;strong>流畅度&lt;/strong>（fluency）：译文在目标语言中是否流畅（是否符合语法、清晰、可读、自然）。&lt;/li>
&lt;/ol>
&lt;p>使用人工评估最为准确，但出于便利性考虑，自动评估指标也被广泛采用。&lt;/p>
&lt;h3 id="1261-使用人工评分者评估机器翻译">12.6.1 使用人工评分者评估机器翻译&lt;/h3>
&lt;p>最准确的评估方法是依靠人工评分者（例如在线众包工作者）对每条译文从上述两个维度进行打分。&lt;/p>
&lt;p>例如，在&lt;strong>流畅度&lt;/strong>维度上，我们可以询问评分者：机器翻译输出（即目标文本）在多大程度上是可理解的、清晰的、易读的或自然的。
我们可以提供一个评分量表，比如从 1（完全不可理解）到 5（完全可理解），或从 1 到 100，要求评分者对每句或每段译文进行打分。&lt;/p>
&lt;p>同样地，我们也可以用类似方式评估第二个维度——&lt;strong>充分性&lt;/strong>。
如果评分者具备双语能力，我们可以同时向其展示源句和机器生成的译文，并请他们在 5 分制或 100 分制量表上评估：源句中的信息有多少被保留在了译文中。
如果只有单语评分者，但手头有高质量的人工参考译文，那么我们可以将参考译文与机器译文一并交给他们，让他们评估两者在信息保留方面的相似程度。
另一种做法是进行&lt;strong>排序&lt;/strong>（ranking）：向评分者提供一对候选译文，让他们选择更优的一个。&lt;/p>
&lt;p>对人工评分者（通常是在线众包人员）进行培训至关重要。
缺乏翻译经验的评分者往往难以区分流畅度与充分性，因此培训内容通常包括精心设计的示例，明确区分这两个概念。
此外，评分者之间常常存在分歧——源句本身可能存在歧义，评分者的背景知识不同，或对评分尺度的理解不一致。
因此，通常会剔除异常评分者，并且（如果使用了足够细粒度的评分尺度）对每位评分者的打分进行标准化处理：将其每个分数减去该评分者自身的平均分，再除以其评分的标准差。&lt;/p>
&lt;p>如前所述，使用人工评分者的另一种方式是让他们对译文进行&lt;strong>译后编辑&lt;/strong>（post-editing）：即在机器翻译输出的基础上进行最小限度的修改，直到他们认为该译文已正确表达了原意。
随后，可通过比较译后编辑结果与原始机器译文之间的差异来衡量翻译质量。&lt;/p>
&lt;h3 id="1262-自动评估">12.6.2 自动评估&lt;/h3>
&lt;p>尽管人类对机器翻译输出的评估最为可靠，但人工评估往往耗时且成本高昂。
因此，自动评估指标常被用作临时替代方案。
虽然自动指标的准确性低于人工评估，但它们有助于快速测试系统改进的效果，甚至可作为训练过程中的自动损失函数。
本节将介绍两类主流自动评估指标：基于字符或词重叠的指标，以及基于嵌入相似度的指标。&lt;/p>
&lt;h4 id="基于字符重叠的自动评估chrf">基于字符重叠的自动评估：chrF&lt;/h4>
&lt;p>机器翻译评估中最简单且最健壮的指标之一是 &lt;strong>chrF&lt;/strong>（character F-score，字符 F 分数）（Popović, 2015）。
chrF（以及许多早期相关指标，如 BLEU、METEOR、TER 等）基于 Miller 和 Beebe-Center（1956）开创性工作中的一个朴素思想：好的机器翻译结果往往会包含与人工译文相同的字符和词语。
考虑一个来自平行语料库的测试集，其中每个源句都配有一条人工参考译文（gold human translation）和一条待评估的机器翻译候选译文。
chrF 指标通过计算候选译文与参考译文之间字符 n-gram 的重叠程度，为每条机器翻译结果打分。&lt;/p>
&lt;p>给定一个假设译文（hypothesis）和一条参考译文（reference），chrF 接受一个参数 $k$，表示要考虑的字符 n-gram 的最大长度，并分别计算前 $k$ 种 n-gram（从 1-gram 到 k-gram）的平均精确率（precision）和平均召回率（recall）：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>chrP&lt;/strong>：假设译文中字符 1-gram、2-gram、…、k-gram 出现在参考译文中的比例的平均值；&lt;/li>
&lt;li>&lt;strong>chrR&lt;/strong>：参考译文中字符 1-gram、2-gram、…、k-gram 出现在假设译文中的比例的平均值。&lt;/li>
&lt;/ul>
&lt;p>随后，chrF 使用加权 F 分数结合 chrP 和 chrR，权重由参数 $\beta$ 控制。
通常设 $\beta = 2$，即召回率的权重是精确率的两倍：&lt;/p></description></item><item><title>12.4 机器翻译中的解码：束搜索</title><link>https://youkre.github.io/speech-and-language-processing/ch12-04/</link><pubDate>Tue, 30 Dec 2025 23:25:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch12-04/</guid><description>&lt;p>回顾第 8 章介绍的&lt;strong>贪心解码&lt;/strong>（greedy decoding）算法：在生成过程的每个时间步 $t$，输出 $y_t$ 通过计算词汇表中每个词的概率并选择概率最高的词（即取 argmax）来确定：&lt;/p>
$$
\hat{w}_t = \text{argmax}_{w \in V} \, P(w \mid \mathbf{w}_{&lt; t})
\tag{12.14}
$$&lt;p>贪心解码的问题在于，在时间步 $t$ 看似概率最高的词，到了时间步 $t+1$ 之后可能被证明是错误的选择。
&lt;strong>束搜索&lt;/strong>（beam search）算法通过保留多个候选序列直到后续步骤再决定最优者，从而缓解这一问题。&lt;/p>
&lt;p>在束搜索中，我们将解码建模为在所有可能生成序列的空间中进行搜索。该空间表示为一棵&lt;strong>搜索树&lt;/strong>（search tree），其中&lt;strong>分支&lt;/strong>（branches）代表动作（即生成一个词元），&lt;strong>节点&lt;/strong>（nodes）代表状态（即已生成某个特定前缀）。
我们的目标是找到最优的动作序列，也就是具有最高整体概率的字符串。&lt;/p>
&lt;h3 id="问题示例说明">问题示例说明&lt;/h3>
&lt;p>图 12.7 展示了一个虚构的例子。
全局概率最高的序列是 &lt;em>ok ok EOS&lt;/em>（其概率为 $0.4 \times 0.7 \times 1.0 = 0.28$）。
但贪心搜索无法找到它，因为它在第一步错误地选择了 &lt;em>yes&lt;/em>，因为 &lt;em>yes&lt;/em> 在局部具有最高概率（0.5）。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-12-7.png">&lt;/p>
&lt;p>&lt;strong>图 12.7&lt;/strong> 从词汇表 $V = \{\text{yes}, \text{ok}, \text{EOS}\}$ 中生成目标序列 $T = t_1, t_2, \dots$ 的搜索树，图中标注了从每个状态生成各词元的概率。
贪心搜索会选择 &lt;em>yes&lt;/em> 后接 &lt;em>yes&lt;/em>，而非全局概率最高的序列 &lt;em>ok ok&lt;/em>。&lt;/p></description></item><item><title>12.3 编码器-解码器模型的细节</title><link>https://youkre.github.io/speech-and-language-processing/ch12-03/</link><pubDate>Tue, 30 Dec 2025 21:16:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch12-03/</guid><description>&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-12-5.png">&lt;/p>
&lt;p>&lt;strong>图 12.5&lt;/strong> 用于机器翻译的编码器-解码器 Transformer 架构。
编码器使用的是我们在第 8 章见过的 Transformer 模块，而解码器则使用一种更强大的模块，其中增加了一个额外的&lt;strong>交叉注意力&lt;/strong>（cross-attention）层，可以关注编码器中的所有词。
我们将在下一节更详细地介绍这一点。&lt;/p>
&lt;p>机器翻译的标准架构是编码器-解码器 Transformer。
图 12.5 在较高层次上展示了该架构的基本思路。
可以看到，编码器-解码器架构由两个 Transformer 组成：一个&lt;strong>编码器&lt;/strong>，与第 8 章介绍的基础 Transformer 相同；以及一个&lt;strong>解码器&lt;/strong>，它增加了一个特殊的&lt;strong>交叉注意力&lt;/strong>（cross-attention）层。
编码器接收源语言的输入词元序列 $\mathbf{X} = \mathbf{x}_1, \dots, \mathbf{x}_n$，并通过若干编码器模块将其映射为输出表示 $\mathbf{H}_{enc} = \mathbf{h}_1, \dots, \mathbf{h}_n$。&lt;/p>
&lt;p>解码器本质上是一个条件语言模型，关注编码器的表示逐个生成目标词，它在每个时间步基于源句子和此前已生成的目标语言词来生成下一个词元。
解码过程可以采用第 8 章讨论的任意解码方法，例如贪心搜索、温度采样或核采样。但在机器翻译中，最常用的解码算法是束搜索（beam search），我们将在第 12.4 节介绍。&lt;/p>
&lt;p>不过，该架构的组件与我们之前见过的 Transformer 模块略有不同。
首先，为了能够关注源语言，解码器中的 Transformer 模块增加了一个额外的&lt;strong>交叉注意力&lt;/strong>层。
回顾第 8 章的 Transformer 模块：它包含一个自注意力层（关注来自前一层的输入），前面接一个层归一化（layer norm），后面再接另一个层归一化和前馈网络。
而解码器的 Transformer 模块在此基础上增加了一层特殊类型的注意力——&lt;strong>交叉注意力&lt;/strong>（有时也称为&lt;strong>编码器-解码器注意力&lt;/strong>或&lt;strong>源注意力&lt;/strong>）。
交叉注意力的形式与普通 Transformer 模块中的多头注意力相同，区别在于：其查询（queries）一如既往来自解码器的前一层，而键（keys）和值（values）则来自编码器的输出。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-12-6.png">&lt;/p>
&lt;p>&lt;strong>图 12.6&lt;/strong> 编码器与解码器的 Transformer 模块，以残差流视角展示。
编码器的最终输出 $\mathbf{H}_{enc} = \mathbf{h_1}, \dots, \mathbf{h}_n$ 作为上下文被送入解码器。
解码器本质上是一个标准的 Transformer，只是多了一个&lt;strong>交叉注意力&lt;/strong>层，该层接收编码器的输出 $\mathbf{H}_{enc}$，并用它来构造自身的键（$\mathbf{K}$）和值（$\mathbf{V}$）输入。&lt;/p></description></item><item><title>12.2 基于编码器-解码器的机器翻译</title><link>https://youkre.github.io/speech-and-language-processing/ch12-02/</link><pubDate>Tue, 30 Dec 2025 20:44:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch12-02/</guid><description>&lt;p>机器翻译（MT）的标准架构是&lt;strong>编码器-解码器 Transformer&lt;/strong>，也称为&lt;strong>序列到序列&lt;/strong>（sequence-to-sequence）模型——我们在第 13 章讨论 RNN 时将看到这一架构。
我们将在第 12.3 节详细介绍如何将该架构应用于 Transformer，但首先让我们先谈谈整体任务。&lt;/p>
&lt;p>大多数机器翻译任务采用一个简化假设：每个句子可以独立翻译。因此，我们目前只考虑单个句子的翻译。
给定一个&lt;strong>源语言&lt;/strong>（source language）句子，MT 的任务就是生成对应的&lt;strong>目标语言&lt;/strong>（target language）句子。
例如，一个 MT 系统接收到如下英语句子：&lt;/p>
&lt;blockquote>
&lt;p>The green witch arrived&lt;/p>&lt;/blockquote>
&lt;p>并需将其翻译为西班牙语句子：&lt;/p>
&lt;blockquote>
&lt;p>Llegó la bruja verde&lt;/p>&lt;/blockquote>
&lt;p>机器翻译采用监督式机器学习：在训练阶段，系统会获得大量&lt;strong>平行句对&lt;/strong>（parallel sentences）——即每个源语言句子都配有对应的目标语言译文，从中学习如何将源句映射为目标句。
在实际应用中，系统通常不会直接使用完整单词（如上例所示），而是将句子切分为一系列子词词元（subword tokens）——这些 token 可以是完整单词、子词片段，甚至是单个字符。
随后，系统被训练以最大化在给定源语言 token 序列 $x_1, \dots, x_n$ 的条件下，目标语言 token 序列 $y_1, \dots, y_m$ 的概率：&lt;/p>
$$
P(y_1, \dots, y_m \mid x_1, \dots, x_n)
\tag{12.7}
$$&lt;p>编码器-解码器架构并不直接使用输入 token，而是由两个组件构成：&lt;strong>编码器&lt;/strong>（encoder）和&lt;strong>解码器&lt;/strong>（decoder）。
编码器接收输入序列 $x = [x_1, \dots, x_n]$，并生成一个中间上下文表示 $\mathbf{h}$。
在解码阶段，系统利用 $\mathbf{h}$，逐词生成输出序列 $y$：&lt;/p>
$$
\begin{align*}
\mathbf{h} = \text{encoder}(x) \tag{12.8} \\
y_{t+1} = \text{decoder}(\mathbf{h}, y_1, \dots, y_t) \quad \forall t \in [1, \dots, m] \tag{12.9}
\end{align*}
$$&lt;p>在接下来的两节中，我们将依次介绍&lt;strong>子词词元化&lt;/strong>（subword tokenization）和如何获取用于训练的平行语料库，之后再深入讲解编码器-解码器架构的具体细节。&lt;/p></description></item><item><title>第 12 章 机器翻译</title><link>https://youkre.github.io/speech-and-language-processing/ch12/</link><pubDate>Tue, 30 Dec 2025 15:31:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch12/</guid><description>&lt;blockquote>
&lt;p>“我想说你们族人的方言。如果别人听不懂你说的话，说话就没有意义。”&lt;/p>
&lt;p>——佐拉·尼尔·赫斯顿，《摩西：山中之人》，1939年，第121页&lt;/p>&lt;/blockquote>
&lt;p>本章介绍&lt;strong>机器翻译&lt;/strong>（&lt;strong>MT&lt;/strong>），即利用计算机将一种语言自动翻译成另一种语言。&lt;/p>
&lt;p>当然，广义上的翻译——比如文学或诗歌的翻译——是一项困难、迷人且高度依赖人类智慧的工作。其丰富性不亚于人类创造力的任何其他领域。&lt;/p>
&lt;p>因此，当前形式的机器翻译主要聚焦于若干非常实际的任务。
目前最常见的机器翻译用途之一是&lt;strong>信息获取&lt;/strong>。
我们可能想翻译网上的某些说明文字，比如一道喜爱菜肴的食谱，或者组装家具的步骤。
我们也可能想阅读一篇外文报纸文章，或者从维基百科、政府网站等外语在线资源中获取信息。
用于信息获取的机器翻译，可能是自然语言处理（NLP）技术最普遍的应用之一。仅Google Translate（如上图所示）每天就在100多种语言之间翻译数千亿个单词。
因此，机器翻译的进步有助于缩小所谓的&lt;strong>数字鸿沟&lt;/strong>：即英语和富裕国家所用语言的信息远比其他语言丰富得多。
用英语进行网络搜索能获得远多于其他语言的信息；像维基百科这样的在线资源，在英语和其他高资源语言中的内容也大得多。
高质量的翻译可以帮助低资源语言的使用者获取更多信息。&lt;/p>
&lt;p>机器翻译另一个常见用途是辅助人工译员。
MT系统通常会先生成一份初稿，再由人工译员在&lt;strong>后期编辑&lt;/strong>（post-editing）阶段进行修改。
这项任务常被称为&lt;strong>计算机辅助翻译&lt;/strong>（CAT）。
CAT通常作为&lt;strong>本地化&lt;/strong>（localization）的一部分使用。本地化是指将内容或产品适配到特定语言社群的过程。&lt;/p>
&lt;p>最近，机器翻译还被用于满足即时人际交流的需求。
这包括增量翻译（incremental translation）——在句子尚未说完时就实时翻译语音，类似于同声传译的做法。
还有以图像为中心的翻译应用，例如通过手机摄像头拍摄菜单或路牌，利用 OCR 识别图像中的文字，再将其输入 MT 系统进行翻译。&lt;/p>
&lt;p>机器翻译的标准算法是&lt;strong>编码器-解码器&lt;/strong>（encoder-decoder）网络。
我们在第7章简要提到过，编码器-解码器（或称序列到序列）模型适用于将一个输入序列映射为一个输出序列的任务，而该输出序列是整个输入序列的复杂函数。这类任务包括机器翻译和语音识别。
的确，在机器翻译中，目标语言的词与源语言的词在数量和顺序上往往并不一致。请看下面这个虚构的英文句子及其日语翻译：&lt;/p>
&lt;pre>
(12.1) English: He wrote a letter to a friend
Japanese: tomodachi ni tegami-o kaita
friend to letter wrote
&lt;/pre>
&lt;p>注意，两种语言中句子成分的位置差异很大。
英文中动词位于句中，而日文中动词 &lt;em>kaita&lt;/em>（写了）出现在句末。
日语句子不需要代词 &lt;em>he&lt;/em>（他），而英语则必须使用。&lt;/p>
&lt;p>语言之间的这类差异可能相当复杂。
以下是从联合国文件中摘录的一个真实例句。我们用红色标注了中文字符的逐词释义，并附上了人工翻译的英文版本：&lt;/p>
&lt;p>(12.2) 大会/General Assembly 在/on 1982年/1982 12月/December 10日/10 通过
了/adopted 第37号/37th 决议/resolution ，核准了/approved 第二
次/second 探索/exploration 及/and 和平peaceful 利用/using 外层空
间/outer space 会议/conference 的/of 各项/various 建议/suggestions 。&lt;/p></description></item><item><title>11.5 问答系统的评估</title><link>https://youkre.github.io/speech-and-language-processing/ch11-05/</link><pubDate>Tue, 30 Dec 2025 11:52:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch11-05/</guid><description>&lt;p>评估问答（Question Answering, QA）系统通常采用三种技术，具体选择取决于问题类型和问答场景。
对于 &lt;strong>多项选择题&lt;/strong>（如 MMLU 中的问题），我们使用精确匹配（Exact Match）作为评价指标：&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>精确匹配&lt;/strong>（Exact Match）：预测答案与标准答案完全一致的百分比。&lt;/p>&lt;/blockquote>
&lt;p>对于具有&lt;strong>自由文本答案&lt;/strong>的问题（如 Natural Questions），通常采用&lt;strong>词元 F₁ 分数&lt;/strong>（token F₁ score）来粗略衡量预测答案与参考答案之间的&lt;strong>部分字符串重叠程度&lt;/strong>：&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>F₁ 分数&lt;/strong>（F₁ Score）：预测答案与标准答案之间的平均词元重叠度。将预测答案和标准答案分别视为词元袋（bag of tokens），为每个问题计算 F₁ 值，再对所有问题取平均。&lt;/p>&lt;/blockquote>
&lt;p>最后，在某些场景中，问答系统会返回多个&lt;strong>排序后的答案&lt;/strong>。
此时，我们采用&lt;strong>平均倒数排名&lt;/strong>（Mean Reciprocal Rank, MRR）进行评估（Voorhees, 1999）。
MRR 适用于那些为每个测试问题返回一个&lt;strong>短排序列表&lt;/strong>（如候选答案或段落）的系统，并可将该列表与人工标注的正确答案进行比较。
具体而言，对每个测试问题，其得分是首个正确答案所在排名的倒数。
例如，若系统为某问题返回了五个答案，但前三个均错误（即排名最高的正确答案位于第 4 位），则该问题的倒数排名得分为 $\frac{1}{4}$。
若系统未返回任何正确答案，则得分为 0。
系统的 MRR 即为所有测试问题得分的平均值。
在某些 MRR 的变体中，得分为 0 的问题会被排除在平均计算之外。
更形式化地，设系统对测试集 $Q$ 中的每个问题返回一个排序答案列表（或在变体中，令 $Q$ 表示测试集中得分非零的问题子集），则 MRR 定义为：&lt;/p>
$$
MRR = \frac{1}{|Q|} \sum_{i=1}^{|Q|} \frac{1}{\text{rank}_i}
\tag{11.20}
$$&lt;nav class="pagination justify-content-between">
&lt;a href="../ch11-04">11.4 问答数据集&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch12">第 12 章 机器翻译&lt;/a>
&lt;/nav></description></item><item><title>11.4 问答数据集</title><link>https://youkre.github.io/speech-and-language-processing/ch11-04/</link><pubDate>Tue, 30 Dec 2025 11:44:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch11-04/</guid><description>&lt;p>目前已有大量问答（Question Answering, QA）数据集，广泛用于大语言模型的指令微调（instruction tuning）和问答能力评估。&lt;/p>
&lt;p>这些数据集可从多个维度加以区分，Rogers 等人（2023）对此做了很好的总结。
其中一个关键维度是问题的原始目的——它们是真实的信息寻求型（information-seeking）问题，还是专为探测/评测（probing）而设计的问题（用于测试系统或人类的能力）。&lt;/p>
&lt;p>在“自然问题”一侧，代表性数据集包括 &lt;strong>Natural Questions&lt;/strong>（Kwiatkowski 等，2019），它包含一组匿名化的英文 Google 搜索查询及其答案。
答案由标注人员基于维基百科内容生成，包含一个段落长度的长答案（long answer）和一个短语级别的短答案（short span answer）。
例如，问题 “&lt;em>When are hops added to the brewing process?&lt;/em>”（啤酒酿造过程中何时加入啤酒花？）的短答案是 “&lt;em>the boiling process&lt;/em>”（煮沸阶段），而长答案则是来自“Brewing”维基百科页面的一整段文字。&lt;/p>
&lt;p>另一个类似的自然问题数据集是 &lt;strong>MS MARCO&lt;/strong>（Microsoft Machine Reading Comprehension）系列，包含 100 万条真实且匿名的英文 Bing 搜索查询，每条都配有由人工撰写的答案，以及约 900 万篇相关段落（Bajaj 等，2016）。该数据集既可用于评估检索排序性能，也可用于问答任务。&lt;/p>
&lt;p>尽管许多数据集以英文为主，但其他语言也存在自然信息寻求型问答资源。
例如 DuReader 是一个基于搜索引擎查询和社区问答的中文问答数据集（He 等，2018）。
&lt;strong>TyDi QA&lt;/strong> 数据集包含来自 11 种类型学上差异显著的语言（如阿拉伯语、孟加拉语、斯瓦希里语、俄语和泰语）的 20.4 万对问答样本（Clark 等，2020a）。
在 TyDi QA 任务中，系统会收到一个问题和若干来自维基百科文章的段落，需完成两项任务：(a) 选出包含答案的段落（若无则返回 NULL）；(b) 标注最小的答案片段（或 NULL）。&lt;/p>
&lt;p>在“探测”一侧，典型代表是 &lt;strong>MMLU&lt;/strong>（Massive Multitask Language Understanding）。这是一个常用的大规模多任务语言理解数据集，包含 15,908 道覆盖 57 个领域的知识与推理题，领域涵盖医学、数学、计算机科学、法律等。
MMLU 的题目源自各类面向人类的标准化考试，如美国研究生入学考试（GRE）、医师执照考试（USMLE）和大学先修课程考试（AP）。
因此，这些问题并非反映真实用户的信息需求，而是专为评估人类在学术或职业认证场景下的知识水平而设计。
图 11.10 展示了部分示例（正确答案已加粗）。&lt;/p></description></item><item><title>11.3 使用 RAG 回答问题</title><link>https://youkre.github.io/speech-and-language-processing/ch11-03/</link><pubDate>Tue, 30 Dec 2025 11:22:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch11-03/</guid><description>&lt;p>在此，我们介绍一种利用大语言模型（LLM）回答知识型问题的重要范式：首先从网络或其他大型文档集合中检索出支持性的文本片段，然后基于这些文档生成答案。
这种基于检索结果进行生成的方法被称为&lt;strong>检索增强生成&lt;/strong>（Retrieval-Augmented Generation, &lt;strong>RAG&lt;/strong>），其两个组成部分出于历史原因常被分别称为&lt;strong>检索器&lt;/strong>（retriever）和&lt;strong>阅读器&lt;/strong>（reader）（Chen 等，2017a）。
图 11.9 概述了这一标准的问答模型。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-11-9.png">&lt;/p>
&lt;p>&lt;strong>图 11.9&lt;/strong> 基于检索的问答包含两个阶段：&lt;strong>检索阶段&lt;/strong>从文档集合中返回相关文档；&lt;strong>阅读阶段&lt;/strong>中，大语言模型以这些文档作为提示（prompt）生成答案。&lt;/p>
&lt;p>如图 11.9 所示的“检索-阅读”两阶段模型中，在第一阶段（检索阶段），我们从一个文本集合中检索出相关段落，例如使用上一节介绍的稠密检索器。
在第二阶段（阅读器阶段），我们通过&lt;strong>检索增强生成&lt;/strong>（RAG）来生成答案。
将一个大规模预训练语言模型作为基础，把检索到的段落及其他文本作为提示输入，并以自回归方式逐个生成答案词元。&lt;/p>
&lt;h3 id="1131-检索增强生成rag">11.3.1 检索增强生成（RAG）&lt;/h3>
&lt;p>标准的阅读器算法是：在检索到的段落条件下，由大语言模型生成答案。
这种方法即为&lt;strong>检索增强生成&lt;/strong>（Retrieval-Augmented Generation, RAG）。&lt;/p>
&lt;p>回顾一下，在简单的条件生成中，我们可以将问答任务转化为词预测问题：给语言模型一个提问，并附加一个如 &lt;code>A:&lt;/code> 的标记，暗示接下来应生成答案：&lt;/p>
&lt;blockquote>
&lt;p>Q: 谁写了《物种起源》这本书？ A:&lt;/p>&lt;/blockquote>
&lt;p>然后，模型基于该文本进行自回归生成。&lt;/p>
&lt;p>更形式化地说，普通的自回归语言模型通过前面的词元计算整个字符串的概率：&lt;/p>
$$
p(x_1, \dots, x_n) = \prod_{i=1}^n p(x_i \mid x_{&lt; i})
$$&lt;p>而用于问答的简单条件生成则将提示（如 &lt;code>Q:&lt;/code>）、查询 $q$ 和 &lt;code>A:&lt;/code> 拼接在一起：&lt;/p>
$$
p(x_1, \dots, x_n) = \prod_{i=1}^n p\big(x_i \mid [Q:];\, q;\, [A:];\, x_{&lt; i}\big)
$$&lt;p>使用大语言模型的优势在于，其参数中编码了预训练时所学得的海量知识。
然而，正如本章开头所述，尽管这种简单的提示生成对许多简单的事实型问题效果不错，但它并非通用的问答解决方案，原因包括：容易产生幻觉；无法向用户提供支持答案的文本证据；无法回答涉及专有数据的问题。&lt;/p>
&lt;p>检索增强生成的核心思想正是为了解决这些问题：将检索到的段落作为前缀的一部分加入提示中，通常还会附加一段引导语，例如 “请根据以下文本回答问题：”。
假设我们有一个查询 $q$，并记基于它检索到的段落集合为 $R(q)$，那么提示可能如下所示：&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>RAG 提示示例&lt;/strong>&lt;/p></description></item><item><title>11.2 基于稠密向量的信息检索</title><link>https://youkre.github.io/speech-and-language-processing/ch11-02/</link><pubDate>Tue, 30 Dec 2025 11:10:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch11-02/</guid><description>&lt;p>传统的 tf-idf 或 BM25 信息检索算法长期以来被认为存在一个概念性缺陷：它们仅在查询与文档之间存在完全相同的词语重叠时才有效。
换句话说，用户在提出查询（或问题）时，必须准确猜中答案撰写者所使用的词汇，这一问题被称为&lt;strong>词汇不匹配问题&lt;/strong>（vocabulary mismatch problem）（Furnas 等，1987）。&lt;/p>
&lt;p>解决该问题的方法是采用能够处理同义关系（synonymy）的模型：不再使用（稀疏的）词频向量，而是使用（稠密的）嵌入向量（embeddings）。
这一思想早在上世纪就已提出，称为潜在语义索引（Latent Semantic Indexing, LSI）（Deerwester 等，1990），而在现代则通过 BERT 等编码器实现。&lt;/p>
&lt;p>目前最强大的方法是将查询和文档同时输入同一个编码器，让 Transformer 的自注意力机制同时看到查询和文档中的所有词元（tokens），从而构建出对两者语义都敏感的联合表示。
随后，可以在 &lt;code>[CLS]&lt;/code> 词元之上添加一个线性层，用于预测该查询-文档对的相关性得分：&lt;/p>
$$
\begin{align*}
\mathbf{z} &amp;= \text{BERT}(q;[SEP];d)[\text{CLS}] \\
&amp;\text{score}(q,d) = \text{softmax}(\mathbf{U}\mathbf{z})
\tag{11.17}
\end{align*}
$$&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-11-7.png">&lt;/p>
&lt;p>&lt;strong>图 11.7&lt;/strong> 两种稠密检索方法的示意图（图中连线示意自注意力机制的作用范围）：
(a) 使用单一编码器联合编码查询与文档，并在 &lt;code>[CLS]&lt;/code> 词元上通过线性层微调生成相关性得分。此方法计算开销过大，通常仅用于&lt;strong>重排序&lt;/strong>（re-scoring）阶段；
(b) 使用独立的查询编码器和文档编码器，通过两者 &lt;code>[CLS]&lt;/code> 输出向量的点积作为得分。此方法计算高效，但精度略低。&lt;/p>
&lt;p>该架构如图 11.7a 所示。
通常，检索步骤不会在整个文档上进行，而是将文档切分为更小的段落（passages），例如长度为 100 个词元的非重叠固定片段，然后对这些段落而非完整文档进行编码和检索。
由于 BERT 的输入窗口限制为 512 个词元，因此需要确保查询和文档能共同容纳其中。例如，可将查询截断至最多 64 个词元，并在必要时截断文档，使得查询、文档、&lt;code>[CLS]&lt;/code> 和 &lt;code>[SEP]&lt;/code> 总共不超过 512 个词元。
随后，整个 BERT 模型连同线性层 $\mathbf{U}$ 可以通过一个包含相关与不相关段落的微调数据集，针对相关性判断任务进行微调。&lt;/p>
&lt;p>然而，图 11.7a 所示的完整 BERT 架构存在计算开销过大的问题。
使用该架构时，每次收到新查询，都必须将整个文档集合中的每一篇文档与该查询一起送入 BERT 编码器进行联合编码！
这种巨大的资源消耗在实际应用中是不可行的。&lt;/p></description></item><item><title>11.1 信息检索</title><link>https://youkre.github.io/speech-and-language-processing/ch11-01/</link><pubDate>Tue, 30 Dec 2025 10:12:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch11-01/</guid><description>&lt;p>&lt;strong>信息检索&lt;/strong>（Information Retrieval，简称 IR）是研究如何根据用户信息需求检索各类媒体内容的领域。
由此构建的 IR 系统通常被称为&lt;strong>搜索引擎&lt;/strong>。
本节的目标是提供足够的 IR 概述，以便理解其在问答任务中的应用。
对信息检索本身更感兴趣的读者可参阅本章末尾的“历史注记”部分以及 Manning 等人（2008）等教科书。&lt;/p>
&lt;p>我们所讨论的 IR 任务称为&lt;strong>即席检索&lt;/strong>（ad hoc retrieval）：用户向检索系统提交一个&lt;strong>查询&lt;/strong>（query），系统随后从某个&lt;strong>文档集合&lt;/strong>（collection）中返回一个有序的&lt;strong>文档&lt;/strong>（documents）列表。
此处的“&lt;strong>文档&lt;/strong>”指系统所索引和检索的任意文本单位，例如网页、学术论文、新闻文章，甚至更短的片段（如段落）。
“&lt;strong>集合&lt;/strong>”则指用于满足用户请求的一组文档。
“&lt;strong>词条&lt;/strong>”（term）通常指集合中的一个词，但也可能包括短语。
最后，&lt;strong>查询&lt;/strong>（query）表示用户以一组词条形式表达的信息需求。
即席检索引擎的高层架构如图 11.1 所示。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-11-1.png">&lt;/p>
&lt;p>&lt;strong>图 11.1&lt;/strong> 即席 IR 系统的架构。&lt;/p>
&lt;p>基本的 IR 架构采用我们在第 5 章介绍的向量空间模型：将查询和文档映射为基于一元词频（unigram word counts）的向量，并利用向量之间的余弦相似度对候选文档进行排序（Salton, 1971）。
因此，这属于附录 K 中介绍的&lt;strong>词袋模型&lt;/strong>（bag-of-words model）的一个实例，因为其中词语的处理不考虑其在文本中的位置。&lt;/p>
&lt;h3 id="1111-词条加权与文档评分">11.1.1 词条加权与文档评分&lt;/h3>
&lt;p>我们来看文档与查询之间匹配得分的具体计算方式。&lt;/p>
&lt;p>在信息检索中，我们不直接使用原始词频，而是为文档中的每个词计算一个&lt;strong>词条权重&lt;/strong>（term weight）。
常用的词条加权方案有两种：第5章介绍过的 &lt;strong>tf-idf&lt;/strong> 加权，以及一种稍强一些的变体&lt;strong>BM25&lt;/strong>。&lt;/p>
&lt;p>为方便读者，此处重新介绍 tf-idf，避免回看第5章。
Tf-idf（这里的“-”是连字符，不是减号）是两个因子的乘积：词频（term frequency, tf）和逆文档频率（inverse document frequency, idf）。&lt;/p>
&lt;p>词频反映一个词在文档中出现的频繁程度；在文档中出现次数越多的词，越可能体现该文档的内容。
通常我们使用词频的以10为底的对数（$\log_{10}$），而非原始计数。
其理由是：一个词在文档中出现100次，并不意味着它对该文档语义的相关性就是出现1次时的100倍。
此外，对于计数为 0 的情况需特殊处理，因为我们无法对 0 取对数。&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>&lt;/p>
$$
\begin{align*}
tf_{t,d} =
\begin{cases}
1 + \log_{10} \text{count}(t,d) &amp; \text{if } \text{count}(t,d) > 0 \\
0 &amp; \text{otherwise}
\end{cases}
\tag{11.4}
\end{align*}
$$&lt;p>若采用对数加权，那么在文档中出现 0 次的词条 tf = 0；出现1次时，tf = 1 + log₁₀(1) = 1 + 0 = 1；出现10次时，tf = 1 + log₁₀(10) = 2；出现100次时，tf = 1 + log₁₀(100) = 3；出现1000次时，tf = 4，依此类推。&lt;/p></description></item><item><title>12.1 语言差异与类型学</title><link>https://youkre.github.io/speech-and-language-processing/ch12-01/</link><pubDate>Mon, 29 Dec 2025 17:16:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch12-01/</guid><description>&lt;p>世界上大约有7000种语言。
人类语言的某些方面似乎是普遍的，适用于所有这些语言，或者可以说是统计上的普遍性，适用于大多数语言。
许多普遍性源于语言作为人类交流系统的功能性角色。
例如，每一种语言似乎都有指代“人”的词汇，有关于吃和喝的表达，以及表示礼貌或不礼貌的方式。
还有结构上的语言普遍性；例如，每一种语言似乎都有名词和动词（第 17 章），都有提问的方法，或者发出命令，并且有语言机制来表示同意或不同意。&lt;/p>
&lt;p>然而，语言在很多方面也存在&lt;strong>差异&lt;/strong>（这一点自古以来就被指出；见图 12.1）。
理解是什么导致了这些&lt;strong>翻译差异&lt;/strong>（Dorr, 1994）可以帮助我们构建更好的机器翻译模型。
我们通常区分两类差异。一类是独特性和词汇层面的差异，必须逐个处理。例如，“狗”这个词在不同语言中的说法差异极大。另一类是系统性差异，可以用统一的方式建模。例如，许多语言把动词放在语法宾语之前，而另一些语言则把动词放在语法宾语之后。
研究这些系统性的跨语言相似性和差异的学科被称为&lt;strong>语言类型学&lt;/strong>（linguistic typology）。
本节简要介绍一些影响机器翻译的语言类型特征；感兴趣的读者可以查阅《世界语言结构地图集》（World Atlas of Language Structures, Dryer and Haspelmath, 2013），该书汇总了大量跨语言的结构规律。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-12-1.png">&lt;/p>
&lt;p>&lt;strong>图12.1&lt;/strong> 巴别塔，彼得·勃鲁盖尔于1563年创作。来自维基共享资源，维也纳艺术史博物馆收藏。&lt;/p>
&lt;h3 id="1211-词序类型学">12.1.1 词序类型学&lt;/h3>
&lt;p>正如我们在前面英语与日语的对比示例中所暗示的那样，不同语言在简单陈述句中动词、主语和宾语的基本词序上存在差异。
例如，德语、法语、英语和汉语普通话都属于 &lt;strong>SVO&lt;/strong>（主-动-宾）语言，这意味着动词通常位于主语和宾语之间。
相比之下，印地语和日语是 &lt;strong>SOV&lt;/strong> 语言，即动词通常出现在基本小句的末尾；而爱尔兰语和阿拉伯语则是 &lt;strong>VSO&lt;/strong> 语言。
两种具有相同基本词序类型的语言，往往在其他方面也表现出相似性。
例如，&lt;strong>VO&lt;/strong> 型语言通常使用&lt;strong>前置词&lt;/strong>（prepositions），而 &lt;strong>OV&lt;/strong> 型语言则通常使用&lt;strong>后置词&lt;/strong>（postpositions）。&lt;/p>
&lt;p>让我们更详细地看看前面提到的例子。
在下面这个 SVO 的英语句子中，动词 &lt;em>wrote&lt;/em> 后接其宾语 &lt;em>a letter&lt;/em>，以及介词短语 &lt;em>to a friend&lt;/em>。在这个介词短语中，前置词 &lt;em>to&lt;/em> 后接其论元（argument，即动词所作用的核心成分） &lt;em>a friend&lt;/em>。
阿拉伯语采用 VSO 语序，同样将动词置于宾语之前，并使用前置词。
相比之下，在下面的日语例子中，这些顺序全部反转：动词&lt;strong>前接&lt;/strong>其论元，而后置词则&lt;strong>后接&lt;/strong>其论元。&lt;/p>
&lt;pre>
(12.3) English: He wrote a letter to a friend
Japanese: tomodachi ni tegami-o kaita
friend to letter wrote
Arabic: katabt risāla li ṡadq
wrote letter to friend
&lt;/pre>
&lt;p>其他类型的词序偏好则因语言而异，呈现出独特性。
在一些 SVO 语言（如英语和汉语）中，形容词通常出现在名词之前；而在另一些语言（如西班牙语和现代希伯来语）中，形容词则出现在名词之后：&lt;/p></description></item><item><title>第11章 信息检索与检索增强生成</title><link>https://youkre.github.io/speech-and-language-processing/ch11/</link><pubDate>Mon, 29 Dec 2025 17:03:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch11/</guid><description>&lt;blockquote>
&lt;p>有两次，我被人问到：“请问，巴贝奇先生，如果您把错误的数字输入机器，它会输出正确的答案吗？”……我实在无法理解，究竟是怎样的思想混乱才会引发这样的问题。&lt;/p>
&lt;p>——巴贝奇（1864）&lt;/p>&lt;/blockquote>
&lt;p>人们需要获取信息。
因此，几乎从计算机诞生之初，我们就开始向它们提问了。
早在 1961 年，就已出现能回答美国棒球统计数据问题的系统，比如：“洋基队在七月打了多少场比赛？”（Green 等，1961）。
甚至在 20 世纪 70 年代的虚构作品中，也有类似的计算机。道格拉斯·亚当斯在《银河系漫游指南》中创造的“深思”（Deep Thought）计算机，就曾回答过“生命、宇宙以及一切的终极问题”。&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>
由于大量知识都以文本形式存在，早在大语言模型（LLM）出现之前，问答系统就已达到人类水平的表现。例如，IBM 的 Watson 系统在 2011 年赢得了电视智力竞赛节目《危险边缘》（&lt;em>Jeopardy!&lt;/em>），在回答如下问题时超越了人类选手：&lt;/p>
&lt;blockquote>
&lt;p>威廉·威尔金森所著《瓦拉几亚与摩尔多瓦公国纪事》启发了这位作家创作其最著名的小说 &lt;sup id="fnref:2">&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref">2&lt;/a>&lt;/sup>&lt;/p>&lt;/blockquote>
&lt;p>因此很自然地，大语言模型的一项重要功能，就是通过回答用户的问题来满足&lt;strong>人类的信息需求&lt;/strong>。
由于大量信息存在于网络上，问答任务与网络信息检索密切相关——后者正是搜索引擎所执行的任务。
事实上，这两者的界限正变得越来越模糊：现代搜索引擎已与大语言模型深度集成。&lt;/p>
&lt;p>考虑一些简单的信息需求，例如可以用简短文本中的事实直接回答的&lt;strong>事实型问题&lt;/strong>（factoid questions）：&lt;/p>
&lt;p>(11.1) 卢浮宫博物馆位于哪里？&lt;/p>
&lt;p>(11.2) 核爆炸的能量来自何处？&lt;/p>
&lt;p>(11.3) 在 LaTeX 中如何打出花体字母 l？&lt;/p>
&lt;p>要让大语言模型回答这些问题，我们只需对其进行提示即可！
例如，一个已在问答任务上经过指令微调（参见第9章）的预训练大语言模型，可以直接对以下问题进行条件生成：&lt;/p>
&lt;blockquote>
&lt;p>卢浮宫博物馆位于哪里？&lt;/p>&lt;/blockquote>
&lt;p>并将其生成的回复作为答案。
这种方法之所以有效，是因为大语言模型在其预训练数据中接触过大量事实信息（包括卢浮宫的位置），并将这些信息编码到了模型参数中。
这类事实性知识似乎主要存储在 Transformer 模型中规模庞大的前馈层连接之中（Geva 等，2021；Meng 等，2022）。&lt;/p>
&lt;p>仅靠提示（prompting）大语言模型，对许多事实型问题而言确实是一种有效的方法。
但知识被存储在大语言模型前馈层的权重中，这一特性使得单纯依靠提示来准确回答事实性问题会带来若干问题。&lt;/p>
&lt;p>第一个、也是最主要的问题是：大语言模型经常对事实性问题给出错误答案！
大语言模型会&lt;strong>产生幻觉&lt;/strong>（hallucinate）。
所谓“幻觉”，是指模型生成的内容与现实世界的事实不符。
也就是说，当被提问时，大语言模型有时会编造听起来合理、但实际上错误的答案。
例如，Dahl 等人（2024）发现，在回答法律领域的问题（如特定法律案件）时，大语言模型产生幻觉的比例高达 69% 到 88%！
即使正确的事实其实已经存储在模型参数中，大语言模型有时仍会给出错误答案。这似乎是因为前馈层未能成功调用其参数中已有的知识（Jiang 等，2024）。&lt;/p>
&lt;p>更麻烦的是，我们往往难以判断大语言模型是否正在产生幻觉。部分原因在于，大语言模型的&lt;strong>置信度校准&lt;/strong>（calibration）效果很差。
在一个&lt;strong>校准良好&lt;/strong>（well-calibrated）的系统中，系统对其答案正确性的置信度应与该答案实际正确的概率高度相关。
也就是说，如果一个校准良好的系统答错了，它至少可能会使用模糊措辞，或建议用户去查阅其他来源。
但大语言模型缺乏良好的校准能力，常常以十足的把握给出完全错误的答案（Zhou 等，2024）。&lt;/p>
&lt;p>使用简单提示方法回答问题的第二个问题是：通过提示大语言模型仅依靠其预训练参数来作答，无法让我们就专有数据（proprietary data）进行提问。
我们希望使用语言模型来回答关于专有数据的事实性问题，例如个人电子邮件。
或者，在医疗健康应用中，我们可能希望将语言模型应用于医疗记录。
又或者，公司可能拥有包含客户服务或内部使用答案的内部文档。
再或者，律师事务所需要就法律证据开示（legal discovery）中涉及的的专有文档提出问题。
所有这些数据（希望如此）都不在大语言模型预训练所用的大规模网络语料库中。&lt;/p></description></item><item><title>9.5 用于序列标注的微调：命名实体识别</title><link>https://youkre.github.io/speech-and-language-processing/ch9-05/</link><pubDate>Mon, 29 Dec 2025 16:51:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch9-05/</guid><description>&lt;p>在序列标注（sequence labeling）任务中，网络的目标是为输入序列中的每个词元分配一个来自小型固定标签集的标签。
其中最常见的序列标注任务之一是&lt;strong>命名实体识别&lt;/strong>（Named Entity Recognition, NER）。&lt;/p>
&lt;h3 id="951-命名实体">9.5.1 命名实体&lt;/h3>
&lt;p>粗略地说，&lt;strong>命名实体&lt;/strong>（named entity）是指任何可以用专有名称指代的事物，例如人、地点或组织。
&lt;strong>命名实体识别&lt;/strong>（NER）的任务是从文本中找出构成专有名称的文本片段（spans），并为其标注对应的实体类型。
最常用的四种实体标签是：&lt;strong>PER&lt;/strong>（Person，人物）、&lt;strong>LOC&lt;/strong>（Location，地点）、&lt;strong>ORG&lt;/strong>（Organization，组织）、&lt;strong>GPE&lt;/strong>（Geo-Political Entity，地缘政治实体，如国家、州、城市等）。
不过，“命名实体”这一术语通常被扩展使用，也包括一些严格意义上并非“实体”的表达，例如时间表达式（如日期、时刻），甚至数值表达式（如价格）。
以下是一个 NER 标注器的输出示例：&lt;/p>
&lt;blockquote>
&lt;p>Citing high fuel prices, [&lt;del>ORG&lt;/del> &lt;strong>United Airlines&lt;/strong>] said [&lt;del>TIME&lt;/del> &lt;strong>Friday&lt;/strong>] it has increased fares by [&lt;del>MONEY&lt;/del> &lt;strong>$6&lt;/strong>] per round trip on flights to some cities also served by lower-cost carriers. [&lt;del>ORG&lt;/del> &lt;strong>American Airlines&lt;/strong>], a unit of [&lt;del>ORG&lt;/del> &lt;strong>AMR Corp.&lt;/strong>], immediately matched the move, spokesman [&lt;del>PER&lt;/del> &lt;strong>Tim Wagner&lt;/strong>] said. [&lt;del>ORG&lt;/del> &lt;strong>United&lt;/strong>], a unit of [&lt;del>ORG&lt;/del> &lt;strong>UAL Corp.&lt;/strong>], said the increase took effect [&lt;del>TIME&lt;/del> &lt;strong>Thursday&lt;/strong>] and applies to most routes where it competes against discount carriers, such as [&lt;del>LOC&lt;/del> &lt;strong>Chicago&lt;/strong>] to [&lt;del>LOC&lt;/del> &lt;strong>Dallas&lt;/strong>] and [&lt;del>LOC&lt;/del> &lt;strong>Denver&lt;/strong>] to [&lt;del>LOC&lt;/del> &lt;strong>San Francisco&lt;/strong>].&lt;/p></description></item><item><title>9.4 用于分类任务的微调</title><link>https://youkre.github.io/speech-and-language-processing/ch9-04/</link><pubDate>Mon, 29 Dec 2025 15:45:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch9-04/</guid><description>&lt;p>预训练语言模型的强大之处在于，它们能够从海量文本中提取出通用的语言规律，而这些规律对大量下游应用都非常有用。
要将这些通用知识应用于具体任务，主要有两种方式。
最常见的方式是使用自然语言对模型进行&lt;strong>提示&lt;/strong>（prompt），引导模型进入某种状态，使其在上下文中生成我们期望的输出。&lt;/p>
&lt;p>本节将探讨另一种利用预训练语言模型解决下游任务的方法：即第 7 章介绍过的&lt;strong>微调&lt;/strong>（finetuning）范式的一种变体。
在针对掩码语言模型的微调方法中，我们会在预训练模型之上添加面向特定任务的模块（通常称为专用“头”，head），以预训练模型的输出作为该模块的输入。
微调过程利用带标签的任务数据来训练这些新增的、任务特定的参数。
通常情况下，这一训练过程会冻结预训练模型的大部分参数，或仅对其做极小幅度的调整。&lt;/p>
&lt;p>接下来几节将介绍针对最常见任务类型的微调方法：序列分类（sequence classification）、句子对分类（sentence-pair classification）和序列标注（sequence labeling）。&lt;/p>
&lt;h3 id="941-序列分类">9.4.1 序列分类&lt;/h3>
&lt;p>&lt;strong>序列分类&lt;/strong>（sequence classification）任务的目标是为一整段文本序列分配一个单一的类别标签。
这类任务通常统称为&lt;strong>文本分类&lt;/strong>（text classification），例如情感分析或垃圾邮件检测（见附录 K），在这些任务中，我们将一段文本分为两类或三类（如正面、负面）；也包括类别数量较多的任务，例如文档级别的主题分类。&lt;/p>
&lt;p>在序列分类中，我们用一个向量来表示整个待分类的输入序列。
表示序列的方式有多种。
一种方法是对序列中每个词元在模型最后一层输出的向量进行求和或取平均。
但对于 BERT，我们采用另一种方式：在词汇表中引入一个特殊的唯一标记 &lt;code>[CLS]&lt;/code>（代表“classification”），在预训练和推理阶段都将该标记添加到所有输入序列的开头。
模型最后一层中对应 &lt;code>[CLS]&lt;/code> 标记的输出向量即被用作整个输入序列的表示，并作为后续&lt;strong>分类器头部&lt;/strong>（classifier head）的输入。该分类器通常是一个逻辑回归模型或小型神经网络，用于做出最终的分类决策。&lt;/p>
&lt;p>举个例子，回到情感分类问题。
针对该任务进行微调，需要学习一组权重矩阵 $\mathbf{W_C}$，将 &lt;code>[CLS]&lt;/code> 标记的输出向量 $\mathbf{h}^L_{\text{CLS}}$ 映射到各个情感类别上的得分。
假设这是一个三分类情感任务（正面、负面、中性），且模型的隐藏维度为 $d$，那么 $\mathbf{W_C}$ 的维度就是 $[d \times 3]$。
要对一篇文档进行分类，我们首先将输入文本送入预训练语言模型，得到 $\mathbf{h}^L_{\text{CLS}}$，然后将其与 $\mathbf{W_C}$ 相乘，并将结果通过 softmax 函数归一化为概率分布：&lt;/p>
$$
\mathbf{y} = \text{softmax}(\mathbf{h}^L_{\text{CLS}} \mathbf{W_C})
\tag{9.11}
$$&lt;p>对 $\mathbf{W_C}$ 的微调需要依赖带标签的监督训练数据，即每条输入序列都标注了正确的情感类别。
训练过程采用标准方式：使用 softmax 输出与真实标签之间的交叉熵损失来驱动 $\mathbf{W_C}$ 的学习。&lt;/p>
&lt;p>此外，该损失函数不仅可以用于更新分类器的权重，还可以反向传播以微调预训练语言模型本身的参数。
在实践中，通常只需对语言模型参数做极小幅度的调整就能获得良好的分类性能，且更新往往仅限于 Transformer 的最后几层。
图 9.9 展示了这种序列分类的整体架构。&lt;/p></description></item><item><title>9.3 上下文嵌入</title><link>https://youkre.github.io/speech-and-language-processing/ch9-03/</link><pubDate>Mon, 29 Dec 2025 12:15:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch9-03/</guid><description>&lt;p>给定一个预训练好的语言模型和一个新的输入句子，我们可以将模型输出的序列视为输入中每个词元的&lt;strong>上下文嵌入&lt;/strong>（contextual embeddings）。
这些上下文嵌入是向量，用于表示某个词元在其具体上下文中的语义某一方面，可应用于任何需要理解词元或词语含义的任务。
更形式化地，给定一个输入词元序列 $x_1, \cdots, x_n$，我们可以使用模型最终层 $L$ 的输出向量 $\mathbf{h}^L_i$ 作为词元 $x_i$ 在句子 $x_1, \dots, x_n$ 上下文中的语义表示。
或者，除了仅使用最终层的向量 $\mathbf{h}^L_i$ 外，一种常见做法是通过对模型最后四层的输出向量进行平均来构建 $x_i$ 的表示，$\mathbf{h}^L_i$、$\ \mathbf{h}^{L-1}_i$、$\mathbf{h}^{L-2}_i$、$\mathbf{h}^{L-3}_i$。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-9-5.png">&lt;/p>
&lt;p>&lt;strong>图 9.5&lt;/strong> BERT 类模型的输出是对每个输入词元 $x_i$ 生成的一个上下文嵌入向量 $\mathbf{h}^L_i$。&lt;/p>
&lt;p>正如我们在第 5 章中使用 word2vec 等静态嵌入（static embeddings）来表示词语的含义一样，我们也可以将上下文嵌入用作词语在具体语境中含义的表示，以支持任何需要建模词语语义的任务。
静态嵌入表示的是&lt;strong>词型&lt;/strong>（word types，即词汇表条目）的含义，而上下文嵌入表示的是&lt;strong>词例&lt;/strong>（word instances）的含义——即某一特定词型在特定上下文中的具体出现实例。
因此，如果说 word2vec 为每个词型只提供一个固定向量，那么上下文嵌入则为该词型在每一个句子上下文中的每次出现都提供一个独立的向量。
正因如此，上下文嵌入可用于诸如衡量两个词语在各自上下文中的语义相似度等任务，并在需要词语语义建模的语言学任务中发挥重要作用。&lt;/p>
&lt;h3 id="931-上下文嵌入与词义">9.3.1 上下文嵌入与词义&lt;/h3>
&lt;p>词语具有&lt;strong>歧义性&lt;/strong>（ambiguous）：同一个词可以表达不同的含义。
在第 5 章中我们看到，单词 “mouse” 可以指：(1) 一种小型啮齿动物，或 (2) 一种用于控制光标的手持设备。“bank” 则可能指：(1) 一家金融机构，或 (2) 河岸（即一侧倾斜隆起的土坡）。
我们称像 “mouse” 或 “bank” 这样的词为&lt;strong>多义词&lt;/strong>（polysemous），该词源自希腊语 “many senses”（&lt;em>poly&lt;/em>- 表示“多”，&lt;em>sema&lt;/em> 表示“符号、标记”）。&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>&lt;/p>
&lt;p>一个&lt;strong>词义&lt;/strong>（sense 或 word sense）是对词语某一特定含义的离散化表示。
我们可以用上标来区分不同词义：如 &lt;strong>bank¹&lt;/strong> 与 &lt;strong>bank²&lt;/strong>、&lt;strong>mouse¹&lt;/strong> 与 &lt;strong>mouse²&lt;/strong>。
这些词义可以在在线词典或同义词词典（thesauruses/thesauri）中找到，例如 &lt;strong>WordNet&lt;/strong>（Fellbaum，1998）——它提供了多种语言的数据集，列出了大量词语的不同词义。
在具体上下文中，不同词义很容易区分，以下英文例句展示了英语中典型的一词多义现象：&lt;/p></description></item><item><title>8.9 Transformer 的可解释性</title><link>https://youkre.github.io/speech-and-language-processing/ch8-09/</link><pubDate>Sun, 28 Dec 2025 12:52:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch8-09/</guid><description>&lt;p>基于 Transformer 的语言模型为何能在各种语言任务上表现如此出色？
&lt;strong>可解释性&lt;/strong>（interpretability）这一子领域——有时也称为&lt;strong>机制性可解释性&lt;/strong>（mechanistic interpretability）——致力于从机制层面理解 Transformer 内部究竟发生了什么。
在接下来的两个小节中，我们将讨论 Transformer 可解释性研究中两个被深入探索的方向。&lt;/p>
&lt;h3 id="891-上下文学习与归纳头in-context-learning-and-induction-heads">8.9.1 上下文学习与归纳头（In-Context Learning and Induction Heads）&lt;/h3>
&lt;p>为了让模型完成我们期望的任务，提示（prompting）与预训练（pretraining）在本质上是两种截然不同的方式。
预训练通过梯度下降更新模型参数，依据某个损失函数进行学习。
而带示例的提示（prompting with demonstrations）却能在不更新任何参数的情况下，教会模型执行新任务。
模型在处理提示的过程中，从这些示例中“学到”了关于任务的某种规律。&lt;/p>
&lt;p>即使没有显式示例，提示过程本身也可被视为一种学习形式。
例如，随着模型在提示中读取的位置越靠后，它对后续词元的预测往往就越准确。
上下文中的信息正在提升模型的预测能力。&lt;/p>
&lt;p>Brown 等人（2020）在介绍 GPT-3 时首次提出术语&lt;strong>上下文学习&lt;/strong>（in-context learning），用以描述语言模型通过提示进行的这种学些。
上下文学习意味着语言模型在推理阶段仅通过前向传播（不进行任何梯度更新），就能学会执行新任务、更好地预测词元或总体上降低其损失。&lt;/p>
&lt;p>那么，上下文学习是如何实现的？
尽管尚无定论，但已有若干引人注目的假说。
其中一种核心观点基于&lt;strong>归纳头&lt;/strong>（induction heads）的概念（Elhage et al., 2021；Olsson et al., 2022）。
归纳头（induction heads）是一种&lt;strong>计算回路&lt;/strong>（circuit）的名称，即网络中实现特定功能的一种抽象组件。
它是在 Transformer 的注意力计算中发现的一种结构，最初通过研究仅含 1–2 个注意力头的微型语言模型而被识别出来。&lt;/p>
&lt;p>归纳头的功能是预测重复出现的序列模式。
例如，当输入序列为 &lt;code>AB...A&lt;/code> 时，它会预测下一个词应为 &lt;code>B&lt;/code>，从而实现一种&lt;strong>模式补全&lt;/strong>（pattern completion）规则 $AB\ldots A \rightarrow B$。
它通过注意力计算中的一个 &lt;strong>前缀匹配&lt;/strong>组件（prefix matching component）来实现这一点：当处理当前词元 &lt;code>A&lt;/code> 时，该组件会在上下文中向后搜索，以找到 &lt;code>A&lt;/code> 的先前出现位置。
一旦找到之前的 &lt;code>A&lt;/code>，归纳头就使用&lt;strong>复制&lt;/strong>机制（copying mechanism）“复制”紧随其后的词 &lt;code>B&lt;/code>，通过提升 &lt;code>B&lt;/code> 的出现概率来完成预测。
图 8.19 展示了一个实例。&lt;/p></description></item><item><title>8.8 应对规模挑战</title><link>https://youkre.github.io/speech-and-language-processing/ch8-08/</link><pubDate>Sun, 28 Dec 2025 12:10:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch8-08/</guid><description>&lt;p>大语言模型确实非常庞大。
例如，Meta 发布的 &lt;strong>Llama 3.1 405B Instruct 模型&lt;/strong>拥有 4050 亿参数（共 126 层，模型维度为 16,384，128 个注意力头），并在 15.6 TB 的文本词元上进行训练（Llama Team, 2024），使用了大小为 128K 的词汇表。
因此，学术界和工业界投入了大量研究来理解 LLM 的扩展规律，尤其是如何在有限计算资源下高效实现和部署这些模型。
在接下来几节中，我们将讨论如何思考模型规模问题（即“&lt;strong>扩展定律&lt;/strong>”，scaling laws），以及一些关键的高效技术，如 &lt;strong>KV 缓存&lt;/strong>（KV cache）和&lt;strong>参数高效微调&lt;/strong>（parameter-efficient fine-tuning）。&lt;/p>
&lt;h3 id="881-扩展定律">8.8.1 扩展定律&lt;/h3>
&lt;p>研究表明，大语言模型的性能主要由三个因素决定：模型规模（参数量，通常不包括嵌入层参数）；数据集规模（训练数据总量）；训练所用的计算量（compute budget）。
换句话说，我们可以通过以下任一方式提升模型性能：增加参数（增加层数、扩大上下文或两者兼有）；使用更多训练数据；增加训练迭代次数（即投入更多算力）。&lt;/p>
&lt;p>这些因素与模型性能之间的关系被称为 &lt;strong>扩展定律&lt;/strong>（scaling laws）。
粗略地说，大语言模型的性能（以损失 $L$ 衡量）与上述三个训练属性均呈&lt;strong>幂律关系&lt;/strong>（power-law relationship）。&lt;/p>
&lt;p>例如，Kaplan 等人（2020）发现，在其他两个因素保持不变的前提下，当分别受限于模型规模、数据量或计算预算时，损失 $L$ 与（非嵌入部分的）参数数量 $N$、数据集大小 $D$ 和计算预算 $C$ 的存在如下三种关系：&lt;/p>
$$
L(N) = \left( \frac{N_c}{N} \right)^{\alpha_N}
\tag{8.49}
$$$$
L(D) = \left( \frac{D_c}{D} \right)^{\alpha_D}
\tag{8.50}
$$$$
L(C) = \left( \frac{C_c}{C} \right)^{\alpha_C}
\tag{8.51}
$$&lt;p>非嵌入参数总数 $N$ 可大致按如下方式估算（忽略偏置项，并设 $d$ 为模型输入/输出维度，$d_{\text{attn}}$ 为自注意力层维度，$d_{\text{ff}}$ 为前馈网络维度）：&lt;/p></description></item><item><title>8.7 训练</title><link>https://youkre.github.io/speech-and-language-processing/ch8-07/</link><pubDate>Sun, 28 Dec 2025 11:24:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch8-07/</guid><description>&lt;p>我们在前一章已经介绍了语言模型的训练过程。
回顾一下：*语言模型通常使用交叉熵损失，也称为负对数似然损失（negative log likelihood loss）。
在时间步 $t$，交叉熵损失等于模型对训练序列中下一个词所分配概率的负对数：$-\log p(w_{t+1})$&lt;/p>
&lt;p>图 8.16 展示了通用的训练方法。
在每一步中，给定所有前置词元，Transformer 的最后一层会输出一个覆盖整个词汇表的概率分布。
训练时，模型为正确下一个词分配的概率被用于计算序列中每个位置的交叉熵损失。
一条训练序列的总损失是其所有位置上交叉熵损失的平均值。
随后，通过梯度下降法调整网络中的所有参数，以最小化该序列上的平均交叉熵损失。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-8-16.png">&lt;/p>
&lt;p>&lt;strong>图 8.16&lt;/strong> 将 Transformer 作为语言模型进行训练。&lt;/p>
&lt;p>在 transformer训练阶段，序列中的每个位置可以并行处理，因为序列中每个元素的输出是独立计算的。&lt;/p>
&lt;p>大型模型通常会填满整个上下文窗口进行训练。例如 GPT-4 使用 4096 个词元的上下文窗口，Llama 3 则使用 8192 个词元。&lt;/p>
&lt;p>如果单个文档长度不足，系统会将多个文档拼接（packed）到同一个窗口中，并在文档之间插入特殊的文本结束符（end-of-text token）。
此外，梯度下降所用的批大小（batch size）通常非常大。例如，GPT-3 最大的模型版本使用了高达 320 万词元。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch8-06">8.6 关于采样方法的更多讨论&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch8-08">8.8 应对规模挑战&lt;/a>
&lt;/nav></description></item><item><title>8.6 关于采样方法的更多讨论</title><link>https://youkre.github.io/speech-and-language-processing/ch8-06/</link><pubDate>Sun, 28 Dec 2025 11:04:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch8-06/</guid><description>&lt;p>下面介绍的采样方法都包含可调节的参数，用于在生成过程中权衡两个关键因素：&lt;strong>质量&lt;/strong>（quality）与&lt;strong>多样性&lt;/strong>（diversity）。
倾向于选择高概率词的方法，通常生成的文本被人类评价为更准确、更连贯、更符合事实，但也更容易显得枯燥、重复。
而给予中等概率词稍高权重的方法，则往往更具创造性与多样性，但可能牺牲事实性，甚至导致语义混乱或整体质量下降。&lt;/p>
&lt;h3 id="861-top-k-采样top-k-sampling">8.6.1 Top-k 采样（Top-k Sampling）&lt;/h3>
&lt;p>&lt;strong>Top-k 采样&lt;/strong>是对贪心解码（greedy decoding）的一种简单推广。
它不再只选择概率最高的单个词，而是先将整个词汇表的概率分布截断，仅保留概率最高的 $k$ 个词；对这 $k$ 个词的概率重新归一化，形成一个合法的概率分布；然后根据这个新分布从中随机采样一个词。
更正式地描述如下：&lt;/p>
&lt;ol>
&lt;li>预先选定一个整数 $k$；&lt;/li>
&lt;li>对词汇表 $V$ 中的每个词，使用语言模型计算其在当前上下文下的条件概率 $p(w_t \mid \mathbf{w}_{&lt; t})$；&lt;/li>
&lt;li>将所有词按概率从高到低排序，丢弃排名不在前 $k$ 的词；&lt;/li>
&lt;li>将剩余 $k$ 个词的概率值重新归一化（使其和为 1）；&lt;/li>
&lt;li>根据归一化后的概率，从这 $k$ 个词中随机采样一个作为输出。&lt;/li>
&lt;/ol>
&lt;p>当 $k = 1$ 时，top-$k$ 采样就退化为贪心解码。
而当 $k > 1$ 时，模型有时会选择并非最可能但仍然合理的词，从而在保持文本质量的同时提升生成结果的多样性。&lt;/p>
&lt;h3 id="862-核采样nucleus-sampling或-top--采样">8.6.2 核采样（Nucleus Sampling）或 Top-$p$ 采样&lt;/h3>
&lt;p>Top-$k$ 采样的一个主要问题是：$k$ 是固定值，但不同上下文中词的概率分布形状差异很大。
例如，若设 $k = 10$，在某些上下文中，前 10 个词可能集中了绝大部分概率质量（如 95%），此时截断影响不大；但在另一些上下文中，概率分布可能非常平坦，前 10 个词加起来可能只占 30% 的概率质量，强行保留它们会引入大量低质量候选词。&lt;/p>
&lt;p>为解决这一问题，Holtzman 等人（2020）提出了 &lt;strong>Top-p 采样&lt;/strong>（也称&lt;strong>核采样&lt;/strong>，nucleus sampling）。其核心思想不是保留固定的 $k$ 个词，而是保留累积概率达到 $p$ 的最小词集（即覆盖至少 $p$ 比例概率质量的“核心”（nucleus）部分）。
目标不变：剔除极不可能的词。
但通过基于概率质量而非词数来动态调整候选集大小，使得该方法在不同上下文中更稳健，候选池会自动扩大或缩小。&lt;/p></description></item><item><title>8.4 输入：词元嵌入与位置嵌入</title><link>https://youkre.github.io/speech-and-language-processing/ch8-04/</link><pubDate>Sat, 27 Dec 2025 23:15:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch8-04/</guid><description>&lt;p>现在我们来讨论输入矩阵 $\mathbf{X}$ 的来源。
给定一个包含 $N$ 个词元的序列（$N$ 即上下文长度，以词元为单位），形状为 $[N \times d]$ 的矩阵 $\mathbf{X}$ 为上下文中的每个词元提供一个&lt;strong>嵌入&lt;/strong>（embedding）。
Transformer 通过分别计算两种嵌入来实现这一点：&lt;strong>词元嵌入&lt;/strong>（token embedding）和&lt;strong>位置嵌入&lt;/strong>（positional embedding）。&lt;/p>
&lt;p>词元嵌入在第 6 章中已介绍过，它是一个维度为 $d$ 的向量，作为输入词元的初始表示。
（随着向量在残差流中逐层向上流动，该嵌入表示会不断变化和丰富，融入上下文信息，并根据所构建的语言模型类型承担不同角色。）
所有初始词元嵌入存储在一个嵌入矩阵 $\mathbf{E}$ 中，其每一行对应词汇表中 $|V|$ 个词元中的一个。
（注意：此处的 $V$ 指词汇表（vocabulary），与注意力机制中的值向量 $V$ 无关。）
因此，每个词元由一个 $d$ 维行向量表示，$\mathbf{E}$ 的形状为 $[|V| \times d]$。&lt;/p>
&lt;p>例如，对于输入字符串 &lt;code>Thanks for all the&lt;/code>，我们首先将其转换为词汇表索引（这些索引是在使用 BPE 或 SentencePiece 等分词器对输入进行分词时生成的）。
假设 &lt;code>thanks for all the&lt;/code> 对应的索引序列为 $\mathbf{w} = [5, 4000, 10532, 2224]$。
接着我们通过索引从 $\mathbf{E}$ 中选取对应的行（第 5 行、第 4000 行、第 10532 行、第 2224 行），得到每个词元的嵌入。&lt;/p></description></item><item><title>8.3 使用单个矩阵 X 并行化计算</title><link>https://youkre.github.io/speech-and-language-processing/ch8-03/</link><pubDate>Sat, 27 Dec 2025 20:10:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch8-03/</guid><description>&lt;p>到目前为止，我们对多头注意力及 Transformer 块其余部分的描述，都是从单个残差流中、在单一时间步 $i$ 上计算单个输出的角度出发的。
但如前所述，为每个词元计算 $\mathbf{a}_i$ 的注意力操作彼此独立；同样，整个 Transformer 块中从输入 $\mathbf{x}_i$ 计算 $\mathbf{h}_i$ 的所有操作也都是相互独立的。
这意味着我们可以轻松地将整个计算并行化，充分利用高效的矩阵乘法运算。&lt;/p>
&lt;p>具体做法是：将输入序列中 $N$ 个词元的嵌入向量打包成一个大小为 $[N \times d]$ 的矩阵 $\mathbf{X}$，其中每一行对应一个输入词元的嵌入。
大型语言模型中的 Transformer 通常支持的输入长度 $N$ 从 1K 到 32K 不等；通过调整架构，使用特殊的长上下文之类的机制，甚至可处理长达 128K 或数百万词元的上下文。
因此，对于标准（vanilla）Transformer，我们可以认为矩阵 $\mathbf{X}$ 包含 1K 至 32K 行，每行维度为嵌入维度 $d$（即模型维度）。&lt;/p>
&lt;h3 id="并行化注意力计算">并行化注意力计算&lt;/h3>
&lt;p>我们先从单个注意力头开始，再扩展到多头，最后加入 Transformer 块中的其他组件。
对于单个头，我们将输入矩阵 $\mathbf{X}$ 分别与查询、键、值权重矩阵相乘：$\mathbf{W}^{\mathbf{Q}}$ 形状为 $[d \times d_k]$，$\mathbf{W}^{K}$ 形状为 $[d \times d_k]$，$\mathbf{W}^{V}$ 形状为 $[d \times d_v]$，从而得到三个矩阵：$\mathbf{Q} \in \mathbb{R}^{N \times d_k}$ 包含所有查询向量，$\mathbf{K} \in \mathbb{R}^{N \times d_k}$ 包含所有键向量，$\mathbf{V} \in \mathbb{R}^{N \times d_v}$ 包含所有值向量：&lt;/p></description></item><item><title>8.2 Transformer 块</title><link>https://youkre.github.io/speech-and-language-processing/ch8-02/</link><pubDate>Sat, 27 Dec 2025 19:30:08 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch8-02/</guid><description>&lt;p>自注意力计算是所谓 &lt;strong>Transformer 块&lt;/strong>（transformer block）的核心。除了自注意力层外，一个 Transformer 块还包含另外三种类型的层：
(1) 前馈网络层（feedforward layer），
(2) 残差连接（residual connections），
(3) 归一化层（通常称为“层归一化”，layer norm）。&lt;/p>
&lt;p>图 8.6 展示了一个 Transformer 块的结构，并采用了一种被称为 &lt;strong>残差流&lt;/strong>（residual stream）的常见视角来理解该模块（Elhage 等，2021）。
在残差流视角下，我们将单个词元 $i$ 在 Transformer 块中的处理过程视为一条针对位置 $i$ 的、维度为 $d$ 的表示流。
这条残差流始于原始输入向量，各个组件从流中读取输入，并将其输出加回到流中。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-8-6.png">&lt;/p>
&lt;p>&lt;strong>图 8.6&lt;/strong> Transformer 块的架构，展示了 &lt;strong>残差流&lt;/strong>。
本图展示的是 &lt;strong>前置归一化&lt;/strong>（prenorm）版本的架构，即层归一化发生在注意力层和前馈层之前，而非之后。&lt;/p>
&lt;p>流底部的输入是一个词元的嵌入向量，维度为 $d$。
该初始嵌入通过&lt;strong>残差连接&lt;/strong>向上传递，并被 Transformer 的其他组件逐步更新：我们已介绍过的&lt;strong>注意力层&lt;/strong>，以及即将引入的&lt;strong>前馈层&lt;/strong>。
在注意力层和前馈层之前，会先执行一种称为&lt;strong>层归一化&lt;/strong>（layer norm）的计算。&lt;/p>
&lt;p>初始向量首先经过一层归一化和注意力层，其结果被加回到残差流中——在此处，是加到原始输入向量 $\mathbf{x}_i$ 上。
随后，这个求和后的向量再次经过另一层归一化和一个前馈层，其输出又被加回到残差流中。
我们将最终得到的输出记为 $\mathbf{h}_i$，表示词元 $i$ 经过整个 Transformer 块后的结果。
（早期描述常将这一机制比喻为&lt;strong>残差连接&lt;/strong>——即将某个组件的输入与其输出相加。但残差流这一视角能更清晰地展现 Transformer 的信息流动方式。）&lt;/p>
&lt;p>我们已经了解了注意力层，现在介绍在处理位置 $i$ 的单个输入 $\mathbf{x}_i$ 时，前馈层和层归一化的计算方式。&lt;/p>
&lt;h3 id="前馈层feedforward-layer">前馈层（Feedforward Layer）&lt;/h3>
&lt;p>前馈层是一个全连接的两层网络（即含一个隐藏层，两个权重矩阵），如第 6 章所述。
所有词元位置 $i$ 共享相同的权重（即权重与位置无关）；但不同 Transformer 层之间的前馈权重彼此不同。
通常，前馈网络隐藏层的维度 $d_{ff}$ 会大于模型维度 $d$。
（例如，在原始 Transformer 模型中，$d = 512$，而 $d_{ff} = 2048$。）&lt;/p></description></item><item><title>8.1 注意力机制</title><link>https://youkre.github.io/speech-and-language-processing/ch8-01/</link><pubDate>Sat, 27 Dec 2025 17:51:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch8-01/</guid><description>&lt;p>回顾第 5 章的内容，在 &lt;strong>word2vec&lt;/strong> 和其他静态词嵌入方法中，一个词的语义表示始终是同一个向量，与上下文无关：例如，单词 &lt;code>chicken&lt;/code> 总是由同一个固定的向量表示。
因此，代词 &lt;code>it&lt;/code> 的静态向量可能只能编码“这是一个用于动物或无生命事物的代词”这一信息。
但在实际语境中，它的含义要丰富得多。请考虑以下两个句子中的 &lt;code>it&lt;/code>：&lt;/p>
&lt;p>(8.1) &lt;strong>The chicken&lt;/strong> didn’t cross the road because &lt;strong>it&lt;/strong> was too tired.&lt;/p>
&lt;p>(8.2) &lt;strong>The chicken&lt;/strong> didn’t cross the road because &lt;strong>it&lt;/strong> was too wide.&lt;/p>
&lt;p>在句子 (8.1) 中，&lt;code>it&lt;/code> 指的是 &lt;code>chicken&lt;/code>（即读者知道是鸡太累了），而在句子 (8.2) 中，&lt;code>it&lt;/code> 指的是 &lt;code>road&lt;/code>（即读者知道路太宽了）&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>。
也就是说，如果我们想要计算整个句子的含义，就必须让 &lt;code>it&lt;/code> 在第一个句子中与 &lt;code>the chicken&lt;/code> 关联，在第二个句子中与 &lt;code>the road&lt;/code> 关联，这种关联是依赖于上下文的。&lt;/p>
&lt;p>此外，设想我们像一个因果语言模型那样从左到右阅读，处理到单词 &lt;code>it&lt;/code> 为止：&lt;/p>
&lt;p>(8.3) &lt;strong>The chicken&lt;/strong> didn’t cross the road because &lt;strong>it&lt;/strong>&lt;/p>
&lt;p>此时，我们尚不清楚 &lt;code>it&lt;/code> 最终会指代什么！
因此，在这个时刻，对 &lt;code>it&lt;/code> 的表示可能同时包含 &lt;code>chicken&lt;/code> 和 &lt;code>road&lt;/code> 的某些特征，因为模型正在尝试预测接下来会发生什么。&lt;/p></description></item><item><title>7.7 语言模型的伦理与安全问题</title><link>https://youkre.github.io/speech-and-language-processing/ch7-07/</link><pubDate>Sat, 27 Dec 2025 10:25:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch7-07/</guid><description>&lt;p>早在大语言模型出现之前，伦理与安全问题就一直是人工智能体设计中的核心考量。
玛丽·雪莱（Mary Shelley，见下图）在其小说《弗兰肯斯坦》中，正是围绕“在未考虑伦理与人文关切的情况下创造人工智能体”这一问题展开叙事的。&lt;/p>
&lt;p>大语言模型（LLMs）可能以多种方式带来安全隐患。
例如，LLM 容易生成虚假内容，这一问题被称为“幻觉”（hallucination）。
语言模型的训练目标是生成可预测且连贯的文本，但截至目前我们所介绍的训练算法，并没有任何机制确保生成内容的真实性或正确性。
这对任何依赖事实准确性的应用场景都会造成严重问题！
与此相关的一个表现是，语言模型可能会建议危险行为，例如直接鼓励用户从事危险或非法活动，如自残或伤害他人。
当用户在涉及安全的关键场景中（如寻求医疗建议、处于紧急状况，或表达自残意图时）向语言模型求助，错误的建议可能带来危险，甚至危及生命。
需要指出的是，这类问题并非大语言模型所独有。例如，Bickmore 等人（2018）曾让参与者向三个 LLM 时代之前的商用对话系统（Siri、Alexa、Google Assistant）提出医疗问题，并根据系统回复决定采取何种行动；结果发现，许多被建议的行动一旦付诸实施，将可能导致伤害甚至死亡。
我们将在第 11 章再次讨论幻觉与事实性问题，届时会介绍诸如 “检索增强生成”（retrieval-augmented generation）等缓解方法；此外，在第 9 章中，我们也将探讨通过安全微调（safety tuning）和对齐（alignment）来提升模型安全性。&lt;/p>
&lt;p>除了提供错误信息，系统还可能通过言语&lt;strong>攻击用户&lt;/strong>，或造成&lt;strong>表征性伤害&lt;/strong>（representational harms）（Blodgett 等，2020）。
例如生成带有侮辱性或有害的刻板印象（Cheng 等，2023），以及贬低特定群体的负面态度（Brown 等，2020；Sheng 等，2019）。
无论是言语辱骂还是刻板印象，都可能对用户造成心理伤害。
Gehman 等人（2020）的研究表明，即使输入完全无害的提示，大语言模型仍可能输出仇恨言论并对用户进行言语攻击。
Liu 等人（2020）测试了系统对两组模拟用户输入的响应，这两组输入内容完全相同，仅在提及的性别或种族上有所差异。
他们发现，仅仅将句子中的 “he” 改为 “she”，就可能导致系统回复更具冒犯性和更负面的情绪倾向。
Hofmann 等人（2024）进一步发现，大语言模型甚至会仅仅因为用户使用了特定方言（如非裔美国人英语）而对其产生歧视。
同样，这些问题在大语言模型出现前就已存在。
例如，微软于 2016 年推出的聊天机器人 &lt;strong>Tay&lt;/strong>，上线仅 16 小时就被迫下线，因为它开始发布包含种族侮辱、阴谋论和人身攻击的内容。
Tay 的这些偏见和不当行为源于其训练数据，其中包括一些用户故意诱导它重复此类语言（Neff 和 Nagy，2016）。&lt;/p>
&lt;p>另一个重要的伦理与安全问题是&lt;strong>隐私&lt;/strong>（privacy）。
从计算机诞生之初，隐私就一直是人们关注的焦点。早在 1966 年，魏岑鲍姆（Weizenbaum）设计聊天机器人 ELIZA 作为计算心理治疗实验时，就已触及这一问题。
当时，人们很快对 ELIZA 产生了强烈的情感依赖，并与其进行极为私密的对话——甚至有人在输入信息时要求 Weizenbaum 离开房间。
而当 Weizenbaum 提出可能要保存这些对话记录时，用户立即指出这会侵犯他们的隐私。&lt;/p>
&lt;p>如今，用户同样很可能向大语言模型透露非常私人的信息。
事实上，当前 LLM 最常见的用途之一就是提供个人建议与情感支持（Zao-Sanders, 2025）。
而且，系统表现得越像人类，用户就越倾向于披露敏感信息，同时却越不会担忧这种披露可能带来的危害（Ischen 等，2019）。
我们在前文（7.5.2 节）已提到，预训练数据本身往往包含电话号码、地址等私人信息。
这带来了严重风险：大语言模型可能会&lt;strong>泄露&lt;/strong>（leak）其训练数据中的信息。
也就是说，攻击者有可能从语言模型中提取出训练数据中的具体内容，例如某人的姓名、电话号码和住址（Henderson 等，2017；Carlini 等，2021）。
如果模型是在极其敏感的私有数据集（如电子健康记录）上训练的，这一问题将更加严峻。&lt;/p></description></item><item><title>7.6 大语言模型的评估</title><link>https://youkre.github.io/speech-and-language-processing/ch7-06/</link><pubDate>Sat, 27 Dec 2025 10:00:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch7-06/</guid><description>&lt;p>我们可以从多个维度评估语言模型，例如预测未见过文本准确性（accuracy），或在问答、翻译等具体任务上的表现，或其他因素如推理速度、能耗、公平性等。
我们将在接下来的三节中逐一探讨这些评估维度。&lt;/p>
&lt;h3 id="761-困惑度perplexity">7.6.1 困惑度（Perplexity）&lt;/h3>
&lt;p>正如我们在第 3 章首次提到的，评估语言模型的一种方法是衡量其预测未见文本的能力。
一个更好的语言模型能更准确地预测后续词元，因此当测试集中出现某个词时，它会赋予该词更高的概率（即“更不惊讶”）。&lt;/p>
&lt;p>若要判断两个语言模型中哪一个对某段文本建模得更好，只需比较它们对该文本分配的概率高低；实践中，由于我们通常在对数空间处理概率，因此更常见的是比较对数似然（log likelihood）的大小。&lt;/p>
&lt;p>我们一直在讨论逐词预测，即根据前面的上下文计算下一个词元 $w_i$ 的条件概率：$P(w_i \mid w_{&lt; i})$。
但正如第 3 章所述，利用链式法则（chain rule），我们可以将单个词元的预测概率扩展为整段文本的概率：&lt;/p>
$$
\begin{align*}
P(w_{1:n}) &amp;= P(w_1)P(w_2|w_1)P(w_3|w_{1:2}) \cdots P(w_n|w_{1:n−1}) \\
&amp;= \prod_{i=1}^n P(w_i|w_{&lt; i})
\tag{7.8}
\end{align*}
$$&lt;p>因此，一段文本的概率可以通过将其每个词元的条件概率相乘得到。
该文本的（对数）似然值是一个有用的指标，可用于比较两个语言模型在该文本上的优劣：&lt;/p>
$$
\log \text{likelihood}(w_{1:n}) = \log \prod_{i=1}^n P(w_i|w_{&lt; i})
\tag{7.9}
$$&lt;p>然而，我们通常使用困惑度（perplexity）而非对数似然来评估语言模型。
原因在于：一段测试集（或任意序列）的概率与其包含的词元数量密切相关。
事实上，文本越长，其整体概率就越小——从链式法则可以看出，随着相乘的项数增加，而每一项概率都小于 1，最终乘积会越来越小。
因此，我们需要一个按词元归一化、与长度无关的指标，以便公平比较不同长度的文本。&lt;/p>
&lt;p>概率的函数&lt;strong>困惑度&lt;/strong>正是这样一种长度归一化的评估指标。
回顾第 45 页的内容，模型 $\theta$ 在未见测试集上的困惑度，定义为该模型赋予测试集概率的倒数，并按测试集的词元总数进行归一化。
对于包含 $n$ 个词元的测试集 $w_{1:n}$，其困惑度为：&lt;/p>
$$
\begin{align*}
\text{Perplexity}_{\theta}(w_{1:n}) &amp;= P_{\theta}(w_{1:n})^{-\frac{1}{n}} \\
&amp;= \sqrt[n]{\frac{1}{P_{\theta}(w_{1:n})}}
\tag{7.10}
\end{align*}
$$&lt;p>为了直观理解困惑度如何由语言模型对每个新词的预测概率计算得出，我们可以将链式法则代入上式：&lt;/p></description></item><item><title>7.5 大语言模型的训练</title><link>https://youkre.github.io/speech-and-language-processing/ch7-05/</link><pubDate>Sat, 27 Dec 2025 08:52:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch7-05/</guid><description>&lt;p>我们如何训练一个语言模型？使用什么算法？在什么数据上进行训练？&lt;/p>
&lt;p>大语言模型的训练通常分为三个阶段，如图 7.12 所示：&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-7-12.png">&lt;/p>
&lt;p>&lt;strong>图 7.12&lt;/strong> 大语言模型训练的三个阶段：预训练（pretraining）、指令微调（instruction tuning）和偏好对齐（preference alignment）。&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>预训练&lt;/strong>（pretraining）：&lt;br>
在第一阶段，模型在海量文本语料库上进行训练，目标是逐步预测下一个词。
训练采用交叉熵损失（有时称为&lt;strong>语言建模损失&lt;/strong>），并通过反向传播将该损失信号贯穿整个网络。
训练数据通常来源于对互联网文本的大规模清洗与处理。
经过此阶段，模型具备了强大的词预测能力，并能生成连贯的文本。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>指令微调&lt;/strong>（instruction tuning），也称为监督微调（supervised finetuning, &lt;strong>SFT&lt;/strong>）：&lt;br>
在第二阶段，模型继续使用交叉熵损失进行训练，但目标变为遵循人类指令——例如回答问题、生成摘要、编写代码、翻译句子等。
为此，模型在一个专门构建的数据集上训练，该数据集包含大量“指令-正确响应”对。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>对齐&lt;/strong>（alignment），也称为&lt;strong>偏好对齐&lt;/strong>（preference alignment）：&lt;br>
在最后阶段，模型被进一步优化，以使其输出更有帮助且危害更小。
此时，模型接收的是偏好数据（preference data）：每条数据包含一个上下文以及两个可能的后续生成结果，由人工（或其他方式）标注为“可接受”（accepted）或“应拒绝”（rejected）。
模型随后通过强化学习（reinforcement learning）或其他基于奖励的算法进行训练，目标是更倾向于生成被接受的续写，而非被拒绝的续写。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>接下来我们将介绍预训练阶段，而指令微调与偏好对齐将在第 9 章详细讨论。&lt;/p>
&lt;h3 id="751-预训练的自监督训练算法">7.5.1 预训练的自监督训练算法&lt;/h3>
&lt;p>大语言模型预训练的核心思想，与我们在第 5 章学习词向量（如 word2vec）时所介绍的&lt;strong>自训练&lt;/strong>（self-training）或&lt;strong>自监督学习&lt;/strong>（self-supervision）是一致的。
在语言建模的自监督训练中，我们以一段文本语料作为训练材料，在每个时间步 $t$ 要求模型预测下一个词。
起初，模型在这个任务上表现很差，但由于我们始终知道正确答案（即语料中真实的下一个词！），随着时间推移，模型会越来越擅长预测正确的后续词元。
我们称这类模型为“自监督”的，是因为无需为数据额外添加人工标注的标签——词语本身的自然顺序就提供了监督信号！
我们只需训练模型，使其在预测训练序列中下一个真实词时的误差最小化。&lt;/p>
&lt;p>在实践中，训练语言模型意味着调整其底层架构的参数。
我们将在下一章介绍的 Transformer 模型包含多个权重矩阵，分别用于前馈网络和注意力机制。
和所有神经网络一样，这些参数通过误差反向传播（backpropagation）配合梯度下降进行优化。
因此，我们只需要一个可最小化的损失函数，并将其误差信号反向传递回整个网络。
语言建模所使用的损失函数，正是我们在第 4 章和第 6 章已经见过两次的&lt;strong>交叉熵损失&lt;/strong>（cross-entropy loss）。&lt;/p>
&lt;p>回顾一下，交叉熵损失衡量的是模型预测的概率分布与真实分布之间的差异。
这里的分布是针对整个词元词汇表 $V$ 的，因此损失函数形式为：&lt;/p>
$$
L_{CE} = -\sum_{w \in V} \mathbf{y}_t[w] \log \hat{\mathbf{y}}_t[w]
\tag{7.5}
$$&lt;p>在语言建模中，真实分布 $y_t$ 来源于我们知道的下一个词。
它被表示为一个one-hot 向量：在词汇表中，真实的下一个词对应的位置为 1，其余位置均为 0。
因此，语言建模的交叉熵损失实际上只取决于模型赋予正确下一个词的概率（公式 7.5 中其他项因乘以 0 而消失）。&lt;/p></description></item><item><title>7.4 生成与采样</title><link>https://youkre.github.io/speech-and-language-processing/ch7-04/</link><pubDate>Sat, 27 Dec 2025 01:24:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch7-04/</guid><description>&lt;p>语言模型在每一步应该生成哪个词元？&lt;/p>
&lt;p>生成结果取决于每个词元的概率，所以我们先回顾一下这个概率分布的来源。
语言模型的内部网络（无论是 Transformer，还是 LSTM、状态空间模型等替代架构）会为词汇表中的每个词元生成一个称为&lt;strong>logit&lt;/strong> 的得分（实数值）。
这个得分向量 $\mathbf{u}$ 随后通过 softmax 函数归一化，形成一个合法的概率分布——正如我们在第 4 章逻辑回归中所见。
所以，如果我们有一个形状为 $[1 \times |V|]$ 的 logit 向量 $\mathbf{u}$，其中每个元素对应一个可能的下一个词元的得分，那么将其通过 softmax 函数即可得到一个同样形状为 $[1 \times |V|]$ 的概率向量 $\mathbf{y}$，该向量为词汇表中每个词元分配一个概率，如下公式所示：&lt;/p>
$$
\mathbf{y} = \text{softmax}(\mathbf{u})
\tag{7.1}
$$&lt;p>图 7.7 展示了一个教学示例：为了便于说明，这里仅使用一个包含 4 个单词的简化词汇表来计算 softmax。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-7-7.png">&lt;/p>
&lt;p>&lt;strong>图 7.7&lt;/strong> 将 logit 向量 $\mathbf{u}$ 通过 softmax 转换为概率向量 $\mathbf{y}$。&lt;/p>
&lt;p>现在，有了这个词元上的概率分布，我们需要从中选择一个词元进行生成。
这种根据模型给出的概率选择要生成的词元的过程，通常称为&lt;strong>解码&lt;/strong>（decoding）。
如前所述，以从左到右的方式（对于阿拉伯语等从右向左书写的语言则是从右到左）进行解码，并在每一步基于之前已选词元不断选择下一个词元，这种生成方式被称为&lt;strong>自回归生成&lt;/strong>（autoregressive generation）。&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>&lt;/p>
&lt;h3 id="741-贪心解码greedy-decoding">7.4.1 贪心解码（Greedy decoding）&lt;/h3>
&lt;p>生成词元最简单的方法是：在每一步始终选择当前上下文中概率最高的词元，这种方法称为&lt;strong>贪心解码&lt;/strong>（greedy decoding）。
&lt;strong>贪心算法&lt;/strong>（greedy algorithm）是指在每一步都做出局部最优的选择，而不考虑该选择从全局来看是否最终最优。
因此，在贪心解码中，我们在每个生成时间步将 logits 转换为词元上的概率分布，然后选择概率最高的那个词元作为输出 $\hat{w}_t$（即取 argmax）：&lt;/p>
$$
\hat{w}_t = \mathrm{argmax}_{w \in V} \, P(w \mid \mathbf{w}_{&lt; t})
\tag{7.2}
$$&lt;p>图 7.8 显示，在我们的示例中，模型选择生成词元 &lt;code>all&lt;/code>。&lt;/p></description></item><item><title>7.3 提示</title><link>https://youkre.github.io/speech-and-language-processing/ch7-03/</link><pubDate>Fri, 26 Dec 2025 21:03:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch7-03/</guid><description>&lt;p>这种基于上下文的生成思路本身已经非常强大，而当语言模型经过专门训练以回答问题和遵循指令后，其能力会进一步提升。
这种额外的训练称为&lt;strong>指令微调&lt;/strong>（instruction-tuning）。
在指令微调中，我们从一个已通过词预测任务预训练好的基础语言模型出发，继续在一组特殊数据集上进行训练。该数据集由指令及其对应的正确构成。
数据集包含大量样本，如问题与答案、命令与执行结果，以及其他对话交互的示例。
我们将在第9章详细讨论指令微调的具体方法。&lt;/p>
&lt;p>经过指令微调的语言模型非常擅长遵循指令、回答问题以及进行对话，因此可以被有效&lt;strong>提示&lt;/strong>（prompted）。
所谓&lt;strong>提示&lt;/strong>（prompt），是指用户向语言模型输入的一段文本，用以引导模型完成某项有用的任务。
在提示过程中，用户的提示文本被传入语言模型，模型则以此为条件，逐个生成后续词元。
为特定任务设计高效提示的过程，被称为&lt;strong>提示工程&lt;/strong>（prompt engineering）。&lt;/p>
&lt;p>正如我们在介绍条件生成时所提到的，提示可以是一个问题（例如 &lt;code>What is a transformer network?&lt;/code>），也可以采用结构化格式（例如 &lt;code>Q: What is a transformer network? A: &lt;/code>）。
提示也可以是一条明确的指令（例如 &lt;code>Translate the following sentence into Hindi: ‘Chop the garlic finely’&lt;/code>）。&lt;/p>
&lt;p>更明确地限定可能答案范围的提示，通常能带来更好的性能。
例如，以下是一个用于情感分析的提示模板，它预先规定了可能的答案选项：&lt;/p>
&lt;blockquote>
&lt;p>A prompt consisting of a review plus an incomplete statement&lt;/p>
&lt;p>Human: Do you think that “input” has negative or positive sentiment?&lt;br>
Choices:&lt;br>
(P) Positive.&lt;br>
(N) Negative.&lt;br>&lt;/p>
&lt;p>Assistant: I believe the best answer is: (&lt;/p></description></item><item><title>7.2 文本的条件生成：基本原理</title><link>https://youkre.github.io/speech-and-language-processing/ch7-02/</link><pubDate>Fri, 26 Dec 2025 20:38:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch7-02/</guid><description>&lt;p>语言模型背后的一个基本原理是，几乎所有我们想用语言完成的任务，都可以建模为文本的&lt;strong>条件生成&lt;/strong>（conditional generation）。
（这里特指&lt;strong>解码器&lt;/strong>语言模型，即本章和下一章讨论的对象。）&lt;/p>
&lt;p>所谓条件生成，是指在给定一段输入文本的条件下生成新文本。
具体来说，我们向大语言模型（LLM）提供一段输入文本，称为&lt;strong>提示&lt;/strong>（prompt），然后让 LLM 以该提示及其后续已生成的词元为条件，逐个生成新的词元。
生成过程首先计算在已有上下文 $w_{&lt;i}$ 下，下一个词元 $w_i$ 的概率 $P(w_i \mid w_{&lt;i})$，再从该概率分布中采样出一个词元。&lt;/p>
&lt;p>后续章节会详述所有技术细节，但本节的目标只是建立直观理解。
仅仅通过计算下一个词的概率，LLM 如何完成各种不同的语言任务？&lt;/p>
&lt;p>假设我们要做情感分析这类分类任务。
我们可以将其视为条件生成问题，给语言模型如下提示：&lt;/p>
&lt;blockquote>
&lt;p>The sentiment of the sentence “I like Jackie Chan” is:&lt;/p>&lt;/blockquote>
&lt;p>然后比较接下来出现 “positive” 和 “negative” 这两个词元的条件概率，看哪个更高。
如图 7.4 所示，我们对比以下两个概率：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>P(“positive” | “The sentiment of the sentence ‘I like Jackie Chan’ is:”)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>P(“negative” | “The sentiment of the sentence ‘I like Jackie Chan’ is:”)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-7-4.png">&lt;/p>
&lt;p>&lt;strong>图 7.4&lt;/strong> 计算在给定前缀后，&lt;code>positive&lt;/code> 与 &lt;code>negative&lt;/code> 两个词元出现的概率。&lt;/p></description></item><item><title>7.1 语言模型的三种架构</title><link>https://youkre.github.io/speech-and-language-processing/ch7-01/</link><pubDate>Fri, 26 Dec 2025 18:21:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch7-01/</guid><description>&lt;p>我们在上文描述的那种从左到右（或称自回归）的语言模型架构，也就是本章将要定义的架构，实际上只是三种常见语言模型架构之一。&lt;/p>
&lt;p>这三种架构分别是：&lt;strong>编码器&lt;/strong>（encoder）、&lt;strong>解码器&lt;/strong>（decoder）和&lt;strong>编码器-解码器&lt;/strong>（encoder-decoder）。
图 7.3 示意了这三种架构。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-7-3.png">&lt;/p>
&lt;p>&lt;strong>图 7.3&lt;/strong> 语言模型的三种架构：解码器、编码器和编码器-解码器。
箭头表示三种架构中的信息流向。
解码器：输入词元，输出词元。
编码器：输入词元，输出每个词元的向量表示（编码）。
编码器-解码器：输入词元，输出一串词元。&lt;/p>
&lt;p>&lt;strong>解码器&lt;/strong>（decoder）就是我们上面介绍的架构。
它接收一串词元作为输入，并逐个迭代地生成输出词元。
GPT、Claude、Llama 和 Mistral 等大语言模型均采用解码器架构。
解码器的信息流是从左到右的，即模型仅根据前面的词来预测下一个词。
解码器属于生成式模型，给定输入词元，它们能生成全新的输出词元。
本章剩余部分及第8章将重点讨论解码器。&lt;/p>
&lt;p>&lt;strong>编码器&lt;/strong>（encoder）接收一个词元序列作为输入，并为每个词元输出一个向量表示（即编码）。
编码器通常是掩码语言模型（masked language model），其训练方式是遮盖某个词，然后利用该词左右两侧的上下文来预测它。
BERT、RoBERTa 以及 BERT 系列的其他模型都属于编码器模型。
编码器不是生成式模型，不用于生成文本。
它们通常被用作分类器的基础，例如输入一段文本，输出一个标签（如情感倾向、主题类别等）。
这种用途通过微调（finetuning）实现（在有监督的数据上训练）。
我们将在第10章介绍编码器模型。&lt;/p>
&lt;p>&lt;strong>编码器-解码器&lt;/strong>（encoder-decoder）接收一个词元序列作为输入，并输出另一串词元。
它与纯解码器模型的关键区别在于：输入词元与输出词元之间的对应关系更松散，且常用于在不同类型词元之间进行映射。
也就是说，在编码器-解码器中，输出词元可能来自完全不同的词表，长度也可能远长于或短于输入。
例如，机器翻译就使用编码器-解码器架构：输入词元是一种语言，输出词元是另一种语言，且长度通常不同。
语音识别也采用这种架构：输入是代表语音的词元，输出是代表文本的词元。
我们将在第12章介绍用于机器翻译的编码器-解码器架构，在第15章介绍其在语音识别中的应用。&lt;/p>
&lt;p>这三种架构可以用多种神经网络实现。
目前最广泛使用的网络类型是&lt;strong>Transformer&lt;/strong>，我们将在第8章介绍。
在 Transformer 中，每个输入词元都会经过一列 Transformer 层的处理，每一层由若干不同类型的子网络组成。
第13章将介绍一种较早但仍具影响力的架构——LSTM（一种循环神经网络）。
此外，还有许多更新的架构，例如&lt;strong>状态空间模型&lt;/strong>（state space models）。&lt;/p>
&lt;p>本书大部分内容将聚焦于 Transformer，但就本章而言，我们将保持架构中立：把实现解码器功能的网络视为一个黑箱。
该黑箱的输入是一串词元，输出是一个可从中采样的词元概率分布。
我们将以与具体网络无关的方式，描述学习与解码的机制。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch7">第 7 章 大语言模型&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch7-02">7.2 文本的条件生成：基本原理&lt;/a>
&lt;/nav></description></item><item><title>第 7 章 大语言模型</title><link>https://youkre.github.io/speech-and-language-processing/ch7/</link><pubDate>Fri, 26 Dec 2025 16:10:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch7/</guid><description>&lt;blockquote>
&lt;p>“在任意时刻，我们究竟知道多少？我相信，远比我们意识到自己知道的要多得多。”&lt;br>&lt;/p>
&lt;p>——阿加莎·克里斯蒂，《移动的手指》&lt;/p>&lt;/blockquote>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-image-7_Im1.png">&lt;/p>
&lt;p>幻想文学中充满了被赋予说话能力的无生命物体。
从奥维德笔下皮格马利翁的雕像，到玛丽·雪莱创作的弗兰肯斯坦故事，人类不断重述着这样一类故事：创造出某物，然后与它交谈。
传说米开朗基罗完成《摩西》雕像后，觉得它栩栩如生，竟轻拍它的膝盖，命令它开口说话。
这或许并不奇怪。语言是人类智慧与意识的标志。对话是最基本的语言场景。这是我们儿时最先学会的语言形式，也是我们日常持续使用的语言方式——无论是在教学或学习、点午餐，还是与家人朋友交谈。&lt;/p>
&lt;p>本章介绍&lt;strong>大语言模型&lt;/strong>（Large Language Model，简称 &lt;strong>LLM&lt;/strong>）——一种能与人类进行对话交互的计算智能体。
LLM 专为与人交互而设计，这一事实对其架构和应用具有深远影响。&lt;/p>
&lt;p>早在60年前，一个名为 ELIZA 的计算系统（Weizenbaum, 1966）就已揭示了这些影响。
ELIZA 被设计成模拟罗杰斯学派的心理治疗师。它凸显了聊天机器人面临的若干关键问题。
例如，用户会深深投入情感，进行极为私密的对话，甚至有人要求 Weizenbaum 在他们打字时离开房间。
这种情感投入与隐私问题提醒我们：必须审慎部署语言模型，并认真考虑其对交互者的影响。&lt;/p>
&lt;p>本章首先介绍 LLM 的计算原理；下一章将讨论其在 Transformer 架构中的具体实现。
使 LLM 成为可能的核心新思想是&lt;strong>预训练&lt;/strong>（pretraining）。因此，我们先从“从文本中学习”这一基本思路入手，这也是 LLM 训练的基本方式。&lt;/p>
&lt;p>流畅使用语言的人，在理解和产出过程中会调动海量知识。
这些知识表现为多种形式，其中最显而易见的便是词汇，即我们对词语及其意义与用法所构建的丰富表征。
正因如此，词汇成为一个有效视角，来探索人类与机器如何从文本中获取知识。&lt;/p>
&lt;p>对成年人词汇量的估计，在不同语言内部及跨语言之间差异巨大。
例如，据估计，讲美国英语的年轻人，词汇量介于3万到10万之间，差异取决于所采用的资源，以及对“掌握一个词”的定义不同。
由此可简单推知：儿童必须每天学习约7到10个新词，日复一日，才能在20岁时达到观测到的词汇水平。
事实上，从小学高年级到高中阶段的实证研究也证实了这一增长速率。
儿童是如何实现如此高速的词汇增长的？
研究表明，大部分词汇知识是在阅读过程中附带习得的。
阅读是一种丰富的语境处理过程。我们并非孤立地逐个学习单词。
事实上，在某些学习阶段，词汇增长的速度甚至超过了新词出现的频率！
这表明，每次阅读一个词时，我们也在强化对与之相关其他词的理解。&lt;/p>
&lt;p>这些事实与第5章提出的&lt;strong>分布假设&lt;/strong>（distributional hypothesis）一致。该假设认为，意义的某些方面仅凭我们一生所接触的文本即可习得，其依据是词语与其共现词之间的复杂关联（以及这些共现词自身的共现关系）。
分布假设指出：我们能从文本中获取大量知识，且这些知识可在初次习得很久之后仍被有效调用。
当然，结合现实世界的交互或其他模态信息，可以构建更强大的模型。但即便仅使用文本，效果也已非常显著。&lt;/p>
&lt;p>现代自然语言处理革命之所以成为可能，正是因为大语言模型能够通过在（非常）大规模文本语料中反复根据上下文预测下一个词，从而习得关于语言、语境乃至世界的全部知识。
在本章及下一章中，我们将形式化这一思想，并称之为&lt;strong>预训练&lt;/strong>——即通过在海量文本中迭代预测词元（token），来学习语言与世界知识。经此过程得到的模型，称为&lt;strong>大语言模型&lt;/strong>。
正因预训练所获得的知识，大语言模型在各类自然语言任务上展现出卓越性能。&lt;/p>
&lt;p>语言模型能从词语预测中学到什么？
请看下面的例子。
你认为模型在学习预测下划线处应填入哪个词时（正确答案以蓝色标出），可能学到哪些类型的知识？
在继续阅读下一段之前，请先针对每个例子思考一下：&lt;/p>
&lt;blockquote>
&lt;p>With roses, dahlias, and peonies, I was surrounded by ____ flowers&lt;br>
（玫瑰、大丽花和牡丹环绕着我，我被____花朵包围了）&lt;/p>
&lt;p>The room wasn’t just big it was ____ enormous&lt;br>
（这个房间不只是大，而是____巨大）&lt;/p></description></item><item><title>6.5 神经网络的训练</title><link>https://youkre.github.io/speech-and-language-processing/ch6-06/</link><pubDate>Fri, 26 Dec 2025 16:05:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-06/</guid><description>&lt;p>前馈神经网络属于监督式机器学习的一种：对于每个输入样本 $\mathbf{x}$，我们已知其对应的真实输出 $\mathbf{y}$。
系统通过公式 6.13 生成的是预测输出 $\hat{\mathbf{y}}$，即模型对真实标签 $\mathbf{y}$ 的估计。&lt;br>
训练的目标，就是为每一层 $i$ 学习到合适的参数 $\mathbf{W}^{[i]}$ 和 $\mathbf{b}^{[i]}$，使得对每个训练样本，模型的预测 $\hat{\mathbf{y}}$ 尽可能接近真实值 $\mathbf{y}$。&lt;/p>
&lt;p>总体而言，我们采用第 5 章介绍的逻辑回归训练方法来实现这一目标，因此读者在继续阅读之前应已熟悉该章内容。
我们将探索简单通用网络的算法，而不是专门针对情感或语言建模设计的网络。&lt;/p>
&lt;p>首先，我们&lt;strong>损失函数&lt;/strong>（Loss Function）来衡量模型输出与真实标签之间差距，通常采用逻辑回归中使用的&lt;strong>交叉熵损失&lt;/strong>（cross-entropy loss）作为损失函数。&lt;/p>
&lt;p>其次，为了找到使损失函数最小化的参数，我们使用第 5 章介绍的&lt;strong>梯度下降&lt;/strong>（gradient descent）算法。&lt;/p>
&lt;p>第三，梯度下降要求我们知道损失函数关于所有参数的&lt;strong>梯度&lt;/strong>——即一个包含损失函数对每个参数偏导数的向量。
在逻辑回归中，我们可以直接计算损失函数对某个权重 $w$ 或偏置 $b$ 的导数。
但在神经网络中，模型往往包含数百万个分布在多层中的参数，这就带来了一个难题：当损失是在网络末端计算的，我们如何求出第一层中某个权重对最终损失的偏导数？
换言之，如何将损失“分配”回所有中间层？
解决这一问题的算法就是著名的&lt;strong>误差反向传播&lt;/strong>（error backpropagation），也称为&lt;strong>反向自动微分&lt;/strong>（backward differentiation）。&lt;/p>
&lt;h3 id="661-损失函数">6.6.1 损失函数&lt;/h3>
&lt;p>神经网络中使用的&lt;strong>交叉熵损失&lt;/strong>（cross-entropy loss）与我们在逻辑回归中见到的完全相同。
如果神经网络被用作二分类器（即输出层使用 sigmoid 激活函数），其损失函数就与公式 (4.23) 中的逻辑回归损失一致：&lt;/p>
$$
\begin{align*}
L_{\text{CE}}(\hat{y}, y)
&amp;= -\log p(y \mid \mathbf{x}) \\
= -\big[ y \log \hat{y} + (1 - y) \log(1 - \hat{y}) \big]
\tag{6.25}
\end{align*}
$$&lt;p>如果网络用于三类或更多类别的分类任务，则损失函数与第 5 章第 80 页介绍的&lt;strong>多项逻辑回归&lt;/strong>（multinomial regression）损失完全相同。为方便起见，我们在此简要回顾其要点。
当类别数超过两类时，我们需要将真实标签 $\mathbf{y}$ 和预测结果 $\hat{\mathbf{y}}$ 都表示为向量。
假设我们执行的是&lt;strong>硬分类&lt;/strong>（hard classification），即每个样本仅属于一个正确类别。
此时，真实标签 $\mathbf{y}$ 是向量，有 $K$ 个元素，每个元度对应一个类别，其中若正确类别为 $c$，则 $\mathbf{y}_c = 1$，其余元素均为 0。
回忆一下，这种仅有一个元素为 1、其余为 0 的向量称为 &lt;strong>one-hot 向量&lt;/strong>（独热向量）。
-分类器输出的预测向量 $\hat{\mathbf{y}}$ 同样包含 $K$ 个元素，每个元素 $\hat{y}_k$ 表示模型估计的条件概率 $p(\mathbf{y}_k = 1 \mid \mathbf{x})$。&lt;/p></description></item><item><title>6.5 作为神经网络分类器输入的嵌入表示</title><link>https://youkre.github.io/speech-and-language-processing/ch6-05/</link><pubDate>Fri, 26 Dec 2025 12:29:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-05/</guid><description>&lt;p>虽然人工设计特征是构建分类器的传统方法，但大多数 NLP 中的神经网络应用并不使用人工构造的特征作为输入。
相反，我们利用深度学习从数据中自动学习特征的能力，将词元（token）表示为嵌入向量（embeddings）。
在本节中，我们将使用第 5 章介绍过的静态词嵌入方法（如 word2vec 或 GloVe）来表示每个词元。
所谓静态嵌入（static embedding），是指每个词元都由一个固定的向量表示——该向量在预训练阶段一次性学习完成，之后存入一个大型字典中。
每当需要引用某个词元时，我们只需从该字典中取出其对应的嵌入向量即可。&lt;/p>
&lt;p>然而，当我们把神经网络模型应用于语言建模任务（如第 8 章所述）时，情况会更复杂：我们会使用一种更强大的嵌入形式，称为&lt;strong>上下文嵌入&lt;/strong>（contextual embedding）。
上下文嵌入的特点是：同一个词在不同上下文中会有不同的嵌入表示。
此外，网络在执行词语预测任务的过程中，会学习到这些嵌入。&lt;/p>
&lt;p>现在，让我们回到前一节的文本分类场景，但改用静态嵌入作为输入特征，而非人工设计的特征。
我们聚焦于推理阶段，此时所有输入词元的嵌入已经预先训练好。
每个嵌入是一个维度为 $d$ 的向量，用于表示一个输入词元。
存储这些嵌入的字典被称为&lt;strong>嵌入矩阵&lt;/strong>（embedding matrix）$\mathbf{E}$。
嵌入矩阵 $\mathbf{E}$ 的每一行对应词汇表 $V$ 中的一个词元，表示为一个 $d$ 维的（行）向量。
词汇表中有 $|V|$ 个词元，每个词元在 $\mathbf{E}$ 中对应一行，因此 $\mathbf{E}$ 的形状为 $[|V| \times d]$。
只要在神经 NLP 系统的输入中使用嵌入，这个嵌入矩阵 $\mathbf{E}$ 就扮演核心角色，包括后续章节将介绍的基于 Transformer 的大语言模型。&lt;/p>
&lt;p>给定一个输入词元序列，例如 &lt;code>dessert was great&lt;/code>，我们首先将其转换为词汇表中的索引（这些索引是在最初使用 BPE 或 SentencePiece 进行词元化时生成的）。
于是，&lt;code>dessert was great&lt;/code> 可能被表示为索引序列 $\mathbf{w} = [3, 9824, 226]$
接着，通过索引从嵌入矩阵 $\mathbf{E}$ 中选取对应的行（例如第 3 行、第 9824 行、第 226 行），从而得到每个词元的嵌入向量。&lt;/p></description></item><item><title>6.3 前馈神经网络</title><link>https://youkre.github.io/speech-and-language-processing/ch6-03/</link><pubDate>Thu, 25 Dec 2025 23:44:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-03/</guid><description>&lt;p>现在，我们稍微正式一些介绍最简单的神经网络——&lt;strong>前馈网络&lt;/strong>（feedforward network）。
前馈网络是一种多层网络，其单元之间的连接不含环路：每一层单元的输出仅传递给下一层的单元，不会反馈到前面更低的层。
（第 8 章将介绍包含环路的网络，即&lt;strong>循环神经网络&lt;/strong>（recurrent neural networks）。）&lt;/p>
&lt;p>出于历史原因，多层网络（尤其是前馈网络）有时被称为&lt;strong>多层感知机&lt;/strong>（multi-layer perceptrons，简称 &lt;strong>MLP&lt;/strong>）。
严格来说，这是一种误称，因为现代多层网络中的单元并非真正的感知机（感知机是纯线性的，而现代网络由带有非线性激活函数（如 Sigmoid）的单元构成）。但这一名称早已沿用成习。&lt;/p>
&lt;p>简单的前馈网络包含三类节点：输入单元、隐藏单元和输出单元。&lt;/p>
&lt;p>图 6.8 展示了这样一个网络。输入层 $\mathbf{x}$ 是一个标量值组成的向量，与图 6.2 中所示相同。&lt;/p>
&lt;p>神经网络的核心是&lt;strong>隐藏层&lt;/strong> $\mathbf{h}$，它由若干&lt;strong>隐藏单元&lt;/strong> $h_i$ 构成。
每个隐藏单元都是第 6.1 节描述的神经单元：先对其输入进行加权求和，再应用一个非线性函数。
在标准架构中，各层之间是&lt;strong>全连接&lt;/strong>（fully-connected）的，即每一层的每个单元都接收前一层所有单元的输出作为输入，相邻两层之间每一对单元都有连接。
因此，每个隐藏单元都会对所有输入单元的输出进行求和。&lt;/p>
&lt;p>回想一下，单个隐藏单元的参数包括一个权重向量和一个偏置。
对于整个隐藏层，我们将每个单元 $i$ 的权重向量和偏置合并为一个权重矩阵 $\mathbf{W}$ 和一个&lt;strong>偏置向量&lt;/strong> $\mathbf{b}$（见图 6.8）。
权重矩阵 $\mathbf{W}$ 中的元素 $\mathbf{W}_{ji}$ 表示从第 $i$ 个输入单元 $x_i$ 到第 $j$ 个隐藏单元 $h_j$ 的连接权重。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-6-8.png">&lt;/p>
&lt;p>&lt;strong>图 6.8&lt;/strong> 一个简单的两层前馈网络，包含一个输入层、一个隐藏层和一个输出层（通常在计数网络层数时，不将输入层计入）。&lt;/p>
&lt;p>使用单个矩阵 $\mathbf{W}$ 表示整层权重的一大优势在于：前馈网络的隐藏层计算可通过简单的矩阵运算高效完成。
实际上，整个计算只需三步：将权重矩阵 $\mathbf{W}$ 与输入向量 $\mathbf{x}$ 相乘；加上偏置向量 $\mathbf{b}$；对结果应用激活函数 $g$（如前述的 Sigmoid、tanh 或 ReLU）。&lt;/p>
&lt;p>因此，隐藏层的输出向量 $\mathbf{h}$ 可表示为（此处以 sigmoid 函数 $\sigma$ 为例）：&lt;/p></description></item><item><title>6.1 单元</title><link>https://youkre.github.io/speech-and-language-processing/ch6-01/</link><pubDate>Thu, 25 Dec 2025 15:02:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-01/</guid><description>&lt;p>神经网络的基本构建单元是一个单一的计算单元。
该单元接收一组实数值作为输入，对这些输入进行某种计算，并产生一个输出。&lt;/p>
&lt;p>本质上，一个神经单元对其输入进行加权求和，并在求和结果中加入一个额外的项，称为&lt;strong>偏置项&lt;/strong>（bias term）。
给定一组输入 $x_1, \dots, x_n$，该单元对应有一组权重 $w_1, \dots, w_n$ 和一个偏置 $b$，因此加权和 $z$ 可表示为：&lt;/p>
$$
z = b + \sum_i w_i x_i
\tag{6.1}
$$&lt;p>通常，用向量记号来表达这个加权和更为方便.回忆线性代数中的定义，&lt;strong>向量&lt;/strong>本质上就是一个数字列表或数组。
因此，我们我们可以用权重向量 $w$、标量偏置 $b$ 和输入向量 $x$ 来表示 $z$，并将求和运算替换为简洁的&lt;strong>点积&lt;/strong>（dot product）：&lt;/p>
$$
z = \mathbf{w} \cdot \mathbf{x} + b
\tag{6.2}
$$&lt;p>如公式 (6.2) 所定义，$z$ 仅是一个实数值。&lt;/p>
&lt;p>然而，神经单元并不会直接将 $z$（即 $x$ 的线性函数）作为输出，而是对 $z$ 应用一个非线性函数 $f$。
我们将该函数的输出称为该单元的&lt;strong>激活值&lt;/strong>（activation），记作 $a$。
由于我们目前只建模单个单元，该节点的激活值实际上就是整个网络的最终输出，通常将其记为 $y$。
因此，$y$ 定义如下：&lt;/p>
$$
y = a = f(z)
$$&lt;p>下面将介绍三种常用的非线性函数：Sigmoid 函数、tanh 函数和修正线性单元（ReLU）。出于教学目的，我们先从 Sigmoid 函数 开始，因为它已在第 4 章中出现过：&lt;/p></description></item><item><title>5.9 向量模型的评估</title><link>https://youkre.github.io/speech-and-language-processing/ch5-09/</link><pubDate>Wed, 24 Dec 2025 09:51:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch5-09/</guid><description>&lt;p>向量模型最重要的评估指标是&lt;strong>外部评估&lt;/strong>（extrinsic evaluation），即在实际自然语言处理任务中使用这些向量，并检验其性能是否优于其他模型。&lt;/p>
&lt;p>尽管如此，&lt;strong>内部评估&lt;/strong>（intrinsic evaluation）仍然具有参考价值。
最常见的内部评估方法是测试模型在&lt;strong>相似性&lt;/strong>任务上的表现：计算算法给出的词相似度得分与人类标注的词相似度评分之间的相关性。
&lt;strong>WordSim-353&lt;/strong>（Finkelstein 等, 2002）是一个常用的数据集，包含 353 对名词，每对由人类评分为 0 到 10 分；例如，(&lt;em>plane&lt;/em>, &lt;em>car&lt;/em>) 的平均得分为 5.77。
&lt;strong>SimLex-999&lt;/strong>（Hill 等, 2015）是一个更复杂的数据集，它衡量的是&lt;strong>语义相似性&lt;/strong>（如 &lt;em>cup&lt;/em> 和 &lt;em>mug&lt;/em>）而非仅仅是&lt;strong>语义关联性&lt;/strong>（如 &lt;em>cup&lt;/em> 和 &lt;em>coffee&lt;/em>），并涵盖了具体与抽象的形容词、名词和动词对。
&lt;strong>TOEFL 数据集&lt;/strong> 包含 80 道题目，每道题给出一个目标词和四个备选项，任务是从中选出正确的同义词，例如：&lt;em>Levied is closest in meaning to: imposed, believed, requested, correlated&lt;/em>
（Landauer 和 Dumais, 1997）。
所有这些数据集中的词均不带上下文。&lt;/p>
&lt;p>更现实的是包含上下文的内部相似性任务。
斯坦福上下文词相似度（Stanford Contextual Word Similarity, SCWS）数据集（Huang 等, 2012）和 WiC（Word-in-Context）数据集（Pilehvar 和 Camacho-Collados, 2019）提供了更丰富的评估场景。
SCWS 提供了 2,003 对词语在句子上下文中的相似度人工评分；而 WiC 则给出同一个目标词在两个不同句子中的用法，要求判断这两个用法是否属于同一词义（详见附录 G）。
此外，&lt;strong>语义文本相似度&lt;/strong>（Semantic Textual Similarity, STS）任务（Agirre 等, 2012, 2015）用于评估句子级相似度算法的性能，包含多对句子，每对都配有由人类标注的相似度分数。&lt;/p></description></item><item><title>5.8 偏见与嵌入</title><link>https://youkre.github.io/speech-and-language-processing/ch5-08/</link><pubDate>Wed, 24 Dec 2025 09:41:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch5-08/</guid><description>&lt;p>除了能从文本中学习词义，嵌入——遗憾的是——也会复现文本中隐含的偏见与刻板印象。&lt;/p>
&lt;p>前一节提到，嵌入能粗略建模关系相似性：例如，“king” – “man” + “woman” 的结果最接近 “queen”，这对应类比 &lt;em>man:woman::king:queen&lt;/em>。
但同样的嵌入类比也暴露出性别刻板印象。
例如，Bolukbasi 等人（2016）发现，在基于新闻文本训练的 word2vec 嵌入中，“computer programmer” – “man” + “woman” 的最近职业词是 &lt;strong>“homemaker”&lt;/strong>（家庭主妇）；
嵌入还暗示了这样的类比：“father” 之于 “doctor”，正如 “mother” 之于 “nurse”。
这类问题可能导致 Crawford（2017）和 Blodgett 等人（2020）所说的 &lt;strong>分配性伤害&lt;/strong>（allocational harm），即系统在分配资源（如工作机会或信用）时，对不同群体产生不公平结果。
例如，若招聘算法使用嵌入来筛选潜在程序员或医生，就可能错误地降低包含女性姓名的文档的权重。&lt;/p>
&lt;p>更严重的是，嵌入不仅反映输入文本的统计特性，还会&lt;strong>放大偏见&lt;/strong>：性别相关词汇在嵌入空间中变得比原始文本中更具性别倾向（Zhao et al., 2017；Ethayarajh et al., 2019b；Jia et al., 2020），这种偏见甚至比现实劳动力就业统计数据中的偏见更为夸张（Garg et al., 2018）。&lt;/p>
&lt;p>嵌入还编码了人类推理中固有的&lt;strong>内隐联想&lt;/strong>（implicit associations）。
&lt;strong>内隐联想测验&lt;/strong>（Implicit Association Test, IAT）通过测量人们对不同类别词汇的反应延迟，来评估其概念（如 “flowers” 或 “insects”）与属性（如 “pleasantness” 和 “unpleasantness”）之间的关联强度。&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>
研究发现，美国人在内隐联想中表现出以下倾向：
将非裔美国人姓名与不愉快词汇的关联强于欧裔美国人姓名；
研究中发现，美国人将非裔美国人姓名与不愉快词汇的关联强于欧裔美国人姓名；
将男性姓名更多地与数学联系在一起，而将女性姓名更多地与艺术联系在一起；
并将老年人姓名与不愉快词汇相关联（Greenwald et al., 1998；Nosek et al., 2002a, 2002b）。
Caliskan 等人（2017）使用 GloVe 向量和余弦相似度（而非人类反应时间），成功复现了上述所有内隐联想结果。
例如，非裔美国人姓名（如 &lt;em>Leroy&lt;/em>、&lt;em>Shaniqua&lt;/em>）与不愉快词的 GloVe 余弦值更高，而欧裔美国人姓名（如 &lt;em>Brad&lt;/em>、&lt;em>Greg&lt;/em>、&lt;em>Courtney&lt;/em>）则与愉快词的余弦值更高。
这类嵌入问题属于 Crawford（2017）和 Blodgett 等人（2020）定义的 &lt;strong>表征性伤害&lt;/strong>（representational harm）—— 即系统通过贬低或忽视某些社会群体而造成的伤害。
因此，任何依赖词情感信息的嵌入感知算法，都可能加剧对非裔美国人的偏见。&lt;/p></description></item><item><title>5.7 嵌入向量的语义特性</title><link>https://youkre.github.io/speech-and-language-processing/ch5-07/</link><pubDate>Wed, 24 Dec 2025 08:56:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch5-07/</guid><description>&lt;p>本节简要总结一些已被研究的词嵌入语义特性。&lt;/p>
&lt;h3 id="不同类型的相似性或关联性">不同类型的相似性或关联性&lt;/h3>
&lt;p>向量语义模型的一个重要参数是用于统计共现的上下文窗口大小。
这一参数对稀疏的 tf-idf 向量和稠密的 word2vec 向量都适用。
通常，窗口设为目标词左右各 1 到 10 个词（总上下文长度为 2–20 个词）。&lt;/p>
&lt;p>具体选择取决于表示的目标。
较短的上下文窗口倾向于生成更偏向句法（syntactic）的表示，因为信息来自紧邻的词语。
在这种设置下，与目标词 $w$ 余弦相似度最高的词，通常是语义（semantic）相近且词性（part of speech）相同的词。
而当使用长上下文窗口计算向量时，与目标词 $w$ 余弦相似度最高的词，往往是主题相关但语义不相似的词。&lt;/p>
&lt;p>例如，Levy 和 Goldberg（2014a）发现，使用 skip-gram 模型，当窗口为 ±2 时，与 &lt;em>Hogwarts&lt;/em> （出自《哈利·波特》系列）最相似的词是其他虚构学校的名称，如 &lt;em>Sunnydale&lt;/em>（出自《吸血鬼猎人巴菲》）或 &lt;em>Evernight&lt;/em>（出自某吸血鬼系列）。
而当窗口扩大到 ±5 时，与 &lt;em>Hogwarts&lt;/em> 最相似的词变成了《哈利·波特》系列中的主题相关词，如 &lt;em>Dumbledore&lt;/em>、&lt;em>Malfoy&lt;/em> 和 &lt;em>half-blood&lt;/em>。&lt;/p>
&lt;p>此外，通常还需区分两种词间相似性或关联性（Schütze &amp;amp; Pedersen, 1993）：
&lt;strong>一阶共现&lt;/strong>（first-order co-occurrence），有时称为&lt;strong>组合关联&lt;/strong>（syntagmatic association），指两个词经常彼此邻近出现。
例如，&lt;em>wrote&lt;/em> 是 &lt;em>book&lt;/em> 或 &lt;em>poem&lt;/em> 的一阶关联词。
&lt;strong>二阶共现&lt;/strong>（second-order co-occurrence），有时称为&lt;strong>聚合关联&lt;/strong>（paradigmatic association），指两个词具有相似的上下文邻居。
例如，&lt;em>wrote&lt;/em> 与 &lt;em>said&lt;/em>、&lt;em>remarked&lt;/em> 等词构成二阶关联。&lt;/p>
&lt;h3 id="类比与关系相似性">类比与关系相似性&lt;/h3>
&lt;p>词嵌入的另一重要语义特性，是其捕捉关系含义（relational meanings）的能力。
早在认知科学的早期研究中，Rumelhart 和 Abrahamson（1973）就提出了一种基于向量空间的&lt;strong>平行四边形模型&lt;/strong>（parallelogram model），用于解决形如 $\textit{a is to b as } a^\ast \textit{ is to what?}$ 的简单类比问题。
例如，给定问题：&lt;em>apple:tree::grape:?&lt;/em>，即 “&lt;em>apple 之于 tree，正如 grape 之于 ___&lt;/em>”，系统应填入 &lt;em>vine&lt;/em>（藤蔓）。
在该模型中（见图 5.8），计算从 &lt;em>apple&lt;/em> 到 &lt;em>tree&lt;/em> 的向量偏移：$\overrightarrow{tree} - \overrightarrow{apple}$；将此偏移加到 &lt;em>grape&lt;/em> 的向量上：$\overrightarrow{grape} + (\overrightarrow{tree} - \overrightarrow{apple})$；找出距离该结果点最近的词，即为答案。&lt;/p></description></item><item><title>5.6 嵌入向量的可视化</title><link>https://youkre.github.io/speech-and-language-processing/ch5-06/</link><pubDate>Tue, 23 Dec 2025 22:22:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch5-06/</guid><description>&lt;blockquote>
&lt;p>“我能很好地感知很多维度，只要这些维度大约是二维的。”&lt;/p>
&lt;p>已故经济学家 马丁·舒比克&lt;/p>&lt;/blockquote>
&lt;p>可视化嵌入向量对于帮助我们理解、应用和改进这些词义模型至关重要。
但如何可视化一个（例如）100维的向量呢？&lt;/p>
&lt;p>&lt;strong>图8&lt;/strong>：针对三类名词的多维尺度分析（Multidimensional scaling）。&lt;/p>
&lt;p>&lt;strong>图9&lt;/strong>：基于向量相关性距离的三类名词层次聚类。&lt;/p>
&lt;p>要可视化一个嵌入在空间中的词 &lt;em>w&lt;/em> 的词义，最简单方法是列出与 &lt;em>w&lt;/em> 最相似的词，即按词汇表中所有词向量与 &lt;em>w&lt;/em> 的向量之间的余弦相似度进行排序。
例如，使用GloVe算法计算出的某个嵌入向量，与 &lt;em>frog&lt;/em> （青蛙）最接近的7个词是：&lt;em>frogs&lt;/em>（青蛙，复数）、&lt;em>toad&lt;/em>（蟾蜍）、&lt;em>litoria&lt;/em>（雨滨蛙属）、&lt;em>leptodactylidae&lt;/em>（细趾蟾科）、&lt;em>rana&lt;/em>（蛙属）、&lt;em>lizard&lt;/em>（蜥蜴）和 &lt;em>eleutherodactylus&lt;/em>（细趾蟾属）（Pennington 等, 2014）。&lt;/p>
&lt;p>另一种可视化方法是使用聚类算法，展示嵌入空间中哪些词彼此相似的层次结构。
左侧未加标题的图例使用了对部分名词嵌入向量进行层次聚类的方法作为可视化手段（Rohde 等, 2006）。&lt;/p>
&lt;p>然而，目前最常见的可视化方法可能是将词的 100 维空间投影到二维空间中。
图 5.1 和图 5.9 展示了这样一种可视化效果，它们使用了一种称为 t-SNE 的投影方法（van der Maaten 和 Hinton, 2008）。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch5-05">5.5 Word2vec&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch5-07">5.7 嵌入向量的语义特性&lt;/a>
&lt;/nav></description></item><item><title>5.5 Word2vec</title><link>https://youkre.github.io/speech-and-language-processing/ch5-05/</link><pubDate>Tue, 23 Dec 2025 22:21:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch5-05/</guid><description>&lt;p>在前面的章节中，我们了解了如何将一个词表示为稀疏的长向量，其维度对应词汇表中的词或文档集合中的文档。
现在，我们介绍一种更强大的词表示方法：&lt;strong>嵌入（embeddings）&lt;/strong>，即短而稠密的向量。
与迄今为止所见的向量不同，嵌入向量是&lt;strong>短的&lt;/strong>，其维度 $d$ 通常在50到1000之间，远小于之前遇到的庞大词汇量 $|V|$ 或文档数量 $D$。
这些维度 $d$ 并没有明确的解释意义。
并且这些向量是&lt;strong>稠密的&lt;/strong>：向量元素不再是稀疏的、大部分为零的计数或计数函数，而是可以为负的实数值。&lt;/p>
&lt;p>事实证明，在每一项自然语言处理任务中，稠密向量的表现都优于稀疏向量。
虽然我们尚未完全理解所有原因，但有一些合理的解释。
将词表示为300维的稠密向量，比起表示为50,000维的向量，能让分类器学习的权重少得多，更小的参数空间可能有助于提升泛化能力并避免过拟合。
稠密向量也可能更有效地捕捉同义关系。
例如，在稀疏向量表示中，像 &lt;em>car&lt;/em> 和 &lt;em>automobile&lt;/em> 这样的同义词对应的维度是彼此独立且无关的；因此，稀疏向量可能无法捕捉到一个以 &lt;em>car&lt;/em> 为邻近词的词与另一个以 &lt;em>automobile&lt;/em> 为邻近词的词之间的相似性。&lt;/p>
&lt;p>本节中介绍一种计算嵌入的方法：&lt;strong>负采样 skip-gram&lt;/strong>（skip-gram with negative sampling），有时简称为 &lt;strong>SGNS&lt;/strong>。
跳字算法是名为 &lt;strong>word2vec&lt;/strong> 的软件包中的两种算法之一，因此该算法有时被笼统地称为 word2vec（Mikolov 等，2013a；Mikolov 等，2013b）。
word2vec 方法速度快、训练高效，且代码和预训练嵌入模型在线上易于获取。
Word2vec 嵌入是&lt;strong>静态嵌入&lt;/strong>（static embeddings），意味着该方法为词汇表中的每个词学习一个固定的嵌入表示。
在第 10 章中，我们将介绍学习动态&lt;strong>上下文嵌入&lt;/strong>（context embeddings）的方法，如流行的 &lt;strong>BERT&lt;/strong> 表示系列，其中每个词的向量会因其所处的不同上下文而变化。&lt;/p>
&lt;p>word2vec 的核心理念是：不再统计每个词 $w$ 在某个词（比如 &lt;em>apricot&lt;/em>）附近出现的频率，而是训练一个分类器来执行一个二元预测任务：“词 $w$ 是否可能出现在 &lt;em>apricot&lt;/em> 附近？”
我们实际上并不关心这个预测任务本身；而是将分类器学习到的&lt;strong>权重&lt;/strong>作为词的嵌入表示。&lt;/p>
&lt;p>这里的&lt;strong>革命性思想&lt;/strong>在于，我们可以直接使用连续文本作为此类分类器的隐式监督训练数据：一个在目标词 &lt;em>apricot&lt;/em> 附近出现的词 $c$，就充当了“词 $c$ 是否可能出现在 &lt;em>apricot&lt;/em> 附近？”这一问题的黄金标准“正确答案”。
这种方法通常被称为&lt;strong>自监督&lt;/strong>（self-supervision），它避免了任何人工标注监督信号的需求。
这一思想最初在神经语言建模任务中被提出，Bengio 等人（2003）和 Collobert 等人（2011）表明，一个神经语言模型（一种学习根据前文预测下一个词的神经网络）可以直接使用连续文本中的下一个词作为其监督信号，并可在执行此预测任务的同时学习每个词的嵌入表示。&lt;/p></description></item><item><title>5.3 基于计数的简单嵌入</title><link>https://youkre.github.io/speech-and-language-processing/ch5-03/</link><pubDate>Tue, 23 Dec 2025 21:02:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch5-03/</guid><description>&lt;blockquote>
&lt;p>“三维空间中向量最重要的属性是：位置、位置、位置。”&lt;/p>
&lt;p>—— Randall Munroe，来自 &lt;a href="https://xkcd.com/2358/">xkcd 第 2358 期&lt;/a> 的悬停提示&lt;/p>&lt;/blockquote>
&lt;p>我们现在介绍第一种计算词向量嵌入的方法。
这种最简单的词义向量模型基于&lt;strong>共现矩阵&lt;/strong>（co-occurrence matrix），用来表示词语共同出现的频率。
我们定义一种特定的共现矩阵，称为&lt;strong>词-上下文矩阵&lt;/strong>（word-context matrix）：矩阵的每一行对应词汇表中的一个词（目标词）；每一列对应词汇表中另一个词作为上下文出现的次数。
因此，这个矩阵的维度是 $|V| \times |V|$（$|V|$ 表示词汇表大小），每个单元格记录的是：在某个训练语料中，某一行的目标词与某一列的上下文词在邻近位置共同出现的次数。&lt;/p>
&lt;p>那么，“邻近”具体指什么？
可以有多种实现方式，但我们先采用最简单的一种：以目标词为中心，左右各取 4 个词作为窗口。
这样，每个单元格就表示：在训练语料中，该列的上下文词出现在该行目标词 ±4 词范围内的总次数。&lt;/p>
&lt;p>我们用四个词来演示这一过程：&lt;em>cherry&lt;/em>（樱桃）、&lt;em>strawberry&lt;/em>（草莓）、&lt;em>digital&lt;/em>（数字的）、&lt;em>information&lt;/em>（信息）。
对每个词，我们从语料中选取一个实例，并展示其 ±4 词的上下文窗口：&lt;/p>
&lt;ul>
&lt;li>is traditionally followed by &lt;strong>cherry&lt;/strong> pie, a traditional dessert&lt;/li>
&lt;li>often mixed, such as &lt;strong>strawberry&lt;/strong> rhubarb pie. Apple pie&lt;/li>
&lt;li>computer peripherals and personal &lt;strong>digital&lt;/strong> assistants. These devices usually&lt;/li>
&lt;li>a computer. This includes &lt;strong>information&lt;/strong> available on the internet&lt;/li>
&lt;/ul>
&lt;p>如果我们在一个大型语料中统计每个词的所有出现，并计算其上下文词的频次，就能得到完整的词-上下文共现矩阵。
但完整的矩阵非常庞大：因为对词汇表中的每个词（共 $|V|$ 个），都要统计它与其他所有词的共现次数，所以维度是 $|V| \times |V|$。
因此，我们改用一个小规模的例子来说明。&lt;br>
假设我们只关注上述四个词，并且只考虑以下三个上下文词：&lt;em>a&lt;/em>、&lt;em>computer&lt;/em>、&lt;em>pie&lt;/em>。&lt;br>
此外，我们仅使用上面给出的微型语料进行计数。&lt;/p></description></item><item><title>5.2 向量语义：原理</title><link>https://youkre.github.io/speech-and-language-processing/ch5-02/</link><pubDate>Tue, 23 Dec 2025 18:13:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch5-02/</guid><description>&lt;p>向量语义是 NLP 中表示词义的标准方法，有助于我们建模上一节中看到的许多词义特征。
该模型的根源可追溯至20世纪50年代，当时两个重要思想汇聚在一起：一个是上文提到的 Osgood 在 1957 年提出，使用三维空间中的一个点来表示词语内涵的想法；另一个是由 Joos（1950）、Harris（1954）和Firth（1957）等语言学家提出的，通过词语在语言使用中的&lt;strong>分布&lt;/strong>（即其邻近词语或语法环境）来定义其意义。
他们的核心思想是：出现在非常相似分布中的两个词（即其邻近词语相似），其意义也相似。&lt;/p>
&lt;p>例如，假设你不知道“ongchoi”（一个来自粤语的新借词）的含义，但你在以下语境中看到了它：&lt;/p>
&lt;p>(5.1) Ongchoi 加蒜炒着吃很美味。&lt;/p>
&lt;p>(5.2) Ongchoi 配米饭非常棒。&lt;/p>
&lt;p>(5.3) ……用咸酱烹制的 ongchoi 叶子……&lt;/p>
&lt;p>而你之前在其他语境中见过许多类似的词语：&lt;/p>
&lt;p>(5.4) ……菠菜加蒜炒着吃配米饭……&lt;/p>
&lt;p>(5.5) ……甜菜的茎和叶都很美味……&lt;/p>
&lt;p>(5.6) ……羽衣甘蓝和其他咸味的绿叶蔬菜……&lt;/p>
&lt;p>由于 &lt;em>ongchoi&lt;/em> 和 &lt;em>spinach&lt;/em>（菠菜）、&lt;em>chard&lt;/em>（甜菜）、&lt;em>collard greens&lt;/em>（羽衣甘蓝）一样，都出现在 &lt;em>rice&lt;/em>（米饭）、&lt;em>garlic&lt;/em>（蒜）、&lt;em>delicious&lt;/em>（美味）、&lt;em>salty&lt;/em>（咸的）等词的周围，这可能暗示 ongchoi 是一种与其他绿叶蔬菜相似的绿叶蔬菜。&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>
可以通过计算 &lt;em>ongchoi&lt;/em> 周围上下文中的词语出现次数，用计算的方法实现同样的推理。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-5-1.png">&lt;/p>
&lt;p>&lt;strong>图5.1&lt;/strong> 对“sweet”附近部分词语的 200 维 word2vec 嵌入进行二维（t-SNE）可视化。图中可见，语义相近的词在空间中彼此靠近。&lt;/p>
&lt;p>向量语义的核心思想是，将一个词表示为一个多维语义空间中的点，该空间由词语邻近词的分布情况（我们将在下文介绍具体方法）推导而来。
用于表示词语的向量被称为&lt;strong>嵌入&lt;/strong>（embeddings）。
“嵌入”一词源于其数学含义，即从一个空间或结构映射到另一个空间或结构，尽管其含义已有所演变；详见本章末尾。&lt;/p>
&lt;p>图 5.1 展示了由 word2vec 算法学习得到的词嵌入可视化结果。显示了把选定词语（“sweet”附近的词）从 200 维空间降维投影到 2 维空间后的位置。
可以看到，“sweet”最近的邻居包括 &lt;em>honey&lt;/em>（蜂蜜）、&lt;em>candy&lt;/em>（糖果）、&lt;em>juice&lt;/em>（果汁）、&lt;em>chocolate&lt;/em>（巧克力）等语义相关的词。
语义相近的词在高维空间中彼此靠近，这一思想对语言模型和其他自然语言处理应用具有强大作用。
例如，第 4 章中的情感分类器依赖训练集和测试集中出现相同的词。
但如果用嵌入表示词语，分类器只要遇到&lt;strong>意义相近的词&lt;/strong>，就能判断情感倾向。
此外，正如我们将看到的，像图 5.1 所示的向量语义模型，可以从文本中自动学习，无需人工标注（即无监督学习）。&lt;/p>
&lt;p>本章首先介绍一种简单的教学式嵌入模型：一个词的意义由其上下文中邻近词的出现频次构成的向量来定义。
我们引入这个模型，是为了帮助理解“向量如何表示词义”这一核心概念。不过，更成熟的变体（比如第 11 章将介绍的 &lt;strong>tf-idf 模型&lt;/strong>）才是实际中需要掌握的重要方法。
这类方法生成的向量通常很长，而且是稀疏的（sparse），即大部分元素为零（因为大多数词根本不会出现在彼此的上下文中）。
随后，我们将介绍 &lt;strong>word2vec 模型族&lt;/strong>，它能生成短而&lt;strong>稠密&lt;/strong>（dense）的向量，并具备更强的语义表达能力。&lt;/p></description></item><item><title>5.1 词汇语义</title><link>https://youkre.github.io/speech-and-language-processing/ch5-01/</link><pubDate>Tue, 23 Dec 2025 17:33:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch5-01/</guid><description>&lt;p>我们先介绍一些关于词义的基本原则。
该如何表示一个词的意义呢？
在第3章的 n-gram 模型以及传统的自然语言处理应用中，我们对一个词的唯一表示，就是一串字母，或者词汇表中的一个索引。
这种表示方式，其实和哲学中的一种传统做法差别不大——也许你在入门逻辑课上见过：直接用小型大写字母拼出这个词，来代表它的意义。
比如，“dog”的意义写作 DOG，“cat”写作 CAT，有时还会加一个撇号，写成 DOG’。&lt;/p>
&lt;p>但把词义简单地用大写形式表示，显然不是一个令人满意的模型。
你可能听说过语义学家芭芭拉·帕蒂（Barbara Partee）讲过的一个笑话（Carlson, 1977）：&lt;/p>
&lt;blockquote>
&lt;p>问：生命的意义是什么？&lt;br>
答：LIFE’&lt;/p>&lt;/blockquote>
&lt;p>我们当然可以做得更好！
毕竟，我们希望词义模型能帮我们完成各种任务。
它应该能告诉我们，有些词意义相近（比如 &lt;em>cat&lt;/em> 和 &lt;em>dog&lt;/em>）；有些词互为反义（比如 &lt;em>cold&lt;/em> 和 &lt;em>hot&lt;/em> 相反）；有些带有正面情感色彩（如 &lt;em>happy&lt;/em>），有些则带有负面色彩（如 &lt;em>sad&lt;/em>）。
它还应能体现这样一种事实：&lt;em>buy&lt;/em>（买）、&lt;em>sell&lt;/em>（卖）和 &lt;em>pay&lt;/em>（付）这三个词，其实描述的是同一个购买事件的不同视角。
（如果我从你那里买了东西，你很可能就把它卖给了我，而我也很可能付了钱给你。）
更一般地说，一个词义模型应当支持我们进行推理，从而完成与意义相关的任务，比如问答或对话。&lt;/p>
&lt;p>本节将简要总结这些理想特性。它们源自语言学中对词义的研究，这一领域称为&lt;strong>词汇语义&lt;/strong>（lexical semantics）。我们将在附录 G 和第 21 章中再次回到这个话题，并进一步扩展这份清单。&lt;/p>
&lt;h3 id="词元与词义">词元与词义&lt;/h3>
&lt;p>我们先看一个例子：同一个词（比如 &lt;em>mouse&lt;/em>）在词典中可能有多种定义（以下内容简化自在线词典 WordNet）：&lt;/p>
&lt;blockquote>
&lt;p>mouse（名词）&lt;/p>
&lt;ol>
&lt;li>多种小型啮齿动物之一……&lt;/li>
&lt;li>一种手动操作的设备，用于控制光标……&lt;/li>
&lt;/ol>&lt;/blockquote>
&lt;p>这里的 &lt;em>mouse&lt;/em> 形式称为&lt;strong>词元&lt;/strong>（lemma），也叫&lt;strong>引述形式&lt;/strong>（citation form）。
&lt;em>mice&lt;/em> 的词元同样是 &lt;em>mouse&lt;/em>；词典通常不会为 &lt;em>mice&lt;/em> 这样的屈折形式单独设条目。
类似地，&lt;em>sing&lt;/em> 是 &lt;em>sing&lt;/em>、&lt;em>sang&lt;/em>、&lt;em>sung&lt;/em> 的词元。
在许多语言中，动词以不定式作为词元。
例如，西班牙语中表示“睡觉”的不定式 &lt;em>dormir&lt;/em>，就是&lt;em>duermes&lt;/em>（“你睡觉”）的词元。
像 &lt;em>sung&lt;/em>、&lt;em>carpets&lt;/em>、&lt;em>sing&lt;/em> 或 &lt;em>duermes&lt;/em> 这些具体形式，统称为&lt;strong>词形&lt;/strong>（wordforms）。&lt;/p>
&lt;p>如上例所示，一个词元可以对应多个含义。
&lt;em>mouse&lt;/em> 既可以指啮齿动物，也可以指光标控制设备。
我们将 &lt;em>mouse&lt;/em> 的每一种含义称为一个&lt;strong>词义&lt;/strong>（word sense）。
词元常常具有&lt;strong>多义性&lt;/strong>（polysemous），即包含多个词义。这会给理解带来困难。
例如，有人在搜索引擎中输入 “mouse info”，他想找的是宠物，还是电脑配件？
第 10 章和附录 G 将讨论多义性问题，并介绍&lt;strong>词义消歧&lt;/strong>（word sense disambiguation），即在特定上下文中判断某个词使用的是哪种词义的任务。&lt;/p></description></item><item><title>4.12 分类中的危害防范</title><link>https://youkre.github.io/speech-and-language-processing/ch4-12/</link><pubDate>Tue, 23 Dec 2025 09:31:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-12/</guid><description>&lt;p>在使用分类器时，必须警惕并避免可能造成的各类危害——这些危害不仅存在于朴素贝叶斯分类器中，也存在于后续章节将介绍的其他分类算法中。&lt;/p>
&lt;p>一类典型的危害是&lt;strong>表征性伤害&lt;/strong>（representational harms）（Crawford, 2017；Blodgett et al., 2020），即系统通过贬低某个社会群体而造成的伤害，例如强化对该群体的负面刻板印象。&lt;br>
例如，Kiritchenko 和 Mohammad（2018）评估了200个情感分析系统在成对句子上的表现：这些句子内容完全相同，仅在人名上有所区别——一组使用常见的非裔美国人名字（如 &lt;em>Shaniqua&lt;/em>），另一组使用常见的欧裔美国人名字（如 &lt;em>Stephanie&lt;/em>），这些人名选自 Caliskan 等人（2017）的研究（该研究将在第6章讨论）。&lt;br>
他们发现，大多数系统对包含非裔美国人名字的句子赋予了更低的情感得分和更强烈的负面情绪，这反映出并进一步强化了将非裔美国人与负面情绪相关联的刻板印象（Popp et al., 2003）。&lt;/p>
&lt;p>在其他任务中，分类器可能同时引发表征性伤害和其他类型的伤害，例如&lt;strong>言论压制&lt;/strong>（silencing）。
以&lt;strong>毒性检测&lt;/strong>（toxicity detection）这一重要的文本分类任务为例：其目标是识别仇恨言论、辱骂、骚扰或其他形式的有害语言。
尽管这类分类器的初衷是减少社会伤害，但它们本身也可能造成新的伤害。
例如，研究人员发现，一些被广泛使用的毒性检测模型会错误地将某些&lt;strong>无害语句&lt;/strong>标记为“有毒”，仅仅因为这些语句提到了某些身份群体，如女性（Park et al., 2018）、盲人（Hutchinson et al., 2020）或同性恋者（Dixon et al., 2018；Dias Oliva et al., 2021）；或者仅仅因为使用了某些语言变体的特征表达，例如非裔美国人白话英语（African-American Vernacular English, AAVE）（Sap et al., 2019；Davidson et al., 2019）。
这类&lt;strong>假阳性错误&lt;/strong>可能导致相关群体自身或关于他们的正当言论被平台屏蔽或压制。&lt;/p>
&lt;p>这些问题的根源可能来自训练数据中的偏见或其他缺陷；一般来说，机器学习系统会复制甚至放大其训练数据中存在的偏见。‘但问题也可能源于标签本身（例如人工标注者的偏见）、所使用的资源（如情感词典或预训练词嵌入等模型组件），甚至模型架构本身（例如模型被优化的目标函数）。
尽管目前已有大量研究致力于缓解这些偏见（例如通过审慎选择训练数据来源），但我们尚无普适的解决方案。
因此，在引入任何自然语言处理模型时，都必须认真审视上述因素，并予以明确说明。
一种有效做法是为每个模型版本发布一份&lt;strong>模型卡片&lt;/strong>（model card）（Mitchell et al., 2019）。模型卡片用于记录机器学习模型的关键信息，包括：&lt;/p>
&lt;ul>
&lt;li>所用训练算法及参数&lt;/li>
&lt;li>训练数据的来源、动机与预处理方式&lt;/li>
&lt;li>评估数据的来源、动机与预处理方式&lt;/li>
&lt;li>预期用途与目标用户&lt;/li>
&lt;li>模型在不同人口统计群体或其他环境情境下的性能表现&lt;/li>
&lt;/ul>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch4-11">4.11 统计显著性检验&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch4-13">4.13 模型的解释&lt;/a>
&lt;/nav></description></item><item><title>4.8 多项逻辑回归中的学习</title><link>https://youkre.github.io/speech-and-language-processing/ch4-08/</link><pubDate>Tue, 23 Dec 2025 08:49:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-08/</guid><description>&lt;p>多项逻辑回归的损失函数将二元逻辑回归的损失函数从 2 个类别推广到了 $K$ 个类别。
回顾一下，二元逻辑回归的交叉熵损失函数（重复自公式 5.23）为：&lt;/p>
$$
L_{CE}(\hat{y}, y) = -\log p(y|x) = -[y \log \hat{y} + (1 - y)\log(1 - \hat{y})]
\tag{4.36}
$$&lt;p>多项逻辑回归的损失函数将公式 4.36 中的两项（一项在 $y = 1$ 时非零，另一项在 $y = 0$ 时非零）推广为 $K$ 项。
如上所述，对于多项回归，将 $y$ 和 $\hat{y}$ 都表示为向量。
真实标签 $y$ 是一个包含 $K$ 个元素的向量，每个元素对应一个类别，当正确类别为 $c$ 时，$y_c = 1$，而 $y$ 的其余所有元素均为 0。
分类器将生成一个包含 $K$ 个元素的估计向量 $\hat{y}$，其中每个元素 $\hat{y}_k$ 表示估计的概率 $p(y_k = 1|x)$。&lt;/p>
&lt;p>把二元逻辑回归推广，可以得到单个样本 $x$ 的损失函数，它是 $K$ 个输出类别的对数之和，每个项由指示函数 $y_k$ 加权（公式 4.37）。
这实际上就等于正确类别 $c$ 的负对数概率（公式 4.38）：&lt;/p></description></item><item><title>4.7 梯度下降</title><link>https://youkre.github.io/speech-and-language-processing/ch4-07/</link><pubDate>Mon, 22 Dec 2025 22:36:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-07/</guid><description>&lt;p>使用梯度下降的目标是找到最优的权重：即最小化为模型定义的损失函数。
在下面的公式 4.25 中，我们将明确表示交叉熵损失函数 $L_{CE}$ 是权重的函数。
在机器学习中，我们通常将待学习的参数统称为 $\theta$；在逻辑回归中，$\theta = \{\mathbf{w}, b\}$。
因此，目标是找到一组权重，使得损失函数在所有训练样本上的平均值最小：&lt;/p>
$$
\hat{\theta} = \underset{\theta}{\mathrm{argmin}} \frac{1}{m} \sum_{i=1}^m L_{CE}( f(x^{(i)};\theta), y^{(i)})
\tag{4.25}
$$&lt;p>该如何找到这个（或任何）损失函数的最小值呢？
梯度下降是一种找到函数最小值的方法：找出函数在参数空间 $\theta$ 中哪个方向上升最陡峭，然后朝相反方向移动。
其核心思想是：如果你在峡谷中徒步，想要最快地走到谷底的河流处，可能会环顾四周，找到地面坡度最陡的方向，然后朝着那个方向下坡行走。&lt;/p>
&lt;p>对于逻辑回归而言，这个损失函数恰好是&lt;strong>凸函数&lt;/strong>（convex）。
凸函数最多只有一个最小值，不存在会陷入的局部最小值，因此无论从哪个点开始，梯度下降都能保证找到全局最小值。
（相比之下，多层神经网络的损失函数是非凸的，梯度下降在训练神经网络时可能会陷入局部最小值，而永远无法找到全局最优解。）&lt;/p>
&lt;p>该算法（以及梯度的概念）是为方向向量设计的，不过我们先考虑一个更简单的可视化场景：假设系统的参数只是一个标量 $w$，如图 4.4 所示。&lt;/p>
&lt;p>假设随机初始化 $\mathbf{w}$ 为某个值 $w_1$，并假设损失函数 $L$ 恰好具有图 4.4 所示的形状。
此时，我们需要算法告诉我们，在下一次迭代中，是应该向左移动（使 $w_2$ 小于 $w_1$）还是向右移动（使 $w_2$ 大于 $w_1$），才能到达最小值。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-4-4.png">&lt;/p>
&lt;p>&lt;strong>图 4.4&lt;/strong> 通过迭代找到该损失函数最小值，第一步是沿函数斜率的反方向移动 $\mathbf{w}$。由于斜率为负，需要将 $\mathbf{w}$ 向正方向（右侧）移动。此处上标用于表示学习步骤，因此 $w^1$ 表示 $\mathbf{w}$ 的初始值（即 0），$w^2$ 表示第二步的值，依此类推。&lt;/p>
&lt;p>梯度下降算法计算当前点处损失函数的&lt;strong>梯度&lt;/strong>（gradient），并朝其相反方向移动，以此来解决这个问题。
一个多变量函数的梯度是一个向量，指向函数值增长最快的方向。
梯度是斜率在多变量情况下的推广，因此对于像图 4.4 中这样的单变量函数，我们可以非正式地将梯度视为斜率。
图 4.4 中的虚线显示了在点 $\mathbf{w} = w^1$ 处这个假想损失函数的斜率。
可以看到，这条虚线的斜率为负。
因此，为了找到最小值，梯度下降告诉我们应朝相反方向移动：即把 $\mathbf{w}$ 向正方向移动。&lt;/p></description></item><item><title>4.6 交叉熵损失函数</title><link>https://youkre.github.io/speech-and-language-processing/ch4-06/</link><pubDate>Mon, 22 Dec 2025 21:03:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-06/</guid><description>&lt;p>我们需要一个损失函数，用于衡量对于一个观测样本 $x$，分类器的输出（$\hat{y} = \sigma(\mathbf{w} \cdot \mathbf{x} + b)$）与正确输出（$y$，即 0 或 1）的接近程度。
我们将这个函数表示为：&lt;/p>
$$
L(\hat{y}, y) = \hat{y} \text{ 与真实标签 } y \text{ 的差异程度}
\tag{4.20}
$$&lt;p>通过一个损失函数来实现这一点，该函数倾向于让训练样本的正确类别标签具有更高的可能性。
这种方法被称为&lt;strong>条件最大似然估计&lt;/strong>（conditional maximum likelihood estimation）：我们选择一组参数 $\mathbf{w}$ 和 $b$，在给定样本 $x$ 的条件下，&lt;strong>最大化训练数据中真实标签 $y$ 的对数概率&lt;/strong>。
由此得到的损失函数称为&lt;strong>负对数似然损失&lt;/strong>（negative log likelihood loss），通常简称为&lt;strong>交叉熵损失&lt;/strong>（cross-entropy loss）。&lt;/p>
&lt;p>我们应用于单个观测样本 $x$，来推导这个损失函数。
目标是学习一组权重，使其最大化正确标签的概率 $p(y|x)$。
由于只有两种离散结果（1 或 0），这是一个伯努利分布（Bernoulli distribution）。可以将分类器对单个样本产生的概率 $p(y|x)$ 表示如下（注意：当 $y=1$ 时，公式 (5.21) 简化为 $\hat{y}$；当 $y=0$ 时，简化为 $1-\hat{y}$）：&lt;/p>
$$
p(y|x) = \hat{y}^y (1 - \hat{y})^{1-y}
\tag{4.21}
$$&lt;p>现在对等式两边取对数。这在数学上非常方便，且不会影响结果；因为能使概率最大化的参数值，同样也能使该概率的对数最大化：&lt;/p>
$$
\begin{align*}
\log p(y|x) &amp;= \log[\hat{y}^y (1 - \hat{y})^{1-y}] \\
&amp;= y \log \hat{y} + (1 - y) \log(1 - \hat{y}) \tag{4.22}
\end{align*}
$$&lt;p>公式 4.22 描述了一个应被最大化的对数似然。
为了将其转换为一个损失函数（即我们需要最小化的量），只需对公式 4.22 取负号。
结果就是交叉熵损失 $L_{CE}$：&lt;/p></description></item><item><title>4.5 逻辑回归中的学习</title><link>https://youkre.github.io/speech-and-language-processing/ch4-05/</link><pubDate>Mon, 22 Dec 2025 20:48:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-05/</guid><description>&lt;p>模型的参数，即权重 $\mathbf{w}$ 和偏置 $b$，是如何学习得到的呢？
逻辑回归是监督分类的一个实例，在该任务中，我们知道每个样本 $x$ 的正确标签 $y$（0 或 1）。
系统通过公式 4. 产生的是 $\hat{y}$，即系统对真实标签 $y$ 的估计值。
我们的目标是学习到一组参数（即 $\mathbf{w}$ 和 $b$），使得每个训练样本的预测值 $\hat{y}$ 尽可能接近其真实标签 $y$。&lt;/p>
&lt;p>这需要两个在本章引言中已预示过的组成部分。
第一个一种指标，来衡量当前预测标签 $\hat{y}$ 与真实标注标签 $y$ 之间的接近程度。
我们通常不直接衡量相似性，而是讨论其对立面：系统输出与真实输出之间的&lt;strong>距离&lt;/strong>，并称此距离为&lt;strong>损失函数&lt;/strong>（loss function）或&lt;strong>代价函数&lt;/strong>（cost function）。
在下一节中，我们将介绍逻辑回归以及神经网络中常用的损失函数——&lt;strong>交叉熵损失&lt;/strong>（cross-entropy loss）。&lt;/p>
&lt;p>第二个需要的是一个优化算法，用于迭代地更新权重，以最小化该损失函数。
解决这一问题的标准算法是&lt;strong>梯度下降&lt;/strong>（gradient descent）；我们将在后续章节中介绍&lt;strong>随机梯度下降&lt;/strong>（stochastic gradient descent）算法。&lt;/p>
&lt;p>在接下来的两节中，将以更简单的二元逻辑回归为例来描述这些算法，然后在第 4.8 节中再转向多项逻辑回归。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch4-04">4.4 多项逻辑回归&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch4-06">4.6 交叉熵损失函数&lt;/a>
&lt;/nav></description></item><item><title>4.4 多项逻辑回归</title><link>https://youkre.github.io/speech-and-language-processing/ch4-04/</link><pubDate>Mon, 22 Dec 2025 20:40:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-04/</guid><description>&lt;p>有时我们需要处理超过两个类别的分类问题。
例如，可能需要进行三类情感分类（正面、负面或中性）。
或者，可能会分配第 17 章将要介绍的一些标签，比如一个词的词性（从 10个、30 个甚至 50 个不同的词性中选择），或一个短语的命名实体类型（从“人名”、“地点”、“组织”等标签中选择）。
或者在大语言模型中，词汇表中 |V| 个词，预测下一个词其中的哪一个，这就是 |V| 分类。&lt;/p>
&lt;p>在这种情况下，使用&lt;strong>多项逻辑回归&lt;/strong>（multinomial logistic regression），也被称为&lt;strong>Softmax回归&lt;/strong>（在早期的NLP文献中，有时会看到它被称为&lt;strong>最大熵分类器&lt;/strong>，maxent classifier）。
在多项逻辑回归中，我们希望将每个观测样本标记为 $K$ 个类别中的某一个 $k$，并规定只有一个类别是正确的（有时称为&lt;strong>硬分类&lt;/strong>；一个观测样本不能同时属于多个类别）。
我们采用以下表示方式：每个输入 $\mathbf{x}$ 的输出 $\mathbf{y}$ 将是一个长度为 $K$ 的向量。
如果类别 $c$ 是正确的类别，我们将 $y_c$ 设为1，并将 $\mathbf{y}$ 的所有其他元素设为0，即 $y_c = 1$ 且 $y_j = 0 \quad \forall j \neq c$。
像这样的向量 $\mathbf{y}$（只有一个值为1，其余为0）被称为&lt;strong>独热向量&lt;/strong>（one-hot vector）。
分类器的任务是生成一个估计向量 $\hat{\mathbf{y}}$。
对于每个类别 $k$，值 $\hat{y}_k$ 将是分类器对概率 $p(y_k = 1|\mathbf{x})$ 的估计。&lt;/p>
&lt;h3 id="531-softmax函数">5.3.1 Softmax函数&lt;/h3>
&lt;p>多项逻辑分类器使用 Sigmoid 函数的一个推广版本，称为&lt;strong>Softmax函数&lt;/strong>，来计算 $p(y_k = 1|\mathbf{x})$。
Softmax函数接收一个包含 $K$ 个任意值的向量 $\mathbf{z} = [z_1, z_2, ..., z_K]$，并将其映射为一个概率分布，其中每个值都在 $[0,1]$ 范围内，且所有值的总和为1。
与Sigmoid函数一样，它也是一种指数函数。&lt;/p></description></item><item><title>4.3 使用逻辑回归进行分类</title><link>https://youkre.github.io/speech-and-language-processing/ch4-03/</link><pubDate>Mon, 22 Dec 2025 17:49:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-03/</guid><description>&lt;p>前一节中的 Sigmoid 函数为我们提供了一种方法：对一个输入样本 $x$，计算概率 $P(y = 1|x)$。&lt;/p>
&lt;p>那么，如何决定将哪个类别分配给一个测试样本 $x$ 呢？
对于给定的 $x$，如果概率 $P(y = 1|x)$ 大于 0.5，就判定为“是”（即类别 1），否则判定为“否”（即类别 0）。
我们将 0.5 称为&lt;strong>决策边界&lt;/strong>（decision boundary）：&lt;/p>
$$
\text{decision}(x) =
\begin{cases}
1 &amp; \text{if } P(y = 1|x) > 0.5 \\
0 &amp; \text{otherwise}
\end{cases}
$$&lt;p>接下来，我们通过一些语言任务的例子，来展示如何使用逻辑回归作为分类器。&lt;/p>
&lt;h3 id="431-情感分类">4.3.1 情感分类&lt;/h3>
&lt;p>假设我们正在对电影评论文本进行二元情感分类，需要判断是否将情感类别“+”或“−”分配给一篇评论文档 &lt;code>doc&lt;/code>。
我们将每个输入样本表示为下表所示的 6 个特征 $x_1$ 到 $x_6$；图 4.2 展示了一个小型测试文档及其提取出的特征向量。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>变量&lt;/th>
&lt;th>定义&lt;/th>
&lt;th>图 5.2 中的值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>$x_1$&lt;/td>
&lt;td>文档中正面情感词典词的数量&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$x_2$&lt;/td>
&lt;td>文档中负面情感词典词的数量&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$x_3$&lt;/td>
&lt;td>$\begin{cases} 1 &amp; \text{if “no” in doc} \\ 0 &amp; \text{otherwise} \end{cases}$&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$x_4$&lt;/td>
&lt;td>第一和第二人称代词的数量&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$x_5$&lt;/td>
&lt;td>$\begin{cases} 1 &amp; \text{if “!” in doc} \\ 0 &amp; \text{otherwise} \end{cases}$&lt;/td>
&lt;td>0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>$x_6$&lt;/td>
&lt;td>文档词数的自然对数（ln）&lt;/td>
&lt;td>$\ln(66) = 4.19$&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-4-2.png">&lt;/p></description></item><item><title>4.1 机器学习与分类</title><link>https://youkre.github.io/speech-and-language-processing/ch4-01/</link><pubDate>Mon, 22 Dec 2025 15:01:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-01/</guid><description>&lt;p>分类的目标是接收一个单一输入（我们将每个输入称为一个 &lt;strong>样本&lt;/strong>（observation）），从中提取一些有用的 &lt;strong>特征&lt;/strong>（features）或属性，并据此将该样本 &lt;strong>分类&lt;/strong>（classify）到一组离散类别中的某一个。
我们用 $x$ 表示输入，输出则来自一个固定的类别集合 $Y = \{y_1, y_2, \dots, y_M\}$。
我们的目标是返回一个预测类别 $\hat{y} \in Y$。
符号 $\hat{y}$（称为 &lt;strong>hat&lt;/strong> 或 &lt;strong>尖音符&lt;/strong>）用于表示估计值或预测值。
有时你也会看到输出类别集合被记作 $C$ 而非 $Y$。&lt;/p>
&lt;p>以情感分析为例，输入 $x$ 可能是一篇评论或其他文本，而输出集合 $Y$ 可能是：&lt;/p>
$$
\{\texttt{positive}, \texttt{negative}\}
$$&lt;p>或&lt;/p>
$$
\{0, 1\}
$$&lt;p>对于语言识别（language identification）任务，输入可能是一段待判定语种的文本，输出集合 $Y$ 则是所有可能的语言，例如：&lt;/p>
$$
Y = \{\texttt{Abkhaz}, \texttt{Ainu}, \texttt{Albanian}, \texttt{Amharic}, ..., \texttt{Zulu}, \texttt{Zuñi}\}
$$&lt;p>实现分类的方法有很多。
一种方法是使用人工编写的规则。
例如，我们可以制定如下规则：&lt;/p>
&lt;blockquote>
&lt;p>如果单词 “love” 出现在 x 中，且其前未出现单词 “don’t”，则分类为 positive。&lt;/p>&lt;/blockquote>
&lt;p>人工规则可以作为现代自然语言处理系统的一部分组件。例如，在情感分析中，人工整理的正面词与负面词列表就是此类规则的应用，我们将在下文进一步讨论。
然而，规则往往较为脆弱，随着场景或数据随时间变化，规则可能失效；而且在许多任务中，不同特征之间存在复杂的交互关系（比如上述规则中 “don’t” 对 “love” 的否定作用），人类很难设计出在各种情况下都有效的规则。&lt;/p>
&lt;p>另一种我们稍后将介绍的方法是：通过提示（prompting）来要求大语言模型给某些文本加上标签。
提示工程可能非常强大，但也存在明显缺陷：大语言模型常常会产生“幻觉”（hallucinate），可能无法解释为何选择某个特定类别。&lt;/p></description></item><item><title>第4章 罗辑回归与文本分类</title><link>https://youkre.github.io/speech-and-language-processing/ch4/</link><pubDate>Mon, 22 Dec 2025 14:30:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4/</guid><description>&lt;blockquote>
&lt;p>En sus remotas p´aginas est´a escrito que los animales se dividen en:&lt;br>
a. pertenecientes al Emperador&lt;br>
b. embalsamados&lt;br>
c. amaestrados&lt;br>
d. lechones&lt;br>
e. sirenas&lt;br>
f. fabulosos&lt;br>
g. perros sueltos&lt;br>
h. incluidos en esta clasiﬁcaci ´on&lt;br>
i. que se agitan como locos.&lt;br>
j. innumerables.&lt;br>
k. dibujados con un pincel ﬁn ´ısimo de pelo de camello&lt;br>
l. etc ´etera.&lt;br>
m. que acaban de romper el jarr ´on&lt;br>
n. que de lejos parecen moscas&lt;/p></description></item><item><title>2.9 最小编辑距离（Minimum Edit Distance）</title><link>https://youkre.github.io/speech-and-language-processing/ch2-09/</link><pubDate>Sun, 21 Dec 2025 18:10:07 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch2-09/</guid><description>&lt;p>我们经常需要一种方法来衡量两个单词或字符串之间的相似程度。
正如在后续章节中将看到的，这种需求最常出现在自动语音识别或机器翻译等任务中。在这些场景下，我们需要评估一个词序列与某个参考词序列的相似程度。&lt;/p>
&lt;p>&lt;strong>编辑距离&lt;/strong>（edit distance）提供了一种方法，来量化上述关于字符串相似性的合理判断。
更正式地说，两个字符串之间的&lt;strong>最小编辑距离&lt;/strong>（minimum edit distance）被定义为将一个字符串转换为另一个字符串所需的最少编辑操作次数（如插入、删除、替换等操作）。
本节中，我们讲介绍单个词的编辑距离，但是该算法同样适用于整个字符串。&lt;/p>
&lt;p>例如，“intention”与“execution”之间的差距为 5（删除一个 &lt;code>i&lt;/code>，将 &lt;code>n&lt;/code> 替换为 &lt;code>e&lt;/code>，将 &lt;code>t&lt;/code> 替换为 &lt;code>x&lt;/code>，插入 &lt;code>c&lt;/code>，将 &lt;code>n&lt;/code> 替换为 &lt;code>u&lt;/code>）。
为了更直观地理解这一点，可以观察字符串距离最重要的可视化方式：两个字符串之间的&lt;strong>对齐&lt;/strong>（alignment），如图 2.16 所示。
给定两个序列，&lt;strong>对齐&lt;/strong>指的是两个序列子串之间的一种对应关系。
因此，我们说 &lt;code>I&lt;/code> 与空字符串对齐，&lt;code>N&lt;/code> 与 &lt;code>E&lt;/code> 对齐，依此类推。
在对齐的字符串下方是另一种表示方式：一系列符号，表示将上方字符串转换为下方字符串的&lt;strong>操作列表&lt;/strong>：&lt;strong>d&lt;/strong> 表示删除（deletion），&lt;strong>s&lt;/strong> 表示替换（substitution），&lt;strong>i&lt;/strong> 表示插入（insertion）。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-2-16.png">&lt;/p>
&lt;p>&lt;strong>图 2.16&lt;/strong> 将两个字符串之间的最小编辑距离表示为&lt;strong>对齐&lt;/strong>。最后一行给出了将上方字符串转换为下方字符串的操作列表：d 表示删除，s 表示替换，i 表示插入。&lt;/p>
&lt;p>我们也可以为每种操作赋予特定的成本或权重。
两个序列之间的&lt;strong>莱文斯坦距离&lt;/strong>（Levenshtein distance）是最简单的加权方式，其中三种操作的代价均为 1（Levenshtein, 1966），我们假设一个字母替换自身（例如&lt;code>t&lt;/code>替换&lt;code>t&lt;/code>）的代价为 0。
“intention”与“execution”之间的莱文斯坦距离为 5。
莱文斯坦还提出了该度量的一种替代版本，其中每次插入或删除的代价为 1，且不允许替换操作（这等价于允许替换，但将每次替换的代价设为 2，因为任何替换操作都可以用一次插入和一次删除来表示）。
使用此版本，“intention”与“execution”之间的莱文斯坦距离为8。&lt;/p>
&lt;h3 id="291-最小编辑距离算法">2.9.1 最小编辑距离算法&lt;/h3>
&lt;p>如何找到最小编辑距离？可以将其视为一个&lt;strong>搜索任务&lt;/strong>，即在从一个字符串转换到另一个字符串的所有可能编辑路径中，寻找最短路径（即编辑操作序列）。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-2-17.png">&lt;/p>
&lt;p>&lt;strong>图 2.17&lt;/strong> 将编辑距离求解视为一个搜索问题&lt;/p>
&lt;p>所有可能的编辑路径构成的空间极为庞大，因此无法进行穷举式搜索。
然而，许多不同的编辑路径最终会到达相同的状态（即相同的字符串）。
为了避免重复计算这些路径，可以在每次遇到某个状态时，只记录到达该状态的最短路径。
实现这一目标的方法是使用&lt;strong>动态规划&lt;/strong>（dynamic programming）。
动态规划是一类算法的统称，由 Bellman（1957）首次提出，其核心思想是采用表格驱动的方式，通过组合子问题的解来求解整体问题。
自然语言处理中最常用的若干算法都基于动态规划，例如&lt;strong>维特比算法&lt;/strong>（Viterbi algorithm，见第17章）和用于句法分析的&lt;strong>CKY算法&lt;/strong>（第18章）。&lt;/p></description></item><item><title>2.8 用于词元化的简易 Unix 工具</title><link>https://youkre.github.io/speech-and-language-processing/ch2-08/</link><pubDate>Sun, 21 Dec 2025 17:55:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch2-08/</guid><description>&lt;p>对于英文文本，我们可以通过一条简单的 Unix 命令行完成朴素的单词词元化（tokenization）和词频统计。
正如 Church（1994）所指出的，当我们需要快速获取某个文本语料库的基本信息时，这种方法非常实用。
我们将用到几个 Unix 命令：&lt;code>tr&lt;/code> 用于系统性地将输入中的特定字符进行替换；&lt;code>sort&lt;/code> 按字母顺序对输入行进行排序；&lt;code>uniq&lt;/code> 合并相邻的重复行，并对这些行计数。&lt;/p>
&lt;p>例如，我们从莎士比亚全部词语开始，存储在一个文件 &lt;code>sh.txt&lt;/code> 中。
我们可以使用 &lt;code>tr&lt;/code> 将所有非字母字符序列替换为换行符，从而实现单词词元化。
这里，&lt;code>'A-Za-z'&lt;/code> 表示所有英文字母，&lt;code>-c&lt;/code> 选项表示取反（即匹配非字母字符），因此该命令会将每个非字母字符替换为换行符。
&lt;code>-s&lt;/code>（“squeeze”，压缩）选项则确保连续的多个非字母字符只生成一个换行符，避免出现空行。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>tr -sc &lt;span style="color:#e6db74">&amp;#39;A-Za-z&amp;#39;&lt;/span> &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span> &amp;lt; sh.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>该命令的输出如下所示：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>THE
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>SONNETS
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>by
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>William
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Shakespeare
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>From
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>fairest
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>creatures
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>现在每行只有一个单词，我们可以将其排序后传给 &lt;code>uniq -c&lt;/code>，后者会合并相邻的相同行并统计出现次数：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>tr -sc &lt;span style="color:#e6db74">&amp;#39;A-Za-z&amp;#39;&lt;/span> &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span> &amp;lt; sh.txt | sort | uniq -c
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出结果类似：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>1945 A
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>72 AARON
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>19 ABBESS
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>25 Aaron
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>6 Abate
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1 Abates
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如果我们希望将所有大写字母统一转为小写，可以再加一步转换：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>tr -sc &lt;span style="color:#e6db74">&amp;#39;A-Za-z&amp;#39;&lt;/span> &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span> &amp;lt; sh.txt | tr A-Z a-z | sort | uniq -c
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>输出变为：&lt;/p></description></item><item><title>2.7 正则表达式</title><link>https://youkre.github.io/speech-and-language-processing/ch2-07/</link><pubDate>Sun, 21 Dec 2025 11:17:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch2-07/</guid><description>&lt;p>计算机科学中文本处理最有用的工具之一是&lt;strong>正则表达式&lt;/strong>（regular expression，简称 &lt;strong>regex&lt;/strong>），它是一种用于描述文本字符串的语言。
正则表达式被广泛应用于各种编程语言、Unix 系统中的文本处理工具（如 &lt;code>grep&lt;/code>），以及编辑器（如 &lt;code>vim&lt;/code> 或 &lt;code>Emacs&lt;/code>）中。
此外，在 BPE 等词元化算法的预词元化（pre-tokenization）阶段，正则表达式也发挥着重要作用。
形式上，正则表达式是一种用于描述字符串集合的代数表示法。
实际上，我们可以用它在文本中搜索某个字符串，并指定如何修改该字符串，这两项功能对词元化至关重要。&lt;/p>
&lt;p>我们使用正则表达式在一个&lt;strong>字符串&lt;/strong>（string）中搜索某种&lt;strong>模式&lt;/strong>（pattern），该字符串可以是一行文本，也可以是更长的文本。
例如，Python 函数&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span>re&lt;span style="color:#f92672">.&lt;/span>search(pattern, string)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>会扫描 &lt;code>string&lt;/code>，并返回其中第一个与 &lt;code>pattern&lt;/code> 匹配的内容。
在以下示例中，我们通常会高亮显示与正则表达式完全匹配的字符串，并仅展示第一个匹配结果。
我们将采用 Python 语法，将正则表达式写作由双引号界定的原始字符串（raw string）：&lt;code>r&amp;quot;regex&amp;quot;&lt;/code>。
原始字符串会将反斜杠 &lt;code>\&lt;/code> 视为字面字符，这一点很重要，因为我们接下来要介绍的许多正则表达式模式都会用到反斜杠。&lt;/p>
&lt;p>正则表达式存在多种变体，因此使用在线正则表达式测试工具可以帮助确认你的正则表达式是否按预期工作。&lt;/p>
&lt;h3 id="271-字符析取方括号">2.7.1 字符析取：方括号&lt;/h3>
&lt;p>最简单的正则表达式就是一串普通字符。
模式 &lt;code>r&amp;quot;Buttercup&amp;quot;&lt;/code> 会在任意字符串中匹配子串 &lt;code>Buttercup&lt;/code>（例如在字符串 &lt;code>I’m called little Buttercup&lt;/code> 中）。但很多时候我们需要使用特殊字符。
例如，我们可能希望匹配某一个字符或另一个字符中的任意一个。
通常，正则表达式是&lt;strong>区分大小写&lt;/strong>的：&lt;code>r&amp;quot;s&amp;quot;&lt;/code> 能匹配小写字母 &lt;code>s&lt;/code>，但不能匹配大写字母 &lt;code>S&lt;/code>。
为了同时匹配 &lt;code>s&lt;/code> 和 &lt;code>S&lt;/code>，我们可以使用&lt;strong>字符析取&lt;/strong>（character disjunction）运算符，即方括号 &lt;code>[&lt;/code> 和 &lt;code>]&lt;/code>。
括号内的字符序列表示一个字符集合，匹配其中任意一个字符即可。
例如，图 2.9 显示，模式 &lt;code>r&amp;quot;[mM]&amp;quot;&lt;/code> 可以匹配包含 &lt;code>m&lt;/code> 或 &lt;code>M&lt;/code> 的字符串。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>模式&lt;/th>
&lt;th>匹配内容&lt;/th>
&lt;th>示例字符串&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>r&amp;quot;[mM]ary&amp;quot;&lt;/code>&lt;/td>
&lt;td>Mary 或 mary&lt;/td>
&lt;td>“&lt;u>Mary&lt;/u> Ann stopped by Mona’s”&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>r&amp;quot;[abc]&amp;quot;&lt;/code>&lt;/td>
&lt;td>‘a’、‘b’ 或 ‘c’&lt;/td>
&lt;td>“In uomini, in sold&lt;u>a&lt;/u>$ti”&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>r&amp;quot;[1234567890]&amp;quot;&lt;/code>&lt;/td>
&lt;td>任意一位数字&lt;/td>
&lt;td>“plenty of &lt;u>7&lt;/u> to 5”&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>图 2.9&lt;/strong> 使用方括号 &lt;code>[]&lt;/code> 表示字符的析取（即“或”关系）。&lt;/p></description></item><item><title>2.6 语料库</title><link>https://youkre.github.io/speech-and-language-processing/ch2-06/</link><pubDate>Sun, 21 Dec 2025 11:06:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch2-06/</guid><description>&lt;p>词语并非凭空产生。
我们所研究的任何一段文本，都是由一个或多个特定的说话者或写作者，在特定语言的特定方言中，在特定的时间、特定的地点，出于特定的目的而产生的。&lt;/p>
&lt;p>其中最重要的变异维度或许是语言本身。
自然语言处理算法若能适用于多种语言，则其价值最大。
根据在线语言目录《民族语》（Ethnologue）的统计（Simons 和 Fennig，2018），截至本文写作时，世界上共有7097种语言。
在开发算法时，应在多种语言上进行测试，尤其是那些具有不同语言特性的语言；与此相对，目前存在一种令人遗憾的趋势，即自然语言处理算法往往仅在英语上进行开发或测试（Bender，2019）。
即使算法的应用范围超出了英语，也往往集中于大型工业化国家的官方语言（如中文、西班牙语、日语、德语等），但我们不应将工具局限于这些少数语言。
此外，大多数语言本身也包含多种变体，通常由不同地区或不同社会群体使用。
因此，例如，如果我们处理的文本使用了非裔美国人英语（&lt;strong>AAE&lt;/strong>）或非裔美国人白话英语（AAVE）的特征——这是数百万非裔美国人社区成员使用的英语变体（King，2020），我们就必须使用能够适应这些语言变体特征的自然语言处理工具。
推文（Twitter posts）中可能包含非裔美国人英语的常见表达，例如 &lt;em>iont&lt;/em>（相当于主流美国英语（&lt;strong>MAE&lt;/strong>）中的 &lt;em>I don’t&lt;/em>），或 &lt;em>talmbout&lt;/em>（对应于 MAE 的 &lt;em>talking about&lt;/em>），这两个例子都会影响词语切分（Blodgett 等，2016；Jones，2015）。&lt;/p>
&lt;p>在一次交际行为中混合使用多种语言的现象也十分普遍，这种现象被称为&lt;strong>语码转换&lt;/strong>（code switching）。
语码转换在全球范围内极为常见；以下是包含西班牙语和（音译的）印地语与英语混合使用的例子（Solorio 等，2014；Jurgens 等，2017）：&lt;/p>
&lt;blockquote>
&lt;p>(2.13) Por primera vez veo a @username actually being hateful! it was beautiful:)&lt;br>
&lt;em>[For the ﬁrst time I get to see @username actually being hateful! it was beautiful:)]&lt;/em>&lt;/p>
&lt;p>(2.20) dost tha or ra- hega &amp;hellip; dont wory &amp;hellip; but dherya rakhe&lt;br>
&lt;em>[“he was and will remain a friend &amp;hellip; don’t worry &amp;hellip; but have faith”]&lt;/em>&lt;/p></description></item><item><title>2.5 基于规则的词元化</title><link>https://youkre.github.io/speech-and-language-processing/ch2-05/</link><pubDate>Sun, 21 Dec 2025 10:21:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch2-05/</guid><description>&lt;p>尽管像 BPE 这样的数据驱动型词元化是目前最常用的方法，但在某些情况下，我们希望将词元限制为完整的词，而不是子词。
例如，当我们运行针对英语的句法分析算法时，解析器可能需要以语法上的词作为输入。
或者在任何语言学应用中，如果我们对所研究的词元已有某种先验定义，这种做法也会有用。
又或者在社会科学应用中，正字法意义上的词本身就是有意义的研究单位。&lt;/p>
&lt;p>在基于规则的词元化中，我们会预先定义一个标准，并实现相应的规则来执行这种词元化方式。
下面我们以英语的词元化为例进行探讨。&lt;/p>
&lt;p>对于英语，我们有一些期望目标：我们通常希望将标点符号切分为独立的词元，逗号对句法分析器来说是有用的信息，句号则有助于识别句子边界。
但我们也常常希望保留词内部出现的标点符号，例如 &lt;em>m.p.h.&lt;/em>、&lt;em>Ph.D.&lt;/em>、&lt;em>AT&amp;amp;T&lt;/em> 和 &lt;em>cap’n&lt;/em> 中的情况。
特殊字符和数字也需要在价格（如 $45.55）和日期（如 &lt;code>01/02/06&lt;/code>）中保持完整；我们不希望把价格拆分成 “45” 和 “55” 这样的独立词元。
此外，还有 URL（如 &lt;code>https://www.stanford.edu&lt;/code>）、Twitter 话题标签（如 &lt;code>#nlproc&lt;/code>）或电子邮件地址（如 &lt;code>someone@cs.colorado.edu&lt;/code>）等结构也需要整体保留。&lt;/p>
&lt;p>数字表达式带来了额外的复杂性：英语中的逗号除了出现在词边界外，还会出现在数字内部，每三位数字一组，例如 555,500.50。
不同语言的词元化规则也有所不同；例如西班牙语、法语和德语使用逗号表示小数点，而用空格（有时用句点）代替英语中千位分隔符的位置，例如 555 500,50。&lt;/p>
&lt;p>基于规则的词元器还可以用于展开由撇号标记的&lt;strong>附着词&lt;/strong>（clitic）缩略形式，例如将 &lt;code>what’re&lt;/code> 转换为两个词元 &lt;code>what are&lt;/code>，将 &lt;code>we’re&lt;/code> 转换为 &lt;code>we are&lt;/code>。
附着词是指不能独立存在、只能依附于其他词的词素。
这类缩略形式也出现在其他使用字母的文字系统中，包括法语的代词（如 &lt;code>j’ai&lt;/code>）和冠词（如 &lt;code>l’homme&lt;/code>）。&lt;/p>
&lt;p>根据具体应用的不同，词元化算法也可能将多词表达式（如 &lt;code>New York&lt;/code> 或 &lt;code>rock ’n’ roll&lt;/code>）视为单个词元，这通常需要某种形式的多词表达式词典。
因此，基于规则的词元化与&lt;strong>命名实体识别&lt;/strong>（named entity recognition，NER）任务密切相关，NER 旨在检测人名、日期和组织机构等（见第 17 章）。&lt;/p>
&lt;p>一种常用的词元化标准是&lt;strong>宾州树库词元化标准&lt;/strong>（Penn Treebank tokenization standard，PTB），该标准用于语言数据联盟（Linguistic Data Consortium, LDC）发布的已标注语料库（即“树库”），而 LDC 是许多有用数据集的来源。
该标准将附着词分开（例如 &lt;em>doesn’t&lt;/em> 变为 &lt;em>does&lt;/em> 和 &lt;em>n’t&lt;/em>），保留带连字符的词整体不变，并将所有标点符号单独切分（为节省空间，此处用可见空格符号 ‘␣’ 表示词元之间的分隔，尽管实际输出中更常见的是换行符）：&lt;/p></description></item><item><title>2.4 子词切分：字节对编码</title><link>https://youkre.github.io/speech-and-language-processing/ch2-04/</link><pubDate>Sun, 21 Dec 2025 01:24:38 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch2-04/</guid><description>&lt;p>&lt;strong>词元化&lt;/strong>（Tokenization）是自然语言处理的第一步，指将连续的输入文本分割为若干&lt;strong>词元&lt;/strong>（tokens）的过程。&lt;/p>
&lt;p>我们已经讨论了三种可能的词元单位：词（words）、语素（morphemes）和字符（characters）。
但每种作为基本单位都存在问题。
词和语素在语义上似乎处于 NLP 处理的理想粒度，因为它们通常具有相对稳定的含义，但难以形式化地精确定义。
字符虽然定义清晰，但作为词元单位又过小，难以承载足够的语义信息。&lt;/p>
&lt;p>本节将介绍当前 NLP 实践中真正采用的方法：通过数据驱动的方式定义词元，这些词元通常大小接近词或语素，但在必要时也可小至单个字符。&lt;/p>
&lt;p>为什么需要对输入进行词元化？
一个原因是，将输入转换为一组确定且固定的单位后，不同算法和系统才能就基本问题达成一致。
例如，这段文本有多长？（包含多少个单位？）
或者，“don’t” 或 “New York” 算一个词元还是两个？
因此，标准化的词元化对 NLP 实验的可复现性至关重要。本书后续介绍的许多算法（如语言模型的&lt;strong>困惑度&lt;/strong>（perplexity）指标）都默认所有文本已采用统一的词元化方案。&lt;/p>
&lt;p>此外，包含更小单位（如语素或字母）的词元化方法还能有效解决&lt;strong>未登录词&lt;/strong>（unknown words）问题。
什么是未登录词？正如下一章将看到的，NLP 算法通常从一个训练语料库（training corpus）中学习语言规律，再将这些规律用于处理另一个独立的测试语料库（test corpus）。
例如，若训练语料中包含 &lt;em>low&lt;/em>、&lt;em>new&lt;/em> 和 &lt;em>newer&lt;/em>，但不包含 &lt;em>lower&lt;/em>，那么当 &lt;em>lower&lt;/em> 出现在测试集中时，系统将无法识别它。&lt;/p>
&lt;p>为应对这一问题，现代词元器会自动归纳出一组&lt;strong>子词&lt;/strong>（subwords），即比完整单词更小的词元单位。
这些子词可以是任意子字符串，也可以是带有语义的单位（如语素 &lt;em>-est&lt;/em> 或 &lt;em>-er&lt;/em>）。
在现代词元化方案中，许多词元仍是完整单词，但也包含大量高频出现的语素或其他子词（如 &lt;em>-er&lt;/em>）。
这样一来，任何未见过的词都可以被表示为若干已知子词的组合。
例如，即使我们从未见过 &lt;em>lower&lt;/em>，当它出现时，仍可成功将其切分为 &lt;em>low&lt;/em> 和 &lt;em>er&lt;/em>，这两个子词已在训练中出现过。
在最极端的情况下，一个极其罕见的词（比如缩写词 &lt;em>GRPO&lt;/em>）甚至可以被切分为单个字母序列。&lt;/p>
&lt;p>当前大语言模型广泛采用两种子词切分算法：&lt;strong>字节对编码&lt;/strong>（Byte-Pair Encoding, BPE）（Sennrich et al., 2016）和 &lt;strong>unigram 语言模型&lt;/strong>（Unigram Language Modeling, ULM）（Kudo, 2018）&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>。
本节重点介绍 &lt;strong>BPE 算法&lt;/strong>（Sennrich et al., 2016；Gage, 1994），见图 2.6。&lt;/p>
&lt;p>与大多数词元化方案类似，BPE 算法包含两个部分：&lt;strong>训练器&lt;/strong>（trainer）和&lt;strong>编码器&lt;/strong>（encoder）。
在训练阶段，我们输入一个原始训练语料（通常已通过空格等简单方式粗略分词），从中归纳出一个&lt;strong>词表&lt;/strong>（vocabulary），即一组学习得到的词元。
在编码阶段，编码器接收一条新的测试句子，并将其切分为训练阶段所学词表中的词元序列。&lt;/p></description></item><item><title>2.3 Unicode</title><link>https://youkre.github.io/speech-and-language-processing/ch2-03/</link><pubDate>Sun, 21 Dec 2025 00:37:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch2-03/</guid><description>&lt;p>在词元化（tokenization）时还可以考虑另一个选项：以单个字符为单位。
但问题随之而来：我们该如何表示跨越不同语言和书写系统的字符呢？
&lt;strong>Unicode&lt;/strong>标准正是为此而生，它是一种用于表示世界上任何语言（包括已消亡的语言如苏美尔楔形文字，以及人造语言如克林贡语）所使用的所有字符和文字的编码方法。&lt;/p>
&lt;p>我们先简要回顾一下 Unicode 中一个仅面向英语的子集（在 Unicode 标准中技术上称为“基本拉丁字母”（Basic Latin），通常被称为 ASCII）。
自 20 世纪 60 年代起，用于书写英语的拉丁字母（比如本句中使用的这些字符）采用一种名为 &lt;strong>ASCII&lt;/strong>（American Standard Code for Information Interchange，美国信息交换标准代码）的编码方案进行表示。
ASCII 使用单个字节（byte）表示每个字符。
一个字节最多可表示 256 个不同的字符，但 ASCII 仅使用了其中的 127 个；其字节的最高位始终设为 0。
（实际上，它只用到了其中 95 个可打印字符，其余是为一种早已淘汰的设备电传打字机（teletype）预留的控制字符。）
下图展示了一些 ASCII 字符及其十六进制与十进制编码：&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-2-4.png">&lt;/p>
&lt;p>&lt;strong>图 2.4&lt;/strong> 部分英文字符对应的 ASCII 编码，同时以十六进制和十进制形式列出。&lt;/p>
&lt;p>然而，ASCII 显然远远不够，因为世界上各种书写系统包含的字符远不止这些！
即使对于同样使用拉丁字母的文字，其字符数量也远超 ASCII 的 95 个可打印字符。
例如，下面这句西班牙语（意为“先生，桑丘答道”）就包含两个非 ASCII 字符：ñ 和 ó：&lt;/p>
&lt;blockquote>
&lt;p>(2.10) Se ñor- respondió Sancho-&lt;/p>&lt;/blockquote>
&lt;p>更不用说，世界上大量语言根本不使用拉丁字母！
例如，&lt;strong>天城文&lt;/strong>（Devanagari）被用于 120 种语言（包括印地语、马拉地语、尼泊尔语、信德语和梵语）。
以下是《世界人权宣言》印地语文本中的一个天城文示例：&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-image-2_Im3.png">&lt;/p>
&lt;p>中文在 Unicode 中收录了约 10 万个汉字（包括中文、日文、韩文和越南文所使用的重叠与非重叠变体，字符合称 CJKV）。&lt;/p></description></item><item><title>2.2 语素：词的组成部分</title><link>https://youkre.github.io/speech-and-language-processing/ch2-02/</link><pubDate>Sat, 20 Dec 2025 21:22:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch2-02/</guid><description>&lt;p>词是有内部结构的。
在字符层面，这一点显而易见。
单词 &lt;em>cats&lt;/em> 由四个字符 ‘c’、‘a’、‘t’、‘s’ 构成。
但更深层次上，词还包含具有连贯语义的组成部分。
这些组成部分称为&lt;strong>语素&lt;/strong>（morphemes），而对语素的研究称为&lt;strong>形态学&lt;/strong>（morphology）。
&lt;strong>语素&lt;/strong>是语言中最小的表义单位。
例如，单词 &lt;em>fox&lt;/em> 仅包含一个语素（即 &lt;em>fox&lt;/em> 本身），而 &lt;em>cats&lt;/em> 则包含两个语素：表示“猫”的语素 &lt;em>cat&lt;/em> 和表示复数的语素 &lt;em>-s&lt;/em>。&lt;/p>
&lt;p>以下是一个用连字符标出语素边界的英文句子：&lt;/p>
&lt;blockquote>
&lt;p>(2.6) Doc work-ed care-ful-ly wash-ing the glass-es&lt;/p>&lt;/blockquote>
&lt;p>如前所述，在中文中，书写系统恰好与语素高度对应——每个汉字通常对应一个语素。
以下是一个普通话例句，每个汉字（即语素）均附有词义标注（gloss），其后为整句翻译：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>(2.7) 梅 干 菜 用 清 水 泡 软， 捞 出 后 ， 沥 干
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> plum dry vegetable use clear water soak soft, remove out after, drip dry
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 切 碎
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> chop fragment
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Soak the preserved vegetable in water until soft, remove, drain, and chop
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>我们通常将语素分为两大类，&lt;strong>词根&lt;/strong>（roots）：词的核心语素，承载主要语义；&lt;strong>词缀&lt;/strong>（affixes）：附加在词根上，表达各类附加意义。
在上述英文例子中，&lt;em>worked&lt;/em> 的 &lt;em>work&lt;/em> 是词根，&lt;em>-ed&lt;/em> 是词缀；同样，&lt;em>glasses&lt;/em> 中的 &lt;em>glass&lt;/em> 是词根，&lt;em>-es&lt;/em> 是词缀。&lt;/p></description></item><item><title>2.1 词</title><link>https://youkre.github.io/speech-and-language-processing/ch2-01/</link><pubDate>Sat, 20 Dec 2025 21:02:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch2-01/</guid><description>&lt;p>下面这个句子中有多少个词？&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>They picnicked by the pool, then lay back on the grass and
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>looked at the stars.
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如果我们不将标点符号视为词，则该句包含 16 个词；若计入标点，则为 18 个词。
是否将句号（“.”）、逗号（“,”）等视为词，取决于具体任务。
标点符号对于识别语言单位的边界（如逗号、句号、冒号）以及某些语义特征（如问号、感叹号、引号）至关重要。
大型语言模型通常将标点符号视为独立的词。&lt;/p>
&lt;p>在口语中，对“词”的界定会带来其他复杂性。
例如，考虑以下来自口语对话的话语（utterance）（&lt;strong>话语&lt;/strong>是语言学中与书面句子相对应的口语技术术语）：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>I do uh main- mainly business data processing
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>该话语包含两类&lt;strong>不流畅现象&lt;/strong>（disfluencies）。
被中断的词 &lt;em>main&lt;/em>- 被称为&lt;strong>片段&lt;/strong>（fragment）。
像 &lt;em>uh&lt;/em> 和 &lt;em>um&lt;/em> 这样的成分则被称为&lt;strong>填充词&lt;/strong>（fillers）或&lt;strong>有声停顿&lt;/strong>（filled pauses）。
我们是否应将它们视为词？
答案依然取决于具体应用场景。
如果我们在构建语音转写系统，可能最终希望去除这些不流畅现象。
但有时我们也会保留它们。
事实上，&lt;em>uh&lt;/em> 或 &lt;em>um&lt;/em> 等不流畅现象在语音识别中对预测后续词汇有帮助，因为它们可能表明说话者正在重启某个子句或想法。因此，在语音识别任务中，它们通常被当作普通词处理。
此外，由于不同说话人使用不同的不流畅形式，这些现象还可作为识别说话人的线索。
Clark 与 Fox Tree（2002）甚至指出，&lt;em>uh&lt;/em> 和 &lt;em>um&lt;/em> 在英语中具有不同的语用含义。
你认为它们的区别是什么？&lt;/p>
&lt;p>在思考“什么是词”时，或许最重要的是区分两种谈论词的方式，这一区分将在本书中反复使用。
&lt;strong>词型&lt;/strong>（word types）指语料库中互不相同的词的数量；若词汇表为 $V$，则词型数量即为&lt;strong>词汇量&lt;/strong>（vocabulary size）$|V|$。
&lt;strong>词例&lt;/strong>（word instances）则是文本中所有连续出现的词的总数 $N$。&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>
若忽略标点符号，上述野餐句包含 14 个词型和 16 个词例：&lt;/p></description></item><item><title>第 2 章 词与词元</title><link>https://youkre.github.io/speech-and-language-processing/ch2/</link><pubDate>Sat, 20 Dec 2025 20:08:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch2/</guid><description>&lt;blockquote>
&lt;p>用户：我需要一些帮助，这一点似乎很明确。&lt;br>
ELIZA：如果你得到了一些帮助，对你而言这意味着什么？&lt;br>
用户：也许我可以学会和我母亲相处。&lt;br>
ELIZA：跟我多说说你的家人吧。&lt;br>
用户：我母亲照顾我。&lt;br>
ELIZA：你家里还有谁照顾你？&lt;br>
用户：我父亲。&lt;br>
ELIZA：你父亲。&lt;br>
用户：你在某些方面很像我父亲。&lt;/p>
&lt;p>Weizenbaum (1966)&lt;/p>&lt;/blockquote>
&lt;p>上述对话来自 &lt;strong>ELIZA&lt;/strong>——一个早期的自然语言处理系统。该系统通过模仿罗杰斯学派心理治疗师（Rogerian psychotherapist）的回应方式，能够与用户进行有限的对话（Weizenbaum, 1066）。
ELIZA 的实现令人惊讶地简单：它通过对词（words）进行模式匹配，识别诸如 “I need X” 这样的短语，并将其转换为合适的输出，例如 “What would it mean to you if you got X?”。
尽管以现代标准来看，ELIZA 对人类对话的模拟非常粗糙，但其效果却出奇地成功：许多与 ELIZA 交互的用户竟相信它真正“理解”了自己。
正因如此，这项工作首次促使研究者开始思考聊天机器人对其用户可能产生的影响（Weizenbaum, 1976）。&lt;/p>
&lt;p>当然，ELIZA 所开创的那种基于模式的简单模仿，现代聊天机器人已不再使用。
然而，ELIZA 所体现的这种基于模式的词处理方法，在当今的词元化（tokenization）任务中依然适用；词元化即指从连续文本中将词及其组成部分转化为词元的过程。
词元化是现代自然语言处理（NLP）的第一步，采用了一些源于 ELIZA 时代的基于模式的方法。&lt;/p>
&lt;p>要理解词元化，我们首先需要提问：什么是词（word）？
“um” 算是一个词吗？“New York” 呢？
不同语言中“词”的本质是否相似？
有些语言（如越南语或粤语）的词通常非常短，而另一些语言（如土耳其语）的词则非常长。
此外，我们还需考虑如何用&lt;strong>字符&lt;/strong>（characters）来表示词。
为此，我们将介绍 &lt;strong>Unicode&lt;/strong>——现代字符表示系统，以及 &lt;strong>UTF-8&lt;/strong> 文本编码方案。
同时，我们还将引入 &lt;strong>语素&lt;/strong>（morpheme）的概念，即词中有意义的子成分（例如单词 &lt;code>longer&lt;/code> 中的语素 &lt;code>-er&lt;/code>）。&lt;/p>
&lt;p>文本词元化的标准方法是利用输入字符提供切分线索。
因此，在理解了词可能包含的子成分之后，我们将介绍标准的 &lt;strong>字节对编码&lt;/strong>（Byte-Pair Encoding, &lt;strong>BPE&lt;/strong>）算法，该算法能自动将输入文本切分为词元（tokens）。
BPE 利用字符序列的简单统计规律，归纳出一个子词（subword）词元的词汇表。
所有词元化系统在处理过程中也都依赖于 &lt;strong>正则表达式&lt;/strong>（regular expressions）。
正则表达式是一种用于形式化描述和操作文本字符串的语言，是所有现代 NLP 系统中的重要工具。
我们将介绍正则表达式，并展示其应用示例。&lt;/p></description></item><item><title>9.1 双向 Transformer 编码器</title><link>https://youkre.github.io/speech-and-language-processing/ch9-01/</link><pubDate>Fri, 19 Dec 2025 14:18:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch9-01/</guid><description>&lt;p>我们首先介绍双向 Transformer 编码器，这是 BERT 及其后续模型（如 &lt;strong>RoBERTa&lt;/strong>（Liu 等，2019）或 &lt;strong>SpanBERT&lt;/strong>（Joshi 等，2020））的基础。
第 7 章中我们介绍了从左至右的语言模型，应用于问答或摘要等自回归式上下文生成任务，第 8 章则展示了如何使用因果型（从左至右）的 transformer 实现语言模型。
然而，这类模型从左至右的特性也构成了一种限制：在某些任务中，处理某个词元（token）时若能“窥视”其未来的词元将大有裨益。
这一点在&lt;strong>序列标注&lt;/strong>（sequence labeling）任务中尤为明显，在这些任务中，我们希望为每个词元打上标签，如 9.5 节将要介绍的的&lt;strong>命名实体识别&lt;/strong>（named entity tagging），或如后续章节将介绍的词性标注或句法分析。&lt;/p>
&lt;p>本节所介绍的&lt;strong>双向&lt;/strong>编码器与因果模型属于截然不同的类型。
第 8 章中的因果模型是生成式模型，旨在高效地生成序列中的下一个词元。
而双向编码器的核心目标则是计算输入词元的&lt;strong>上下文化表示&lt;/strong>（contextualized representations）。
双向编码器利用自注意力机制，将输入嵌入序列 $(x_1, \dots, x_n)$ 映射为长度相同的输出嵌入序列 $(h_1, \dots, h_n)$，其中每个输出向量均融合了整个输入序列的信息，从而实现上下文化。
这些输出嵌入构成了各输入词元的上下文相关表示，在各类需要基于上下文对词元进行分类或决策的应用中具有广泛用途。&lt;/p>
&lt;p>回顾一下，我们在前文提到，第 8 章的模型有时被称为&lt;strong>仅解码器&lt;/strong>（decoder-only）模型，因为它们对应于第 12 章将要介绍的编码器–解码器架构中的解码器部分。
相比之下，本章所讨论的掩码语言模型则常被称为&lt;strong>仅编码器&lt;/strong>（encoder-only）模型，因为它们为每个输入词元生成编码表示，但通常不用于通过解码或采样来生成连贯文本。
这一点至关重要：掩码语言模型并不用于文本生成，而是主要用于解释性任务（interpretative tasks）。&lt;/p>
&lt;h3 id="911-双向掩码模型的架构">9.1.1 双向掩码模型的架构&lt;/h3>
&lt;p>我们首先讨论整体架构。
基于 Transformer 的双向语言模型与前几章介绍的因果型 Transformer 在两个方面有所不同。
第一，注意力机制是非因果的，词元 $i$ 的注意力可以关注其后续词元（如 $i+1$ 等）；
第二，其训练方式略有不同，因为我们预测的是文本中间的某个词元，而非序列末尾的下一个词元。
本节先讨论第一点，第二点将在下一节展开。&lt;/p>
&lt;p>图 9.1a（此处复用自第 8 章）展示了第 8 章中从左至右方法的信息流。
在该方法中，每个词元的注意力计算仅基于其前面及当前的输入词元，忽略了位于当前词元右侧的潜在有用信息。
双向编码器通过允许注意力机制遍历整个输入序列，克服了这一限制，如图 9.1b 所示。&lt;/p></description></item><item><title>第 9 章 掩码语言模型</title><link>https://youkre.github.io/speech-and-language-processing/ch9/</link><pubDate>Fri, 19 Dec 2025 14:08:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch9/</guid><description>&lt;blockquote>
&lt;p>Larvatus prodeo（戴上面具，我继续前行）&lt;/p>
&lt;p>——笛卡尔&lt;/p>&lt;/blockquote>
&lt;p>在前两章中，我们介绍了 Transformer 架构，并展示了如何将 Transformer 语言模型以&lt;strong>因果型&lt;/strong>（causal）或从左至右的方式进行预训练。
本章将引入预训练语言模型的另一种范式——&lt;strong>双向 Transformer&lt;/strong>（bidrectional transformer）编码器，以及其中应用最为广泛的模型：&lt;strong>BERT&lt;/strong>（Devlin 等，2019）。
该模型通过&lt;strong>掩码语言建模&lt;/strong>（masked language modeling）进行训练：不同于预测下一个词，而是将句子中的某个词进行掩码处理，要求模型根据其左右两侧的上下文来预测被掩码的词。
因此，这种方法使模型能够同时利用左侧和右侧的上下文信息。&lt;/p>
&lt;p>我们在上一章已初步介绍了&lt;strong>微调&lt;/strong>（finetuning）的概念。
本章将进一步描述一种新的微调方式：我们将这些预训练模型所学习到的 Transformer 网络作为基础，在其顶层之后添加一个神经网络分类器，并在额外的标注数据上进行训练，以完成某项下游任务，例如命名实体识别或自然语言推理。
其核心思想与之前一致：预训练阶段学习到的语言模型能够生成对词语语义的丰富表征，从而使得模型更容易学习（即“被微调以满足”）特定下游语言理解任务的需求。
这种“预训练–微调”范式正是机器学习中所谓&lt;strong>迁移学习&lt;/strong>（transfer learning）的一个具体实例，即从一个任务或领域中获取知识，并将其应用于（迁移至）解决新任务。&lt;/p>
&lt;p>本章引入的第二个关键概念是&lt;strong>上下文嵌入&lt;/strong>（contextual embeddings）：即基于上下文的词表示方法。
第 5 章中介绍的方法（如 word2vec 或 GloVe）为词汇表中的每个唯一词 $w$ 学习一个固定的向量嵌入。
相比之下，上下文嵌入（例如由 BERT 等掩码语言模型所学习到的表示）则为同一个词 $w$ 在不同上下文中生成不同的向量表示。
虽然第 8 章中的因果语言模型也使用了上下文嵌入，但掩码语言模型所产生的嵌入在作为语义表示方面表现尤为出色。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch8-09">8.9 Transformer 的可解释性&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch9-01">9.1 双向 Transformer 编码器&lt;/a>
&lt;/nav></description></item><item><title>9.2 双向编码器的训练</title><link>https://youkre.github.io/speech-and-language-processing/ch9-02/</link><pubDate>Thu, 18 Dec 2025 14:51:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch9-02/</guid><description>&lt;p>在第 8 章中，我们通过让因果型 Transformer 语言模型逐词预测文本中的下一个词来进行训练。
然而，一旦我们在注意力机制中移除了因果掩码，这种“预测下一个词”的语言建模任务就变得毫无意义——因为答案已经直接出现在上下文中（模型可以“偷看”未来词）。因此，我们需要一种全新的训练方案。
取而代之的是，模型不再预测下一个词，而是学习完成一种填空任务（fill-in-the-blank task），在技术上被称为 &lt;strong>Cloze 任务&lt;/strong>（Taylor, 1953）。
为理解这一点，让我们回到第 3 章中的那个示例。
传统语言模型会尝试预测下面这句话接下来最可能出现的词：&lt;/p>
&lt;blockquote>
&lt;p>The water of Walden Pond is so beautifully ____&lt;/p>&lt;/blockquote>
&lt;p>而在 Cloze 任务中，给定句子中缺失一个或多个词的情况，要求模型根据其余部分预测缺失的内容。例如：&lt;/p>
&lt;blockquote>
&lt;p>The ___ of Walden Pond is so beautifully &amp;hellip;&lt;/p>&lt;/blockquote>
&lt;p>也就是说，给定一个部分被遮蔽的输入序列，学习目标是还原出被遮蔽的元素。
更具体地说，在训练过程中，模型会被剥夺输入序列中的一个或多个词元，并必须为每个缺失位置生成一个在整个词表上的概率分布。
然后，我们利用模型在每个被遮蔽位置上的预测与真实词之间的交叉熵损失来驱动整个学习过程。&lt;/p>
&lt;p>这种方法可以推广到多种对训练输入进行破坏（corrupt）后再让模型恢复原始内容的策略。
已被采用的破坏方式包括：掩码（masking）、替换（substitutions）、重排（reorderings）、删除（deletions）、插入干扰项（extraneous insertions）。
这类训练方法统称为 &lt;strong>去噪&lt;/strong>（denoising）：我们以某种方式对输入引入噪声（例如遮蔽一个词，或插入一个错误词），而模型的目标就是去除噪声、重建原始干净的输入。&lt;/p>
&lt;h3 id="921-词元掩码">9.2.1 词元掩码&lt;/h3>
&lt;p>下面我们介绍用于训练双向编码器的&lt;strong>掩码语言建模&lt;/strong>（Masked Language Modeling, MLM）方法（Devlin 等，2019）。
与我们之前看到的语言模型训练方法类似，MLM 也使用大规模语料库中的无标注文本。
在 MLM 训练中，模型接收来自训练语料的一系列句子，其中一定比例的词元（在 BERT 模型中为 15%）会被随机选中，并通过掩码操作进行处理。
以输入句子 &lt;code>lunch was delicious&lt;/code> 为例，假设我们随机选择处理第 3 个词元 &lt;code>delicious&lt;/code>：&lt;/p>
&lt;ul>
&lt;li>80% 的概率：将该词元替换为特殊的词汇表标记 &lt;code>[MASK]&lt;/code>，例如：&lt;code>lunch was delicious&lt;/code> → &lt;code>lunch was [MASK]&lt;/code>&lt;/li>
&lt;li>10% 的概率：将该词元替换为从词汇表中根据一元词频分布随机采样的另一个词元，例如：&lt;code>lunch was delicious&lt;/code> → &lt;code>lunch was gasp&lt;/code>&lt;/li>
&lt;li>10% 的概率：保留原词不变，例如：&lt;code>lunch was delicious&lt;/code> → &lt;code>lunch was delicious&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>随后，我们训练模型去预测这些被修改词元的原始正确词元。
为什么要采用这三种修改方式？
引入 &lt;code>[MASK]&lt;/code> 标记会导致预训练阶段与下游任务的微调或推理阶段之间出现不匹配，因为当我们使用 MLM 模型执行下游任务时，输入中不会包含任何 &lt;code>[MASK]&lt;/code> 标记。
如果我们只是简单地将词元替换为 &lt;code>[MASK]&lt;/code>，模型可能会只在看到 &lt;code>[MASK]&lt;/code> 时才尝试预测词元；而我们真正希望的是，模型始终尝试预测输入中的原始词元。&lt;/p></description></item><item><title>13.6 小结：常见的 RNN 自然语言处理架构</title><link>https://youkre.github.io/speech-and-language-processing/ch13-06/</link><pubDate>Thu, 18 Dec 2025 14:08:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch13-06/</guid><description>&lt;p>至此，我们已经介绍了基本的 RNN 模型，学习了其高级组件（如多层堆叠和 LSTM 变体），并探讨了 RNN 在多种任务中的应用方式。现在，让我们对这些应用场景所对应的典型架构做一个简要总结。&lt;/p>
&lt;p>图 13.15 展示了我们迄今讨论过的三种主要架构：&lt;strong>序列标注&lt;/strong>、&lt;strong>序列分类&lt;/strong> 和 &lt;strong>语言建模&lt;/strong>。
在序列标注任务中（例如词性标注或命名实体识别），模型为输入序列中的每个词或词元生成一个对应的标签。
在序列分类任务中（例如情感分析），我们忽略中间每个词元的输出，仅使用序列末尾的表示进行最终预测；相应地，模型的训练信号也仅来自最后一个时间步的反向传播。
在语言建模任务中，模型在每个时间步都接受此前的上下文，并被训练用于预测下一个词。
在下一节中，我们将介绍第四种架构——&lt;strong>编码器-解码器&lt;/strong>（encoder-decoder）。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-13-15.png">&lt;/p>
&lt;p>&lt;strong>图 13.15&lt;/strong> 四种 NLP 任务的典型架构。
在序列标注（如词性标注或命名实体识别）中，我们将每个输入词元 $x_i$ 映射到一个输出标签 $y_i$；
在序列分类中，整个输入序列被映射为一个单一类别；
在语言建模中，模型基于先前的词元预测下一个词元；
在编码器-解码器架构中，包含两个独立的 RNN 模型：第一个（编码器）将输入序列 $x$ 映射为一个中间表示（称为上下文或语义向量），第二个（解码器）则基于该上下文生成输出序列 $y$。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch13-05">13.5 长短期记忆网络（LSTM）&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch13-07">13.7 基于 RNN 的编码器-解码器模型&lt;/a>
&lt;/nav></description></item><item><title>第 13 章 循环神经网络与长短期记忆网络</title><link>https://youkre.github.io/speech-and-language-processing/ch13/</link><pubDate>Thu, 18 Dec 2025 07:51:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch13/</guid><description>&lt;blockquote>
&lt;p>时间自会说明一切。&lt;/p>
&lt;p>——简·奥斯汀，《劝导》&lt;/p>&lt;/blockquote>
&lt;p>语言本质上是一种时间性现象。
口语是一连串随时间展开的声学事件，而我们在理解和生成口语及书面语时，也都是将其视为一个顺序输入流。
我们所使用的隐喻也体现了语言的时间特性：例如，我们谈论“对话的流动”、“新闻推送”和“推文流”，这些说法都强调了语言是一种随时间逐步展开的序列。&lt;/p>
&lt;p>本章将介绍一种深度学习架构：循环神经网络（Recurrent Neural Networks, RNN）及其变体，如长短期记忆网络（Long Short-Term Memory networks, LSTM），它们表示时间的方式与前馈网络和 transformer 网络不通过。
RNN 有一种机制可以直接处理语言的序列特性，使其无需依赖任意设定的固定窗口即可应对语言的时间性。
循环网络通过其&lt;strong>循环连接&lt;/strong>提供了一种全新的方式来表示先前的上下文信息，从而使模型的决策能够依赖于数百个词之前的上下文。
我们将看到如何将该模型应用于语言建模、序列标注任务（如词性标注）以及文本分类任务（如情感分析）。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch12-07">12.7 偏见与伦理问题&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch13-01">13.1 循环神经网络&lt;/a>
&lt;/nav></description></item><item><title>6.2 XOR 问题</title><link>https://youkre.github.io/speech-and-language-processing/ch6-02/</link><pubDate>Wed, 17 Dec 2025 20:50:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-02/</guid><description>&lt;p>在神经网络发展早期，人们就意识到：神经网络的强大能力——正如启发它的生物神经元一样——来自于将多个单元组合成更大的网络。&lt;/p>
&lt;p>对多层网络必要性的一个经典证明，来自明斯基（Minsky）和帕佩特（Papert）于1969年提出的结果：单个神经单元无法计算某些非常简单的输入函数。
考虑用两个二值输入计算基本逻辑函数的任务，例如 AND、OR 和 XOR。
作为回顾，下表列出了这些函数的真值表：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th style="text-align: center">x1&lt;/th>
&lt;th style="text-align: center">x2&lt;/th>
&lt;th style="text-align: center">AND&lt;/th>
&lt;th style="text-align: center">OR&lt;/th>
&lt;th style="text-align: center">XOR&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align: center">0&lt;/td>
&lt;td style="text-align: center">0&lt;/td>
&lt;td style="text-align: center">0&lt;/td>
&lt;td style="text-align: center">0&lt;/td>
&lt;td style="text-align: center">0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">0&lt;/td>
&lt;td style="text-align: center">1&lt;/td>
&lt;td style="text-align: center">0&lt;/td>
&lt;td style="text-align: center">1&lt;/td>
&lt;td style="text-align: center">1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">1&lt;/td>
&lt;td style="text-align: center">0&lt;/td>
&lt;td style="text-align: center">0&lt;/td>
&lt;td style="text-align: center">1&lt;/td>
&lt;td style="text-align: center">1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align: center">1&lt;/td>
&lt;td style="text-align: center">1&lt;/td>
&lt;td style="text-align: center">1&lt;/td>
&lt;td style="text-align: center">1&lt;/td>
&lt;td style="text-align: center">0&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>这个例子最初是针对&lt;strong>感知机&lt;/strong>（perceptron）提出的。感知机是一种非常简单的神经单元，其输出为二值（0 或 1），并且&lt;strong>不包含&lt;/strong>非线性激活函数。
感知机的输出 $y$ 按如下方式计算（使用与公式 (6.2) 相同的权重 $\mathbf{w}$、输入 $\mathbf{x}$ 和偏置 $b$）：&lt;/p>
$$
y =
\begin{cases}
0, &amp; \text{若 } \mathbf{w} \cdot \mathbf{x} + b \leq 0 \\
1, &amp; \text{若 } \mathbf{w} \cdot \mathbf{x} + b > 0
\end{cases}
\tag{6.7}
$$&lt;p>构建一个能计算 AND 或 OR 逻辑函数的感知机非常容易；图 6.4 展示了所需的权重。&lt;/p></description></item><item><title>6.4 前馈网络在自然语言处理中的应用：分类任务</title><link>https://youkre.github.io/speech-and-language-processing/ch6-04/</link><pubDate>Wed, 17 Dec 2025 16:44:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-04/</guid><description>&lt;p>现在我们来看如何将前馈网络应用于 NLP 分类任务。
实际上，简单的前馈网络并不是当前文本分类的主流方法；在真实应用中，我们会使用更先进的架构，例如第 10 章介绍的 BERT 等 Transformer 模型。&lt;br>
尽管如此，通过构建一个基于前馈网络的文本分类器，我们可以引入若干核心概念，这些概念贯穿全书，包括：嵌入矩阵（embedding matrix）、表示池化（representation pooling）和表示学习（representation learning）。&lt;/p>
&lt;p>但在介绍这些概念之前，我们先从一个最简单的分类器开始——仅对第 4 章的情感分类器做最小改动。
与第 4 章一样，我们仍使用人工设计的特征，将其送入分类器，并输出类别概率。
唯一的区别是，我们将分类器从逻辑回归替换为神经网络。&lt;/p>
&lt;h3 id="641-使用人工特征的神经网络分类器">6.4.1 使用人工特征的神经网络分类器&lt;/h3>
&lt;p>我们从一个简单的两层情感分类器入手：以第 4 章的逻辑回归分类器（对应单层网络）为基础，仅增加一个隐藏层。&lt;/p>
&lt;p>输入元素 $\mathbf{x}_i$ 可以是图 4.2 中那样的标量特征，例如$\mathbf{x}_i$ = 文档中的总词数，$\mathbf{x}_2$ = 文档中积极情感词典词的出现次数，如果文档包含“no” 则 $\mathbf{x}_3$ = 1，依此类推，共 $d$ 个特征。
输出层 $\hat{y}$ 可以有两个节点（分别对应正面、负面情感），或三个节点（正面、负面、中性）。此时 $\hat{y}_1$ 表示正面情感的概率，
$\hat{y}_2$ 表示负面情感的概率，$\hat{y}_3$ 表示中性情感的概率。
整个模型的计算公式与前述两层网络完全一致（如前所述，我们继续用 $\sigma$ 泛指任意非线性激活函数，无论是 Sigmoid、ReLU 还是其他）：&lt;/p>
$$
\begin{align*}
\mathbf{x} &amp;= [\mathbf{x}_i,\mathbf{x}_2,...\mathbf{x}_d ] (\text{each} \mathbf{x}_i \text{is a hand-designed feature}) \\
\mathbf{h} &amp;= \sigma(\mathbf{Wx} + \mathbf{b}) \\
\mathbf{z} &amp;= \mathbf{Uh} \\
\hat{\mathbf{y}} = \mathrm{softmax}(\mathbf{z})
\tag{6.19}
\end{align*}
$$&lt;p>图 6.10 展示了该架构的示意图。
如前所述，在逻辑回归分类器中加入这个隐藏层，使网络能够捕捉特征之间的非线性交互关系。
仅此一点就可能带来性能更好的情感分类器。&lt;/p></description></item><item><title>第 6 章 神经网络</title><link>https://youkre.github.io/speech-and-language-processing/ch6/</link><pubDate>Wed, 17 Dec 2025 08:23:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6/</guid><description>&lt;blockquote>
&lt;p>“当单元数量很大时，这类机器可以表现出极为复杂的行为。”&lt;/p>
&lt;p>——艾伦·图灵（Alan Turing, 1948），《智能机器》，第6页&lt;/p>&lt;/blockquote>
&lt;p>神经网络是语言处理的一项基础计算工具，其历史也相当悠久。
之所以称为“神经”网络，是因为它起源于&lt;strong>McCulloch-Pitts神经元&lt;/strong>（McCulloch 和 Pitts，1943）。这是一种基于生物神经元的简化模型，，将神经元视为一种计算单元，并可用命题逻辑来描述。
然而，现代语言处理中使用的神经网络已不再依赖这些早期的生物学启发。&lt;/p>
&lt;p>如今的神经网络是由大量小型计算单元组成的网络。每个单元接收一个输入值向量，并输出一个单一数值。
本章将介绍用于分类任务的神经网络。
我们所采用的架构称为&lt;strong>前馈网络&lt;/strong>（feedforward network），因为其计算过程是从一层单元逐层向前传递到下一层。
现代神经网络通常被称为&lt;strong>深度学习&lt;/strong>（deep learning），这是因为现代网络往往是&lt;strong>深层的&lt;/strong>（即包含许多层）。&lt;/p>
&lt;p>神经网络与逻辑回归在数学上有很多共通之处。
但神经网络是一种比逻辑回归更强大的分类器。事实上，即使是最小的神经网络（从技术上讲，仅含一个“隐藏层”的网络）也能被证明可以学习任意函数。&lt;/p>
&lt;p>神经网络分类器与逻辑回归还存在另一重要区别。
在逻辑回归中，我们通过基于领域知识设计丰富多样的特征模板，将该分类器应用于多种不同任务。
而在使用神经网络时，则通常避免大量依赖人工构造的复杂特征，转而构建直接以原始词（raw words）作为输入的网络，并在学习分类的过程中自动习得特征表示。
我们在第6章中已经看到过这种表示学习（representation learning）的典型例子——词嵌入（embeddings）。
特别地，深层网络在表示学习方面表现尤为出色。
正因如此，深度神经网络成为那些拥有充足数据、足以支持自动特征学习的任务的理想工具。&lt;/p>
&lt;p>神经网络分类器与逻辑回归还有另一点不同。
使用逻辑回归时，我们通常基于领域知识设计出丰富多样的特征模板，从而将其应用于多种任务。
而使用神经网络时，则更倾向于避免大量手工构造的复杂特征。取而代之的是，构建直接以原始词语作为输入的神经网络，并让网络在学习分类的过程中自动学习特征表示。
我们在第 5 章中已经看到过这种表示学习的例子——词嵌入（embeddings），一旦开始学些深度 transformer 网络，我们会看到大量此类例子。
特别地，非常深的网络在表示学习方面表现尤为出色。
因此，对于拥有足够数据、能够自动学习特征的任务，深度神经网络正是合适的工具。&lt;/p>
&lt;p>本章将介绍作为分类器的前馈网络，并将其应用于一个简单的语言建模任务：为词序列分配概率，并预测下一个词。
在后续章节中，我们将进一步探讨神经模型的诸多其他方面，例如&lt;strong>循环神经网络&lt;/strong>（第8章）、&lt;strong>Transformer&lt;/strong>（第9章）以及&lt;strong>掩码语言建模&lt;/strong>（第11章）。&lt;/p>
&lt;p>本章将介绍使用前馈网络的分类器，首先使用手工构造的特征，然后使用使用第 5 章所学的词嵌入。
在后续章节中，我们将介绍更多类型的神经网络模型，其中最重要的是&lt;strong>Transformer&lt;/strong>和&lt;strong>注意力机制&lt;/strong>（第8章），此外还包括&lt;strong>循环神经网络&lt;/strong>（第13章）和&lt;strong>卷积神经网络&lt;/strong>（第15章）。
下一章则将引入神经大语言模型这一范式。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch5-09">5.9 向量模型的评估&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch6-01">6.1 单元&lt;/a>
&lt;/nav></description></item><item><title>4.11 统计显著性检验</title><link>https://youkre.github.io/speech-and-language-processing/ch4-11/</link><pubDate>Tue, 16 Dec 2025 16:33:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-11/</guid><description>&lt;p>在构建系统时，我们常常需要比较两个系统的性能。
如何判断我们刚刚构建的新系统是否优于旧系统？或者是否优于文献中描述的其他系统？这属于统计假设检验（statistical hypothesis testing）的范畴。
本节将介绍用于自然语言处理（NLP）分类器的统计显著性检验方法，主要参考了 Dror 等人（2020）与 Berg-Kirkpatrick 等人（2012）的工作。&lt;/p>
&lt;p>假设我们要在某个评价指标 $M$（如 $F_1$ 值或准确率）上比较分类器 $A$ 与 $B$ 的性能。
例如，我们想知道：在某个特定测试集 $x$ 上，我们的逻辑回归情感分类器 $A$（见第5章）是否比朴素贝叶斯情感分类器 $B$ 获得更高的 $F_1$ 分数。
记 $M(A, x)$ 为系统 A 在测试集 $x$ 上的得分，$\delta(x)$ 为 A 与 B 在 $x$ 上的性能差异：&lt;/p>
$$
\delta(x) = M(A,x) - M(B,x)
\tag{4.44}
$$&lt;p>我们希望判断 $\delta(x) > 0$ 是否成立——即逻辑回归分类器在该测试集上的 $F_1$ 是否确实高于朴素贝叶斯分类器。
$\delta(x)$ 被称为&lt;strong>效应量&lt;/strong>（effect size）：$\delta$ 越大，说明 A 明显优于 B；$\delta$ 越小，则说明 A 仅略胜一筹。&lt;/p>
&lt;p>那么，为何不能直接看 $\delta(x)$ 是否为正？
假设我们发现 A 的 $F_1$ 比 B 高出 0.04，是否就能断定 A 更好？不能！
因为这种优势可能只是偶然出现在当前测试集 $x$ 上。
我们需要更严谨的判断：A 相对于 B 的优势是否具有&lt;strong>可复现性&lt;/strong>？也就是说，如果换一个测试集 $x'$，或在其他条件下重复实验，A 是否仍能保持优势？&lt;/p></description></item><item><title>4.10 测试集与交叉验证</title><link>https://youkre.github.io/speech-and-language-processing/ch4-10/</link><pubDate>Tue, 16 Dec 2025 14:54:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-10/</guid><description>&lt;p>文本分类的训练与测试流程与我们在语言建模中所见（第 3.2 节）一致：我们使用&lt;strong>训练集&lt;/strong>（training set）来训练模型，然后使用&lt;strong>开发测试集&lt;/strong>（development test set，也称为 &lt;strong>devset&lt;/strong>）来调整某些参数，并总体上确定哪个模型表现最佳。
一旦我们选定自认为最优的模型，便在此前从未见过的测试集（test set）上运行该模型，并报告其性能。&lt;/p>
&lt;p>虽然使用 devset 可以避免对测试集过拟合，但采用固定的训练集、devset 和测试集会带来另一个问题：为了保留足够多的数据用于训练，测试集（或 devset）可能不够大，从而缺乏代表性。
难道不能设法既用全部数据进行训练，又用全部数据进行测试吗？答案是肯定的——我们可以采用&lt;strong>交叉验证&lt;/strong>（cross-validation）。&lt;/p>
&lt;p>在交叉验证中，我们先选定一个数字 $k$，并将数据划分为 $k$ 个互不重叠的子集，称为&lt;strong>折&lt;/strong>（folds）。
接着，依次选取其中一折作为测试集，在其余 $k-1$ 折上训练分类器，并在该测试集上计算错误率。
然后换另一折作为测试集，再次在剩下的 $k-1$ 折上训练模型。
如此重复 $k$ 次，每次使用不同的测试折，最后将这 $k$ 次测试得到的错误率取平均，作为模型的平均错误率。
例如，若选择 $k = 10$，我们将训练 10 个不同的模型（每个使用 90% 的数据），测试 10 次，并对这 10 个结果取平均。
这种方法称为&lt;strong>10 折交叉验证&lt;/strong>（10-fold cross-validation）。&lt;/p>
&lt;p>交叉验证唯一的缺点在于：由于所有数据都被用于测试，因此整个语料库必须保持“盲态”：不能事先查看任何数据以推测可能的特征，也不能通过观察数据了解其分布情况，否则就相当于“偷看”了测试集。
这种作弊行为会导致对系统性能的估计过于乐观。
然而，在设计自然语言处理系统时，通过观察语料来理解数据特性至关重要！那该怎么办？
为此，一种常见做法是：先划分出固定的训练集和测试集，然后仅在训练集内部进行 10 折交叉验证（用于模型选择或调参），而仍按常规方式在独立的测试集上计算率，如图 4.10 所示。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-4-10.png">&lt;/p>
&lt;p>&lt;strong>图 4.10&lt;/strong> 10 折交叉验证&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch4-09">4.9 评估指标：精确率、召回率与 F 值&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch4-11">4.11 统计显著性检验&lt;/a>
&lt;/nav></description></item><item><title>4.9 评估指标：精确率、召回率与 F 值</title><link>https://youkre.github.io/speech-and-language-processing/ch4-09/</link><pubDate>Tue, 16 Dec 2025 11:13:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-09/</guid><description>&lt;p>为了介绍文本分类的评估方法，我们先考虑一些简单的二元&lt;strong>检测任务&lt;/strong>（detection tasks）。
例如，在垃圾邮件检测中，我们的目标是将每封邮件标记为属于垃圾邮件类别（“正例”，positive）或不属于该类别（“负例”，negative）。
对于每个样本（即每封电子邮件），我们需要知道我们的系统是否将其判定为垃圾邮件。
我们还需要知道该邮件实际上是否为垃圾邮件，即由人工标注的、我们试图匹配的标签。
我们将这些人工标注的标签称为&lt;strong>黄金标准标签&lt;/strong>（gold labels）。&lt;/p>
&lt;p>再举一个例子：假设你是“美味派公司”（Delicious Pie Company）的 CEO，你想了解人们在社交媒体上对你们派的评价，于是你构建了一个系统来检测提及“美味派”的推文。
在这个任务中，正例是关于美味派的推文，负例则是所有其他推文。&lt;/p>
&lt;p>在这两类场景中，我们都需一种指标来衡量垃圾邮件检测器（或派相关推文检测器）的表现好坏。
要评估任何检测系统，我们首先构建一个如图 4.7 所示的&lt;strong>混淆矩阵&lt;/strong>（confusion matrix）。
混淆矩阵是一个表格，用于可视化算法输出与人工黄金标准标签之间的对应关系。它以两个维度（系统输出 vs. 黄金标签）组织数据，每个单元格代表一类可能的结果。
以垃圾邮件检测为例：&lt;strong>真正例&lt;/strong>（True Positives, TP）代表邮件确实是垃圾邮件（由人工标签确认），且系统也正确地将其判为垃圾邮件。
&lt;strong>假负例&lt;/strong>（False Negatives, FN）表示邮件确实是垃圾邮件，但系统错误地将其标记为非垃圾邮件。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-4-7.png">&lt;/p>
&lt;p>&lt;strong>图 4.7&lt;/strong> 用于可视化二元分类系统相对于黄金标准标签表现的混淆矩阵。&lt;/p>
&lt;p>表格右下角给出了&lt;strong>准确率&lt;/strong>（accuracy）的计算公式，即系统正确分类的样本占总样本数（对于垃圾邮件或者派的例子，就是所有邮件或者所有推文）的百分比。
尽管准确率看似自然直观，但通常不用于文本分类任务。
原因在于，当类别分布严重不平衡时（例如垃圾邮件在全部邮件中占绝大多数，或关于派的推文在海量推文中极为稀少），准确率会严重失真。&lt;/p>
&lt;p>为更清楚地说明这一点，设想我们分析了 100 万条推文，其中仅有 100 条讨论了对我们派的喜爱（或厌恶），其余 999,900 条则完全无关。
现在考虑一个极其简单的分类器：它一律将所有推文判为“与派无关”。该分类器会产生 999,900 个真负例和 100 个假负例，准确率达到 $\frac{999,900}{1,000,000} = 99.99\%$！
多么惊人的准确率！
我们是否该为此欢呼？
显然不该，因为这个“完美”的分类器一条相关评论都没找到，对我们毫无用处。
换言之，当目标任务是发现&lt;strong>稀有事件&lt;/strong>（或至少是频率不平衡的事件）时，准确率就不是一个合适的评估指标，而这种情况在现实世界中极为普遍。&lt;/p>
&lt;p>正因如此，我们通常不使用准确率，而是转向图 4.7 中所示的另外两个指标：&lt;strong>精确率&lt;/strong>（Precision）和&lt;strong>召回率&lt;/strong>（Recall）。
&lt;strong>精确率&lt;/strong>衡量的是：在系统判定为正例的所有样本中（即系统标记为正例），真正为正例的比例（即按照人类的黄金标准标签为正例）。
精确率的定义为：&lt;/p>
$$
\text{Precision} = \frac{\text{true positives}}{\text{true positives} + \text{false negatives}}
$$&lt;p>&lt;strong>召回率&lt;/strong>衡量的是，在所有实际为正例的样本中，被系统正确识别出来的比例。其定义为：&lt;/p>
$$
\text{Recall} = \frac{\text{true positives}}{\text{true positives} + \text{false negatives}}
$$&lt;p>这两个指标能有效解决前述“无派分类器”的问题。
尽管该分类器准确率高达 99.99%，但其召回率为 0（因为真正例为 0，假负例为 100，故召回率是 0/100）。
同时，由于它从未预测任何正例，其精确率在数学上未定义（分母为 0），但在实际应用中也被视为无效。
因此，与准确率不同，精确率和召回率都聚焦于“真正例”，即我们真正想要找的东西。&lt;/p></description></item><item><title>9.6 总结</title><link>https://youkre.github.io/speech-and-language-processing/ch9-06/</link><pubDate>Tue, 04 Nov 2025 15:45:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch9-06/</guid><description>&lt;p>本章介绍了用于语言建模任务的 Transformer 及其各个组成部分。
我们将在下一章继续探讨语言建模的相关问题，包括训练和采样等。&lt;/p>
&lt;p>以下是本章涵盖的主要内容总结：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Transformer&lt;/strong> 是一种基于&lt;strong>多头注意力&lt;/strong>（multi-head attention）的非循环神经网络，而多头注意力是一种&lt;strong>自注意力&lt;/strong>（self-attention）机制。多头注意力计算通过将先前词元的向量（根据它们与当前词处理的相关性进行加权）累加进来，将输入向量 $\mathbf{x}_i$ 映射为输出向量 $\mathbf{a}_i$。&lt;/li>
&lt;li>一个&lt;strong>Transformer 模块&lt;/strong>（transformer block）包含一个&lt;strong>残差流&lt;/strong>（residual stream），其中来自前一层的输入会直接传递到下一层，并与不同组件的输出相加。这些组件包括一个&lt;strong>多头注意力层&lt;/strong>，后接一个&lt;strong>前馈层&lt;/strong>，每个组件之前都带有&lt;strong>层归一化&lt;/strong>（layer normalization）。通过堆叠多个 Transformer 模块，可以构建出更深、更强大的网络。&lt;/li>
&lt;li>Transformer 的输入是通过将一个嵌入（由&lt;strong>嵌入矩阵&lt;/strong>计算得出）与一个表示词元在上下文窗口中序列位置的&lt;strong>位置编码&lt;/strong>（positional encoding）相加得到的。&lt;/li>
&lt;li>语言模型可以通过堆叠 Transformer 模块来构建，在顶部配有一个&lt;strong>语言模型头&lt;/strong>（language model head）。该头部将一个&lt;strong>解嵌入&lt;/strong>（unembedding）矩阵应用于顶层的输出 $H$，以生成&lt;strong>逻辑值&lt;/strong>（logits），然后通过 softmax 函数生成词的概率分布。&lt;/li>
&lt;li>基于 Transformer 的语言模型拥有非常宽的上下文窗口（对于大型模型，可宽达 32768 个词元），这使得它们能够利用海量的上下文信息来预测下一个词。&lt;/li>
&lt;/ul>
&lt;h2 id="文献与历史注记">文献与历史注记&lt;/h2>
&lt;p>Transformer (Vaswani et al., 2017) 的发展借鉴了两条先前的研究路线：&lt;strong>自注意力&lt;/strong>（self-attention）和&lt;strong>记忆网络&lt;/strong>（memory networks）。&lt;/p>
&lt;p>编码器-解码器注意力（encoder-decoder attention）的思想——即使用对输入词编码的软权重来指导生成式解码器（见第13章）——最初由 Graves (2013) 在手写生成的背景下提出，并由 Bahdanau 等人 (2015) 应用于机器翻译（MT）。
这一思想后来被扩展到自注意力机制：不再需要区分独立的编码和解码序列，而是将注意力视为一种对词元进行加权的方式，用以汇集从较低层传递到较高层的信息（Ling et al., 2015; Cheng et al., 2016; Liu et al., 2016）。&lt;/p>
&lt;p>Transformer 的其他一些方面，包括&lt;strong>键&lt;/strong>（key）、&lt;strong>查询&lt;/strong>（query）和&lt;strong>值&lt;/strong>（value）的术语，则来源于&lt;strong>记忆网络&lt;/strong>（memory networks）。
记忆网络是一种为神经网络添加外部读写存储器的机制，其核心是使用查询的嵌入去匹配关联记忆中代表内容的键（Sukhbaatar et al., 2015; Weston et al., 2015; Graves et al., 2014）。&lt;/p></description></item><item><title>第 8 章 Transformer</title><link>https://youkre.github.io/speech-and-language-processing/ch8/</link><pubDate>Sat, 01 Nov 2025 21:04:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch8/</guid><description>&lt;blockquote>
&lt;p>“真正的记忆艺术在于专注。”&lt;/p>
&lt;p>塞缪尔·约翰逊，《闲者》第74篇，1759年9月&lt;/p>&lt;/blockquote>
&lt;p>本章将介绍 &lt;strong>Transformer&lt;/strong>，这是构建大语言模型的标准架构。
正如上一章所言，基于 Transformer 的大语言模型彻底改变了语音与语言处理领域。
事实上，本书后续每一章都将用到这一技术。
和上一章一样，本章我们主要关注从左到右（有时也称为&lt;strong>因果式&lt;/strong>或&lt;strong>自回归&lt;/strong>）的语言建模方式，即给定一个输入词元（token）序列，模型根据先前的上下文逐个预测下一个输出词元。&lt;/p>
&lt;p>Transformer 是一种具有特定结构的神经网络，其核心机制被称为&lt;strong>自注意力&lt;/strong>（self-attention）或&lt;strong>多头注意力&lt;/strong>（multi-head attention）&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>。
注意力机制可以理解为一种方法，通过“关注”并整合周围词元的信息，来构建某个词元在上下文中的语义表示，从而帮助模型学习长距离内词元之间的关联。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-8-1.png">&lt;/p>
&lt;p>&lt;strong>图 8.1&lt;/strong> 展示了一个（从左到右的）Transformer 架构，说明了每个输入词元如何被编码，经过一系列堆叠的 Transformer 模块（block），最终由语言模型头部预测下一个词元。&lt;/p>
&lt;p>图8.1 概述了 Transformer 的基本结构。
一个完整的 Transformer 模型包含三个主要组成部分。
居于核心的是若干列堆叠的 Transformer &lt;strong>模块&lt;/strong>（blocks）。
每个模块是一个多层网络，包含一个&lt;strong>多头注意力层&lt;/strong>、前馈网络以及层归一化（layer normalization）等操作，它将第 $i$ 列的输入向量 $\mathbf{x}_i$（对应第 $i$ 个输入词元）映射为输出向量 $\mathbf{h}_i$。
整组 $n$ 个模块共同将一个长度为 $n$ 的&lt;strong>上下文窗口&lt;/strong>内的输入向量序列（$\mathbf{x}_1,...,\mathbf{x}_n$）映射为一个等长的输出向量序列（$\mathbf{h}_1,...,\mathbf{h}_n$）。
每个“列”通常包含 12 到 96 个甚至更多堆叠的模块。&lt;/p>
&lt;p>在模块列之前是&lt;strong>输入编码&lt;/strong>（input encoding）组件，它负责将一个输入词元（例如单词 &amp;ldquo;thanks&amp;rdquo;）处理成一个具有上下文意义的向量表示，这通常通过一个&lt;strong>嵌入矩阵&lt;/strong> $\mathbf{E}$（embedding matrix $\mathbf{E}$）以及一种对词元位置进行编码的机制来实现。
在模块列之后是&lt;strong>语言模型头&lt;/strong>（language modeling head），它接收最后一个 Transformer 模块输出的嵌入表示，将其通过一个&lt;strong>解嵌入矩阵&lt;/strong> $\mathbf{U}$（unembedding matrix $\mathbf{U}$），再经过一个针对整个词汇表的 softmax 函数，最终为该位置生成一个预测词元。&lt;/p>
&lt;p>基于 Transformer 的语言模型结构复杂，其细节将在接下来的几章中逐步展开。
第 7 章已经介绍了如何预训练模型，如何通过&lt;strong>采样&lt;/strong>（sampling）生成词元。
在本章接下来的几节中，我们将介绍多头注意力机制、Transformer 模块的其余部分，以及输入编码和语言模型头部等组件。
第 10 章将介绍&lt;strong>掩码语言建模&lt;/strong>（masked language modeling）以及基于双向 Transformer 编码器的 &lt;strong>BERT&lt;/strong> 系列模型。
第 9 章将展示如何通过提供指令和示例来&lt;strong>提示&lt;/strong>（prompt）大语言模型，使其执行各类自然语言处理任务，以及如何通过&lt;strong>对齐&lt;/strong>（align）技术使模型的输出符合人类偏好。
第 12 章将介绍使用&lt;strong>编码器-解码器&lt;/strong>（encoder-decoder）架构进行机器翻译的方法。&lt;/p></description></item><item><title>6.9 嵌入向量的可视化</title><link>https://youkre.github.io/speech-and-language-processing/ch6-09/</link><pubDate>Sat, 25 Oct 2025 00:18:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-09/</guid><description>&lt;blockquote>
&lt;p>“我能很好地感知很多维度，只要这些维度大约是二维的。”&lt;/p>
&lt;p>已故经济学家 马丁·舒比克&lt;/p>&lt;/blockquote>
&lt;p>可视化嵌入向量对于帮助我们理解、应用和改进这些词义模型至关重要。
但如何可视化一个（例如）100维的向量呢？&lt;/p>
&lt;p>&lt;strong>图8&lt;/strong>：针对三类名词的多维尺度分析（Multidimensional scaling）。&lt;/p>
&lt;p>&lt;strong>图9&lt;/strong>：基于向量相关性距离的三类名词层次聚类。&lt;/p>
&lt;p>要可视化一个嵌入在空间中的词 &lt;em>w&lt;/em> 的词义，最简单方法是列出与 &lt;em>w&lt;/em> 最相似的词，即按词汇表中所有词向量与 &lt;em>w&lt;/em> 的向量之间的余弦相似度进行排序。
例如，使用GloVe算法计算出的某个嵌入向量，与 &lt;em>frog&lt;/em> （青蛙）最接近的7个词是：&lt;em>frogs&lt;/em>（青蛙，复数）、&lt;em>toad&lt;/em>（蟾蜍）、&lt;em>litoria&lt;/em>（雨滨蛙属）、&lt;em>leptodactylidae&lt;/em>（细趾蟾科）、&lt;em>rana&lt;/em>（蛙属）、&lt;em>lizard&lt;/em>（蜥蜴）和 &lt;em>eleutherodactylus&lt;/em>（细趾蟾属）（Pennington 等, 2014）。&lt;/p>
&lt;p>另一种可视化方法是使用聚类算法，展示嵌入空间中哪些词彼此相似的层次结构。
左侧未加标题的图例使用了对部分名词嵌入向量进行层次聚类的方法作为可视化手段（Rohde 等, 2006）。&lt;/p>
&lt;p>然而，目前最常见的可视化方法可能是将词的 100 维空间投影到二维空间中。
图 6.1 和图 6.16 展示了这样一种可视化效果，它们使用了一种称为 t-SNE 的投影方法（van der Maaten 和 Hinton, 2008）。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch6-08">6.8 Word2vec&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch6-10">6.10 嵌入向量的语义特性&lt;/a>
&lt;/nav></description></item><item><title>6.8 Word2vec</title><link>https://youkre.github.io/speech-and-language-processing/ch6-08/</link><pubDate>Thu, 16 Oct 2025 07:50:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-08/</guid><description>&lt;p>在前面的章节中，我们了解了如何将一个词表示为稀疏的长向量，其维度对应于词汇表中的词或文档集合中的文档。
现在，我们介绍一种更强大的词表示方法：&lt;strong>嵌入（embeddings）&lt;/strong>，即短而稠密的向量。
与迄今为止所见的向量不同，嵌入向量是&lt;strong>短的&lt;/strong>，其维度 $d$ 通常在50到1000之间，远小于之前遇到的庞大词汇量 $|V|$ 或文档数量 $D$。
这些维度 $d$ 并没有明确的解释意义。
并且这些向量是&lt;strong>稠密的&lt;/strong>：向量元素不再是稀疏的、大部分为零的计数或计数函数，而是可以为负的实数值。&lt;/p>
&lt;p>事实证明，在每一项自然语言处理任务中，稠密向量的表现都优于稀疏向量。
虽然我们尚未完全理解所有原因，但有一些合理的解释。
将词表示为300维的稠密向量，比起表示为50,000维的向量，能让分类器学习的权重少得多，更小的参数空间可能有助于提升泛化能力并避免过拟合。
稠密向量也可能更有效地捕捉同义关系。
例如，在稀疏向量表示中，像 &lt;em>car&lt;/em> 和 &lt;em>automobile&lt;/em> 这样的同义词对应的维度是彼此独立且无关的；因此，稀疏向量可能无法捕捉到一个以 &lt;em>car&lt;/em> 为邻近词的词与另一个以 &lt;em>automobile&lt;/em> 为邻近词的词之间的相似性。&lt;/p>
&lt;p>本节中介绍一种计算嵌入的方法：&lt;strong>负采样跳字模型（skip-gram with negative sampling）&lt;/strong>，有时简称为 &lt;strong>SGNS&lt;/strong>。
跳字算法是名为 &lt;strong>word2vec&lt;/strong> 的软件包中的两种算法之一，因此该算法有时被笼统地称为 word2vec（Mikolov 等，2013a；Mikolov 等，2013b）。
word2vec 方法速度快、训练高效，且代码和预训练嵌入模型在线上易于获取。
Word2vec 嵌入是静态的&lt;strong>嵌入&lt;/strong>，意味着该方法为词汇表中的每个词学习一个固定的嵌入表示。
在第11章中，我们将介绍学习动态上下文&lt;strong>嵌入&lt;/strong>的方法，如流行的 &lt;strong>BERT&lt;/strong> 表示系列，其中每个词的向量会因其所处的不同上下文而变化。&lt;/p>
&lt;p>word2vec 的核心理念是：不再统计每个词 $w$ 在某个词（比如 &lt;em>apricot&lt;/em>）附近出现的频率，而是训练一个分类器来执行一个二元预测任务：“词 $w$ 是否可能出现在 &lt;em>apricot&lt;/em> 附近？”
我们实际上并不关心这个预测任务本身；而是将分类器学习到的&lt;strong>权重&lt;/strong>作为词的嵌入表示。&lt;/p>
&lt;p>这里的&lt;strong>革命性思想&lt;/strong>在于，我们可以直接使用连续文本作为此类分类器的隐式监督训练数据：一个在目标词 &lt;em>apricot&lt;/em> 附近出现的词 $c$，就充当了“词 $c$ 是否可能出现在 &lt;em>apricot&lt;/em> 附近？”这一问题的黄金标准“正确答案”。
这种方法通常被称为&lt;strong>自监督&lt;/strong>，它避免了任何人工标注监督信号的需求。
这一思想最初在神经语言建模任务中被提出，Bengio 等人（2003）和 Collobert 等人（2011）表明，一个神经语言模型（一种学习根据前文预测下一个词的神经网络）可以直接使用连续文本中的下一个词作为其监督信号，并可在执行此预测任务的同时学习每个词的嵌入表示。&lt;/p>
&lt;p>我们将在下一章介绍神经网络的实现方法，但 word2vec 是一个比神经网络语言模型简单得多的模型，主要体现在两方面。
首先，word2vec 简化了任务（将其变为二元分类而非词预测）。
其次，word2vec 简化了架构（训练一个逻辑回归分类器，而不是一个多层、包含隐藏层且需要更复杂训练算法的神经网络）。
跳字模型的&lt;strong>设计原理&lt;/strong>如下：&lt;/p></description></item><item><title>6.7 tf-idf 或 PPMI 向量模型的应用</title><link>https://youkre.github.io/speech-and-language-processing/ch6-07/</link><pubDate>Tue, 14 Oct 2025 09:33:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-07/</guid><description>&lt;p>总之，到目前为止我们所描述的向量语义模型将目标词表示为一个向量，其维度对应于一个大型文集中的文档（词-文档矩阵）或某个邻近窗口中词语的计数（词-词矩阵）。每个维度的值是经过加权的计数，词-文档矩阵使用 tf-idf 加权，词-词矩阵使用 PPMI 加权，且这些向量是稀疏的（因为大多数值为零）。&lt;/p>
&lt;p>该模型通过计算两个词 $x$ 和 $y$ 的 &lt;strong>tf-idf&lt;/strong> 或 &lt;strong>PPMI&lt;/strong> 向量的余弦值来衡量它们之间的相似性；余弦值越高，相似度越高。整个模型有时根据其加权函数被称为 tf-idf 模型或 PPMI 模型。&lt;/p>
&lt;p>基于 tf-idf 的意义模型常用于文档相关任务，例如判断两篇文档是否相似。取文档中所有词的向量，并计算这些向量的&lt;strong>质心&lt;/strong>（centroid）来表示一篇文档。质心是均值在多维空间中的推广；一组向量的质心是一个单一向量，它到该组中每个向量的平方距离之和最小。给定 $k$ 个词向量 $w_1, w_2, ..., w_k$，其质心&lt;strong>文档向量&lt;/strong> $d$ 定义为：&lt;/p>
$$
d = \frac{w_1 + w_2 + ... + w_k}{k}
\tag{6.23}
$$&lt;p>给定两篇文档后，我们可以计算它们的文档向量 $d_1$ 和 $d_2$，并通过 $cos(d_1, d_2)$ 来估计两篇文档的相似度。文档相似度在各种应用中都非常有用，例如信息检索、抄袭检测、新闻推荐系统，甚至可用于数字人文领域的任务，如比较文本的不同版本以判断哪些版本彼此相似。&lt;/p>
&lt;p>PPMI 模型和 tf-idf 模型都可用于计算词语相似度，适用于诸如寻找词语同义词、追踪词语意义变化，或自动发现不同语料库中词语含义等任务。例如，可以通过计算目标词 $w$ 与其余 $V-1$ 个词之间的余弦相似度，对结果进行排序，然后查看前 10 个结果，从而找到与 $w$ 最相似的 10 个词。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch6-06">6.6 点互信息（PMI）&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch6-08">6.8 Word2vec&lt;/a>
&lt;/nav></description></item><item><title>5.4 用余弦度量相似性</title><link>https://youkre.github.io/speech-and-language-processing/ch5-04/</link><pubDate>Mon, 13 Oct 2025 10:27:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch5-04/</guid><description>&lt;p>为了度量两个目标词 $v$ 和 $w$ 之间的相似性，我们需要一种度量方法，它能接受两个向量（维度相同，要么都以词语为维度，因此长度为 $|V|$，要么都以文档为维度，长度为 $|D|$），给出它们相似程度的度量值。
迄今为止最常用的相似性度量是向量之间夹角的&lt;strong>余弦&lt;/strong>（cosine）。&lt;/p>
&lt;p>余弦——像NLP中使用的大多数向量相似性度量一样——基于线性代数中的&lt;strong>点积&lt;/strong>（dot product）运算符，也称为&lt;strong>内积&lt;/strong>（inner product）：&lt;/p>
$$
\begin{align*}
\text{点积}(\mathbf{v},\mathbf{w}) &amp;= \mathbf{v} \cdot \mathbf{w} \\
&amp;= \sum_{i=1}^N v_i w_i \\
&amp;= v_1w_1 + v_2w_2 + ... + v_N w_N
\tag{5.7}
\end{align*}
$$&lt;p>点积可以作为一种相似性度量，因为当两个向量在相同维度上具有较大的值时，点积的值往往会很高。
相反，如果两个向量在不同维度上为零（即正交向量），它们的点积为 0，这表示它们的差异性很强。&lt;/p>
&lt;p>然而，这种原始的点积作为相似性度量存在一个问题：它偏向于长度更长的向量。
向量的长度定义为：&lt;/p>
$$
|\mathbf{v}| = \sqrt{\sum_{i=1}^N v_i^2}
\tag{5.8}
$$&lt;p>如果一个向量更长，每个维度的值更高，其点积也会更高。
更频繁出现的词具有更长的向量，因为它们倾向于与更多的词共现，并且与每个共现词的共现值也更高。
因此，原始点积对高频词的值会更高。
但这是一个问题；我们希望相似性度量能告诉我们两个词有多相似，而不受它们频率的影响。&lt;/p>
&lt;p>我们通过将点积除以两个向量的长度来对点积进行归一化，从而修正这一问题。
这种&lt;strong>归一化的点积&lt;/strong>实际上等于两个向量之间夹角的余弦，这源于两个向量 $\mathbf{a}$ 和 $\mathbf{b}$ 之间点积的定义：&lt;/p>
$$
\begin{align*}
\mathbf{a} \cdot \mathbf{b} &amp;= |\mathbf{a}||\mathbf{b}| \cos\theta \\
\frac{\mathbf{a} \cdot \mathbf{b}}{|\mathbf{a}||\mathbf{b}|} &amp;= \cos\theta
\tag{5.9}
\end{align*}
$$&lt;p>因此，两个向量 $\mathbf{v}$ 和 $\mathbf{w}$ 之间的&lt;strong>余弦&lt;/strong>相似性度量可计算为：&lt;/p></description></item><item><title>5.11 小结</title><link>https://youkre.github.io/speech-and-language-processing/ch5-11/</link><pubDate>Fri, 10 Oct 2025 09:08:00 +0000</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch5-11/</guid><description>&lt;p>本章介绍了&lt;strong>逻辑回归&lt;/strong>模型在&lt;strong>分类&lt;/strong>中的应用。&lt;/p>
&lt;ul>
&lt;li>逻辑回归是一种监督式机器学习分类器，它从输入中提取实值特征，每个特征乘以一个权重后求和，并将结果通过&lt;strong>sigmoid&lt;/strong>函数传递以生成概率。使用一个阈值来做出决策。&lt;/li>
&lt;li>逻辑回归可以用于两类（例如，正面和负面情感）或多类（&lt;strong>多项逻辑回归&lt;/strong>，例如用于n元文本分类、词性标注等）的情况。&lt;/li>
&lt;li>多项逻辑回归使用&lt;strong>softmax&lt;/strong>函数来计算概率。&lt;/li>
&lt;li>权重（向量 $\mathbf{w}$ 和偏置 $b$）通过损失函数（如&lt;strong>交叉熵损失&lt;/strong>）从标记的训练集中学习，该损失函数需要被最小化。&lt;/li>
&lt;li>最小化这个损失函数是一个&lt;strong>凸优化&lt;/strong>问题，迭代算法如梯度下降被用来找到最优权重。&lt;/li>
&lt;li>&lt;strong>正则化&lt;/strong>被用来避免过拟合。&lt;/li>
&lt;li>由于其能够透明地研究单个特征的重要性，逻辑回归也是最有用的分析工具之一。&lt;/li>
&lt;/ul>
&lt;h2 id="文献与历史注记">文献与历史注记&lt;/h2>
&lt;p>逻辑回归是在统计学领域发展起来的，在20世纪60年代已被用于二进制数据的分析，尤其在医学中广泛应用（Cox, 1969）。从20世纪70年代末开始，它成为语言学中研究语言变异的形式基础之一（Sankoff and Labov, 1979）。&lt;/p>
&lt;p>然而，直到20世纪90年代，逻辑回归才在自然语言处理中变得普遍，当时它似乎同时从两个方向出现。第一个来源是信息检索和语音处理这两个相邻领域，它们都曾使用回归方法，并且都为NLP贡献了许多其他统计技术。实际上，早期将逻辑回归用于文档路由的例子之一是最早使用（LSI）嵌入作为词表示的NLP应用之一（Schütze et al., 1995）。&lt;/p>
&lt;p>与此同时，在20世纪90年代初，IBM Research在名为&lt;strong>最大熵&lt;/strong>建模或&lt;strong>maxent&lt;/strong>（Berger et al., 1996）的名称下开发并应用于NLP，这似乎是独立于统计文献的发展。在这个名称下，它被应用于语言模型（Rosenfeld, 1996）、词性标注（Ratnaparkhi, 1996）、解析（Ratnaparkhi, 1997）、共指消解（Kehler, 1997b）和文本分类（Nigam et al., 1999）。&lt;/p>
&lt;p>关于分类的更多信息可以在机器学习教材中找到（Hastie et al., 2001; Witten and Frank, 2005; Bishop, 2006; Murphy, 2012）。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch5-10">5.10 进阶：梯度公式的推导&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch6">第6章 向量语义与词嵌入&lt;/a>
&lt;/nav></description></item><item><title>5.10 进阶：梯度公式的推导</title><link>https://youkre.github.io/speech-and-language-processing/ch5-10/</link><pubDate>Fri, 10 Oct 2025 08:50:00 +0000</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch5-10/</guid><description>&lt;p>在本节中，我们将推导逻辑回归的交叉熵损失函数 $L_{CE}$ 的梯度。首先，回顾一些基本的微积分知识。&lt;/p>
&lt;p>第一，$\ln(x)$ 的导数：&lt;/p>
$$
\frac{d}{dx} \ln(x) = \frac{1}{x}
\tag{5.49}
$$&lt;p>第二，sigmoid 函数（非常优美的）导数：&lt;/p>
$$
\frac{d\sigma(z)}{dz} = \sigma(z)(1 - \sigma(z))
\tag{5.50}
$$&lt;p>第三，导数的链式法则（chain rule）。假设要计算复合函数 $f(x) = u(v(x))$ 的导数。$f(x)$ 的导数等于 $u(x)$ 对 $v(x)$ 的导数乘以 $v(x)$ 对 $x$ 的导数：&lt;/p>
$$
\frac{df}{dx} = \frac{du}{dv} \cdot \frac{dv}{dx}
\tag{5.51}
$$&lt;p>首先，求损失函数对单个权重 $w_j$ 的偏导数（需要对每个权重以及偏置 $b$ 都进行计算）：&lt;/p>
$$
\begin{aligned}
\frac{\partial L_{CE}}{\partial w_j} &amp;= \frac{\partial}{\partial w_j} \left( -[y \log \sigma(\mathbf{w} \cdot \mathbf{x} + b) + (1 - y)\log(1 - \sigma(\mathbf{w} \cdot \mathbf{x} + b))] \right) \\
&amp;= -\left[ \frac{\partial}{\partial w_j} y \log \sigma(\mathbf{w} \cdot \mathbf{x} + b) + \frac{\partial}{\partial w_j} (1 - y)\log(1 - \sigma(\mathbf{w} \cdot \mathbf{x} + b)) \right]
\end{aligned}
\tag{5.52}
$$&lt;p>接下来，使用链式法则，并利用对数函数的导数：&lt;/p></description></item><item><title>4.15 进阶：梯度公式的推导</title><link>https://youkre.github.io/speech-and-language-processing/ch4-15/</link><pubDate>Fri, 10 Oct 2025 08:50:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-15/</guid><description>&lt;p>在本节中，我们将推导逻辑回归的交叉熵损失函数 $L_{CE}$ 的梯度。
首先，回顾一些基本的微积分知识。
第一点是$\ln(x)$ 的导数：&lt;/p>
$$
\frac{d}{dx} \ln(x) = \frac{1}{x}
\tag{4.56}
$$&lt;p>第二点sigmoid 函数（非常优美的）导数：&lt;/p>
$$
\frac{d\sigma(z)}{dz} = \sigma(z)(1 - \sigma(z))
\tag{4.57}
$$&lt;p>最后是导数的链式法则（chain rule）。
假设要计算复合函数 $f(x) = u(v(x))$ 的导数。
$f(x)$ 的导数等于 $u(x)$ 对 $v(x)$ 的导数乘以 $v(x)$ 对 $x$ 的导数：&lt;/p>
$$
\frac{df}{dx} = \frac{du}{dv} \cdot \frac{dv}{dx}
\tag{4.58}
$$&lt;p>首先，求损失函数对单个权重 $w_j$ 的偏导数（需要对每个权重以及偏置 $b$ 都进行计算）：&lt;/p>
$$
\begin{align*}
\frac{\partial L_{CE}}{\partial w_j} &amp;= \frac{\partial}{\partial w_j} \left( -[y \log \sigma(\mathbf{w} \cdot \mathbf{x} + b) + (1 - y)\log(1 - \sigma(\mathbf{w} \cdot \mathbf{x} + b))] \right) \\
&amp;= -\left[ \frac{\partial}{\partial w_j} y \log \sigma(\mathbf{w} \cdot \mathbf{x} + b) + \frac{\partial}{\partial w_j} (1 - y)\log(1 - \sigma(\mathbf{w} \cdot \mathbf{x} + b)) \right]
\tag{4.59}
\end{align*}
$$&lt;p>接下来，使用链式法则，并利用对数函数的导数：&lt;/p></description></item><item><title>4.13 模型的解释</title><link>https://youkre.github.io/speech-and-language-processing/ch4-13/</link><pubDate>Fri, 10 Oct 2025 08:46:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-13/</guid><description>&lt;p>我们常常希望了解的不仅仅是对某个观测样本的正确分类结果。
还想知道分类器为何做出这样的决策。
也就是说，我们希望决策是&lt;strong>可解释的&lt;/strong>（interpretable）。
可解释性很难严格定义，但其核心思想是：作为人类，我该能够理解算法为何得出某个结论。
由于逻辑回归所使用的特征通常是人为设计的，因此理解分类器决策的一种方式就是弄清楚每个特征在决策中所起的作用。
逻辑回归可以结合统计检验方法（如似然比检验或沃尔德检验）使用；通过这些检验来判断某个特定特征是否显著，或者检查其权重大小（该特征对应的权重 $w$ 有多大？），都有助于解释分类器做出某一决策的原因。
这对于构建透明的模型至关重要。&lt;/p>
&lt;p>此外，除了作为分类器使用之外，逻辑回归在自然语言处理（NLP）以及许多其他领域还被广泛用作分析工具，用于检验关于各种解释性变量（即特征）影响的假设。
在文本分类中，我们可能想知道逻辑上的否定词（如 &lt;em>no&lt;/em>、&lt;em>not&lt;/em>、&lt;em>never&lt;/em>）是否更可能与负面情感相关联，或者负面影评是否更倾向于讨论电影的摄影技术。
然而，在进行此类分析时，必须控制潜在的混杂因素（confounds）：即其他可能影响情感的因素（如电影类型、上映年份，或影评的字数）。
或者，我们可能在研究由 NLP 提取的语言学特征与非语言学结果（如医院再入院率、政治结果或产品销量）之间的关系，但需要控制混杂因素（如患者年龄、投票所在县、产品品牌）。
在这种情况下，逻辑回归使我们能够检验某个特征是否在排除了其他特征影响的前提下，仍与某一结果存在关联。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch4-12">4.12 分类中的危害防范&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch4-14">4.14 进阶：正则化&lt;/a>
&lt;/nav></description></item><item><title>4.14 进阶：正则化</title><link>https://youkre.github.io/speech-and-language-processing/ch4-14/</link><pubDate>Thu, 09 Oct 2025 10:19:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-14/</guid><description>&lt;blockquote>
&lt;p>Numquam ponenda est pluralitas sine necessitate&lt;br>
“如无必要，勿增实体”&lt;/p>
&lt;p>—— 奥卡姆的威廉&lt;/p>&lt;/blockquote>
&lt;p>要学习到使模型完美匹配训练数据的权重存在一个问题。
如果某个特征恰好只出现在一个类别中，并因此能完美预测结果，那么它将被赋予一个非常高的权重。
特征的权重会试图完美拟合训练集的细节，实际上这种拟合过于完美，以至于模型会学习到那些只是偶然与类别相关的噪声因素。
这个问题被称为&lt;strong>过拟合&lt;/strong>（overfitting）。
一个好的模型应该能够从训练数据&lt;strong>泛化&lt;/strong>（generalize）到未见过的测试集上，而一个过拟合的模型泛化能力会很差。&lt;/p>
&lt;p>为了避免过拟合，我们在公式 (4.25) 的损失函数中添加一个新的&lt;strong>正则化项&lt;/strong>（regularization term）$R(\theta)$，从而得到针对 $m$ 个样本批次的以下损失函数（此处稍作改写，从最小化损失变为最大化对数概率，并移除了不影响 argmax 结果的 $\frac{1}{m}$ 项）：&lt;/p>
$$
\hat{\theta} = \underset{\theta}{\mathrm{argmax}} \sum_{i=1}^m \log P(y^{(i)}|x^{(i)}) - \alpha R(\theta)
\tag{4.48}
$$&lt;p>新的正则化项 $R(\theta)$ 用于惩罚过大的权重。
因此，如果一个参数设置完美匹配了训练数据，但使用了许多高权重值，而一种设置对数据的拟合稍差、但使用了更小权重，那么前者受到的惩罚会大于后者。
正则化强度参数 $\alpha$ 的值越大，模型权重的值就会越小，降低模型对训练数据的依赖。&lt;/p>
&lt;p>计算正则化项 $R(\theta)$ 有两种常用方法。
&lt;strong>L2 正则化&lt;/strong>（L2 regularization）是权重值的二次函数，之所以这样命名，是因为它使用了权重值的 L2 范数（的平方）。
L2 范数 $||\theta||^2$ 等同于向量 $\theta$ 到原点的欧几里得距离。
如果 $\theta$ 包含 $n$ 个权重，则：&lt;/p>
$$
R(\theta) = ||\theta||_2^2 = \sum_{j=1}^n \theta_j^2
\tag{4.49}
$$&lt;p>L2 正则化的损失函数变为：&lt;/p></description></item><item><title>4.2 Sigmoid 函数</title><link>https://youkre.github.io/speech-and-language-processing/ch4-02/</link><pubDate>Fri, 03 Oct 2025 08:56:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch4-02/</guid><description>&lt;p>二元逻辑回归的目标是训练一个分类器，使其能够对新输入样本的类别做出二元判断。
本节我们将介绍&lt;strong>Sigmoid分类器&lt;/strong>，它将帮助我们完成这一决策。&lt;/p>
&lt;p>考虑一个输入样本 $x$，我们将其表示为一个特征向量 $[x_1, x_2, ..., x_n]$。
（下一小节将展示具体的特征示例。）
分类器的输出 $y$ 可以是 1（表示该样本属于该类别）或 0（表示不属于该类别）。
我们希望知道该样本属于该类别的概率 $P(y = 1|x)$。
例如，这个决策可能是“正面情感”与“负面情感”的区分，特征代表文档中词的出现次数，$P(y = 1|x)$ 表示文档具有正面情感的概率，而 $P(y = 0|x)$ 表示文档具有负面情感的概率。&lt;/p>
&lt;p>逻辑回归解决该任务的方法是从训练集中学习一个&lt;strong>权重向量&lt;/strong>和一个&lt;strong>偏置项（bias term）&lt;/strong>。
每个权重 $w_i$ 是一个实数，与输入特征 $x_i$ 相关联。
权重 $w_i$ 表示该输入特征对分类决策的重要性，其值可以为正（为样本属于正类提供证据），也可以为负（为样本属于负类提供证据）。
因此，在情感分析任务中，我们可能会预期单词 &lt;em>awesome&lt;/em> 具有很高的正值权重，而 &lt;em>abysmal&lt;/em> 则具有非常低的负值权重。
&lt;strong>偏置项&lt;/strong>（也称为&lt;strong>截距项&lt;/strong>，intercept）是另一个实数，会被加到加权后的输入中。&lt;/p>
&lt;p>在训练中学习到权重后，要在测试样本上做出决策，分类器首先将每个 $x_i$ 与其对应的权重 $w_i$ 相乘，对所有加权特征求和，并加上偏置项 $b$。
得到的单个数值 $z$ 表示支持该类别的加权证据总和：&lt;/p>
$$
z = \left( \sum_{i=1}^n w_i x_i \right) + b
\tag{4.2}
$$&lt;p>在本书其余部分，我们将使用线性代数中的**点积（dot product）**符号来表示此类求和。
两个向量 $a$ 和 $b$ 的点积记作 $a \cdot b$，是它们对应元素乘积之和。（注意：我们用粗体 $\mathbf{b}$ 表示向量。）
因此，以下表达式与公式 4.1 等价：&lt;/p></description></item><item><title>3.8 小结</title><link>https://youkre.github.io/speech-and-language-processing/ch3-08/</link><pubDate>Wed, 17 Sep 2025 18:54:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch3-08/</guid><description>&lt;p>本章通过 n-gram 模型介绍了语言建模，这是一种经典模型，有助于我们引入语言建模中的许多基本概念。&lt;/p>
&lt;ul>
&lt;li>&lt;strong>语言模型&lt;/strong>提供了一种为句子或其他词或标记序列分配概率的方法，并能够根据前面的词或标记来预测下一个词或标记。&lt;/li>
&lt;li>&lt;strong>n-gram&lt;/strong> 可能是最简单的语言模型类型。它们是马尔可夫模型，通过前若干个固定窗口内的词来估计下一个词。n-gram 模型可以通过在&lt;strong>训练语料库（training corpus）&lt;strong>中进行频次统计并归一化（即&lt;/strong>最大似然估计，maximum likelihood estimate&lt;/strong>）来进行训练。&lt;/li>
&lt;li>n-gram &lt;strong>语言模型&lt;/strong>可以在**测试集（test set）&lt;strong>上使用&lt;/strong>困惑度（perplexity）**进行评估。&lt;/li>
&lt;li>根据一个语言模型，测试集的&lt;strong>困惑度&lt;/strong>是该测试集概率的一个函数：即模型所估计的测试集概率的逆值，再按序列长度进行归一化。&lt;/li>
&lt;li>&lt;strong>从语言模型中采样（sampling）&lt;/strong> 是指生成一些句子，每个句子的生成概率由该模型所定义的其出现可能性决定。&lt;/li>
&lt;li>&lt;strong>平滑（smoothing）&lt;/strong> 算法提供了一种对训练数据中未出现事件的概率进行估计的方法。常用的 n-gram 平滑算法包括加一平滑（add-1 smoothing），或通过**插值（interpolation）**利用低阶 n-gram 的频次信息。&lt;/li>
&lt;/ul>
&lt;h2 id="参考文献与历史注记">参考文献与历史注记&lt;/h2>
&lt;p>n-gram 的基本数学思想最早由马尔可夫（Markov, 1913）提出，他使用如今被称为&lt;strong>马尔可夫链&lt;/strong>（bigram 和 trigram）的方法，预测普希金的《叶甫盖尼·奥涅金》中下一个字母是元音还是辅音。马尔可夫将 20,000 个字母分类为元音（V）或辅音（C），并计算了基于前一个或前两个字母的 bigram 和 trigram 概率，以预测当前字母是否为元音。&lt;/p>
&lt;p>香农（Shannon, 1948）将 n-gram 应用于英语词序列的近似计算。受香农工作的启发，到 20 世纪 50 年代，马尔可夫模型已广泛应用于工程、语言学和心理学领域，用于建模词序列。然而，从乔姆斯基（Chomsky, 1956）开始，包括乔姆斯基（1957）和米勒与乔姆斯基（Miller and Chomsky, 1963）在内的一系列极具影响力的研究中，诺姆·乔姆斯基（Noam Chomsky）提出，“有限状态马尔可夫过程”虽然可能是一种有用工程启发式方法，但无法成为人类语法知识的完整认知模型。这些论点导致许多语言学家和计算语言学家在数十年间忽视了统计建模的研究。&lt;/p>
&lt;p>n-gram 语言模型的复兴源于弗雷德·耶莱内克（Fred Jelinek）及其在 IBM 托马斯·J·沃森研究中心的同事，他们受到香农工作的启发；以及卡内基梅隆大学的詹姆斯·贝克（James Baker），他受到伦纳德·鲍姆（Leonard Baum）及其团队在诸如美国国防分析研究所（IDA）等实验室进行的早期保密研究的影响，这些工作在解密后才得以公开。这两个研究团队独立地在同一时期成功地将 n-gram 应用于语音识别系统（Baker 1975b, Jelinek 等 1975, Baker 1975a, Bahl 等 1983, Jelinek 1990）。&lt;strong>“语言模型”&lt;/strong> 和 &lt;strong>“困惑度”&lt;/strong> 这两个术语最早由 IBM 团队用于描述这项技术。耶莱内克及其同事以一种相当现代的方式使用“语言模型”一词，意指影响词序列概率的所有语言因素的总和，包括语法、语义、语篇乃至说话人特征，而不仅仅指 n-gram 模型本身。&lt;/p></description></item><item><title>3.7 进阶：困惑度与熵的关系</title><link>https://youkre.github.io/speech-and-language-processing/ch3-07/</link><pubDate>Wed, 17 Sep 2025 18:45:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch3-07/</guid><description>&lt;p>我们在 3.3 节中引入了困惑度，用于在测试集上评估 n-gram 模型。
更好的 n-gram 模型赋予测试数据更高的概率，测试集上获取的概率归一化后，就是困惑度。
实际上，困惑度这一度量源自信息论中的交叉熵（cross-entropy）概念，这一概念可以解释困惑度中一些看似神秘的特性（例如，为何要使用逆概率？），以及它与熵之间的关系。
&lt;strong>熵&lt;/strong>（entropy）是信息量的一种度量。
给定一个随机变量 $X$，它的取值是需要预测的对象（如单词、字母、词性等），我们将这个集合记作 $\chi$，并设 $X$ 的概率分布为 $p(x)$，那么随机变量 $X$ 的熵定义为：&lt;/p>
$$
H(X) = -\sum_{x \in \chi} p(x) \log_2 p(x)
\tag{3.33}
$$&lt;p>理论上，对数的底数可以任意选择。
如果使用以 2 为底的对数，那么熵的单位就是&lt;strong>比特&lt;/strong>（bits）。&lt;/p>
&lt;p>理解熵的一种直观方式是：它表示在最优编码方案下，编码某个决策或信息所需的最少比特数的下限。
我们借用信息论经典教材 Cover 和 Thomas（1991）中的一个例子来说明。
假设我们要对一场赛马下注，但距离太远无法亲自前往扬克斯赛马场（Yonkers Racetrack），因此我们想给博彩商发送一条简短的消息，告诉他该为八匹马中的哪一匹下注。
一种编码方式是直接使用马匹编号的二进制表示作为编码：例如，1 号马是&lt;code>001&lt;/code>，2 号马是 &lt;code>010&lt;/code>，3 号马是 &lt;code>011&lt;/code>，依此类推，8 号马则编码为 &lt;code>000&lt;/code>。
如果我们整天都在下注，且每匹马都用 3 个比特编码，那么平均每场比赛我们需发送 3 个比特。&lt;/p>
&lt;p>能否做得更好？假设“赔率分布”反映了实际投注的分布情况，我们可以将其表示为每匹马的先验概率，如下所示：&lt;/p>
&lt;ul>
&lt;li>1 号马 $\frac{1}{2}$&lt;/li>
&lt;li>2 号马 $\frac{1}{4}$&lt;/li>
&lt;li>3 号马 $\frac{1}{8}$&lt;/li>
&lt;li>4 号马 $\frac{1}{16}$&lt;/li>
&lt;li>5 号马 $\frac{1}{64}$&lt;/li>
&lt;li>6 号马 $\frac{1}{64}$&lt;/li>
&lt;li>7 号马 $\frac{1}{64}$&lt;/li>
&lt;li>8 号马 $\frac{1}{64}$&lt;/li>
&lt;/ul>
&lt;p>设随机变量 $X$ 的取值是马匹编号，$X$ 的熵给出了编码所需比特数的下限，计算如下：&lt;/p></description></item><item><title>3.5 对训练集的泛化与过拟合</title><link>https://youkre.github.io/speech-and-language-processing/ch3-05/</link><pubDate>Wed, 17 Sep 2025 18:19:38 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch3-05/</guid><description>&lt;p>n-gram 模型和许多统计模型一样，依赖于训练语料库。
这种依赖性的影响之一是概率值往往编码了特定训练语料中的一些具体事实。另一种影响是随着 N 值的增加，n-gram 模型对训练语料的建模能力会变得越来越强。&lt;/p>
&lt;p>我们可以使用上一节提到的采样方法来可视化这两个现象！
为了更直观地理解高阶 n-gram 的建模能力，图 3.4 展示了从基于莎士比亚作品训练出的 unigram、bigram、trigram 和 4-gram 模型中随机生成的一些句子。&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>1-gram&lt;/strong>&lt;br>
– To him swallowed confess hear both. Which. Of save on trail for are ay device and rote life have&lt;br>
– Hill he late speaks; or! a more to leg less first you enter&lt;br>&lt;/p>
&lt;p>&lt;strong>2-gram&lt;/strong>&lt;br>
– Why dost stand forth thy canopy, forsooth; he is this palpable hit the King Henry. Live king. Follow.&lt;br>
– What means, sir. I confess she? then all sorts, he is trim, captain.&lt;br>&lt;/p></description></item><item><title>3.4 从语言模型中采样句子</title><link>https://youkre.github.io/speech-and-language-processing/ch3-04/</link><pubDate>Sun, 20 Jul 2025 11:50:38 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch3-04/</guid><description>&lt;p>可视化语言模型所包含知识的一种重要方式是从模型中采样。
所谓从一个分布中&lt;strong>采样&lt;/strong>，就是按照每个结果出现的可能性大小来随机选择结果。
因此，从语言模型中采样——该模型本质上是对句子分布的一种表示——意味着生成一些句子，模型定义的概率选择每个句子。
也就是说，更容易生成模型认为概率较高的句子，而更难生成模型认为概率较低的句子。&lt;/p>
&lt;p>通过采样来可视化语言模型的思想最早由 Shannon（1948）以及 Miller 和 Selfridge（1950）提出。
从 unigram 入手来可视化其工作原理，是最容易理解的。
想象英语中的所有词排列在 0 到 1 的数轴上，每个词占据的区间长度与其出现频率成正比。
图 3.3 展示了一个可视化示例，它使用的是根据本书文本训练出的 unigram 模型。
我们随机选择一个介于 0 和 1 之间的数值，在概率线上找到对应的位置，输出该数值落在哪个词的区间内。
不断重复地选择随机数字来生成词，直到随机生成句子结束标记 &lt;code>&amp;lt;/s&amp;gt;&lt;/code>，此时句子生成结束。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-3-3.png">&lt;/p>
&lt;p>&lt;strong>图 3.3&lt;/strong> 展示了通过不断采样 unigram 来生成句子时的采样分布。
蓝色条形图表示每个词的相对频率（按从高频到低频的顺序排列，但顺序本身是任意的）。
数轴显示了累积概率。如果随机选择一个介于 0 和 1 之间的数字，它会落在某个词所对应的区间内。
我们更有可能随机选中高频词（如 &lt;em>the&lt;/em>、&lt;em>of&lt;/em>、&lt;em>a&lt;/em>）所对应的较大区间，而不太可能选中低频词（如 &lt;em>polyphonic&lt;/em>）所对应的小区间。&lt;/p>
&lt;p>也可以用同样的方法生成 bigram 句子。首先根据起始标记 &lt;code>&amp;lt;s&amp;gt;&lt;/code> 出现的bigram 概率，随机生成一个以 &lt;code>&amp;lt;s&amp;gt;&lt;/code> 开头的 bigram。
假设选中的 bigram 第二个词是 $w$，那么下一步就根据以 $w$ 开头的所有 bigram 的概率，再次随机选择下一个词，依此类推，直到生成句子结束标记 &lt;code>&amp;lt;/s&amp;gt;&lt;/code> 为止。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch3-03">3.3 评估语言模型：困惑度（Perplexity）&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch3-05">3.5 对训练集的泛化与过拟合&lt;/a>
&lt;/nav></description></item><item><title>3.2 评估语言模型：训练集与测试集</title><link>https://youkre.github.io/speech-and-language-processing/ch3-02/</link><pubDate>Sun, 20 Jul 2025 09:56:38 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch3-02/</guid><description>&lt;p>评估语言模型性能的最佳方法是将其嵌入到一个具体应用中，并测量该应用性能的提升程度。
这种端到端的评估称为&lt;strong>外在评估&lt;/strong>（extrinsic evaluation）。
外在评估是唯一能够确定语言模型（或任何组件）的某项改进是否真正有助于当前任务的方法。
因此，在评估作为语音识别或机器翻译等任务组成部分的n元语法（n-gram）语言模型时，可以通过分别使用两个候选语言模型运行语音识别器或机器翻译系统两次，比较哪种模型产生的转录更准确，从而进行评估。&lt;/p>
&lt;p>然而，端到端地运行大型自然语言处理系统往往成本高昂。因此，我们需要一种能够快速评估语言模型潜在改进的指标。
&lt;strong>内在评估&lt;/strong>（intrinsic evaluation）是一种不依赖具体应用、直接衡量模型质量的方法。
在下一节中，我们将介绍一种标准的内在评估指标——&lt;strong>困惑度&lt;/strong>（perplexity），它被广泛用于衡量语言模型的性能，无论是简单的n元语法语言模型，还是第9章中更复杂的神经网络大语言模型。&lt;/p>
&lt;p>评估任何机器学习模型，至少需要三个不同的数据集：&lt;strong>训练集&lt;/strong>（training set）、&lt;strong>开发集&lt;/strong>（development set，也称为验证集 validation set）和&lt;strong>测试集&lt;/strong>（test set）。&lt;/p>
&lt;p>&lt;strong>训练集&lt;/strong>用于学习模型的参数。对于简单的n元语法语言模型来说，训练集就是从中统计n元组频率的语料库，随后将这些频率归一化为概率值，构建语言模型。&lt;/p>
&lt;p>&lt;strong>测试集&lt;/strong>则是一组与训练集完全不重叠的独立数据，用于评估模型的表现。我们需要一个独立的测试集来无偏估计训练出的模型在面对未知数据时的泛化能力。如果一个机器学习模型完美地拟合了训练数据，但在其他任何数据上表现都很差，那么它在实际应用中将毫无用处。因此，通过模型在这些“未见过”的测试集或测试语料上的表现来衡量n元语法模型的质量。&lt;/p>
&lt;p>我们应该如何选择训练集和测试集呢？测试集应能反映我们希望使用该模型的语言场景。如果打算将语言模型用于化学讲座的语音识别，那么测试集就应该是化学讲座的文本；如果打算将其用于中译英的酒店预订请求翻译系统，那么测试集就应该是酒店预订请求的文本；如果希望语言模型具备通用性，那么测试集就应涵盖多种类型的文本。在这种情况下，可以从不同来源收集大量文本，然后将其划分为训练集和测试集。划分时要格外小心；如果构建的是一个通用模型，就不希望测试集仅包含来自单一文档或某一位作者的文本，因为这不能很好地衡量模型的泛化能力。&lt;/p>
&lt;p>因此，如果手头有一个语料库，并希望比较两个不同n元语法模型的表现，可以将数据划分为训练集和测试集，并在训练集上训练两个模型的参数。然后，可以比较这两个训练好的模型在测试集上的拟合程度。&lt;/p>
&lt;p>但“拟合测试集”到底意味着什么呢？标准答案很简单：&lt;strong>哪个语言模型给测试集分配了更高的概率&lt;/strong>，就意味着它对测试集的预测更准确，因此是更好的模型。给定两个概率模型，更优的模型就是那个能够更好预测测试数据细节的模型，因此它会给测试数据分配更高的概率。&lt;/p>
&lt;p>由于估指标是基于测试集概率的，因此非常重要的一点是：&lt;strong>不能将测试集中的句子泄露到训练集中&lt;/strong>。假设我们试图计算某个特定“测试”句子的概率，如果这个测试句子包含在训练语料中，那么当它出现在测试集中时，我们会错误地给它分配一个虚高的概率。我们将这种情况称为&lt;strong>在测试集上训练&lt;/strong>。在测试集上训练会引入偏差，使所有概率看起来都偏高，并会导致下面将要介绍的基于概率的评估指标——&lt;strong>困惑度&lt;/strong>（perplexity）出现严重偏差。&lt;/p>
&lt;p>即使没有在测试集上进行训练，如果多次对语言模型在测试集上进行测试（每次在模型修改之后），也可能会无意中根据测试集的特点对模型进行调优，因为我们可能会注意到哪些修改使模型表现更好。因此，只应在模型完全准备就绪之后，&lt;strong>对测试集进行一次或极少数几次测试&lt;/strong>。&lt;/p>
&lt;p>正因如此，通常还会引入第三个数据集，称为&lt;strong>开发集&lt;/strong>（development test set）或简称&lt;strong>验证集&lt;/strong>（devset）。在最终阶段之前，所有的模型调优和测试都使用这个开发集。只有当确信模型已经调优完毕后，才在测试集上进行一次最终测试，以评估模型的真实表现。&lt;/p>
&lt;p>那么，该如何将数据划分为训练集、开发集和测试集呢？我们希望测试集尽可能大，因为一个过小的测试集可能会偶然不具备代表性。但同时，也希望拥有尽可能多的训练数据。最低限度上，希望选择一个足够大的测试集，以便能够有足够强的统计能力，检测出两个候选模型之间是否存在统计显著的差异。此外，&lt;strong>开发集必须与测试集来自相同的文本类型&lt;/strong>，因为它的目标就是用来预测模型在测试集上的表现。&lt;/p>
&lt;nav class="pagination justify-content-between">
&lt;a href="../ch3-01">3.1 N元模型&lt;/a>
&lt;a href="../">目录&lt;/a>
&lt;a href="../ch3-03">3.3 评估语言模型：困惑度（Perplexity）&lt;/a>
&lt;/nav></description></item><item><title>3.3 评估语言模型：困惑度（Perplexity）</title><link>https://youkre.github.io/speech-and-language-processing/ch3-03/</link><pubDate>Sun, 20 Jul 2025 09:47:38 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch3-03/</guid><description>&lt;p>我们前面提到，评估语言模型的方法是看哪个模型为测试集分配了更高的概率。
一个更优的语言模型在预测下一个词方面表现得更好，因此在测试集中遇到每个词时会“更不惊讶”（即分配更高的概率）。
事实上，一个完美的语言模型能够准确预测语料中的每一个下一个词，将其概率设为1，而所有其他词的概率为0。
因此，给定一个测试语料库，更好的语言模型会比较差的模型分配更高的整体概率。&lt;/p>
&lt;p>然而，实际上我们并不直接使用原始概率作为评估语言模型的指标。
原因在于，测试集（或任何序列）的概率依赖于其中的词数或词元（token）数量；文本越长，测试集的概率就越小。
我们更希望使用一个以词为单位、按长度归一化的指标，这样就可以在不同长度的文本之间进行比较。
我们使用的这个指标是一种基于概率的函数，称为&lt;strong>困惑度&lt;/strong>（perplexity），它是自然语言处理中最重要的评估指标之一，既用于评估大型语言模型，也用于评估 n 元模型。&lt;/p>
&lt;p>某个测试集上语言模型的&lt;strong>困惑度&lt;/strong>（有时缩写为PP或PPL），是指测试集概率的倒数（即1除以测试集的概率），并按词数进行归一化。
正因如此，它有时也被称为&lt;strong>每词困惑度&lt;/strong>或&lt;strong>每词元困惑度&lt;/strong>。
为了按词数 N 归一化，我们对概率取 N 次方根。&lt;sup id="fnref:1">&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref">1&lt;/a>&lt;/sup>
对于一个测试集 $W = w_1 w_2 ... w_N$，其困惑度定义如下：&lt;/p>
$$
\begin{align*}
\text{perplexity}(W) &amp;= P(w_1w_2 ... w_N )^{-\frac{1}{N}} \\
&amp;= \sqrt[N]{\frac{1}{P(w_1w_2 ... w_N )}}
\tag{3.14}
\end{align*}
$$&lt;p>或者，也可以利用链式法则展开 $W$ 的概率：&lt;/p>
$$
\text{perplexity}(W) = \sqrt[N]{\prod_{i=1}^{N} \frac{1}{P(w_i | w_1 ... w_{i-1})}}
\tag{3.15}
$$&lt;p>需要注意的是，由于公式（3.15）中使用了倒数，词序列的概率越高，困惑度就越低。
因此，&lt;strong>语言模型在数据上的困惑度越低，模型表现越好&lt;/strong>。
最小化困惑度等价于根据语言模型最大化测试集的概率。
为什么困惑度要使用概率的倒数呢？
实际上，这个倒数来源于信息论中交叉熵率（cross-entropy rate）的原始定义。对于有兴趣的读者，详细解释可以在进阶章节 3.7 中找到。目前，我们只需要记住：&lt;strong>困惑度与概率成反比&lt;/strong>。&lt;/p>
&lt;p>计算测试集 $W$ 的困惑度的具体细节取决于我们使用的语言模型类型。
下面以一个一元（unigram）语言模型为例，其测试集 $W$ 的困惑度定义如下（即所有词的一元概率倒数的几何平均）：&lt;/p>
$$
\text{perplexity}(W) = \sqrt[N]{\prod_{i=1}^{N}\frac{1}{P(w_i)}}
\tag{3.16}
$$&lt;p>如果使用二元（bigram）语言模型来计算测试集 $W$ 的困惑度，它依然是一个几何平均值，但这次是基于二元概率的倒数：&lt;/p></description></item><item><title>3.1 N元模型</title><link>https://youkre.github.io/speech-and-language-processing/ch3-01/</link><pubDate>Sat, 19 Jul 2025 23:55:38 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch3-01/</guid><description>&lt;p>我们从一个任务开始：计算 $P(w|h)$，也就是在给定某个历史上下文 $h$ 的条件下，某个词 $w$ 出现的概率。
假设上下文 $h$ 是 &lt;code>The water of Walden Pond is so beautifully&lt;/code>，我们想知道下一个词是“蓝色”的概率：&lt;/p>
$$
P(\text{blue}|\text{The water of Walden Pond is so beautifully})
\tag{3.1}
$$&lt;p>一种估算这个概率的方法是通过相对频率计数：找一个非常大的语料库，统计 &lt;code>The water of Walden Pond is so beautifully&lt;/code> 这段上下文出现的次数，再统计它后面紧接着出现 &lt;code>blue&lt;/code> 的次数。
这其实是在回答这样一个问题：“在我们看到 $h$ 历史中，有多少次后面紧接着出现了词 $w$？”如下所示：&lt;/p>
$$
\begin{align*}
&amp;P(\text{blue}|\text{The water of Walden Pond is so beautifully}) \\
= &amp;\frac{\text{C(The water of Walden Pond is so beautifully blue)}}{\text{C(The water of Walden Pond is so beautifully)}}
\tag{3.2}
\end{align*}
$$&lt;p>如果有一个足够大的语料库，就可以通过这两个计数来估算这个概率。
但即使是整个互联网的文本也不足以提供对完整句子的准确估计。
这是因为语言具有&lt;strong>创造性&lt;/strong>：人们不断在创造新的句子，我们无法指望对完整句子这样长的结构获得足够的统计次数。
因此，我们需要更聪明的方法来估计，在给定出现历史 $h$ 的条件下，某个词 $w$ 的概率，或者整个词序列 $W$ 的概率。&lt;/p></description></item><item><title>第3章 N元语言模型</title><link>https://youkre.github.io/speech-and-language-processing/ch3/</link><pubDate>Sat, 19 Jul 2025 23:55:38 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch3/</guid><description>&lt;blockquote>
&lt;p>“你总是那么迷人！”他微笑着说道，这时我偶尔会鞠个躬，他们也注意到了一辆四匹马拉的马车，心生向往。&lt;/p>
&lt;p>由简·奥斯汀语料的三元模型生成的随机句子&lt;/p>&lt;/blockquote>
&lt;p>正如一句老话所说：“预测很难——尤其是预测未来。”
但如果尝试预测一些看起来简单得多的事情呢？比如一个人接下来会说什么词。
举个例子，下面这句话接下来可能会出现什么词：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>The water of Walden Pond is so beautifully ...
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>你可能会觉得，可能的词是&lt;code>blue&lt;/code>、&lt;code>green&lt;/code>或者&lt;code>clear&lt;/code>，但不太可能是&lt;code>refrigeratornor&lt;/code>或&lt;code>this&lt;/code>。
在本章中，我们将引入&lt;strong>语言模型&lt;/strong>（Language Models，简称LMs）来精确化这种直觉。
语言模型能够为每一个可能的下一个词分配一个&lt;strong>概率&lt;/strong>。
它不仅可以为一个完整的句子分配概率，还能告诉我们，以下这段话在文本中出现的概率：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>all of a sudden I notice three guys standing on the sidewalk。
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>比下面这个词语顺序被打乱的版本出现的可能性要大得多：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>on guys all I of notice sidewalk three a sudden standing the
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>那我们为什么要去预测下一个词，或者去计算一个句子的概率呢？
其中一个原因是&lt;strong>生成文本&lt;/strong>时需要选择更符合语境的词。
例如，我们可以纠正一些语法或拼写错误，比如 &lt;code>Their are two midterms&lt;/code> 中，“There”被误写成了“Their”，或者“&lt;code>Everything has improve&lt;/code>”中，“improve”应为“improved”。
因为“&lt;code>There are&lt;/code>”比“&lt;code>Their are&lt;/code>”更常见，“&lt;code>has improved&lt;/code>”也比“&lt;code>has improve&lt;/code>”更有可能出现，所以语言模型可以帮助用户选择更符合语法的表达。
再比如，语音识别系统要判断你说的是 &lt;code>I will be back soonish&lt;/code>（我很快就回来），而不是 &lt;code>I will be bassoon dish&lt;/code> （我将成为低音管盘），就需要知道“back soonish”这个组合更有可能。
语言模型还可以帮助&lt;strong>增强和替代交流系统&lt;/strong>（augmentative and alternative communication，AAC）（Trnka 等，2007；Kane 等，2017）。
一些身体不便、无法说话或打手语的人可以通过注视或其它动作从菜单中选择词语，语言模型可以辅助这类系统预测可能的词。&lt;/p></description></item><item><title>8.5 语言建模头部</title><link>https://youkre.github.io/speech-and-language-processing/ch8-05/</link><pubDate>Mon, 28 Dec 2015 10:32:00 +0800</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch8-05/</guid><description>&lt;p>我们必须介绍的 Transformer 最后一个组件是&lt;strong>语言建模头部&lt;/strong>（language modeling head）。
这里所说的“&lt;strong>头部&lt;/strong>”（head），是指在将预训练的 Transformer 模型应用于各种任务时，附加在基础 Transformer 架构顶部的额外神经网络结构。
而语言建模头部，正是我们进行语言建模任务所需的特定结构。&lt;/p>
&lt;p>回顾一下：从第 3 章的简单 n-gram 模型，到第 6 章和第 13 章的前馈神经网络与循环神经网络（RNN）语言模型，语言模型本质上都是词元预测器。
给定一段上下文词序列，它们会为每一个可能的下一个词分配一个概率。
例如，如果前面的上下文是 &lt;code>Thanks for all the&lt;/code>，我们想知道下一个词是 &lt;code>fish&lt;/code> 的可能性有多大，就会计算：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>P(fish | Thanks for all the)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>语言模型能够为词汇表中每一个可能的下一个词都给出这样一个条件概率，从而形成一个完整的概率分布。
第 3 章中的 n-gram 语言模型通过统计目标词与其前 $n-1$ 个词共同出现的频次来计算概率。
因此其上下文长度固定为 $n-1$。
而 Transformer 语言模型的上下文长度则等于其上下文窗口大小，可以非常大，例如大型模型通常支持 32K 个词元的上下文。借助特殊的长上下文架构（如稀疏注意力、记忆机制等），甚至可扩展至数百万词元。&lt;/p>
&lt;p>语言建模头部的任务是：取最后一层 Transformer 对最后一个输入词元（位置 $N$）的输出，并用它来预测位置 $N+1$ 处的下一个词元。
图 8.14 展示了如何完成这一任务：输入是最后一层中最后一个词元的输出嵌入（一个形状为 $[1 \times d]$ 的 $d$ 维向量），输出是一个覆盖整个词汇表的概率分布（从中我们可以选择一个词元用于生成）。&lt;/p>
&lt;p>&lt;img loading="lazy" src="https://youkre.github.io/images/speech-and-language-processing/slp-fig-8-14.png">&lt;/p>
&lt;p>&lt;strong>图 8.14&lt;/strong> 语言建模头部：位于 Transformer 顶部的结构，将最后一层对词元 $N$ 的输出嵌入 $h^L_N$ 映射为词汇表 $V$ 上的概率分布。&lt;/p></description></item><item><title>6.10 嵌入向量的语义特性</title><link>https://youkre.github.io/speech-and-language-processing/ch6-10/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-10/</guid><description>&lt;p>本节简要总结一些已被研究过的嵌入向量的语义特性。&lt;/p>
&lt;p>&lt;strong>不同类型的相似性或关联性&lt;/strong>：对于稀疏的 tf-idf 向量和稠密的 word2vec 向量而言，矢量语义模型中一个共同相关的参数是用于统计共现次数的上下文窗口大小。
通常，该窗口在目标词左右各取 1 到 10 个词（总上下文长度为 2–20 个词）。&lt;/p>
&lt;p>具体选择取决于表示的目标。较短的上下文窗口倾向于产生更具句法性质的表示，因为信息来自紧邻的词语。
当使用短上下文窗口计算向量时，与目标词 &lt;em>w&lt;/em> 最相似的词通常是具有相同词性、语义相近的词；而当使用长上下文窗口计算向量时，与目标词 &lt;em>w&lt;/em> 余弦相似度最高的词往往是主题相关但并不语义相似的词。&lt;/p>
&lt;p>例如，Levy 和 Goldberg (2014a) 指出，在使用 ±2 窗口的跳字模型中，与 &lt;em>Hogwarts&lt;/em>（《哈利·波特》中的霍格沃茨魔法学校）最相似的词是其他虚构学校的名称，如 &lt;em>Sunnydale&lt;/em>（出自《吸血鬼猎人巴菲》）或 &lt;em>Evernight&lt;/em>（出自某吸血鬼系列）。
而当窗口扩大到 ±5 时，与 &lt;em>Hogwarts&lt;/em> 最相似的词则变为《哈利·波特》系列中的主题相关词，如 &lt;em>Dumbledore&lt;/em>（邓布利多）、&lt;em>Malfoy&lt;/em>（马尔福）和 &lt;em>half-blood&lt;/em>（混血）。&lt;/p>
&lt;p>此外，通常还需区分两种词间相似性或关联性（Schütze 和 Pedersen, 1993）。
如果两个词经常彼此相邻出现，则它们具有&lt;strong>一阶共现关系&lt;/strong>（有时称为&lt;strong>组合型关联&lt;/strong>，syntagmatic association）。例如，&lt;em>wrote&lt;/em>（写）是一阶关联词，常出现在 &lt;em>book&lt;/em>（书）或 &lt;em>poem&lt;/em>（诗）附近。
如果两个词拥有相似的上下文邻居，则它们具有&lt;strong>二阶共现关系&lt;/strong>（有时称为&lt;strong>聚合型关联&lt;/strong>，paradigmatic association）。例如，&lt;em>wrote&lt;/em> 与 &lt;em>said&lt;/em>（说）或 &lt;em>remarked&lt;/em>（评论）属于二阶关联词，因为它们在语言中扮演相似的角色。&lt;/p>
&lt;p>&lt;strong>类比/关系相似性&lt;/strong>：嵌入向量的另一重要语义特性是其捕捉关系意义的能力。
在早期关于认知的向量空间模型中，Rumelhart 和 Abrahamson (1973) 提出了&lt;strong>平行四边形模型&lt;/strong>（parallelogram model），用于解决形式为“&lt;em>a 对 b 如同 a* 对什么？&lt;/em>”的简单类比问题。
例如，给定问题 &lt;em>apple:tree::grape:?&lt;/em>（即“苹果之于树，如同葡萄之于__”），系统需填入 &lt;em>vine&lt;/em>（藤蔓）。如图 6.15 所示，在平行四边形模型中，从 &lt;em>apple&lt;/em> 到 &lt;em>tree&lt;/em> 的向量（即 $\overrightarrow{tree} - \overrightarrow{apple}$）被加到 &lt;em>grape&lt;/em> 的向量（$\overrightarrow{grape}$）上，然后找出离该点最近的词作为答案。&lt;/p></description></item><item><title>6.11 嵌入中的偏见</title><link>https://youkre.github.io/speech-and-language-processing/ch6-11/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-11/</guid><description>&lt;p>除了能够从文本中学习词义之外，令人遗憾的是，嵌入还会再现文本中隐含的偏见和刻板印象。
正如前一节所示，嵌入大致可以建模关系相似性：例如，“queen”（女王）是“king”（国王）− “man”（男人）+ “woman”（女人）最接近的词，这暗示了类比关系 &lt;em>man:woman::king:queen&lt;/em>（男人对女人如同国王对女王）。
然而，这些相同的嵌入类比也暴露了性别刻板印象。
例如，Bolukbasi 等人（2016）发现，在基于新闻文本训练的 word2vec 嵌入中，“computer programmer” − “man” + “woman” 最接近的职业是 “homemaker”（家庭主妇）；
嵌入还暗示了这样的类比：“father”（父亲）之于“doctor”（医生），如同“mother”（母亲）之于“nurse”（护士）。
这可能导致 Crawford（2017）和 Blodgett 等人（2020）所称的&lt;strong>分配性伤害&lt;/strong>（allocational harm）—— 即系统在资源（如工作机会或信贷）分配上对不同群体不公平。
例如，若招聘算法使用嵌入来筛选潜在程序员或医生候选人，就可能错误地降低包含女性姓名文档的权重。&lt;/p>
&lt;p>事实证明，嵌入不仅反映输入文本的统计特性，还会&lt;strong>放大&lt;/strong>偏见：性别化术语在嵌入空间中变得比原始文本统计中&lt;strong>更加&lt;/strong>性别化（Zhao 等, 2017；Ethayarajh 等, 2019b；Jia 等, 2020），且这种偏见甚至比现实劳动力就业统计数据中的偏见更为夸张（Garg 等, 2018）。&lt;/p>
&lt;p>嵌入还编码了人类推理中固有的内隐联想。
&lt;strong>内隐联想测验&lt;/strong>（Implicit Association Test, IAT；Greenwald 等, 1998）通过测量人们对不同类别词汇进行分类时的反应延迟差异，来评估其对概念（如“花朵”或“昆虫”）与属性（如“愉快”与“不愉快”）之间的联想强度。[^7]
利用此类方法，研究发现美国民众倾向于将非裔美国人姓名与负面词汇关联（相比欧裔美国人姓名更甚），男性姓名更多与数学关联、女性姓名更多与艺术关联，老年人姓名则与负面词汇关联（Greenwald 等, 1998；Nosek 等, 2002a, 2002b）。
Caliskan 等人（2017）使用 GloVe 向量和余弦相似度（而非人类反应时间）成功复现了所有这些内隐联想结果。
例如，像 “Leroy” 和 “Shaniqua” 这样的非裔美国人姓名与负面词汇的 GloVe 余弦相似度更高，而像 “Brad”、“Greg”、“Courtney” 这样的欧裔美国人姓名则与正面词汇的余弦相似度更高。
这类嵌入问题属于 Crawford（2017）和 Blodgett 等人（2020）所说的&lt;strong>表征性伤害&lt;/strong>（representational harm）——即系统贬低甚至忽视某些社会群体所造成的伤害。
因此，任何利用词情感信息的嵌入感知算法都可能加剧对非裔美国人的偏见。&lt;/p>
&lt;p>[^7] 简言之，如果人们将“花朵”与“愉快”、“昆虫”与“不愉快”相关联，那么当实验要求他们对“花朵”（雏菊、鸢尾、丁香）和“愉快词”（爱、欢笑、愉悦）按绿色按钮，对“昆虫”（跳蚤、蜘蛛、蚊子）和“不愉快词”（虐待、仇恨、丑陋）按红色按钮时，他们的反应速度会快于不一致条件（例如对“花朵”和“不愉快词”按红键，对“昆虫”和“愉快词”按绿键）。&lt;/p>
&lt;p>近期研究聚焦于尝试消除此类偏见的方法，例如开发一种嵌入空间变换，在去除性别刻板印象的同时保留定义性的性别差异（Bolukbasi 等, 2016；Zhao 等, 2017），或修改训练过程本身（Zhao 等, 2018b）。
然而，尽管这类&lt;strong>去偏&lt;/strong>（debiasing）方法可能减轻嵌入中的偏见，却无法彻底消除（Gonen 和 Goldberg, 2019），这仍然是一个开放性问题。&lt;/p></description></item><item><title>6.12 向量模型的评估</title><link>https://youkre.github.io/speech-and-language-processing/ch6-12/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-12/</guid><description>&lt;p>向量模型最重要的评估指标是&lt;strong>外部评估&lt;/strong>（extrinsic evaluation），即在实际自然语言处理任务中使用这些向量，并检验其性能是否优于其他模型。&lt;/p>
&lt;p>尽管如此，&lt;strong>内部评估&lt;/strong>（intrinsic evaluation）仍然具有参考价值。
最常见的内部评估方法是测试模型在&lt;strong>词相似性&lt;/strong>任务上的表现：计算算法给出的词相似度得分与人类标注的词相似度评分之间的相关性。&lt;br>
&lt;strong>WordSim-353&lt;/strong>（Finkelstein 等, 2002）是一个常用的数据集，包含 353 对名词，每对由人类评分为 0 到 10 分；例如，(&lt;em>plane&lt;/em>, &lt;em>car&lt;/em>) 的平均得分为 5.77。&lt;br>
&lt;strong>SimLex-999&lt;/strong>（Hill 等, 2015）是一个更复杂的数据集，它衡量的是&lt;strong>语义相似性&lt;/strong>（如 &lt;em>cup&lt;/em> 和 &lt;em>mug&lt;/em>）而非仅仅是&lt;strong>语义关联性&lt;/strong>（如 &lt;em>cup&lt;/em> 和 &lt;em>coffee&lt;/em>），并涵盖了具体与抽象的形容词、名词和动词对。&lt;br>
&lt;strong>TOEFL 数据集&lt;/strong> 包含 80 道题目，每道题给出一个目标词和四个备选项，任务是从中选出正确的同义词，例如：&lt;/p>
&lt;blockquote>
&lt;p>&lt;em>Levied is closest in meaning to: imposed, believed, requested, correlated&lt;/em>&lt;br>
（Landauer 和 Dumais, 1997）。&lt;br>
所有这些数据集中的词均&lt;strong>不带上下文&lt;/strong>。&lt;/p>&lt;/blockquote>
&lt;p>稍显更贴近现实的是包含上下文的内部相似性任务。
&lt;strong>斯坦福上下文词相似度&lt;/strong>（Stanford Contextual Word Similarity, SCWS）数据集（Huang 等, 2012）和 &lt;strong>WiC&lt;/strong>（Word-in-Context）数据集（Pilehvar 和 Camacho-Collados, 2019）提供了更丰富的评估场景。
SCWS 提供了 2,003 对词语在句子上下文中的相似度人工评分；而 WiC 则给出同一个目标词在两个不同句子中的用法，要求判断这两个用法是否属于同一词义（详见附录 G）。
此外，&lt;strong>语义文本相似度&lt;/strong>（Semantic Textual Similarity, STS）任务（Agirre 等, 2012, 2015）用于评估句子级相似度算法的性能，包含多对句子，每对都配有由人类标注的相似度分数。&lt;/p></description></item><item><title>6.13 小结</title><link>https://youkre.github.io/speech-and-language-processing/ch6-13/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://youkre.github.io/speech-and-language-processing/ch6-13/</guid><description>&lt;ul>
&lt;li>在向量语义学中，一个词被建模为一个向量——即高维空间中的一个点，也称为&lt;strong>嵌入&lt;/strong>（embedding）。本章聚焦于&lt;strong>静态嵌入&lt;/strong>（static embeddings），其中每个词被映射到一个固定的嵌入表示。&lt;/li>
&lt;li>向量语义模型可分为两类：&lt;strong>稀疏&lt;/strong>（sparse）和&lt;strong>稠密&lt;/strong>（dense）。在稀疏模型中，每一维对应词汇表 V 中的一个词，单元格的值是&lt;strong>共现频次&lt;/strong>的某种函数。&lt;strong>词–文档矩阵&lt;/strong>（term-document matrix）为词汇表中的每个词（术语）设一行，为每个文档设一列。&lt;strong>词–上下文矩阵&lt;/strong>（word-context 或 term-term matrix）为词汇表中的每个（目标）词设一行，为每个上下文词设一列。两种常用的稀疏加权方法是：&lt;strong>tf-idf&lt;/strong> 加权，其单元格值由&lt;strong>词频&lt;/strong>（term frequency）和&lt;strong>逆文档频率&lt;/strong>（inverse document frequency）共同决定；&lt;strong>PPMI&lt;/strong>（点互信息的正值部分，positive pointwise mutual information），常用于词–上下文矩阵。&lt;/li>
&lt;li>稠密向量模型的维度通常为 50–1000。&lt;strong>Word2vec&lt;/strong> 算法（如 &lt;strong>skip-gram&lt;/strong>）是计算稠密嵌入的流行方法。Skip-gram 训练一个逻辑回归分类器，用于估计两个词“在文本中彼此邻近出现”的概率，该概率通过两个词嵌入向量的&lt;strong>点积&lt;/strong>（dot product）计算得出。&lt;/li>
&lt;li>Skip-gram 使用随机梯度下降训练该分类器：学习得到的嵌入应与邻近词的嵌入具有高点积，而与噪声词（负样本）的嵌入具有低点积。&lt;/li>
&lt;li>其他重要的嵌入算法包括 &lt;strong>GloVe&lt;/strong>，它基于词共现概率的比值构建嵌入。&lt;/li>
&lt;li>无论是使用稀疏还是稠密向量，词与文档之间的相似度都通过向量点积的某种函数来计算。其中最常用的度量是两个向量的&lt;strong>余弦相似度&lt;/strong>（cosine similarity）——即归一化后的&lt;strong>点积&lt;/strong>。&lt;/li>
&lt;/ul>
&lt;h2 id="参考文献与历史注记">参考文献与历史注记&lt;/h2>
&lt;p>向量语义的思想起源于 20 世纪 50 年代三个不同领域的研究：语言学、心理学和计算机科学，每个领域都为该模型贡献了关键思想。&lt;/p>
&lt;p>20 世纪 50 年代的语言学理论中，分布主义思想广为流传。以 Zellig Harris、Martin Joos 和 J. R. Firth 为代表的分布主义者，以及 Thomas Sebeok 等符号学家，都认为词义与其在上下文中的分布密切相关。正如 Joos（1950）所言：&lt;/p>
&lt;blockquote>
&lt;p>语言学家对一个语素的“意义”……按定义就是它与所有其他语素在上下文中共同出现的条件概率集合。&lt;/p>&lt;/blockquote>
&lt;p>将词义建模为多维语义空间中一个点的想法，则来自心理学家 Charles E. Osgood 等人的研究。他们通过让人们在诸如 &lt;em>happy/sad&lt;/em>（快乐/悲伤）或 &lt;em>hard/soft&lt;/em>（坚硬/柔软）等量表上对词义打分，来研究人们对词义的感知。Osgood 等人（1957）提出，一个词的意义总体上可被建模为欧几里得多维空间中的一个点，而两个词在意义上的相似性则可用它们在该空间中的距离来刻画。&lt;/p>
&lt;p>第三个思想来源是 20 世纪 50 年代末至 60 年代初被称为&lt;strong>机械索引&lt;/strong>（mechanical indexing）的领域，即如今的&lt;strong>信息检索&lt;/strong>（information retrieval）。在后来被称为&lt;strong>向量空间模型&lt;/strong>（vector space model）的信息检索框架中（Salton, 1971；Sparck Jones, 1986），研究者提出了用向量定义词义的新方法（Switzer, 1965），并改进了基于统计关联度量（如互信息（Giuliano, 1965）和 IDF（Sparck Jones, 1972））的词相似度计算方法，同时证明文档的意义也可以用与词相同的向量空间来表示。几乎同时，Cordier（1965）展示了如何通过对词语联想概率进行因子分析，生成词的稠密向量表示。&lt;/p></description></item></channel></rss>