自然语言处理(上) · 深度学习 09

关键字深度学习自然语言处理NLPword2vecskip-gramCBOW负采样fastTextPyTorch

摘要 —— 自然语言处理(NLP)是非常典型的人工智能应用场景。本文作为 NLP 章节的上篇,将重点介绍了一些前置知识,包含词嵌入,近似训练、二次采样以及子词嵌入等部分。

本文首先给出典型的词嵌入模型(skip-gram 和 CBOW)的理论原理,然后给出这两种模型的训练方法。

词嵌入(word2vec)

对于词典中的单词而言,one-hot 编码方式无法衡量不同单词之间的相似度(任何两个不同词的 one-hot 向量的余弦相似度 $\frac{\boldsymbol{x}^\top \boldsymbol{y}}{\Vert \boldsymbol{x} \Vert \cdot \Vert \boldsymbol{y} \Vert}$ 都为 0)。

word2vec 工具的提出正是为了解决这个问题。它将每个词表示成一个定长的向量,并使得这些向量能较好地表达不同词之间的相似和类比关系。 word2vec 工具包含了两个模型:跳字模型(skip-gram)和连续词袋模型(continuous bag of words,CBOW)。

跳字模型(skip-gram)

跳字模型假设基于某个词(定义为中心词)来生成它在文本序列周围的词(定义为背景词)。

例如,假设文本序列是 “the” “man” “loves” “his” “son”。以 “loves” 作为中心词,设背景窗口大小为 2, 我们想要计算的是与它距离不超过 2 个词的背景词 “the” “man” “his” “son” 在 “loves” 出现的条件下出现的概率。

图 1 跳字模型

如何计算这一概率? 将每个词被表示成两个 $d$ 维向量,假设这个词在词典中索引为 $i$,当它为中心词时向量表示为 $\vec{v}_i \in \mathbb{R}^d$,为背景词时向量表示为 $\vec{u}_i \in \mathbb{R}^d$。 设中心词 $w_c$ 在词典中索引为 $c$,背景词 $w_o$ 在词典中索引为 $o$,给定中心词生成背景词的条件概率可以通过对向量内积做 softmax 运算而得到: $$ \mathbb{P} (w_o \mid w_c) = \frac{\exp (\boldsymbol{u}_o^\top \boldsymbol{v}_c)}{\sum_{i \in \mathcal{V}} \exp (\boldsymbol{u}_i^\top \boldsymbol{v}_c)}, $$ 其中 $\mathcal{V} \triangleq \{0, 1, ..., |\mathcal{V}|-1 \}$ 为词典中所有单词的索引的集合。

给定一个长度为 $T$ 的文本序列,设时间步 $t$ 的词为 $w^{(t)}$。假设给定中心词的情况下背景词的生成相互独立,当背景窗口大小为 $m$ 的时候,跳字模型的似然函数, 即给定 “任意” 中心词生成 “所有” 背景词的概率,为 $$ \prod_{t=1}^T \prod_{-m \leq j \leq m, j \neq 0} \mathbb{P} (w^{(t+j)} \mid w^{(t)}). $$ 自动忽略大于 $T$ 和小于 $1$ 的时间步。

训练跳字模型

