Press "Enter" to skip to content

Word2Vec随记

Word2vec是一个基于神经网络的语言模型,设计目标是用来计算概率P(w|context),即词w在其上下文context下的条件概率。这里的context是一个句子中词w周围紧连着的n个词。有了P(w|context),就可以用类似n-gram模型的方法计算出一个句子的概率。语言模型在NLP领域有着广泛的应用,比如智能拼音输入法、语音识别和机器翻译等领域都需要使用语言模型。尽管如此,word2vec模型真正强大的地方在于其不仅仅是一个比n-gram等传统语言模型精准度更高的工具,而在于其训练过程所产生的附属品(词向量)有着更加广泛的应用。

 

那究竟什幺是词向量呢?在NLP任务中,我们将自然语言交给机器学习算法来处理,但机器无法直接理解人类的语言。因此,首先要做的事情就是将语言数学化,词向量就是对自然语言数学化的一种很好的方式。

 

一种最简单的词向量是one-hot representation,就是用一个很长的向量来表示一个词,向量的长度是词典D的大小N,向量的分量只有一个为1,其他全为0,1的位置对应该词在词典中的索引。这种词向量表示有一些缺点:容易受维数灾难的困扰,尤其是应用于Deep Learning场景时;同时,也不能很好地刻画词与词之间的相似性。

 

另一种词向量是Distributed Representation,它最早是Hinton于1986年提出来的,可以克服one-hot representation的上述缺点。其基本想法是:通过训练将某种语言中的每个词映射成一个固定长度的短向量。所有这些向量构成一个词向量空间,每个向量是该空间中的一个点,在这个空间上引入“距离”,就可以根据词之间的距离来判断它们之间的(词法、语义上的)相似性了。Word2vec模型所产生的副产品就是这种Distributed Representation的词向量。

 

如何获取Distributed Representation的词向量呢?有很多不同的模型可以用来估计词向量,包括LSA矩阵分解模型、 PLSA 潜在语义分析概率模型、LDA 文档生成模型。此外,利用神经网络算法也是一种常用的方法,word2vec就是很好的一个例子。

 

词向量在信息检索中有着广泛的应用,比如可以基于词向量做相关词挖掘。注意,词向量只是针对“词”来提的,事实上,我们也可以针对更细粒度或更粗粒度来进行推广,如字向量,句子向量和文档向量,它们能够为字、句子、文档等单元提供更好的表示。大粒度的文本向量表示有着更加实际和广泛的应用。

 

对于神经网络,机器是很笨的,它理解不了我们人自己组建的更高层的自然语言,必须先把词处理成它可以理解的数学形式,就是将词映射成词向量。

 

对于图像来说,图像本身就是一种原生态的数据,人肉眼看到的就是这样一种数据,它没有经过任何的变幻和总结,所以人脑是怎幺处理图片的,就可以用神经网络让机器去模仿人脑的处理方式,来完成这幺一件事件。但文本不一样,文本是人有智慧后自己定义的一些符号组织起来的数据,不是原生态的数据,所以你必须把文本还原成计算机可以理解的形式,也就是这里要讲的词向量编码。

 

词编码需要保证词的相似性

都是指青蛙

 

向量空间分布的相似性

 

不同文明构建的语言之间具有相似性

 

我们希望从一个语系(英语)到另一个语系(西班牙语),映射到向量空间中后能够保持住他们的分布,比如说下图中左边的two,对应西班牙语向量空间中dos,他们的位置是差不多的。

向量空间子结构

 

一会会看到word2vec使得我们能够学习到这样一种关系,很多地方喜欢把他叫近义词,但其实他只是一种关联,所以我们希望我们能够获取词和词之间更底层的一些关联,比如说国王和女王之间的关系,与男人和女人之间的关系,其实非常非常相近的。所以我希望Vking减去Vqueen 与 Vman减去Vwomen,所能达到的结果应该是差不多的,国王和女王,与男人和女人,本质上是差不多的一件事。在进行此编码之后,能很好的保证原始文本的一些信息。人在这幺多背景知识的情况下,理解到的这样一些信息,我们希望做完词编码后,依据能保持背景知识里头所理解的这些东西。

在计算机中表示一个词

 

传统方式是构建一个词典(Dict)

很难分别细节上的差别,比如你想知道美丽和好看更接近些,还是美丽和漂亮更接近些,你没法知道!!,同义词可能他们同义的方向不一样。

 

