MENU

Word2Vec

April 7, 2020 • Read: 14737 • Deep Learning阅读设置

自然语言处理问题中,一般以词作为基本单元,例如我们想要分析 "我去过华盛顿州" 这句话的情感,一般的做法是先将这句话进行分词,变成去过华盛顿州,由于神经网络无法处理词,所以我们需要将这些词通过某些办法映射成词向量。词向量是用来表示词的向量,也可被认为是词的特征向量。把词映射为实数域向量的技术也叫词嵌入(word embedding)

为何不采用 one-hot 向量

假设词典中不同词的数量为 $N$,每个词可以和从 0 到 $N-1$ 的连续整数一一对应。假设一个词的相应整数表示为 $i$,为了得到该词的 one-hot 向量表示,我们创建一个全 0 的长为 $N$ 的向量,并将其第 $i$ 为设位 1

然而,使用 one-hot 词向量并不是一个好选择。一个主要的原因是,one-hot 词向量无法表达不同词之间的相似度,例如,任何一对词的 one-hot 向量的余弦相似度都为 0

word2vec

2013 年,Google 团队发表了 word2vec 工具。word2vec 工具主要包含两个模型:跳字模型(skip-gram)连续词模型(continuous bag of words,简称 CBOW),以及两种高效训练的方法:负采样(negative sampling)层序 softmax(hierarchical softmax)。值得一提的是,word2vec 词向量可以较好地表达不同词之间的相似度和类比关系

跳字模型

在跳字模型中,我们用一个词来预测它在文本序列周围的词。例如,给定文本序列 "the","man","hit","his","son"。设背景窗口大小为 2, 跳字模型所关心的是,给定 "hit",生成它邻近词 "the","man"."his","son" 的概率(在这个例子中,"hit" 叫中心词,"the","man","his","son" 叫背景词),即

$$ P(\text{the},\text{man},\text{his},\text{son}\mid \text{hit}) $$

假设在给定中心词的情况下,背景词的生成是相互独立的,那么上式可以改写成

$$ P(\text{the}\mid \text{hit})·P(\text{man}\mid \text{hit})·P(\text{his}\mid \text{hit})·P(\text{son}\mid \text{hit}) $$

我们来描述一下跳字模型。假设词典大小为 $|V|$,我们将词典中的每个词与 0 到 $|V|-1$ 的整数一一对应:词典索引集 $V=\{0,1,...,|V|-1\}$。一个词在该词典中所对应的整数称为词的索引,给定一个长度为 $T$ 的文本序列,$t$ 时刻的词为 $w^{(t)}$。当时间窗口大小为 $m$ 时,跳字模型需要最大化给定任一中心词生成背景词的概率

$$ \prod_{t=1}^T {\prod_{-m≤j≤m,\ j\neq 0}{P(w^{(t+j)}\mid w^{(t)})}} $$

上式得最大似然估计与最小化以下损失函数等价

$$ -\frac{1}{T}\sum_{t=1}^{T}\sum_{-m≤j≤m,\ j\neq 0}\log P(w^{(t+j)}\mid w^{(t)}) $$

我们可以用 $\boldsymbol v$ 代表中心词的词向量,$\boldsymbol u$ 代表背景词的词向量。换言之,对于词典中一个索引为 $i$ 的词,它本身有两个向量 $\boldsymbol {v}_i$ 和 $\boldsymbol {u}_i$ 进行表示,在计算的过程中,根据其所处的角色不同,选择不同的词向量。词典中所有词的这两种向量正是跳字模型所需要学习的参数。为了将模型参数植入损失函数,我们需要使用模型参数表达损失函数中的中心词生成背景词的概率。假设中心词的概率是相互独立的。给定中心词 $w_c$ 在词典中的索引为 $c$,背景词 $w_o$ 在词典中的索引为 $o$,损失函数中中心词生成背景词的概率可以使用 softmax 函数进行定义:

$$ P(w_o|w_c)=\frac{\exp(\boldsymbol{u}_o^T\boldsymbol {v}_c)}{\sum_{i\in V}\exp(\boldsymbol{u}_i^T\boldsymbol{v}_c)} $$

当序列长度 $T$ 较大时,我们通常随机采样一个较小的子序列来计算损失函数并使用 SGD 优化该损失函数。通过求导,我们可以计算出上式生成概率的对数关于中心词向量 $\boldsymbol {v}_c$ 的梯度为:

$$ \begin{aligned} \frac{\partial \log P(w_o\mid w_c)}{\partial \boldsymbol{v}_c}&=\frac{\partial}{\partial \boldsymbol{v}_c}\log\frac{\exp(\boldsymbol{u}_o^T\boldsymbol{v}_c)}{\sum_{i=1}^{|V|}\exp(\boldsymbol{u}_i^T\boldsymbol{v}_c)}\\&=\underbrace {\frac{\partial}{\partial \boldsymbol{v}_c} \log \exp(\boldsymbol{u}_o^T\boldsymbol{v}_c)}_1-\underbrace{\frac{\partial}{\partial \boldsymbol{v}_c}\log \sum_{i=1}^{|V|}\exp(\boldsymbol{u}_i^T{\boldsymbol{v}_c})}_2 \end{aligned} $$

第一部分推导

$$ \frac { \partial} {\partial \boldsymbol{v}_c} \color{red}{\log \exp (\boldsymbol{u}_o^T \boldsymbol{v}_c) } = \frac { \partial} {\partial \boldsymbol{v}_c} \color{red}{\boldsymbol{u}_o^T \boldsymbol{v}_c} = \mathbf{\boldsymbol{u}_o} $$

第二部分推导

$$ \begin{aligned} \frac { \partial} {\partial \boldsymbol{v}_c} \log \sum_{i=1}^{|V|} \exp(\boldsymbol{u}_i^T \boldsymbol{v}_c) & = \frac{1}{\sum_{i=1}^{|V|} \exp(\boldsymbol{u}_i^T \boldsymbol{v}_c)} \cdot \color{red}{ \frac { \partial} {\partial \boldsymbol{v}_c} \sum_{x=1}^{|V|} \exp(\boldsymbol{u}_x^T \boldsymbol{v}_c)} \\ & = \frac{1}{A} \cdot \sum_{x=1}^{|V|} \color{red} {\frac { \partial} {\partial \boldsymbol{v}_c} \exp(\boldsymbol{u}_x^T \boldsymbol{v}_c)} \\ & = \frac{1}{A} \cdot \sum_{x=1}^{|V|} \exp (\boldsymbol{u}_x^T \boldsymbol{v}_c) \color{red} {\frac { \partial} {\partial \boldsymbol{v}_c} \boldsymbol{u}_x^T \boldsymbol{v}_c} \\ & = \frac{1}{\sum_{i=1}^{|V|} \exp(\boldsymbol{u}_i^T \boldsymbol{v}_c)} \sum_{x=1}^{|V|} \exp (\boldsymbol{u}_x^T \boldsymbol{v}_c) \color{red} {\boldsymbol{u}_x} \\ & = \sum_{x=1}^{|V|} \color{red} { \frac{\exp (\boldsymbol{u}_x^T \boldsymbol{v}_c)} {\sum_{i=1}^{|V|} \exp(\boldsymbol{u}_i^T \boldsymbol{v}_c)}} \boldsymbol{u}_x \\ & = \sum_{x=1}^{|V|} \color{red} {P(w_x \mid w_c) }\boldsymbol{u}_x \end{aligned} $$

综上所述

$$ \frac{\partial \log P(w_o\mid w_c)}{\partial \boldsymbol{v}_c}=\boldsymbol{u}_o-\sum_{j\in V}P(w_j\mid w_c)\boldsymbol {u}_j $$

通过上面计算得到梯度后,我们可以使用随机梯度下降来不断迭代模型参数 $\boldsymbol {v}_c$。其它模型参数 $\boldsymbol {u}_o$ 的迭代方式同理可得。最终,对于词典中任一索引为 $i$ 的词,我们均得到该词作为中心词和背景词的两组词向量 $\boldsymbol {v}_i$ 和 $\boldsymbol {u}_i$

连续词袋模型

连续词袋模型与跳字模型类似。与跳字模型最大的不同是,连续词袋模型是用一个中心词在文本序列周围的词 来预测中心词。简单的说就是,跳字模型用中心词预测周围的词;连续词袋模型用周围的词预测中心词。例如,给定文本 "the","man","hit","his","son",连续词袋模型所关心的是,邻近词 "the","man","his","son" 一起生成中心词 "hit" 的概率

连续词袋模型需要最大化由背景词生成任一中心词的概率:

$$ \prod_{t=1}^TP(w^{(t)}\mid w^{(t-m)},...,w^{(t-1)},w^{(t+1)},...,w^{(t+m)}) $$

上式得最大似然估计与最小化以下损失函数等价

$$ -\sum_{t=1}^T\log P(w^{(t)}\mid w^{(t-m)},...,w^{(t-1)},w^{(t+1)},...,w^{(t+m)}) $$