跳字模型的参数是每个词所对应的中心词向量和背景词向量,可以通过最大化似然来训练参数。具体地,最大化上文中的似然函数等价于最小化以下损失函数: $$ - \sum_{t=1}^{T} \sum_{-m \leq j \leq m,\ j \neq 0} \text{log}\, \mathbb{P} (w^{(t+j)} \mid w^{(t)}).$$ 如果使用随机梯度下降,那么在每一次迭代中随机采样一个较短的子序列来计算有关该子序列的损失,然后计算梯度来更新模型参数。对于所有属于以 $w_c$ 为中心词的窗口内的背景词 $w_o$, $$ \log \mathbb{P} (w_o \mid w_c) = \boldsymbol{u}_o^\top \boldsymbol{v}_c - \log\left(\sum_{i \in \mathcal{V}} \text{exp}(\boldsymbol{u}_i^\top \boldsymbol{v}_c)\right). $$ 所以 $$ \begin{aligned} \frac{\partial \text{log}\, \mathbb{P} (w_o \mid w_c)}{\partial \boldsymbol{v}_c} &= \boldsymbol{u}_o - \frac{\sum_{j \in \mathcal{V}} \exp(\boldsymbol{u}_j^\top \boldsymbol{v}_c)\boldsymbol{u}_j}{\sum_{i \in \mathcal{V}} \exp(\boldsymbol{u}_i^\top \boldsymbol{v}_c)}\\ &= \boldsymbol{u}_o - \sum_{j \in \mathcal{V}} \left(\frac{\text{exp}(\boldsymbol{u}_j^\top \boldsymbol{v}_c)}{ \sum_{i \in \mathcal{V}} \text{exp}(\boldsymbol{u}_i^\top \boldsymbol{v}_c)}\right) \boldsymbol{u}_j \\ &= \boldsymbol{u}_o - \sum_{j \in \mathcal{V}} \mathbb{P} (w_j \mid w_c) \boldsymbol{u}_j. \end{aligned} $$ 它的计算需要词典中所有词以 $w_c$ 为中心词的条件概率。 同样地,对于所有属于以 $w_c$ 为中心词的窗口内的背景词 $w_o$ 的背景词向量 $\boldsymbol{u}_o$, $$ \frac{\partial \text{log}\, \mathbb{P} (w_o \mid w_c)}{\partial \boldsymbol{u}_o} = \boldsymbol{v}_c - \mathbb{P} (w_o \mid w_c) \boldsymbol{v}_c. $$

训练结束后,对于词典中的任一索引为 $i$ 的词,我们均得到该词作为中心词和背景词的两组词向量 $\boldsymbol{v}_i$ 和 $\boldsymbol{u}_i$。 一般使用跳字模型的中心词向量作为词的表征向量参与后续的操作(如判定单词相似度等)。

连续词袋模型(CBOW)

连续词袋模型假设基于某中心词在文本序列前后的背景词来生成该中心词。 在同样的文本序列 “the”“man”“loves”“his”“son” 里,以 “loves” 作为中心词,且背景窗口大小为 2 时,连续词袋模型关心的是,给定背景词 “the”“man”“his”“son” 生成中心词 “loves” 的条件概率。

图 2 连续词袋模型

因为连续词袋模型的背景词有多个,我们将这些背景词向量取平均,然后使用和跳字模型一样的方法来计算条件概率。 设 $\boldsymbol{v_i}\in\mathbb{R}^d$ 和 $\boldsymbol{u_i}\in\mathbb{R}^d$ 分别表示词典中索引为 $i$ 的词作为背景词和中心词的向量(注意符号的含义与跳字模型中的相反)。 设中心词 $w_c$ 在词典中索引为 $c$,背景词 $w_{o_1}, \ldots, w_{o_{2m}}$ 在词典中索引分别为 $o_1, \ldots, o_{2m}$,那么给定背景词生成中心词的条件概率 $$ \mathbb{P} (w_c \mid w_{o_1}, \ldots, w_{o_{2m}}) = \frac{\text{exp}\left(\frac{1}{2m}\boldsymbol{u}_c^\top (\boldsymbol{v}_{o_1} + \ldots + \boldsymbol{v}_{o_{2m}}) \right)}{ \sum_{i \in \mathcal{V}} \text{exp}\left(\frac{1}{2m}\boldsymbol{u}_i^\top (\boldsymbol{v}_{o_1} + \ldots + \boldsymbol{v}_{o_{2m}}) \right)}. $$

