关于Word2Vec的一些总结

什么是word2vec

关于word2vec,首先需要弄清楚它并不是一个模型或者DL算法,而是描述从自然语言到词向量转换的技术。
Word2Vec本质上就是一个只有一个hidden layer的全连接神经网络,它可以将所有的词向量化,这样词与词就可以定量的去度量他们之间的关系.

在NLP中,把x看做一个句子里的一个词语,y是这个词语的上下文词语,那么这里的$f$便是nlp中经常出现的语言模型,这个模型的目的就是判断样本$(x,y)$是否符合自然语言语法规则.
word2vec并不在乎$f$训练的有多完美,而是只关心模型训练结束后模型参数(这里就是神经网络的参数),并将这些参数作为输入x的向量化表示,也就是词向量.
后面会介绍为什么是这样.

词向量

自然语言处理系统通常将词汇作为离散的单一符号,例如”cat”一词也可以表示为ID666,而”dog”一词表示为ID888.但是我们可以发现这些符号编码毫无规律,无法提供不同词汇之间可能存在的关联信息.也就是”dog”和”cat”都是动物,四条腿啊..等等,但是通过我们的单一符号却根本无法体现出他们之间的关系.可见,将词汇表达为上述的独立离散符号将进一步导致数据稀疏,使我们在训练统计模型时不得不寻求更多的数据。而词汇的向量表示将克服上述的难题。
在word2vec出现之前,最简单常用的词向量技术就是one-hot encoder,它使用的词向量维度为整个词汇表大小,将所有的词按照特定顺序固定,对于每个词汇表中的单词,其对应位置为1其余为0.如图:

可以发现这种方法是很稀疏的,其次词汇表一般很大,这也导致我们向量的维度很大,带来内存灾难.于是就产生了连续向量表示,也就是用实数向量来表示一个单词啥的,比如100维,这就大大降低了维度,同时还能蕴含语义信息,词之间的相似度等等…
举个例子,给出一个文档,文档就是一个单词序列比如 “A B A C B F G”, 希望对文档中每个不同的单词都得到一个对应的向量(往往是低维向量)表示。比如,对于这样的“A B A C B F G”的一个序列,也许我们最后能得到:A对应的向量为[0.1 0.6 -0.5],B对应的向量为[-0.2 0.9 0.7] (此处的数值只用于示意),这个向量就是我们说的word embedding。

这里需要说明下word2vec和word embedding的区别和联系: word embedding是一个将词向量化的概念,而word2vec是谷歌提出的一种基于word embedding的工具或算法集合.

Word2Vec

word2vec是基于分布假设,认为上下文环境相同的词语其语义也相似.,主要的方法有两种:CBOW和skip-gram.
Word2vec能将one-hot Encoder转化为低维度的连续值,也就是稠密向量,具有相似语义的单词的向量之间距离会比较小,部分词语之间的关系能够用向量的运算表示.

Word2Vec的优势

1.低维稠密
一般来说分布式词向量的维度设置成100-500就足够使用,而one-hot的词向量维度与词表的大小成正比,是一种高维稀疏的表示方法,这种表示方法导致其在计算上有比较低的效率.

2.蕴含语义信息
one-hot这种表示方式使得每一个词映射到高维空间都是相互正交的,也就是说one-hot向量空间中词与词之间没有任何联系,或者说我们无法通过词向量来判断出他们之间是否有联系.word2vec利用”分布假设,具有相同上下文信息的词语语义相近”,使得语义相近的词映射在欧式空间后具有较高的余弦相似度.(至于为什么是余弦相似度,下面你了解一下网络结构就会发现本质是网络中存在向量间的內积)

Word2Vec的结构

上面我们提到过word2vec本质上是只有一个隐藏层的全连接神经网络,如图:

1.输入为One-Hot Encoder
2.隐藏层激活函数为线性的
3.输出层使用的是softmax

CBOW(Continuous Bag-Of-Words)

CBOW模型是通过中心词的上下文来预测该中心词.
那么这个模型的输入输出是如何得到的呢?
CBOW模型的训练输入是某一个特征词的上下文相关的词对应的词向量,而输出就是这特定的一个词的词向量.比如下面这段话,我们上下文大小为4,特定的这个词是”Learning”,也就是我们需要的输出向量.那么上下文词应该有8个,前后4个,这8个词就是我们模型的输入.
由于CBOW使用的是词袋模型,因此这8个词都是平等的,也就是不考虑他们和我们关注的词之间的距离大小,只要在我们上下文之内即可
如图:

这样我们就得到了我们模型的输入输出,输入是8个上下文词向量,输出是所有词的softmax概率(我们希望我们的特定中心词的概率最大),对应的CBOW模型输入层有8个神经元,输出有词汇表大小个神经元,隐藏层个数我们自己指定.

CBOW的结构

