word2vec详解 | Jason Hao's Blog
0%

word2vec详解

Word2vec的训练目标

Word2vec都被认为是用于训练词向量表达的工具。但是词向量其实是一个完成了Word2vec网络模型的一个副产品。它的训练目标是训练一个三层神经网络,使得上下文相似的词汇的相似度变高。达到这个目标后,发现输入层到隐藏层的参数竟然奇迹般的能用于词的向量表示,并且还有些神奇的效果,比如 ”King“-"Men"+"Women"="Queen"、 ”日本“-”东京“+"中国"="北京";或者 "北京"和"烤鸭"的相似性 > "北京"和"早茶"的相似性。 假设数据集为 \(D\),数据集中的词汇表为 \(C\)。如果当前词为 \(w_t\),上下文窗口大小为 5. 那么这个词的上下文 \(Context(w_t)=[w_{t-2},w_{t-1},w_{t+1},w_{t+2}]\)。对于下面的例子的第三个窗口而言,当前输入词为“brown”,它的上下文为 [“the”,“quick”,“fox”,“jumps”]

Skip-gram

Skip-gram 通过当前词汇来预测上下文,为此它的最大化目标函数为

\(L=\sum_{w\in D}logp(w|Context(w))\)

CBOW

CBOW 的思想则是通过上下文来预测当前词汇,为此它的最大化目标函数为

\(L=\sum_{w\in D}logp(Context(w)|w)\)

Word2vec模型