定义 $\mathcal{W}_o \triangleq {w_{o_1}, \ldots, w_{o_{2m}}}$,$\bar{\boldsymbol{v}}_o \triangleq \frac{1}{2m} \left(\boldsymbol{v}_{o_1} + \ldots + \boldsymbol{v}_{o_{2m}} \right)$, 则上式简化为 $$ \mathbb{P} (w_c \mid \mathcal{W}_o) = \frac{\exp\left(\boldsymbol{u}_c^\top \bar{\boldsymbol{v}}_o\right)}{\sum_{i \in \mathcal{V}} \exp\left(\boldsymbol{u}_i^\top \bar{\boldsymbol{v}}_o\right)}. $$ 给定一个长度为 $T$ 的文本序列,设时间步 $t$ 的词为 $w^{(t)}$,背景窗口大小为 $m$,连续词袋模型的似然函数是由背景词生成 任意 中心词的概率: $$ \prod_{t=1}^{T} \mathbb{P} (w^{(t)} \mid w^{(t-m)}, \ldots, w^{(t-1)}, w^{(t+1)}, \ldots, w^{(t+m)}). $$

训练连续词袋模型

连续词袋模型的最大似然估计等价于最小化损失函数 $$ -\sum_{t=1}^T \text{log}\, \mathbb{P}(w^{(t)} \mid w^{(t-m)}, \ldots, w^{(t-1)}, w^{(t+1)}, \ldots, w^{(t+m)}). $$ 注意到 $$ \log\,\mathbb{P}(w_c \mid \mathcal{W}_o) = \boldsymbol{u}_c^\top \bar{\boldsymbol{v}}_o - \log\,\left(\sum_{i \in \mathcal{V}} \exp\left(\boldsymbol{u}_i^\top \bar{\boldsymbol{v}}_o\right)\right). $$ 所以对于 $\boldsymbol{v}_{o_i}$($i = 1, \ldots, 2m$), $$ \begin{aligned} \frac{\partial \log\, \mathbb{P}(w_c \mid \mathcal{W}_o)}{\partial \boldsymbol{v}_{o_i}} &= \frac{1}{2m} \left(\boldsymbol{u}_c - \sum_{j \in \mathcal{V}} \frac{\exp(\boldsymbol{u}_j^\top \bar{\boldsymbol{v}}_o)\boldsymbol{u}_j}{ \sum_{i \in \mathcal{V}} \text{exp}(\boldsymbol{u}_i^\top \bar{\boldsymbol{v}}_o)} \right) \\ &= \frac{1}{2m}\left(\boldsymbol{u}_c - \sum_{j \in \mathcal{V}} P(w_j \mid\mathcal{W}_o) \boldsymbol{u}_j \right). \end{aligned} $$ 同理 $$ \frac{\partial \log\, \mathbb{P}(w_c \mid \mathcal{W}_o)}{\partial \boldsymbol{u}_c} = \bar{\boldsymbol{v}}_o - \mathbb{P} (w_c \mid \mathcal{W}_o) \bar{\boldsymbol{v}}_o. $$

连续词袋模型中,一般使用连续词袋模型的背景词向量作为词的表征向量

近似训练

跳字模型的核心在于使用 softmax 运算得到给定中心词 $w_c$ 来生成背景词 $w_o$ 的条件概率 $$ \mathbb{P} (w_o \mid w_c) = \frac{\text{exp}(\boldsymbol{u}_o^\top \boldsymbol{v}_c)}{ \sum_{i \in \mathcal{V}} \text{exp}(\boldsymbol{u}_i^\top \boldsymbol{v}_c)}. $$ 该条件概率相应的对数损失为 $$ -\log \mathbb{P} (w_o \mid w_c) = -\boldsymbol{u}_o^\top \boldsymbol{v}_c + \log\left(\sum_{i \in \mathcal{V}} \text{exp}(\boldsymbol{u}_i^\top \boldsymbol{v}_c)\right).$$ 以上损失包含了词典大小数目的项的累加。对于含几十万或上百万词的较大词典, 每次的梯度计算开销可能过大。为了降低该计算复杂度,常常使用两种近似训练方法:负采样(negative sampling)和层序 softmax(hierarchical softmax)。

