理解这个叫做“世界”的操作系统
灵光一现 → 精巧实现 → 无人知晓 → 自己遗忘,几乎是每个认真思考的工程师都会经历的隐性知识流失
用 PyTorch 从头实现语言模型
《Speech and Language Processing》(2025版草稿)中文版
理解这个叫做“世界”的操作系统
灵光一现 → 精巧实现 → 无人知晓 → 自己遗忘,几乎是每个认真思考的工程师都会经历的隐性知识流失
用 PyTorch 从头实现语言模型
《Speech and Language Processing》(2025版草稿)中文版
现在,我们稍微正式一些介绍最简单的神经网络——前馈网络(feedforward network)。 前馈网络是一种多层网络,其单元之间的连接不含环路:每一层单元的输出仅传递给下一层的单元,不会反馈到前面更低的层。 (第 8 章将介绍包含环路的网络,即循环神经网络(recurrent neural networks)。) 出于历史原因,多层网络(尤其是前馈网络)有时被称为多层感知机(multi-layer perceptrons,简称 MLP)。 严格来说,这是一种误称,因为现代多层网络中的单元并非真正的感知机(感知机是纯线性的,而现代网络由带有非线性激活函数(如 Sigmoid)的单元构成)。但这一名称早已沿用成习。 简单的前馈网络包含三类节点:输入单元、隐藏单元和输出单元。 图 6.8 展示了这样一个网络。输入层 $\mathbf{x}$ 是一个标量值组成的向量,与图 6.2 中所示相同。 神经网络的核心是隐藏层 $\mathbf{h}$,它由若干隐藏单元 $h_i$ 构成。 每个隐藏单元都是第 6.1 节描述的神经单元:先对其输入进行加权求和,再应用一个非线性函数。 在标准架构中,各层之间是全连接(fully-connected)的,即每一层的每个单元都接收前一层所有单元的输出作为输入,相邻两层之间每一对单元都有连接。 因此,每个隐藏单元都会对所有输入单元的输出进行求和。 回想一下,单个隐藏单元的参数包括一个权重向量和一个偏置。 对于整个隐藏层,我们将每个单元 $i$ 的权重向量和偏置合并为一个权重矩阵 $\mathbf{W}$ 和一个偏置向量 $\mathbf{b}$(见图 6.8)。 权重矩阵 $\mathbf{W}$ 中的元素 $\mathbf{W}_{ji}$ 表示从第 $i$ 个输入单元 $x_i$ 到第 $j$ 个隐藏单元 $h_j$ 的连接权重。 图 6.8 一个简单的两层前馈网络,包含一个输入层、一个隐藏层和一个输出层(通常在计数网络层数时,不将输入层计入)。 使用单个矩阵 $\mathbf{W}$ 表示整层权重的一大优势在于:前馈网络的隐藏层计算可通过简单的矩阵运算高效完成。 实际上,整个计算只需三步:将权重矩阵 $\mathbf{W}$ 与输入向量 $\mathbf{x}$ 相乘;加上偏置向量 $\mathbf{b}$;对结果应用激活函数 $g$(如前述的 Sigmoid、tanh 或 ReLU)。 因此,隐藏层的输出向量 $\mathbf{h}$ 可表示为(此处以 sigmoid 函数 $\sigma$ 为例): ...
神经网络的基本构建单元是一个单一的计算单元。 该单元接收一组实数值作为输入,对这些输入进行某种计算,并产生一个输出。 本质上,一个神经单元对其输入进行加权求和,并在求和结果中加入一个额外的项,称为偏置项(bias term)。 给定一组输入 $x_1, \dots, x_n$,该单元对应有一组权重 $w_1, \dots, w_n$ 和一个偏置 $b$,因此加权和 $z$ 可表示为: $$ z = b + \sum_i w_i x_i \tag{6.1} $$通常,用向量记号来表达这个加权和更为方便.回忆线性代数中的定义,向量本质上就是一个数字列表或数组。 因此,我们我们可以用权重向量 $w$、标量偏置 $b$ 和输入向量 $x$ 来表示 $z$,并将求和运算替换为简洁的点积(dot product): $$ z = \mathbf{w} \cdot \mathbf{x} + b \tag{6.2} $$如公式 (6.2) 所定义,$z$ 仅是一个实数值。 然而,神经单元并不会直接将 $z$(即 $x$ 的线性函数)作为输出,而是对 $z$ 应用一个非线性函数 $f$。 我们将该函数的输出称为该单元的激活值(activation),记作 $a$。 由于我们目前只建模单个单元,该节点的激活值实际上就是整个网络的最终输出,通常将其记为 $y$。 因此,$y$ 定义如下: $$ y = a = f(z) $$下面将介绍三种常用的非线性函数:Sigmoid 函数、tanh 函数和修正线性单元(ReLU)。出于教学目的,我们先从 Sigmoid 函数 开始,因为它已在第 4 章中出现过: ...
向量模型最重要的评估指标是外部评估(extrinsic evaluation),即在实际自然语言处理任务中使用这些向量,并检验其性能是否优于其他模型。 尽管如此,内部评估(intrinsic evaluation)仍然具有参考价值。 最常见的内部评估方法是测试模型在相似性任务上的表现:计算算法给出的词相似度得分与人类标注的词相似度评分之间的相关性。 WordSim-353(Finkelstein 等, 2002)是一个常用的数据集,包含 353 对名词,每对由人类评分为 0 到 10 分;例如,(plane, car) 的平均得分为 5.77。 SimLex-999(Hill 等, 2015)是一个更复杂的数据集,它衡量的是语义相似性(如 cup 和 mug)而非仅仅是语义关联性(如 cup 和 coffee),并涵盖了具体与抽象的形容词、名词和动词对。 TOEFL 数据集 包含 80 道题目,每道题给出一个目标词和四个备选项,任务是从中选出正确的同义词,例如:Levied is closest in meaning to: imposed, believed, requested, correlated (Landauer 和 Dumais, 1997)。 所有这些数据集中的词均不带上下文。 更现实的是包含上下文的内部相似性任务。 斯坦福上下文词相似度(Stanford Contextual Word Similarity, SCWS)数据集(Huang 等, 2012)和 WiC(Word-in-Context)数据集(Pilehvar 和 Camacho-Collados, 2019)提供了更丰富的评估场景。 SCWS 提供了 2,003 对词语在句子上下文中的相似度人工评分;而 WiC 则给出同一个目标词在两个不同句子中的用法,要求判断这两个用法是否属于同一词义(详见附录 G)。 此外,语义文本相似度(Semantic Textual Similarity, STS)任务(Agirre 等, 2012, 2015)用于评估句子级相似度算法的性能,包含多对句子,每对都配有由人类标注的相似度分数。 ...
除了能从文本中学习词义,嵌入——遗憾的是——也会复现文本中隐含的偏见与刻板印象。 前一节提到,嵌入能粗略建模关系相似性:例如,“king” – “man” + “woman” 的结果最接近 “queen”,这对应类比 man:woman::king:queen。 但同样的嵌入类比也暴露出性别刻板印象。 例如,Bolukbasi 等人(2016)发现,在基于新闻文本训练的 word2vec 嵌入中,“computer programmer” – “man” + “woman” 的最近职业词是 “homemaker”(家庭主妇); 嵌入还暗示了这样的类比:“father” 之于 “doctor”,正如 “mother” 之于 “nurse”。 这类问题可能导致 Crawford(2017)和 Blodgett 等人(2020)所说的 分配性伤害(allocational harm),即系统在分配资源(如工作机会或信用)时,对不同群体产生不公平结果。 例如,若招聘算法使用嵌入来筛选潜在程序员或医生,就可能错误地降低包含女性姓名的文档的权重。 更严重的是,嵌入不仅反映输入文本的统计特性,还会放大偏见:性别相关词汇在嵌入空间中变得比原始文本中更具性别倾向(Zhao et al., 2017;Ethayarajh et al., 2019b;Jia et al., 2020),这种偏见甚至比现实劳动力就业统计数据中的偏见更为夸张(Garg et al., 2018)。 嵌入还编码了人类推理中固有的内隐联想(implicit associations)。 内隐联想测验(Implicit Association Test, IAT)通过测量人们对不同类别词汇的反应延迟,来评估其概念(如 “flowers” 或 “insects”)与属性(如 “pleasantness” 和 “unpleasantness”)之间的关联强度。1 研究发现,美国人在内隐联想中表现出以下倾向: 将非裔美国人姓名与不愉快词汇的关联强于欧裔美国人姓名; 研究中发现,美国人将非裔美国人姓名与不愉快词汇的关联强于欧裔美国人姓名; 将男性姓名更多地与数学联系在一起,而将女性姓名更多地与艺术联系在一起; 并将老年人姓名与不愉快词汇相关联(Greenwald et al., 1998;Nosek et al., 2002a, 2002b)。 Caliskan 等人(2017)使用 GloVe 向量和余弦相似度(而非人类反应时间),成功复现了上述所有内隐联想结果。 例如,非裔美国人姓名(如 Leroy、Shaniqua)与不愉快词的 GloVe 余弦值更高,而欧裔美国人姓名(如 Brad、Greg、Courtney)则与愉快词的余弦值更高。 这类嵌入问题属于 Crawford(2017)和 Blodgett 等人(2020)定义的 表征性伤害(representational harm)—— 即系统通过贬低或忽视某些社会群体而造成的伤害。 因此,任何依赖词情感信息的嵌入感知算法,都可能加剧对非裔美国人的偏见。 ...
本节简要总结一些已被研究的词嵌入语义特性。 不同类型的相似性或关联性 向量语义模型的一个重要参数是用于统计共现的上下文窗口大小。 这一参数对稀疏的 tf-idf 向量和稠密的 word2vec 向量都适用。 通常,窗口设为目标词左右各 1 到 10 个词(总上下文长度为 2–20 个词)。 具体选择取决于表示的目标。 较短的上下文窗口倾向于生成更偏向句法(syntactic)的表示,因为信息来自紧邻的词语。 在这种设置下,与目标词 $w$ 余弦相似度最高的词,通常是语义(semantic)相近且词性(part of speech)相同的词。 而当使用长上下文窗口计算向量时,与目标词 $w$ 余弦相似度最高的词,往往是主题相关但语义不相似的词。 例如,Levy 和 Goldberg(2014a)发现,使用 skip-gram 模型,当窗口为 ±2 时,与 Hogwarts (出自《哈利·波特》系列)最相似的词是其他虚构学校的名称,如 Sunnydale(出自《吸血鬼猎人巴菲》)或 Evernight(出自某吸血鬼系列)。 而当窗口扩大到 ±5 时,与 Hogwarts 最相似的词变成了《哈利·波特》系列中的主题相关词,如 Dumbledore、Malfoy 和 half-blood。 此外,通常还需区分两种词间相似性或关联性(Schütze & Pedersen, 1993): 一阶共现(first-order co-occurrence),有时称为组合关联(syntagmatic association),指两个词经常彼此邻近出现。 例如,wrote 是 book 或 poem 的一阶关联词。 二阶共现(second-order co-occurrence),有时称为聚合关联(paradigmatic association),指两个词具有相似的上下文邻居。 例如,wrote 与 said、remarked 等词构成二阶关联。 类比与关系相似性 词嵌入的另一重要语义特性,是其捕捉关系含义(relational meanings)的能力。 早在认知科学的早期研究中,Rumelhart 和 Abrahamson(1973)就提出了一种基于向量空间的平行四边形模型(parallelogram model),用于解决形如 $\textit{a is to b as } a^\ast \textit{ is to what?}$ 的简单类比问题。 例如,给定问题:apple:tree::grape:?,即 “apple 之于 tree,正如 grape 之于 ___”,系统应填入 vine(藤蔓)。 在该模型中(见图 5.8),计算从 apple 到 tree 的向量偏移:$\overrightarrow{tree} - \overrightarrow{apple}$;将此偏移加到 grape 的向量上:$\overrightarrow{grape} + (\overrightarrow{tree} - \overrightarrow{apple})$;找出距离该结果点最近的词,即为答案。 ...
“我能很好地感知很多维度,只要这些维度大约是二维的。” 已故经济学家 马丁·舒比克 可视化嵌入向量对于帮助我们理解、应用和改进这些词义模型至关重要。 但如何可视化一个(例如)100维的向量呢? 图8:针对三类名词的多维尺度分析(Multidimensional scaling)。 图9:基于向量相关性距离的三类名词层次聚类。 要可视化一个嵌入在空间中的词 w 的词义,最简单方法是列出与 w 最相似的词,即按词汇表中所有词向量与 w 的向量之间的余弦相似度进行排序。 例如,使用GloVe算法计算出的某个嵌入向量,与 frog (青蛙)最接近的7个词是:frogs(青蛙,复数)、toad(蟾蜍)、litoria(雨滨蛙属)、leptodactylidae(细趾蟾科)、rana(蛙属)、lizard(蜥蜴)和 eleutherodactylus(细趾蟾属)(Pennington 等, 2014)。 另一种可视化方法是使用聚类算法,展示嵌入空间中哪些词彼此相似的层次结构。 左侧未加标题的图例使用了对部分名词嵌入向量进行层次聚类的方法作为可视化手段(Rohde 等, 2006)。 然而,目前最常见的可视化方法可能是将词的 100 维空间投影到二维空间中。 图 5.1 和图 5.9 展示了这样一种可视化效果,它们使用了一种称为 t-SNE 的投影方法(van der Maaten 和 Hinton, 2008)。 5.5 Word2vec 目录 5.7 嵌入向量的语义特性
在前面的章节中,我们了解了如何将一个词表示为稀疏的长向量,其维度对应词汇表中的词或文档集合中的文档。 现在,我们介绍一种更强大的词表示方法:嵌入(embeddings),即短而稠密的向量。 与迄今为止所见的向量不同,嵌入向量是短的,其维度 $d$ 通常在50到1000之间,远小于之前遇到的庞大词汇量 $|V|$ 或文档数量 $D$。 这些维度 $d$ 并没有明确的解释意义。 并且这些向量是稠密的:向量元素不再是稀疏的、大部分为零的计数或计数函数,而是可以为负的实数值。 事实证明,在每一项自然语言处理任务中,稠密向量的表现都优于稀疏向量。 虽然我们尚未完全理解所有原因,但有一些合理的解释。 将词表示为300维的稠密向量,比起表示为50,000维的向量,能让分类器学习的权重少得多,更小的参数空间可能有助于提升泛化能力并避免过拟合。 稠密向量也可能更有效地捕捉同义关系。 例如,在稀疏向量表示中,像 car 和 automobile 这样的同义词对应的维度是彼此独立且无关的;因此,稀疏向量可能无法捕捉到一个以 car 为邻近词的词与另一个以 automobile 为邻近词的词之间的相似性。 本节中介绍一种计算嵌入的方法:负采样 skip-gram(skip-gram with negative sampling),有时简称为 SGNS。 跳字算法是名为 word2vec 的软件包中的两种算法之一,因此该算法有时被笼统地称为 word2vec(Mikolov 等,2013a;Mikolov 等,2013b)。 word2vec 方法速度快、训练高效,且代码和预训练嵌入模型在线上易于获取。 Word2vec 嵌入是静态嵌入(static embeddings),意味着该方法为词汇表中的每个词学习一个固定的嵌入表示。 在第 10 章中,我们将介绍学习动态上下文嵌入(context embeddings)的方法,如流行的 BERT 表示系列,其中每个词的向量会因其所处的不同上下文而变化。 word2vec 的核心理念是:不再统计每个词 $w$ 在某个词(比如 apricot)附近出现的频率,而是训练一个分类器来执行一个二元预测任务:“词 $w$ 是否可能出现在 apricot 附近?” 我们实际上并不关心这个预测任务本身;而是将分类器学习到的权重作为词的嵌入表示。 这里的革命性思想在于,我们可以直接使用连续文本作为此类分类器的隐式监督训练数据:一个在目标词 apricot 附近出现的词 $c$,就充当了“词 $c$ 是否可能出现在 apricot 附近?”这一问题的黄金标准“正确答案”。 这种方法通常被称为自监督(self-supervision),它避免了任何人工标注监督信号的需求。 这一思想最初在神经语言建模任务中被提出,Bengio 等人(2003)和 Collobert 等人(2011)表明,一个神经语言模型(一种学习根据前文预测下一个词的神经网络)可以直接使用连续文本中的下一个词作为其监督信号,并可在执行此预测任务的同时学习每个词的嵌入表示。 ...
“三维空间中向量最重要的属性是:位置、位置、位置。” —— Randall Munroe,来自 xkcd 第 2358 期 的悬停提示 我们现在介绍第一种计算词向量嵌入的方法。 这种最简单的词义向量模型基于共现矩阵(co-occurrence matrix),用来表示词语共同出现的频率。 我们定义一种特定的共现矩阵,称为词-上下文矩阵(word-context matrix):矩阵的每一行对应词汇表中的一个词(目标词);每一列对应词汇表中另一个词作为上下文出现的次数。 因此,这个矩阵的维度是 $|V| \times |V|$($|V|$ 表示词汇表大小),每个单元格记录的是:在某个训练语料中,某一行的目标词与某一列的上下文词在邻近位置共同出现的次数。 那么,“邻近”具体指什么? 可以有多种实现方式,但我们先采用最简单的一种:以目标词为中心,左右各取 4 个词作为窗口。 这样,每个单元格就表示:在训练语料中,该列的上下文词出现在该行目标词 ±4 词范围内的总次数。 我们用四个词来演示这一过程:cherry(樱桃)、strawberry(草莓)、digital(数字的)、information(信息)。 对每个词,我们从语料中选取一个实例,并展示其 ±4 词的上下文窗口: is traditionally followed by cherry pie, a traditional dessert often mixed, such as strawberry rhubarb pie. Apple pie computer peripherals and personal digital assistants. These devices usually a computer. This includes information available on the internet 如果我们在一个大型语料中统计每个词的所有出现,并计算其上下文词的频次,就能得到完整的词-上下文共现矩阵。 但完整的矩阵非常庞大:因为对词汇表中的每个词(共 $|V|$ 个),都要统计它与其他所有词的共现次数,所以维度是 $|V| \times |V|$。 因此,我们改用一个小规模的例子来说明。 假设我们只关注上述四个词,并且只考虑以下三个上下文词:a、computer、pie。 此外,我们仅使用上面给出的微型语料进行计数。 ...
向量语义是 NLP 中表示词义的标准方法,有助于我们建模上一节中看到的许多词义特征。 该模型的根源可追溯至20世纪50年代,当时两个重要思想汇聚在一起:一个是上文提到的 Osgood 在 1957 年提出,使用三维空间中的一个点来表示词语内涵的想法;另一个是由 Joos(1950)、Harris(1954)和Firth(1957)等语言学家提出的,通过词语在语言使用中的分布(即其邻近词语或语法环境)来定义其意义。 他们的核心思想是:出现在非常相似分布中的两个词(即其邻近词语相似),其意义也相似。 例如,假设你不知道“ongchoi”(一个来自粤语的新借词)的含义,但你在以下语境中看到了它: (5.1) Ongchoi 加蒜炒着吃很美味。 (5.2) Ongchoi 配米饭非常棒。 (5.3) ……用咸酱烹制的 ongchoi 叶子…… 而你之前在其他语境中见过许多类似的词语: (5.4) ……菠菜加蒜炒着吃配米饭…… (5.5) ……甜菜的茎和叶都很美味…… (5.6) ……羽衣甘蓝和其他咸味的绿叶蔬菜…… 由于 ongchoi 和 spinach(菠菜)、chard(甜菜)、collard greens(羽衣甘蓝)一样,都出现在 rice(米饭)、garlic(蒜)、delicious(美味)、salty(咸的)等词的周围,这可能暗示 ongchoi 是一种与其他绿叶蔬菜相似的绿叶蔬菜。1 可以通过计算 ongchoi 周围上下文中的词语出现次数,用计算的方法实现同样的推理。 图5.1 对“sweet”附近部分词语的 200 维 word2vec 嵌入进行二维(t-SNE)可视化。图中可见,语义相近的词在空间中彼此靠近。 向量语义的核心思想是,将一个词表示为一个多维语义空间中的点,该空间由词语邻近词的分布情况(我们将在下文介绍具体方法)推导而来。 用于表示词语的向量被称为嵌入(embeddings)。 “嵌入”一词源于其数学含义,即从一个空间或结构映射到另一个空间或结构,尽管其含义已有所演变;详见本章末尾。 图 5.1 展示了由 word2vec 算法学习得到的词嵌入可视化结果。显示了把选定词语(“sweet”附近的词)从 200 维空间降维投影到 2 维空间后的位置。 可以看到,“sweet”最近的邻居包括 honey(蜂蜜)、candy(糖果)、juice(果汁)、chocolate(巧克力)等语义相关的词。 语义相近的词在高维空间中彼此靠近,这一思想对语言模型和其他自然语言处理应用具有强大作用。 例如,第 4 章中的情感分类器依赖训练集和测试集中出现相同的词。 但如果用嵌入表示词语,分类器只要遇到意义相近的词,就能判断情感倾向。 此外,正如我们将看到的,像图 5.1 所示的向量语义模型,可以从文本中自动学习,无需人工标注(即无监督学习)。 本章首先介绍一种简单的教学式嵌入模型:一个词的意义由其上下文中邻近词的出现频次构成的向量来定义。 我们引入这个模型,是为了帮助理解“向量如何表示词义”这一核心概念。不过,更成熟的变体(比如第 11 章将介绍的 tf-idf 模型)才是实际中需要掌握的重要方法。 这类方法生成的向量通常很长,而且是稀疏的(sparse),即大部分元素为零(因为大多数词根本不会出现在彼此的上下文中)。 随后,我们将介绍 word2vec 模型族,它能生成短而稠密(dense)的向量,并具备更强的语义表达能力。 ...
我们先介绍一些关于词义的基本原则。 该如何表示一个词的意义呢? 在第3章的 n-gram 模型以及传统的自然语言处理应用中,我们对一个词的唯一表示,就是一串字母,或者词汇表中的一个索引。 这种表示方式,其实和哲学中的一种传统做法差别不大——也许你在入门逻辑课上见过:直接用小型大写字母拼出这个词,来代表它的意义。 比如,“dog”的意义写作 DOG,“cat”写作 CAT,有时还会加一个撇号,写成 DOG’。 但把词义简单地用大写形式表示,显然不是一个令人满意的模型。 你可能听说过语义学家芭芭拉·帕蒂(Barbara Partee)讲过的一个笑话(Carlson, 1977): 问:生命的意义是什么? 答:LIFE’ 我们当然可以做得更好! 毕竟,我们希望词义模型能帮我们完成各种任务。 它应该能告诉我们,有些词意义相近(比如 cat 和 dog);有些词互为反义(比如 cold 和 hot 相反);有些带有正面情感色彩(如 happy),有些则带有负面色彩(如 sad)。 它还应能体现这样一种事实:buy(买)、sell(卖)和 pay(付)这三个词,其实描述的是同一个购买事件的不同视角。 (如果我从你那里买了东西,你很可能就把它卖给了我,而我也很可能付了钱给你。) 更一般地说,一个词义模型应当支持我们进行推理,从而完成与意义相关的任务,比如问答或对话。 本节将简要总结这些理想特性。它们源自语言学中对词义的研究,这一领域称为词汇语义(lexical semantics)。我们将在附录 G 和第 21 章中再次回到这个话题,并进一步扩展这份清单。 词元与词义 我们先看一个例子:同一个词(比如 mouse)在词典中可能有多种定义(以下内容简化自在线词典 WordNet): mouse(名词) 多种小型啮齿动物之一…… 一种手动操作的设备,用于控制光标…… 这里的 mouse 形式称为词元(lemma),也叫引述形式(citation form)。 mice 的词元同样是 mouse;词典通常不会为 mice 这样的屈折形式单独设条目。 类似地,sing 是 sing、sang、sung 的词元。 在许多语言中,动词以不定式作为词元。 例如,西班牙语中表示“睡觉”的不定式 dormir,就是duermes(“你睡觉”)的词元。 像 sung、carpets、sing 或 duermes 这些具体形式,统称为词形(wordforms)。 如上例所示,一个词元可以对应多个含义。 mouse 既可以指啮齿动物,也可以指光标控制设备。 我们将 mouse 的每一种含义称为一个词义(word sense)。 词元常常具有多义性(polysemous),即包含多个词义。这会给理解带来困难。 例如,有人在搜索引擎中输入 “mouse info”,他想找的是宠物,还是电脑配件? 第 10 章和附录 G 将讨论多义性问题,并介绍词义消歧(word sense disambiguation),即在特定上下文中判断某个词使用的是哪种词义的任务。 ...