吴恩达深度学习课程五:自然语言处理 第二周:词嵌入(五)GloVe 算法
此分类用于记录吴恩达深度学习课程的学习笔记。
课程相关信息链接如下:
- 原课程视频链接:[双语字幕]吴恩达深度学习deeplearning.ai
- github课程资料,含课件与笔记:吴恩达深度学习教学资料
- 课程配套练习(中英)与答案:吴恩达深度学习课后习题与答案
本篇为第五课的第二周内容,2.8的内容以及一些相关知识的补充。
本周为第五课的第二周内容,与 CV 相对应的,这一课所有内容的中心只有一个:自然语言处理(Natural Language Processing,NLP)。
应用在深度学习里,它是专门用来进行文本与序列信息建模的模型和技术,本质上是在全连接网络与统计语言模型基础上的一次“结构化特化”,也是人工智能中最贴近人类思维表达方式的重要研究方向之一。
这一整节课同样涉及大量需要反复消化的内容,横跨机器学习、概率统计、线性代数以及语言学直觉。
语言不像图像那样“直观可见”,更多是抽象符号与上下文关系的组合,因此理解门槛反而更高。
因此,我同样会尽量补足必要的背景知识,尽可能用比喻和实例降低理解难度。
本周的内容关于词嵌入,是一种相对于独热编码,更能保留语义信息的文本编码方式。通过词嵌入,模型不再只是“记住”词本身,而是能够基于语义关系进行泛化,在一定程度上实现类似“举一反三”的效果。词嵌入是 NLP 领域中最重要的基础技术之一。
本篇的内容关于 GloVe 算法,是 Word2Vec 外,另一种以“全局”思想指导的词嵌入算法。
1. GloVe 算法思想
在前面介绍 Word2Vec 时,我们已经看到了一条非常清晰的学习路线:通过预测任务,让模型在训练中“顺便”学到词的向量表示。这种思路高效且直观,但也有一个绕不开的事实——它几乎完全依赖局部上下文。
这不难理解,在 Word2Vec 中,我们每次训练,都是使用窗口内的序列信息来学习相应的语义并更新词向量,每次更新只使用窗口内的词信息,词向量是在多次局部预测中逐步学习出来的。
由此,一个新的想法产生了:如果我们不只看窗口内的几步关系,而是把“整个语料里,词与词出现过多少次”都考虑进来,会发生什么?
GloVe 正是这一想法的产物。
在 2014 年,论文 GloVe: Global Vectors for Word Representation被发表,论文认为词的语义信息,本质上蕴含在词与词的全局共现统计关系中,而词向量的任务,就是用一个低维连续空间去重现这种统计结构。
最终,GloVe 将传统共现统计方法的全局视角,与分布式词向量的表达能力结合起来,形成了一种介于“计数方法”和“预测方法”之间的折中方案。
这里要专门说明的是,相比于传统神经网络,GloVe 没有隐藏层或激活函数,更像是一条通过词向量内积加偏置构成的线性计算流水线,但它仍然使用梯度下降来更新参数,实现对共现统计信息的拟合,我们很难用模型那一套来描述它,因此也相对较难理解。
下面就来分点展开 GloVe 算法的实现逻辑:
2. GloVe 算法的统计部分
GloVe 算法 的起手其实是传统的共现统计方法,这一部分并不涉及模型训练,而是对数据进行统计和处理,得到词汇间的全局关系。
依旧分点来看这部分内容:
2.1 统计词共现矩阵
词共现矩阵 是传统统计方法里的基础概念,顾名思义,它是用来表示词与词之间共现关系的矩阵。
规范一下,设词表大小为 \(V\),定义一个矩阵 \(X \in \mathbb{R}^{V \times V}\),其中:
简单举个例子,假设语料只有一句话:
I like deep learning
显然,词表为:
现在,设定上下文窗口大小为 1,即只考虑左右各一个词。
我们统计各词的共性关系如下:
- 以 I 为中心:上下文只有 like
- 以 like 为中心:上下文是 I 和 deep
- 以 deep 为中心:上下文是 like 和 learning
- 以 learning 为中心:上下文只有 deep
由此,我们可以得到完整的词共现矩阵 \(X\):
补充几点细节:
- 在常见的统计设定中,通常手工设定不将词与自身计入共现关系,因此共现矩阵的对角线往往为 0,但在真实语料中,若相同词在窗口范围内连续出现,则对应的对角元素也可能为非零值。
- 词共现矩阵往往是高度稀疏的,大多数词对在语料中根本不会共现。
- 词共现矩阵是否对称,取决于设计的统计方式,在对称窗口下,这里的 \(X\) 是对称的,若区分左右上下文,矩阵则不一定对称。
由此,我们就完成了 GloVe 算法在统计部分的第一步。
下一步,我们会把共现次数 \(X_{ij}\) 转化为条件概率 \(P(j|i)\),进一步引入向量训练的目标。
2.2 统计条件概率 \(P(j \mid i)\)
在完成共现矩阵统计后,GloVe 的下一步是把绝对共现次数转化为条件概率,从而刻画词与词之间更直观的关系。
我们定义条件概率为:
其中:
- \(X_{ij}\) 是词 \(j\) 出现在词 \(i\) 上下文中的次数,来自词共现矩阵。
- \(\sum_k X_{ik}\) 是以词 \(i\) 为中心时,所有上下文词出现次数的总和
最终,\(P(j \mid i)\) 表示在语料库中,已知中心词为 \(i\) 的前提下,上下文词为 \(j\) 的经验概率。
我们继续使用上一节中的例子,根据共现矩阵:
我们可以计算条件概率,例如:
- 以 like 为中心:
于是:
- 以 I 为中心:
所以:
最终,通过这种方式,我们就得到了语料库中每个词的上下文概率分布。
我们整理例子的概率分布矩阵如下:
其中:
- 行表示中心词 \(i\)
- 列表示上下文词 \(j\)
- 每个元素 \(P_{ij}\) 即为 \(P(j|i)\)
自此,我们就完成了GloVe 算法在统计部分的全部内容。
下面,就是它的建模部分。
3. GloVe 算法的模型部分
在完成统计阶段后,我们得到了全局的共现信息及概率分布。模型部分的核心任务就是:利用这些统计信息训练出词向量,使得词向量能够反映词与词之间的语义关系。
GloVe 的核心思想可以概括为一句话:词向量的内积应该能够拟合词与词之间的共现概率。
我们依旧分点来进行这部分内容:
3.1 计算概率比例
首先,GloVe 并不直接去拟合条件概率 \(P(j|i)\),而是利用概率比例刻画语义关系。
设有中心词 \(i\),上下文词 \(j\) 和 \(k\),则概率比例如下:
这并不难理解:
- 如果比例大,说明 \(i\) 更倾向于与 \(j\) 一起出现。
- 如果比例小,说明 \(i\) 更倾向于与 \(k\) 一起出现。
继续使用同样的例子,我们刚刚得到条件概率矩阵如下:
对于中心词 like,其上下文词分别为 I 和 deep,则:
这个比例表示,“like”与“I”和“deep”的关系同样强。
换句话说,如果模型想拟合这个关系,词向量在空间中的表现应该让 like-I 与 like-deep 的内积接近。
而如果概率比例不是 1,例如假设在更大语料中统计到:
则比例为:
这个比例小于 1,说明“like”更倾向于与 deep 一起出现,与 I 的关联较弱。模型训练时,GloVe 就会尝试让词向量 like-deep 的内积大于 like-I 的内积,以反映这种强弱关系。
这一步,我们通过比例概率实现了对语义的量化,而下一步就是 GloVe 的核心内容:
3.2 构建向量关系
在这一步,GloVe 就可以将概率比例量化的语义偏好转化为向量空间中的相对位置,从而实现统计信息到词向量的映射。
换句话说,我们希望通过训练得到的词向量,使得在向量空间中,中心词与上下文词的相对位置能够反映它们在语料中的共现强弱。
来看看 GloVe 实现这一步的具体逻辑:
首先,设定:
- 中心词 \(i\) 的词向量为 \(w_i \in \mathbb{R}^d\)
- 上下文词 \(j,k\) 的词向量为 \(\tilde w_j, \tilde w_k \in \mathbb{R}^d\)
GloVe 通过以下假设将概率比例与向量联系起来:
其中函数 \(F\) 的含义是:用向量操作去表示概率比例,模型的目标就是拟合这个函数 \(F\) 。
也就是说,我们的目标是:
但是,直接拟合比例本身有几个问题:
- 比例范围广:条件概率 \(P(j|i)\) 属于 \([0,1]\),两个概率比值可能非常大或非常小(比如 \(0.001/0.5 = 0.002\)),直接拟合容易数值不稳定。
- 向量空间线性映射困难:我们希望用向量内积(\(w_i^\top \tilde w_j\))表示关系,但向量内积是线性且可正可负,而概率比总是正且变化范围大,直接用内积去拟合会很不直观,也容易数值不稳定。
所以我们需要一个桥梁函数,把比例转换成更适合线性建模的形式。
3.3 转换概率比例
在这里,GloVe 选择了 对数函数,把比例变成 内积差:
我们来详细解释一下这步推导的逻辑:
- 对数的作用:
对数函数可以把原本范围很广的正数概率比压缩到数值更稳定的区间,并且把乘法关系转化为加法关系。数值范围收敛,更利于模型学习,同时便于线性处理。 - 对映射的影响:
取了对数之后,原本的比例关系就转化为“加减法”的形式,而向量内积本身就是线性可加的操作(\(w_i^\top \tilde w_j\) 是实数线性组合)。对数后的比例差可以直接用 线性模型(内积加偏置)来拟合,保证概率比越大,内积差越大;概率比越小,内积差越小。 - 偏置项的作用 :
偏置项 \(b_i, \tilde b_j\) 用于捕捉词自身的出现频率差异。
高频词往往在语料中出现次数多,直接用向量内积可能被整体频率影响而偏离比例。
偏置项可以单独调整每个词的基准水平,让向量内积专注于词与词之间的相对关系,而不受词频本身干扰。
最终,我们通过公式实现了这样的作用:
回到例子,假设在某大语料中统计到:
则:
因此,模型希望通过训练得到的向量,使得:
这样,训练后,词向量在空间中,“like” 会更靠近 “deep”,远离 “I”,以反映概率比例。
下面就是最后一步了:
3.4 构建损失函数并训练
在完成概率比例到向量内积映射后,GloVe 还需要一个可优化的损失函数来让训练可执行。
这一步的思想是:让向量内积(加偏置)尽量逼近对数共现概率,同时对高频和低频词对做合理的权衡。
GloVe 的损失函数定义为:
看起来很复杂,实际上也不简单,我们详细解释一下各部分含义:
-
权重函数 \(f(X_{ij})\):
为了平衡高频和低频词对的影响,GloVe 引入了一个加权函数:\[ f(x) = \begin{cases} \left(\dfrac{x}{x_\text{max}}\right)^\alpha, & x < x_\text{max} \\ 1, & x \ge x_\text{max} \end{cases} \]这里 \(x_\text{max}\) 是阈值,\(\alpha\) 通常取 \(0.75\)。
这是为了让高频词对不会主导训练,低频词对仍有一定权重。 -
\(w_i^\top \tilde w_j + b_i + \tilde b_j\) :模型预测的对数共现次数,即词向量加偏置的线性组合。
-
\(\log X_{ij}\) :对应统计信息的对数共现次数,是我们希望模型逼近的目标。
-
平方误差 \((\cdot)^2\) :衡量预测值与目标值之间的差距,使模型通过梯度下降最小化误差。
这里就可以解释我们在本周第一篇中留下的问题:词向量的长度受什么影响?
因为高频词在语料中出现次数多,因此它的共现矩阵行/列上的元素整体偏大,经过训练后,模型为了尽量逼近 \(\log X_{ij}\),会使得这些高频词的向量内积整体偏大,从而对应的向量长度也相对较长。
也就是说,词向量的长度与词频正相关,但本身没有其他明确的语义解释,只是统计特性导致的结果。
同时,在这里你可能会有一个问题:我们刚刚引入了概率比例和内积差的关系,为什么损失函数里都没有用到?
实际上,对某个中心词 \(i\),任意两个上下文词 \(j,k\),若你看损失梯度,会发现:
在优化过程中,梯度会自然调整 \(w_i\),让 共现次数更多、概率大的词对应内积更大,共现次数更少、概率小的词对应内积更小。
换句话说,比例关系会通过梯度自动体现出来,不需要显式算比值,并且这样还避免了显式计算所有词对之间的概率比造成的计算开销。
还是用我们的例子,假设在大语料中:
| 中心词 | 上下文词 | 共现次数 \(X_{ij}\) |
|---|---|---|
| like | I | 3 |
| like | deep | 6 |
则训练目标:
- 对 like-I:
- 目标 \(\log X_{\text{like,I}} = \log 3 \approx 1.099\)
- 模型希望 \(w_\text{like}^\top \tilde w_\text{I} + b_\text{like} + \tilde b_\text{I} \approx 1.099\)
- 对 like-deep:
- 目标 \(\log X_{\text{like,deep}} = \log 6 \approx 1.792\)
- 模型希望 \(w_\text{like}^\top \tilde w_\text{deep} + b_\text{like} + \tilde b_\text{deep} \approx 1.792\)
- 权重函数 \(f(X_{ij})\) 可以调节两者在训练中的影响,使模型更稳健。
训练时,GloVe 会遍历所有有共现的词对,计算加权平方误差,利用梯度下降优化 \(w_i, \tilde w_j, b_i, \tilde b_j\),直到误差收敛。
最后,你会发现,GloVe 的整个传播过程同时在维护两个词向量矩阵:
- 中心词向量 \(w_i\)
- 上下文词向量 \(\tilde w_j\)
而通常,我们将两者相加或平均作为最终词向量:
这样得到的 \(v_i\) 便同时存在作为中心词和上下文词的语义距离,刻画了词与词之间的全局共现关系。
4. 总结
因为 GloVe 相比起来较为复杂,这里我们不再表格整理概念了,而是整体梳理一遍其传播过程。


浙公网安备 33010602011771号