接下来以跳字模型为例介绍这两种方法。

负采样(negative sampling)

负采样修改了原来的目标函数。给定中心词 $w_c$ 的一个背景窗口,我们把背景词 $w_o$ 出现在该背景窗口看作一个事件,并将该事件的概率计算为 $$\mathbb{P} (D=1\mid w_c, w_o) = \sigma(\boldsymbol{u}_o^\top \boldsymbol{v}_c),$$ 其中的 $\sigma$ 是 sigmoid 激活函数,二值性的随机变量 $D$ 取值 1 表示 $w_o$ 出现在了以 $w_c$ 作为中心词的背景窗口中

先考虑最大化文本序列中所有该事件的联合概率来训练词向量。具体来说,给定一个长度为 $T$ 的文本序列,设时间步 $t$ 的词为 $w^{(t)}$ 且背景窗口大小为 $m$,考虑最大化联合概率 $$ \prod_{t=1}^{T} \prod_{-m \leq j \leq m,\ j \neq 0} P(D=1\mid w^{(t)}, w^{(t+j)}).$$ 以上模型中包含的事件仅考虑了正类样本,只有当所有词向量相等且值为无穷大时,以上的联合概率才被最大化为 1。很明显,这样的词向量毫无意义。 负采样通过采样并添加负类样本使目标函数更有意义。具体地,设背景词 $w_o$ 出现在中心词 $w_c$ 的一个背景窗口为事件 $P$,我们根据分布 $P$ 采样 $K$ 个未出现在该背景窗口中的词, 即噪声词。设噪声词 $w_k$($k=1, \ldots, K$)不出现在中心词 $w_c$ 的该背景窗口为事件 $N_k$。假设同时含有正类样本和负类样本的事件 $P, N_1, \ldots, N_K$ 相互独立, 则上文的联合概率被改写为 $$ \prod_{t=1}^{T} \prod_{-m \leq j \leq m,\ j \neq 0} P(w^{(t+j)} \mid w^{(t)}),$$ 其中 $$ \mathbb{P} (w^{(t+j)} \mid w^{(t)}) = \mathbb{P} (D=1\mid w^{(t)}, w^{(t+j)}) \cdot \prod_{k=1,\ w_k \sim P(w)}^K \mathbb{P} (D=0\mid w^{(t)}, w_k).$$

设文本序列中时间步 $t$ 的词 $w^{(t)}$ 在词典中的索引为 $i_t$,噪声词 $w_k$ 在词典中的索引为 $h_k$。有关以上条件概率的对数损失(二元交叉熵损失函数)为 $$ \begin{aligned} -\log \mathbb{P}(w^{(t+j)} \mid w^{(t)}) =& -\log \mathbb{P}(D=1\mid w^{(t)}, w^{(t+j)}) - \sum_{k=1,\ w_k \sim P(w)}^K \log \mathbb{P}(D=0\mid w^{(t)}, w_k)\\ =&- \log\, \sigma\left(\boldsymbol{u}_{i_{t+j}}^\top \boldsymbol{v}_{i_t}\right) - \sum_{k=1,\ w_k \sim P(w)}^K \log\left(1-\sigma\left(\boldsymbol{u}_{h_k}^\top \boldsymbol{v}_{i_t}\right)\right)\\ =&- \log\, \sigma\left(\boldsymbol{u}_{i_{t+j}}^\top \boldsymbol{v}_{i_t}\right) - \sum_{k=1,\ w_k \sim P(w)}^K \log\sigma\left(-\boldsymbol{u}_{h_k}^\top \boldsymbol{v}_{i_t}\right). \end{aligned} $$

现在,训练中每一步的梯度计算开销不再与词典大小相关,而与 $K$ 线性相关。当 $K$ 取较小的常数时,负采样在每一步的梯度计算开销较小。简言之, 负采样通过考虑同时含有正类样本和负类样本的相互独立事件来构造损失函数,其训练中每一步的梯度计算的开销仅与采样的噪声词的个数线性相关