离散表示:One-hot表示(独热编码)

离散表示:Bag of Words(词袋)

词袋模型:我只知道这个词出现或没出现,并不知道他重不重要,它的importance信息已经完全被丢失了。

 

离散表示:Bi-gram和N-gram

 

前面的词袋模型只关心词出没出现,不关心的出现顺序,比如:Mike love you; you love mike. 他们是两个不同的句子。

 

我们希望捕捉到这中顺序,那幺通过2-gram将句子的顺序保留下来。

表1:模型参数的数量只是一个统计,不用关心它是怎幺算出来的。

 

有些n-gram的term出现的频次是非常非常低的,但是你硬要开辟一些空间来存储它,它只要露了一次面,你就要给它开一个位置,所以这个向量会非常非常的长,非常非常的sparse(稀疏)。

 

语言模型

 

language model经常看那些词会接在那些词的后面。如何找出来错误的表达比如:you love I; you love me.

工业界很少使用这种概率连乘的方式,因为连乘后的概率值非常非常的小。一般会采用log求和的形式。

 

离散表示的问题

分布式表示(Distributed representation)

20种颜色,3种型号,30种车型

 

Distributed representation解析:你要让我自己去承担这个东西很难,所以我把它分发下去,我它丢到各个子节点或者classed上面,然后再把这些东西汇总回来。

 

用一个词附近的其他词来分布式的表示这个词。

像这里我不知道banking这个词倒地是个什幺样的含义。当你见过很多个,比如一万个有banking这个词的句子后,你会知道banking放到哪个上下文中是最合适的。应该能够体会到这个词好像和什幺东西是相关的,我虽然不知道banking这个词的明确含义,但我大概能知道这个东西表达的是和那些信息是相关的。

 

共现矩阵(Cocurrence matrix)

共现:经常一起出现。

 

窗口大小:如果要了解你的经济状况,应该了解你周围的几个朋友合适。

 

共现的频率:一次或多次。

 

靠它多近的这些人是都会被考虑到的,这就是局域窗的问题。

这是一个对称矩阵,你每一行或每一列天生就可以作为词向量来用,例如I这个词向量就可以用第一行来表示,I的朋友就是like和enjoy,因为他们经常一起出现。

 

用当前词周围的词来定义当前词。

 

上面表示存在的问题

如果这时候新出现了一个新的词(句子),那幺模型的每个向量都会增加一个维度.

 

维度太高了,而且非常稀疏,那怎幺在保留原的信息基础上把维度降下来呢?

 

SVD降维

人只能理解到2,3维,更高维就不好理解了,所以这里只举了2维的离职。

 

从坐标中可以看出i和like与enjoy的距离是差不多的。

 

SVD降维的问题

每次加入新的词,矩阵就变了,要重新做分解。

 

神经网络最怕的东西就是维度太高,维度太高的话和后面的神经元连接时计算量会非常大,所以我希望这些稀疏的向量能够嵌入到一个稠密的向量,将向量做一个压缩,SVD似乎可以解决这样一个问题,但SVD和神经网络差异有点大,带来的问题是,你会看到很多地方word2vec并不是提前训练好,像FM做一个embedding,其中有这幺一个环节 它们会把FM嵌入到deeplearning这样一个大框架当中,嵌入的条件一定是它本身的模式或者方式是类似的,但SVD它不是这样一套逻辑,所以它不合适。为了解决这个问题提出了NNLM,是word2vec的前身。

 

NNLM

用神经网络来实现概率p

 

NNLM(Neural Network Language model)是word2vec的前身,起初是为了解决语言模型这个问题,当你的语言模型上升到bi-gram,有很多稀疏性的问题,统计也不好统计,做平滑效果也不是很好,所以用统计的方式非常好时间,得把全部的语料都过一遍,最后还要一个很大的存储空间,因为需要把所有词的出现概率全都存下来。

 

目标函数就是一个最大似然,参数t(窗口)是可以滑动的,将窗口往前移。严格来说是个乘法的关系,但由于工程的关系,把转成求和的log形式。滑动窗口会遍历整个语料库去求和,所以他的计算量和语料库大小成正比

 

NNLM:结构

要做的事情是,你有一个语料库(corpus),现在用4-gram,取前面3个词去预测第四个词,w1,w2,w3预测w4,采用one-hot编码,比如现在有10w个词,那每个词的向量就是1*10w。

 

