Word2vec

来自集智百科
跳转到: 导航搜索

传统自然语言处理的表达,一般以词为单位。自然语言字符表达成计算机能处理的信息,采取离散表达。假设有个词表,可以理解为字典,如何在这一万个字中表达这一个字。用一万维的向量表达这个字,某个字只可能在某一维地方为1,其他位置都为0。如下图所示:

blob.png


这种方法特点:根据词表大小决定向量长度。很占空间,即使稀疏表示。缺乏泛化性(lack of generalization)。这种表示没法表达相似的概念。所以希望能够有一种方式计算这种泛化性,稠密向量。

“You shall know a word by the company it keeps.”--J.R. Firth(1957)基于同一种思想,生出很多方法,主要有两种假说。


微信截图_20170216183448.png



假说一:The distributional hypothesis 分布式假说

一个词由周围词来推断。相似的词会出现在相似的语境里。例如今晚的天空有很多星星。句子中天空和星星相关,横向共现。这样,我们可以由词跟语境的关系来判断相似度,天空和星星就是想死的。BOW, LSI, LDA等模型都是由这种假说出发的,产生的很多种方法来计算这个实值向量。1954年BOW模型不考虑语序,出现一次加1。2003年LDA模型,是主题模型中的某一个特例。PMI/PPMI等方法都研究共现,相关词共同出现几次,然后再做SVD矩阵分解等。


假说二:Distributed models

相似词在相似语境contex下。例如今天天空有很多星星。今天天空有个太阳。这两个句子中的星星和太阳这两个词出现在了同样的上下文之中,它们是相似的,但它们是一种纵向的相似性。基于这种假说诞生的方法,最重要的就是这个Word2Vec。


微信截图_20170216183508.png


因此,我们可以看到,对于这两种方法来说,两个词的相似性依赖于它们彼此所处的环境,而环境又有两种,一种是同一个句子之中,另一种是在不同句子,但是相似的上下文之中。

当然,我们要讲解的重点是Word2Vec。事实上,Word2Vec是由神经网络语言模型得到的一个副产物。这就是Bangio的那篇经典的论文:(http://citeseerx.ist.psu.edu/showciting?doi=10.1.1.133.9693),文中提出了一种利用神经网络的方法来做自然语言理解的思路:

微信截图_20170216183537.png


尽管这一框架本身并不实用,但是却包含了将单词进行向量编码的操作,而这却成为了后来词向量算法Word2Vec的前身。

于是,到了2013年Google的Mikolov提出了两套实用的算法,它们统称为Word2Vec。Word2vec 是代码项目的名字,只是计算词嵌入(word embedding)的一个工具,是CBOW和Skip-Gram这两个模型的合体,目前这套工具完全开源。。

如下图所示,左边的CBOW是利用词的上下文预测当前的单词;而Skip-Gram则是利用当前词来预测上下文。

微信截图_20170216183548.png


二、Skipgram的原理 在这节课中,我们重点介绍后一种,即Skipgram,它的结构如图:

qqq.jpg


它的工作原理如下:


首先要有语料库和词库,大概词库需要包含所有语料库中的词,或者把没囊括的词encode成一个统一的值。如上图所示,每一个input都是一个1-hot编码的词。每一个output是一个概率Vector表示Vector位置上的词出现在当前output位置的概率,Vector的位置和input的词的位置相符。

举个例子吧,如果有这样一个词序列 (我爱中国)那么就会有四个1-hot 编码的输入向量: 1000, 0100,0010,0001。这就是可能的CBow模型的输入,假设我们当前的输入是0100,也就是“爱”这个字。


再来看输出,假如我们希望预测“爱”这个词的上下文,,比如说取前后各一个。


那么就会有两个output,刚才说了每个output是一个概率Vector, 假设这两个output Vector是(0.3, 0.5, 0.7,), (0.1,0.9,0.1)。第一个(0.3,0.5,0.7)中的数字表示的就是“我”出现在“爱”之前一位的概率是0.3, “爱”出现在“爱”之前一位的概率是0.5, “中国”出现在“爱”前一位的概率是0.7。同样,后一个向量(0.1,0.9,0.1)则表示“我”出现在“爱”之后的概率是0.1,“爱”出现在“爱”之后的概率是0.1,……。


这样的话,只要我们给定了一个词,整个CBow网络就可以得到这个词上下文中各个词出现的概率,我们用蒙特卡洛模拟的方法根据哪些概率值去采样,就能得到一个具体的上下文。


如果这部分理解了,那么我们就可以有一个优化的目标了,就是使得这一系列的Output Vector最接近真实的情况。所谓真实的情况就是机器通过随机采样得到的序列能够逼近真实的人类语言序列。也就是说在收集的大量文本数据中,对于“爱”这个词,之前(第一个Vector)出现“我”,之后出现“中国”的次数如果足够多,那么我们的模型预测这两个词的概率也应该足够大,这就是所谓的极大似然原理(maximum likelihood principle)。


这样,Input 、 output优化目标都有了,那么通过一系列复杂的公式,以及参照上图,就会得到两个参数W和W’。 W我们可以简单的理解为词向量,也就是说这样的形式:


我 (0.9,-0.2,0.1)

爱 (0.8, 0.2,0.2)

中 (0.1, 0.3,0.4)

国 (0.2, 0.3,0.6)


那么这一系列的复杂运算是怎么做的呢?答案就在于优化。我们让训练这个网络的最终目标就是去根据当前词来优化预测出它的上下文的概率,于是,我们就可以写出目标函数:

blob.png

其中,T是语料库单词的总个数,p(wt+j|wt)是已知当前词wt,预测周围词的总概率对数值。 (1)一个 tips: 这里值得注意的不是函数本身,因为之所以在目标函数中用对数,完全是为了计算方便,值得注意的是第二个求和号的下标,需要在第 j 个词的左右分别有 c个词。 这里,概率的计算方式如下:


blob.png

(2)再来一个 tips:这里无论是 v 还是 v’对应的都是向量,维度是 v-dim,因此这里的乘法是向量乘法。而后,我们依然可以采用反向传播等方式计算。

三、负采样 然而,在实际的计算过程中,运算量过于巨大,于是人们就像出了一个绝妙的解决办法,从而快速地完成任务。这种方法就被称为“负采样”(Negative sampling)。 负采样的核心思想是,如果将自然语言看作是一串单词的随机组合,那么它的出现概率是很小的。于是,如果我们将拼凑的单词随机组合(负采样)起来将会以很大的概率不会出现在当前文章中。于是,我们很显然应该至少让我们的模型在这些负采样出来的单词组合上面出现概率应该尽可能地小,同时要让真正出现在文中的单词组合出现概率大。这样我们的模型才足够有效。于是,我们的目标变成了优化新的概率函数:


blob.png

,从而得到最优的词向量嵌入。这里D是出现在文章中的那些单词组合,Dbar是所有的未出现的,但是由机器生成的随机单词组合。Theta则是包含词向量的待优化参数。 实验证明,采用了新的目标函数以后,我们整个计算过程会非常快,而词向量嵌入的效果也很好。

个人工具
名字空间
操作
导航
工具箱