层序 softmax(hierarchical softmax)

层序 softmax 使用了二叉树这一数据结构,树的每个叶结点代表词典 $\mathcal{V}$ 中的每个词。

图 3 二叉树的每个叶结点代表词典 $\mathcal{V}$ 中的每个词

假设 $L(w)$ 为从二叉树的根结点到词 $w$ 的叶结点的路径(包括根结点和叶结点)上的结点数。设 $n(w,j)$ 为该路径上第 $j$ 个结点, 并设该结点的背景词向量为 $\boldsymbol{u}_{n(w,j)}$。以图 3 为例,$L(w_3) = 4$。层序 softmax 将跳字模型中的条件概率近似表示为 $$P(w_o \mid w_c) = \prod_{j=1}^{L(w_o)-1} \sigma\left( [ n(w_o, j+1) = \texttt{leftChild}(n(w_o,j)) ] \cdot \boldsymbol{u}_{n(w_o,j)}^\top \boldsymbol{v}_c\right),$$ 其中 $\sigma$ 是 sigmoid 激活函数,$\texttt{leftChild}(n)$ 是结点 $n$ 的左子结点,且 $[x] = 1 \textrm{ if } x \textrm{ is }\texttt{True}\textrm{ else -1}$。

以计算图 3 中给定词 $w_c$ 生成词 $w_3$ 的条件概率为例,需要将 $w_c$ 的词向量 $\boldsymbol{v}_c$ 和根结点到 $w_3$ 路径上的非叶结点向量一一求内积。 由于在二叉树中由根结点到叶结点 $w_3$ 的路径上需要向左、向右再向左地遍历(上图中加粗的路径),所以 $$P(w_3 \mid w_c) = \sigma(\boldsymbol{u}_{n(w_3,1)}^\top \boldsymbol{v}_c) \cdot \sigma(-\boldsymbol{u}_{n(w_3,2)}^\top \boldsymbol{v}_c) \cdot \sigma(\boldsymbol{u}_{n(w_3,3)}^\top \boldsymbol{v}_c).$$

由于 $\sigma(x)+\sigma(-x) = 1$,给定中心词 $w_c$,生成词典 $\mathcal{V}$ 中任一词的条件概率之和为 1 这一条件也将满足 $\sum_{w \in \mathcal{V}} P(w \mid w_c) = 1$(这是因为二叉树中左右子树个数相等)。

由于 $L(w_o)-1$ 的数量级为 $\mathcal{O}(\text{log}_2|\mathcal{V}|)$,所以当词典 $\mathcal{V}$ 很大时,层序 softmax 在训练中每一步的梯度计算开销相较未使用近似训练时大幅降低。

二次采样

文本数据中一般会出现一些高频词,如英文中的 “the”“a” 和“in”。通常来说,在一个背景窗口中,一个词(如“chip”)和较低频词(如“microprocessor”)同时出现比和较高频词(如“the”)同时出现对训练词嵌入模型更有益。 因此,训练词嵌入模型之前可以进行二次采样,即数据集中的任意被索引词 $w_i$ 都有一定的概率会被丢弃: $$ \mathbb{P} = \max \Bigg( 1 - \sqrt{\frac{t}{f(w_i)}}, 0 \Bigg), $$ 其中 $f(w_i)$ 是单词 $w_i$ 的个数与总词数之比,$t$ 是一个超参数,我们设置为 $10^{-4}$。具体地,对于每一个词,若 $\texttt{rand}() < \mathbb{P}$,则该词被丢弃。

子词嵌入(fastText)