我们可以用 $\boldsymbol {v}$ 和 $\boldsymbol {u}$ 分别代表背景词和中心词的向量(注意符号和跳字模型不同)。给定中心词 $w_c$ 在词典中的索引为 $c$,背景词 $w_{o_1},...,w_{o_{2m}}$ 在词典中的索引为 $o_1,...,o_{2m}$,损失函数中的背景词生成中心词的概率可以使用 softmax 函数定义为

$$ P(w_c\mid w_{o_1},...,w_{o_{2m}})=\frac{\exp[\boldsymbol{u}_c^T(\boldsymbol{v}_{o_1}+...+\boldsymbol{v}_{o_{2m}})/(2m)]}{\sum_{j\in V}\exp[\boldsymbol{u}_j^T(\boldsymbol{v}_{o_1}+...+\boldsymbol{v}_{o_{2m}})/(2m)]} $$

同样,当序列长度 $T$ 较大时,我们通常随机采样一个较小的子序列来计算损失函数,并使用随机梯度下降优化该损失函数,通过微分,我们可以计算出上式生成概率的对数关于任一背景词向量 $\boldsymbol {v}_{o_i}(i=1,...,2m)$ 的梯度为:

$$ \frac{\partial \log P(w_c\mid w_{o_1},...,w_{o_{2m}})}{\partial \boldsymbol{v}_{o_i}}=\frac{1}{2m}(\boldsymbol {u}_c-\sum_{j\in V}\frac{\exp(\boldsymbol u_j^T\boldsymbol v_c)}{\sum_{i\in V}\exp(\boldsymbol u_i^T\boldsymbol v_c)}\boldsymbol u_j) $$

而上式与下式等价:

$$ \frac{\partial \log P(w_c\mid w_{o_1},...,w_{o_{2m}})}{\partial \boldsymbol{v}_{o_i}}=\frac{1}{2m}(\boldsymbol {u}_c-\sum_{j\in V}P(w_j\mid w_c)\boldsymbol u_j) $$

近似训练法

可以看到,无论是跳字模型还是连续词袋模型,每一步梯度计算的开销与词典 $V$ 的大小呈正相关。显然,当词典较大时,这种训练方法的计算开销会很大。所以使用上述训练方法在实际中是由难度的。我们可以使用近似的方法来计算这些梯度,从而减小计算开销。常用的近似训练法包括负采样层序 softmax

负采样

以跳字模型为例讨论负采样。词典 $V$ 的大小之所以会在目标函数中出现,是因为中心词 $w_c$ 生成背景词 $w_o$ 的概率 $P (w_o|w_c)$ 使用了 softmax,而 softmax 考虑到了背景词可能是词典中任一词,并体现在了 softmax 的分母上

我们不妨换个角度,假设中心词 $w_c$ 生成背景词 $w_o$ 由以下两个互相独立的联合事件组成来近似

  1. 中心词 $w_c$ 和背景词 $w_o$ 同时出现在该训练数据窗口
  2. 中心词 $w_c$ 和噪声词不同时出现在该训练数据窗口

    • 中心词 $w_c$ 和第 1 个噪声词 $w_1$ 不同时出现在训练数据窗口(噪声词 $w_1$ 按噪声词分布 $P (w)$ 随机生成)
    • ...
    • 中心词 $w_c$ 和第 $K$ 个噪声词 $w_k$ 不同时出现在训练数据窗口(噪声词 $w_K$ 按噪声词分布 $P (w)$ 随机生成)

我们可以使用 $\sigma (x)=\frac {1}{1+\exp (-x)}$ 函数来表达中心词 $w_c$ 和背景词 $w_o$ 同时出现在训练数据窗口的概率:

$$ P(D=1\mid w_o,w_c)=\sigma(\boldsymbol{u}_o^T,\boldsymbol{v}_c) $$

那么,中心词 $w_c$ 生成背景词 $w_o$ 的对数概率可以近似为

$$ \log P(w_o\mid w_c)=\log[P(D=1\mid w_o,w_c)\prod_{k=1,w_k\sim P(w)}^KP(D=0\mid w_k,w_c)] $$

假设噪声词 $w_k$ 在词典中的索引为 $i_k$,上式可改写为

$$ \log P(w_o\mid w_c)=\log\frac{1}{1+\exp(-\boldsymbol u_o^T\boldsymbol{v}_c)}+\sum_{k=1,w_k\sim P(w)}^K\log[1-\frac{1}{1+\exp(-\boldsymbol u_{i_k}^T\boldsymbol{v}_c)}] $$

因此,有关中心词 $w_c$ 生成背景词 $w_o$ 的损失函数是