假设这里我们将词embedding到n维,设词汇表维度为$|V|$
1.输入层: $2c$个节点,上下文共 $2c$个词的n维向量,注意一开始为随机初始化
2.隐藏层: n个节点,上下文共$2c$个词的词向量相加后取平均值
3.隐藏层到输出层的权重$W_0$: 维度$|V| \times n$
4.输出层:|V|个节点.采用softmax回归.
对于这里来说输入层的就是输入的词向量,我们看到,输入层每个周围词用n个节点表示,n就是词向量的大小,一开始随机初始化,在之后作为模型参数学习更新,最终得到合适的词向量。在gensim 和 google的 word2vec实现中,也是这样的结构,就是输入层初始化的时候直接为每个词随机生成一个n维的向量,并且把这个n维向量作为模型参数学习,最终得到该词向量。

另一种结构

1.输入层: $2c$个词的one-hot 编码,每个的维度为$|V|$
输入层到隐藏层的权重$W_0$的维度:$|V| \times n$
2.隐藏层: $n$个节点,上下围共$2c$个词的one-hot编码和$W_0$相乘得到的词向量求和再取平均值.
隐藏层到输入层的权重$W_1$的维度$|V| \ times n$
3.输出层$|V|$个节点,采用softmax.

然后词向量就是神经网络的权重,生成词向量的过程就是使用训练数据使模型变优的一个参数更新的过程.某个词的one-hot编码可以看成是$|V| \times 1$的向量与$n \times |V|$的权重矩阵$W_0$相乘,因为one-hot中只有一个1,所以可以看成它只是激活了$W_0$中的特定列,那么该列就可以看成是该词的一个词向量.对于隐藏层到输出层的权重$W_1$同理,所以这里$W_0$和$W_1$我们分别叫做输入向量和输出向量,它们两个本质上没什么区别,我们一般使用输入向量.

skip-gram模型

skip-gram模型和CBOW的思路是相反的,CBOW是根据上下为来预测中心词,skip-gram模型是根据中心词来预测上下文.即输入是特定词,输出是softmax概率排前8的几个词,对应的skip-gram神经网络模型的输入层有1个神经元,输出层有词汇大小个神经元.隐藏层的个数还是我们自己指定.
例如: 句子为“the quick brown fox jumped over the lazy dog”(实际语料库中单词的数量会很非常大),当上下文窗口为1时,skip-gram的任务是从”quick”预测”the”和”brown”,从”brown”预测”quick”和”fox”,从”fox”预测…因此训练skip-gram的输入输出对(input,output)为:(quick,the),(quick,brown),(brown,quick),(brown,fox)…
在结构上和CBOW一样,也是两种角度,其中对应CBOW的第二种:

我们知道,Word2vec 本质上是一个语言模型,它的输出节点数是 V 个,对应了 V 个词语,也是一个多分类问题,但实际当中,词语的个数非常非常多,直接softmax来计算会给计算造成很大困难,所以需要用技巧来加速训练,下面就介绍word2vec对应的两个加速技巧hierarchical softmax和negative sampling。注意:这两个技巧只是加速训练的技巧

基于Hierarchical Softmax的模型概述

对于原始的模型来说,里面最大的问题在于从隐藏层到输出的softmax层的计算量很大,因为要计算所有词的softmax概率,再去找概率最大的值.为了避免要计算所有词的softmax概率,word2vec采用了哈夫曼树(关于什么是哈夫曼树,如何构建哈夫曼树,这里不做介绍)来代替从隐藏层到输出softmax层的映射.由于我们把之前所有都要计算的输出层softnax层的概率计算变成了一个二叉哈夫曼树,那么我们的softmax概率计算只需要沿着树形结构进行就可以了,如下图,我们可以沿着哈夫曼树从根节点一直走到我们的叶子节点的词$w_2$.

和之前的模型相比,我们的哈夫曼树的所有内部节点就类似之前隐藏层神经元,其中根节点的词向量对应我们的投影后的词向量,而所有叶子节点就类似于之前神经网络softmax输出层的神经元,叶子节点的个数就是词汇表的大小.在哈夫曼树中,隐藏层到输出层的softmax映射不是一下子完成的,而是沿着哈夫曼树一步步完成的,因此这种softmax取名为”Hierarchical Softmax”。

具体过程

在word2vec中,采用二元逻辑回归的方法,即规定沿着左子树走就是负类(哈夫曼树编码为1),沿着右子树走为正类(哈夫曼树编码为0).判断正负类的方法是sigmoid的函数,即:

其中$x_w$是当前内部节点的词向量,而$\theta$则是我们需要从训练样本求出的逻辑回归的模型参数。
由于是二叉树,所以计算量由原来的$|V|$变为了$log|V|$,而且使用哈夫曼树使得高频的词靠近词根,这样高频词需要更少的时间会被找到.
容易理解,被划分为左子树而成为负类的概率为$P(−)=1−P(+)P(−)=1−P(+)$。在某一个内部节点,要判断是沿左子树还是右子树走的标准就是看$P(−),P(+)P(−),P(+)$谁的概率值大。而控制$P(−),P(+)P(−),P(+)$谁的概率值大的因素一个是当前节点的词向量,另一个是当前节点的模型参数$\theta$。
对于上图中的$w_2$,如果它是一个训练样本的输出,那么我们期望对于里面的隐藏节点$n(w_2,1)$的$P(−)$概率大,$n(w_2,2)$的$P(−)$概率大,$n(w_2,3)$的$P(+)$概率大。
回到基于Hierarchical Softmax的word2vec本身,我们的目标就是找到合适的所有节点的词向量和所有内部节点$\theta$, 使训练样本达到最大似然。那么如何达到最大似然呢?