英语单词通常有其内部结构和形成方式。例如,可以从 “dog” “dogs” 和 “dogcatcher” 的字面上推测它们的关系。这些词都有同一个词根 “dog”,但使用不同的后缀来改变词的含义。 而且,这个关联可以推广至其他词汇。例如,“dog” 和 “dogs” 的关系如同 “cat” 和 “cats” 的关系,“boy” 和 “boyfriend” 的关系如同 “girl” 和“girlfriend” 的关系。 构词学(morphology)作为语言学的一个重要分支,研究的正是词的内部结构和形成方式。

word2vec 没有直接利用构词学中的信息。无论是在跳字模型还是连续词袋模型中,我们都将形态不同的单词用不同的向量来表示。例如,“dog”和 “dogs” 分别用两个不同的向量表示, 而模型中并未直接表达这两个向量之间的关系。鉴于此,fastText 提出了子词嵌入(subword embedding)的方法,从而试图将构词信息引入 word2vec 中的跳字模型。

在 fastText 中,每个中心词被表示成子词的集合。以单词 “where” 为例,首先,我们在单词的首尾分别添加特殊字符 “<” 和 “>” 以区分作为前后缀的子词。然后, 将单词当成一个由字符构成的序列来提取 $n$ 元语法。例如,当 $n=3$ 时,我们得到所有长度为 3 的子词:“<wh>” “whe” “her” “ere” “<re>” 以及特殊子词 “<where>”。

在 fastText 中,对于一个词 $w$,我们将它所有长度在 $3 \sim 6$ 的子词和特殊子词的并集记为 $\mathcal{G}_w$。那么词典则是所有词的子词集合的并集。 假设词典中子词 $g$ 的向量为 $\boldsymbol{z}_g$,那么跳字模型中词 $w$ 的作为中心词的向量 $\boldsymbol{v}_w$ 则表示成 $$ \boldsymbol{v}_w = \sum_{g\in\mathcal{G}_w} \boldsymbol{z}_g. $$ fastText 的其余部分同跳字模型一致。

可以看到,与跳字模型相比,fastText 中词典规模更大,造成模型参数更多,同时一个词的向量需要对所有子词向量求和,继而导致计算复杂度更高。但与此同时, 较生僻的复杂单词,甚至是词典中没有的单词,可能会从同它结构类似的其他词那里获取更好的词向量表示。

GloVe

将跳字模型中使用 softmax 运算表达的条件概率 $P(w_j\mid w_i)$ 记作 $q_{ij}$,即 $$ q_{ij}=\frac{\exp(\boldsymbol{u}_j^\top \boldsymbol{v}_i)}{ \sum_{k \in \mathcal{V}} \text{exp}(\boldsymbol{u}_k^\top \boldsymbol{v}_i)}, $$ 其中 $\boldsymbol{v}_i$ 和 $\boldsymbol{u}_i$ 分别是索引为 $i$ 的词 $w_i$ 作为中心词和背景词时的向量表示,$\mathcal{V} = {0, 1, \ldots, |\mathcal{V}|-1}$ 为词典索引集。

对于词 $w_i$,它在数据集中可能多次出现。我们将每一次以它作为中心词的所有背景词全部汇总并保留重复元素,记作多重集 $\mathcal{C}_i$(multiset)。 一个元素在多重集中的个数称为该元素的重数(multiplicity)。例如,假设词 $w_i$ 在数据集中出现 2 次:文本序列中以这两个 $w_i$ 作为中心词的背景窗口分别包含背景词索引 $2,1,5,2$ 和 $2,3,2,1$。 那么多重集 $\mathcal{C}_i = \{1,1,2,2,2,2,3,5\}$,其中元素 1 的重数为 2,元素 2 的重数为 4,元素 3 和 5 的重数均为 1。将多重集 $\mathcal{C}_i$ 中元素 $j$ 的重数记作 $x_{ij}$, 它表示了整个数据集中所有以 $w_i$ 为中心词的背景窗口中词 $w_j$ 的个数。因此,跳字模型的损失函数还可以表达为: $$ -\sum_{i\in\mathcal{V}}\sum_{j\in\mathcal{V}} x_{ij} \log\,q_{ij}. $$ 我们将数据集中所有以词 $w_i$ 为中心词的背景词的数量之和 $\left|\mathcal{C}_i\right|$ 记为 $x_i$,并将以 $w_i$ 为中心词生成背景词 $w_j$ 的条件概率 $x_{ij}/x_i$ 记作 $p_{ij}$。 我们可以进一步改写跳字模型的损失函数为 $$ -\sum_{i\in\mathcal{V}} x_i \sum_{j\in\mathcal{V}} p_{ij} \log\,q_{ij}. $$ 上式中,$-\sum_{j\in\mathcal{V}} p_{ij} \log\,q_{ij}$ 计算的是以 $w_i$ 为中心词的背景词条件概率分布 $p_{ij}$ 和模型预测的条件概率分布 $q_{ij}$ 的交叉熵, 且损失函数使用所有以词 $w_i$ 为中心词的背景词的数量之和来加权。最小化上式中的损失函数会令预测的条件概率分布尽可能接近真实的条件概率分布