Word2vedc 模型由输入层,隐藏层和输出层组成,它的模型参数包括了输入层到隐藏层的权重矩阵 \(W\)(最终保留的词向量矩阵),以及隐藏层到输出层的权重矩阵 \(W'\),数据集的词汇表中一共包含 \(V\) 个唯一的词汇,词向量的维度设置为 \(N\)

CBOW 模型

对于当前词汇 \(w_t\) 而言,它是词汇表中第 \(v\) 个词汇。它的一个训练样本为 \((Context(w_t), w_t)\). 输入层是一个只包含 0 和 1 的向量,1 的位置代表词汇表中该位置的词汇在上下文 \(Context(w_t)\) 中. 隐藏层的向量 \(h=x^TW=\sum_{w'\in Context(w_t)}W_{w'}\). 其实隐藏层就是上下文词汇的词向量的和。输出层为向量 \(o=hW'=x^TWW'\)。对于向量 \(o\) 而言,希望第 \(v\) 个位置为 1,其他位置为 0. 对于这一个训练样本而言,我们希望最大化

\(L=\sum_{w_t\in C}log(\prod_{w\in C}p(w|Context(w_t)))\)

\(g(w_t,w)=p(w|Context(w_t))={[\sigma(hW'_{w})]}^{L^{w_t}(w)}\times {[1-\sigma(hW'_{w})]}^{1-L^{w_t}(w)}\)

其中 \(\sigma(x)=\frac{1}{1+e^{-x}}\)\(L^{w_t}(w)=1\) if \(w_t=w\)\(L^{w_t}(w)=1\) if \(w_t\neq w\).

\(W'_{w}\) 求导 \(\frac{\partial g(w_t,w)}{\partial W'_w}=[L^{w_t}(w)-\sigma(hW'_{w})]h\)

\(h\) 求导 \(\frac{\partial g(w_t,w)}{\partial h}=[L^{w_t}(w)-\sigma(hW'_{w})]W'_{w}\)

更新 \(W'_{w}=W'_{w}+\eta \frac{\partial g(w_t,w)}{\partial W'_w}\)

更新 \(W_{w'} (w'\in Context(w_t))\)\(W_{w'}=W_{w'} + \eta \sum_{w\in C} \frac{\partial g(w_t,w)}{\partial h}\)

SKip-gram 模型

对于当前词汇 \(w_t\) 而言,它是词汇表中第 \(v\) 个词汇。它的一个训练样本为 \((w_t,Context(w_t))\). 输入层是一个 one-hot 向量,其中第 \(v\) 个位置为 1,其他位置为 0. 隐藏层的向量 \(h=x^TW=\sum_{w\in Context(w_t)}W_{w}\). 其实隐藏层就是上下文词汇的词向量的和。输出层为向量 \(o=hW'=x^TWW'\)。对于向量 \(o\) 而言,希望所有与 \(Context(w_t)\) 中词汇对应的位置为 1,其他位置为 0. 对于这一个训练样本而言,我们希望最大化

\(L=\sum_{w_t\in C}log(\prod_{u\in Context(w_t)}\prod_{w\in C}p(w|w_t,u))\)

\(g(w_t,u,w)=p(w|w_t,u)={[\sigma(W_{u}^T W'_{w})]}^{L^{w_t}(w)}\times{[1-\sigma(W_{u}^T W'_{w})]}^{1-L^{w_t}(w)}\)

其中 \(\sigma(x)=\frac{1}{1+e^{-x}}\)\(L^{w_t}(w)=1\) if \(w_t=w\)\(L^{w_t}(w)=1\) if \(w_t\neq w\).

\(W'_{w}\) 求导 \(\frac{\partial g(w_t,w,u)}{\partial W'_w}=[L^{w_t}(w)-\sigma(W_{u}W'_{w})]W_{u}\)

\(W_u\) 求导 \(\frac{\partial g(w_t,w)}{\partial W_{u}}=[L^{w_t}(w)-\sigma(W_{u}W'_{w})]W_{u}\)

更新 \(W'_{w}=W'_{w}+\eta \frac{\partial g(w_t,w)}{\partial W'_w}\)

更新 \(W_{u} (u\in Context(w_t))\)\(W_{u}=W_{u} + \eta \sum_{w\in C} \frac{\partial g(w_t,w)}{\partial W_u}\)

负采样

从上面的模型可以看到,每个训练样本经过,都需要更新整个 \(W'\),这样代价太大了,因此,负采样对于上面的 \(w\in C\) 更改为 \(w\in NEG(w_t)\cup w_t\). 这样每次只需要更新更少的参数. 对于 \(w_t\) 而言,除了自己,其他词汇都是负样本词汇. 但是有那么多个负样本词汇,我们怎么去挑选呢,答案是根据负样本词汇的词频。为此 Word2vec 模型定义了一个概率计算公式用于挑选负样本词汇:\(P(w)=\frac{tf(w)^{3/4}}{\sum_{w'}tf(w')^{3/4}}\).公式中加了一个 \(3/4\) 次方纯粹是一个经验值.

下采样

回到一个图中的例子中我们构建的训练样本。里面会存在大量的("fox", "the")这样的词对,并且像("the", XXX)这样词对也会频繁出现在训练样本中。我们知道其实 "the" 并不能为 "fox" 这样的词提供多少语义含义,此外对于("the", XXX)这样的词对,XXX有很高的重复率。为此,Word2vec使用下采样来对付这样的情况。简单来说对于像 ”fox" 这样有意义的词语,我们去掉它的包含 "the" 的词对;对于 "the" 这样的词汇,我们采用更少的训练样本量。

那么对于一个像 "the" 这样的高频词汇,我们按照怎样的方法来选择性的丢掉它的一些样本呢?Word2vec 采用了一个计算词汇被保留的概率公式 \(P(w)=(\sqrt{\frac{z(w)}{0.001}}+1)\frac{0.001}{z(w)}\),其中 \(z(w)=\frac{tf(w)}{corpus\ size}\)。函数\(f(x)=(\sqrt{\frac{x}{0.001}}+1)\frac{0.001}{x}\)的图像如下图所示:

从图中可以看出,高频词汇被保留的概率较少,低频词汇被保留的概率较高。当 \(z(w)\leq 0.0026\) 时,\(P(w)=1\),此时 \(w\) 所有的词对样本都被保留;当 \(z(w)= 0.00746\) 时,\(P(w)=0.5\),此时 \(w\) 的词对样本只保留一半。

参考 (References)

  1. http://mccormickml.com/2016/04/19/word2vec-tutorial-the-skip-gram-model/
  2. http://mccormickml.com/2017/01/11/word2vec-tutorial-part-2-negative-sampling/