梯度计算

我们使用最大似然法来寻找所有节点的词向量和所有内部节点$\theta$.先拿上面$w_2$的例子来说,我们期望最大化下面的似然函数:

对于所有的训练样本,我们期望最大化所有样本的似然函数乘积。

基于Hierarchical Softmax的CBOW模型

首先我们要定义词向量的维度大小$M$,以及CBOW的上下文大小$2c$,这样我们对于训练的每一个词,其前面的$c$个词和后面的$c$个词作为了CBOW模型的输入,该词本身作为了输出,期望softmax概率最大.
在做CBOW模型前,我们要先将词汇表建立成一颗哈夫曼树.
对于从输出层到隐藏层的投影,这一步比较简单,就是对$w$周围的$2c$个词向量求和平均即可,即:

第二步根据梯度下降法来更新参数$\theta_{j-1}^w$和$x_w$,注意这里$x_w$是由$2c$个词向量相加而成,我们做梯度更新完毕后会用梯度直接更新原始的各个$x_i$,即:

基于Hierarchical Softmax的skip-gram模型

这里包括上面不清楚的都可以参考刘建平的blog

基于Negative Sampling的模型

上面所说的层级softmax虽然可以将$O(|V|)$的softmax变为$log|V|$的二分类问题,但是当我们的中心词$w$是一个很生僻的词,那么就得在哈夫曼树中辛苦向下走很久了.

什么是负采样呢?

比如我们有一个训练样本,中心词是$w$,它周围有上下文共$2c$个词,记为$context(w)$.由于这个中心词$w$,的确和$context(w)$相关存在,因此它是一个真正的正例.通过negative sampling采样,我们得到neg个和$w$不同的中心词$w_i, i=1,2,..neg$,这样$context(w)$和$w_i$就组成了$neg$个不真实存在的负例.利用这一个正例和$neg$个负例,我们进行二元逻辑回归,得到负采样对应的每个词$w_i$对应的模型参数$\theta_i$和每个词的词向量.

梯度计算

Negative Sampling 也是采用了二元逻辑回归来求解模型参数,通过负采样,我们得到了neg个负例$(context(w),w_i),i = 1,2,3,…neg$ 为了统一描述,我们将正例定义为$w_0$
在逻辑回归中我们的正例应该期望满足:

我们的负例期望满足:

我们期望可以最大化下式:

利用逻辑回归和上一节的知识,我们容易写出此时模型的似然函数为:

对应的对数似然函数为:

和Hierarchical Softmax类似,我们采用随机梯度上升法,仅仅每次只用一个样本更新梯度,来进行迭代更新得到我们需要的$x_{w_i},\theta^{w_i},i = 0,1,…neg$.

Negative Sampling 负采样方法

现在我们来看看如何进行负采样,得到neg个负例。word2vec采样的方法并不复杂,如果词汇表的大小为V,那么我们就将一段长度为1的线段分成V份,每份对应词汇表中的一个词。当然每个词对应的线段长度是不一样的,高频词对应的线段长,低频词对应的线段短。每个词w的线段长度由下式决定:

在word2vec中,分子和分母都取了3/4次幂如下:

在采样前,我们将这段长度为1的线段划分成$M$等份,这里$M>>V$,这样可以保证每个词对应的线段都会划分成对应的小块。而M份中的每一份都会落在某一个词对应的线段上。在采样的时候,我们只需要从MM个位置中采样出negneg个位置就行,此时采样到的每一个位置对应到的线段所属的词就是我们的负例词。

在word2vec中,$M$取默认值为$10^8$

基于Negative Sampling的CBOW模型和skip-gram

具体请参考刘建平

word2vec词向量性质观察

查看某个词在embedding里的最近邻居可以看到单词间的语义接近关系,将vector构成的空间降维,可以高效地查找最近单词,但降维过程中要保持邻居关系(用哪种降维方法?),比如我们可以把学习向量映射到2维中以便我们观察,其中用到的技术可以参考 t-SNE 降纬技术。当我们第一次发现这样的诱导向量空间中,展示了一些特定的语义关系,这是非常有趣的,比如文字中 _male-female_,_gender_ 甚至还有 _country-capital_ 的关系, 如下方的图所示

另外,我们能得到的不仅是单词的邻接关系,由于将单词向量化,可以对单词进行计算可以通过计算进行语义加减,语法加减。

好的资料

全面理解word2vec
一步一步理解word2Vec
王喆
达观数据
刘建平
《Efficient estimation of word representations in vector space》


-------------本文结束感谢您的阅读-------------


本文标题:关于Word2Vec的一些总结

文章作者:Statusrank

CSDN博客欢迎来访!

发布时间:2019年01月13日 - 13:01

最后更新:2019年01月14日 - 11:01

原始链接:https://statusrank.xyz/articles/b43ed602.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

万水千山总是情,就给五毛行不行!