word2vec介绍

word2vec是自然语言处理中常用的词嵌入(word  embedding)模型,他基于一个独立假设,认为处于相同语境(上下文)的词汇具有相同的含义,相对于之前基于词频统计的词嵌入模型,word2vec提供了更好的语义相关性,广义的word2vec就是表示词汇级别的嵌入模型,狭义的word2vec表示google在2013年开源的词嵌入模型,此外,还有斯坦福大学提出的Glove,文章的最后会有这两种类型的比较。

word2vec模型目标

最大化目标函数:

\[J(\theta) = \frac{1}{T}\sum_{t=1}^{T}\sum_{-c \le j \le c \, j\ne 0} \log{p(w_{t+j}|w_{t})}\]

word2vec的优化方式

作为笔记性质的文章,这里不想把各种公式和损失函数求导的步骤写上来,一切以核心思想为重。

首先,单词会用设定维度的向量进行表示。

其次,使用向量内积来衡量两个词向量的相似程度。

再次,使用softmax表示词汇在给定上下文的条件概率,如上述公式所示。

最后,由上下文更新中心词的词向量。

注意到最后一点,因为在实现的时候是划窗的方式进行数据集创建的,所以本次划窗得到的数据对里的中心词,在下一次划窗的时候就会变成上下文,所以所有单词都会得到更新。

对于更新向量这里,起初我有过一点不解,构造出来的数据集上下文词汇是作为label来使用的,如果也被更新了,那岂不是变成了一个动态的数据集,会不会最后产生让所有词向量都收敛到同一个词汇上,因为此时是最符合word2vec的目标函数的。经过实现我才知道实现和公式的差距有多大。

word2vec的实现

首先是每个词汇是存在两个词向量的,一个是他作为中心词的时候,一个是作为上下文的时候,词汇起初都被映射到一个数字编号上,然后这个编号作为index来在两个大的词向量矩阵中找到自己对应的两种情况下的词向量。(实际实现中词向量矩阵使用Embedding层来实现),这就解决了我上面的疑惑。到这里,定义一下损失函数,然后bp就可以完成一个基本的word2vec了,这样的情况下只要初始化是随机的,几乎不会出现我说的第二个问题,但是还是一种没有保障的状态,后来看到了负采样技术,终于明朗了。

word2vec中的负采样(negative sampling)

这个技术的提出实际上是为了提高准确率,解答我的疑惑是另一回事。负采样(以下简称NS)是在上述实现方式的基础之上,在损失函数上加上一项,表示中心词和一个随机的上下文的匹配程度,通俗的说此时的损失函数有两部分,第一是中心词和上下文的匹配程度,第二是中心词和随机上下文的区分程度,这样直观上也能感觉到对准确率有帮助。此时损失函数的公式为:

\[\log{\sigma(    { \nu’_{\omega_{O}}}^{\top} \nu_{\omega_{I}}         ) } +\sum_{i=1}^{k}E_{\omega_{i}\sim P_{n}(\omega})\left[ \log{\sigma({-\nu’_{\omega_{i}}}^{\top}} \nu_{\omega_{I}})\right]\]

实现过程中,也直接使用这个函数作为自定义损失函数。

代码在我的github

讨论word2vec与glove

在学习cs224的时候,我觉得glove的损失函数构成比word2vec更加漂亮,但是却没有胜出word2vec,既然都是各自提出的方法,肯定很难以从理论角度上证明谁更好,不过有个国外小哥用心的比较了二者的差异,在这里,绝大多数的任务中我都使用word2vec而非glove,所以不做太多介绍。对glove感兴趣的可以看原文在这里。 

参考文献

[1]http://web.stanford.edu/class/cs224n/

[2]https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/tutorials/word2vec

发表评论

电子邮件地址不会被公开。 必填项已用*标注