然而,交叉熵损失函数有时并不是好的选择。一方面,令模型预测 $q_{ij}$ 成为合法概率分布的代价是它在分母中基于整个词典的累加项,计算开销很大;另一方面, 词典中往往有大量生僻词,它们在数据集中出现的次数极少。而有关大量生僻词的条件概率分布在交叉熵损失函数中的最终预测往往并不准确。

鉴于此,GloVe 模型采用了平方损失,并对跳字模型做了 3 点改动:

所以,GloVe 模型的目标是最小化损失函数

$$\sum_{i\in\mathcal{V}} \sum_{j\in\mathcal{V}} h(x_{ij}) \left(\boldsymbol{u}_j^\top \boldsymbol{v}_i + b_i + c_j - \log\,x_{ij}\right)^2.$$ 其中权重函数 $h(x)$ 的一个建议选择是:当 $x < c$ 时(如 $c = 100$),令 $h(x) = (x/c)^\alpha$(如 $\alpha = 0.75$),反之令 $h(x) = 1$。因为 $h(0)=0$, 所以对于 $x_{ij}=0$ 的平方损失项可以直接忽略。当使用小批量随机梯度下降来训练时,每个时间步我们随机采样小批量非零 $x_{ij}$,然后计算梯度来迭代模型参数。这些非零 $x_{ij}$ 是预先基于整个数据集计算得到的,包含了数据集的全局统计信息。因此,GloVe 模型的命名取 “全局向量”(Global Vectors)之意。

需要强调的是,如果词 $w_i$ 出现在词 $w_j$ 的背景窗口里,那么词 $w_j$ 也会出现在词 $w_i$ 的背景窗口里。也就是说,$x_{ij}=x_{ji}$。不同于 word2vec 中拟合的是非对称的条件概率 $p_{ij}$, GloVe 模型拟合的是对称的 $\log\, x_{ij}$。因此,任意词的中心词向量和背景词向量在 GloVe 模型中是等价的。但由于初始化值的不同,同一个词最终学习到的两组词向量可能不同。 当学习得到所有词向量以后,GloVe 模型使用中心词向量与背景词向量之和作为该词的最终词向量。

从条件概率的比值来理解 GloVe 模型所做的改动

作为源于某大型语料库的真实例子,图 4 列举了两组分别以 “ice”(冰)和 “steam”(蒸汽)为中心词的条件概率以及它们之间的比值:

图 4 计算条件概率的比值

可以看到: + 对于与 “ice” 相关而与 “steam” 不相关的词 $w_k$,如 $w_k=$ “solid”(固体),我们期望条件概率比值较大,如上表最后一行中的值 8.9; + 对于与 “ice” 不相关而与 “steam” 相关的词 $w_k$,如 $w_k=$ “gas”(气体),我们期望条件概率比值较小,如上表最后一行中的值 0.085; + 对于与 “ice” 和“steam”都相关的词 $w_k$,如 $w_k=$ “water”(水),我们期望条件概率比值接近 1,如上表最后一行中的值 1.36; + 对于与 “ice” 和“steam”都不相关的词 $w_k$,如 $w_k=$ “fashion”(时尚),我们期望条件概率比值接近 1,如上表最后一行中的值 0.96。