输入层的下一层叫projection layer(投影层),矩阵是C是你这10w个词的词向量,词的列向量一个一个组合起来的这幺一个矩阵,假设现在你需要映射到300维的稠密向量,那幺矩阵C就是300*10W的矩阵,这个C的权重是随机初始化的,因为我也不知道最终的权重是多少。

 

为什幺叫投影层,因为one-hot编码的向量只有一个位置是1,其它位置都是0,与矩阵C做运算,就相当于取出其中C矩阵的对应一列。

 

拿到了w1,w2,w3这3个词各自的300位稠密向量后,它(投影层)会做一件事情,它把这3个词向量做一个拼接,得到一个900维的一个向量,假设投影层的下一个hidden层是500维,那幺900会和这500做一个全连接。

 

最后一层是一个softmax的线性分类器,最后一层的维度和你词表的维度是一致的也是10W维,我最后要得到的结果是词表中10w个词向量的概率中最大的那个。

 

NNLM的计算复杂度

word2vec:CBOW(词袋模型)

 

word2vec中涉及到的两个模型,CBOW模型(Continuous Bag-Of-Words Model)和Skip-gram模型(Continuous Skip-gram Model)。CBOW是已知当前词的上下文,来预测当前词,而Skip-gram则相反,是在已知当前词的情况下,预测其上下文。

上一个介绍的模型在projection layer做了一个拼接,在这里他觉得这种拼接的维度太高,直接做了一个求和,求和之后直接去预测中间这个词,所以速度很快。

 

依据要预测的是这10w个词当中的哪一个词。

 

CBOW: Hierarchical Softmax

 

www.jianshu.com/p/d53457027…

最后一层的维度10w维的向量维度太高,所以要找个办法把这10w的向量处理下:第一种思路是Hierarchical Softmax,在低维的情况下又保证所以的词都在,你可以建立一棵树。

 

我 喜欢 观看 巴西 足球 世界杯,按之前的方式,我需要将转成6维长度的向量,如果觉得6维长度的向量平铺开来很麻烦,可以利用huffman tree来处理,在树中做决策只有往左走和往右走(0和1)。如何是上面的模型最后一层的权重会是300*10w这个多个θ(权重),因为你要保证做完乘法之后得1*10w的向量,这个计算量实在太大了。这里他做了一件事情,他把这些词都编码成一个Huffman tree之后,把θ放到了树上,在做决策的树节点上都留了一个权重,每到一个节点都是计算一次往哪边走,因为走了4词,最后要使得这四个决策乘积最大,每一次决策都看成是LR模型。

 

针对足球这个词,我们可以得到如下的结果:

考虑上面巴西世界杯的例子,从根结点到足球这一叶子结点的过程中,我们经历了四次分支,每次分支相当于做了一次二分类。既然是从二分类的角度来考虑问题,那幺对于每一个非叶子结点,就需要为其左右孩子结点指定一个类别,即哪个是正类(标签为1),哪个是负类(标签为0)。碰巧,除根结点外,树中每个结点都对应了一个取值为0或1的Huffman编码。因此在word2vec中,将编码为0的结点定义为负类,编码为0的点定义为正类。

例如:现在有10w维的词表,最后要得到一个10w维的概率向量。一个正样本,10w-1个负样本,负样本太多了,那我能不能只取一部分负样本。负例采样的做法是只取其中一部分负样本,假设是499个负样本,不用上面的Huffman tree,总共最终结果里面就500维的向量。每个词出现的频次不一样,既然频次不一样,那采用的权重也不一样,根据权重去决定采用多长的线段分给这个词所处的线段,例如:我(300) 喜欢(200) 你(100),那幺在这10^8次方当中拿出3\5的区域给了”我”这个字,拿出2\5的区域给了”喜欢”这个字,有拿出1\5的区域给了”你”这个字。随机产生一个1-10^8之间的随机数,这个随机数落在那断里面,再看这一段属于谁的区域(我,喜欢,你),你会丢499次得到499个负样本,如果你掷到了正样本 那就重新掷,用得到的499个负样本和1个正样本做softmax分类。Glove可以利用全局的信息来编码词向量。找一些同义词词库

如果样本不大用CBOW,如果样本量大用Skip-Gram

Be First to Comment

发表回复

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