$$ -\log P(w_o\mid w_c)=-\log\frac{1}{1+\exp(-\boldsymbol u_o^T\boldsymbol{v}_c)}-\sum_{k=1,w_k\sim P(w)}^K\log\frac{1}{1+\exp(\boldsymbol u_{i_k}^T\boldsymbol{v}_c)} $$

现在,训练中每一步的梯度计算开销不再与词典大小相关,而与 $K$ 线性相关。当 $K$ 取较小的常数时,负采样的每一步梯度计算开销也较小

同理,也可以对连续词袋模型进行负采样。有关背景词 $w^{(t-m)},...,w^{(t-1)},w^{(t+1)},...,w^{(t+m)}$

生成中心词 $w_c$ 的损失函数

$$ -\log P(w^{(t)}\mid w^{(t-m)},...,w^{(t-1)},w^{(t+1)},...,w^{(t+m)}) $$

在负采样中可以近似为

$$ -\log\frac{1}{1+\exp[-\boldsymbol{u}_c^T(\boldsymbol{v}_{o_1}+...+\boldsymbol{v}_{o_{2m}})/(2m)]}-\sum_{k=1,w_k\sim P(w)}^K\log\frac{1}{1+\exp[\boldsymbol{u}_{i_k}^T(\boldsymbol{v}_{o_1}+...+\boldsymbol{v}_{o_{2m}})/(2m)]} $$

层序 softmax

层序 softmax 利用了二叉树。树的每个叶子节点代表着词典 $V$ 中的每个词。每个词 $w_i$ 对应的词向量为 $\boldsymbol {v}_i$。我们以下图为例,来描述层序 softmax 的工作机制

设 $L (w)$ 为从二叉树根节点到代表词 $w$ 的叶子节点的路径上的节点数,并设 $n (w,i)$ 为该路径上第 $i$ 个节点,该节点的向量为 $\boldsymbol {u}_{n (w,j)}$。以上图为例,$L (w_3)=4$。那么,跳字模型和连续词袋模型所需要计算的任意词 $w_i$ 生成词 $w$ 的概率为:

$$ P(w\mid w_i)=\prod_{j=1}^{L(w)-1}\sigma([n(w,j+1)=left\_child(n(w,j))]·\boldsymbol{u}_{n(w,j)}^T\boldsymbol{v}_i) $$

其中,如果 $x$ 为真,$[x]=1$;反之 $[x]=-1$

由于 $\sigma (x)+\sigma (-x)=1$,$w_i$ 生成词典中任何词的概率之和为 1:

$$ \sum_{w=1}^VP(w\mid w_i)=1 $$

上面公式可能比较抽象,下面举个具体的例子,计算 $w_i$ 生成 $w_3$ 的概率,由于在二叉树中由根到 $w_3$ 的路径需要向左、向右、再向左地遍历,所以得到

$$ P(w_3\mid w_i)=\sigma(\boldsymbol{u}_{n(w_3,1)}^T\boldsymbol{v}_i)·\sigma(-\boldsymbol{u}_{n(w_3,2)}^T\boldsymbol{v}_i)·\sigma(\boldsymbol{u}_{n(w_3,3)}^T\boldsymbol{v}_i) $$

由此,我们就可以使用随机梯度下降在跳字模型和连续词袋模型中不断迭代计算词典中所有词向量 $\boldsymbol {v}$ 和非叶子节点的向量 $\boldsymbol {u}$。每次迭代的计算开销由 $O (|V|)$ 降为二叉树的高度 $O (\log|V|)$

最后一个问题,层序 softmax 的二叉树是如何建立的?

这里的二叉树 Huffman 树,权重是语料库中 word 出现的频率

Last Modified: August 2, 2021
Archives Tip
QR Code for this page
Tipping QR Code
Leave a Comment

9 Comments
  1. 理想家 理想家

    博主,网站乱码了

    1. mathor mathor

      @理想家刷新

  2. heng heng

    那儿的公式推导,怎么多了 x 和 j 呢,skip-gram 的损失函数第二部分

  3. tzj tzj

    博主,梯度求导 “第 1 部分 - 第 2 部分” 那里,第 2 部分是不是多写了个 exp?

    1. mathor mathor

      @tzj 是的,已修改,感谢提醒

  4. 啥也不会 啥也不会

    请问第二部分第一行的公式推导是怎么来的?

    1. mathor mathor

      @啥也不会对 logf (x) 求偏导,本质上是复合函数求导,链式法则

    2. 啥也不会 啥也不会

      @mathor 明白了,感谢~

  5. ther ther

    博主请问负采样那里,中心词生成背景词的对数概率的近似公式怎么来的呀