由此可见,条件概率比值能比较直观地表达词与词之间的关系。我们可以构造一个词向量函数使它能有效拟合条件概率比值: $$ f(\boldsymbol{u}_j, \boldsymbol{u}_k, {\boldsymbol{v}}_i) \approx \frac{p_{ij}}{p_{ik}}. $$

接下来给出 $f$ 的一种可行的构造方式。注意到条件概率比值是一个标量,我们可以将 $f$ 限制为一个标量函数:$f(\boldsymbol{u}_j, \boldsymbol{u}_k, {\boldsymbol{v}}_i) = f\left((\boldsymbol{u}_j - \boldsymbol{u}_k)^\top {\boldsymbol{v}}_i\right)$。 交换索引 $j$ 和 $k$ 后可以看到函数 $f$ 应该满足 $f(x)f(-x)=1$,因此一种可能是 $f(x)=\exp(x)$,于是 $$f (\boldsymbol{u}_j, \boldsymbol{u}_k, {\boldsymbol{v}}_i) = \frac{\exp\left(\boldsymbol{u}_j^\top {\boldsymbol{v}}_i\right)}{\exp\left(\boldsymbol{u}_k^\top {\boldsymbol{v}}_i\right)} \approx \frac{p_{ij}}{p_{ik}}. $$ 满足最右边约等号的一种可能是 $\exp\left(\boldsymbol{u}_j^\top {\boldsymbol{v}}_i\right) \approx \alpha p_{ij}$,这里 $\alpha$ 是一个常数。 考虑到 $p_{ij}=x_{ij}/x_i$,取对数后 $\boldsymbol{u}_j^\top {\boldsymbol{v}}_i \approx \log\,\alpha + \log\,x_{ij} - \log\,x_i$。 我们使用额外的偏差项来拟合 $- \log\,\alpha + \log\,x_i$,因此引入中心词偏差项 $b_i$ 和背景词偏差项 $c_j$: $$ \boldsymbol{u}_j^\top \boldsymbol{v}_i + b_i + c_j \approx \log(x_{ij}). $$ 对上式左右两边取平方误差并加权,即得到 GloVe 模型的损失函数。

到目前为止,我们介绍了如何用词向量表征单词,并给出了几种训练词向量的方式。实际使用中,我们大多是直接下载已在各类大型文本库上经过训练的词向量,常用的有:

# vocab.pretrained_aliases.keys()
dict_keys([
    'charngram.100d',
    'fasttext.en.300d', 'fasttext.simple.300d',
    'glove.42B.300d', 'glove.840B.300d',
    'glove.twitter.27B.25d', 'glove.twitter.27B.50d',
    'glove.twitter.27B.100d', 'glove.twitter.27B.200d',
    'glove.6B.50d', 'glove.6B.100d', 'glove.6B.200d', 'glove.6B.300d'
])

可以直接基于这些预训练的词向量借助 top-$k$ 余弦相似度求解近义词和类比词。

最后

本文所使用的图片来自《动手学深度学习》(PyTorch 版)章节 10。 本文的部分文字摘自此书,如果需要获得更详尽的解释,请前往本链接阅读原文。

本文提及的各种 NLP 模型的 PyTorch 实现见本链接

转载申请

本作品采用 知识共享署名 4.0 国际许可协议 进行许可, 转载时请注明原文链接。您必须给出适当的署名,并标明是否对本文作了修改。

您也可以通过下方按钮直接分享本页面:


发表评论

登录以发表评论

最新评论


Designed & written by Hailiang Zhao.
hliangzhao.cn. Copyright © 2021 - 2022 | 浙ICP备2021026965号-1
Manage