本文目录一览:
Word2Vec教程-Skip-Gram模型
原文: Word2Vec Tutorial - The Skip-Gram Model
skip-gram实际上是非常简单的神经网络模型形式;我认为任何所有微小的调整和变化都会使解释困扰。
我们进一步看,你可能在机器学习使用Word2Vec时用到下面一个技巧:使用一个隐藏层的简单神经网络来执行某个任务,但是接下来我们将不会在训练模型任务时使用那样的神经网络,而是仅仅是使用它来学习隐层神经网络的权重,在Word2Vec中指的是“词向量”。
现在我们需要讨论一下这种“伪”任务,我们要构建并运行神经网络,然后我们间接地获得到的后面所需的词向量。
我们要训练skip-gram神经网络做以下任务:给出一个句子中间的某个单词(输入词),观察输入单词旁边的单词并随机选择一个。而我们训练的神经网络将告诉我们词汇表中每个单词被选作为“邻近单词”(nearby word)的概率。
输出概率与输入单词与每个词汇表单词邻近程度相关。举例来说,训练的神经网络的输入单词为“苏联”,那么像“联盟”和“俄罗斯”的输出概率将会远大于像“西瓜”和“袋鼠”不相关单词的概率。
我们将通过“喂养”在训练文档中找到的“单词对”(word pair)来训练神经网络。下面的例子显示了一些训练样本(单词对),句子为“The quick brown fox jumps over the lazy dog.”,窗口大小为2,蓝色突出显示的是输入单词。
思考下,这些单词应该怎么被表示哪?
首先,我们不能够将单词作为一个字符串输入到神经网络,所以我们需要一种方式去表示单词。为了达到目的,我们从训练文档中创建一个单词词汇表,假如我们现在有一个具有10000个不同单词的词汇表。
我们将输入单词比如“蚂蚁”(ants)表示为一个one-hot向量,这种向量有10000个元素(词汇表中的每个单词都被表示为这种形式)。1 的位置对应该词在词典中的位置,其他全为0。
下面是我们神经网络的结构:
在隐藏层中没有使用激活函数,而在输出层使用了softmax,我们稍后在讨论这个原因。
假如,我们要学习有关词向量的300个特征(比如词性,语义等等),那么隐藏层结构将会表示为一个权重矩阵:10000行(代表着词汇表中的每个单词)和300列(代表每一个隐层的神经单元)。
现在你可能反问自己,-“one hot向量几乎全部是0,那么它的作用是什么呢?”如果你将一个1×10000 one hot向量乘以10000×300的矩阵,那么就会有效地选中矩阵中与1对应的行。下面是一个例子:
这就意味着模型中的隐藏层其实运作为一个单词查找表,隐藏层的输出为输入单词的“词向量”。
隐藏层产生的 1×300 的词向量将会传送到输出层,这个输出层是一个softmax regressio分类器,其要领就是每一个输出神经单元将会产生一个介于0到1的输出,并且所有输出值的和为1。
每个输出单元有一个权重矩阵,然后与来自隐藏层的词向量相乘,然后对结果运用 exp(x) 函数。最后,为了将输入结果加起来为1,我们将结果除以10000个输出节点的所有之和。
下面是单词“car”输出单元的计算。
到这里,我们来进一步了解下skip gram model。如果有两个不同的单词非常相似的“上下文”(就是,出现在这个两个单词周围的词语非常相似),对于这两个单词模型会输出非常相似的结果。如果两个单词的词向量非常相似,那么模型预测输出来的上下文也将是非常相似。
什么是所谓的两个单词有非常相似的上下文?我猜你想到近义词,比如“intelligent”和“smart”。或者是单词是非常相关的,比如“transmission”和“engine”
你可能注意到 skip-gram 神经网络将包含一个非常大的weights向量。例如,一个带有300个特征,含有10000词的词汇表,那么在隐藏层和输出增将会产生3百万维的weights向量。在如此巨大的数据集训练代价将会是非常高的,接下来我们将会讲下word2vec作者优化的措施
【Word2Vec Resources】
Word2Vec教程-Negative Sampling 负采样
word2vec 之 skip-gram
Word2vec 主要有两种形式,CBOW 和Skip-gram,其中CBOW是通过上下文context来预测当前位置词,SKip-gram则是通过当前词来预测上下文
Fake Task
word2vec 实际上分为两部分,1,建立模型,2,通过模型获取词的嵌入向量(隐层参数)。整个过程与自编码器的思想类似,即基于训练数据训练一个神经网络,模型训练好后,并不会用这个模型处理后续的任务,真正需要的是这个模型学到的参数,如隐层的权重矩阵,基于训练数据建模的过程叫“Fake Task”,意味着建模并不是我们最终的目的。
Train
如何训练我们的神经网络模型?假如我们有一个句子“ The dog barked at the mailman”。
首先,我们选择句子中一个词作为我们的input word, 如 dog
然后,我们需要定义一个skip_window参数,来指定上下文的大小,即input word 一侧选取词的数量,假如skip_window=2,那将从dog出发向左右两个方向取最近的两个word,即(the, dog,barked,at),此时的span = skip_window * 2 + 1 = 5
另一个需要定义的参数是num_skips,即从上下文中选取多少个word来作为output word,这个参数应该小于等于2 * skip_window,即最多将所有上下文都作为output,但是不能重复。如设置num_skips = 2,此时从上下文选取2个词作为output,如(the, barked),最终我们将得到两组训练数据(dog, the) (dog, barked)
神经网络将基于这些训练数据输出一个概率分布,这个概率分布代表着在输入数据下,词典中每个词是output的概率。如拿数据(dog, barked)来训练,则模型将会告诉我们每个单词是’barked’的概率大小。
模型的输出概率代表着词典中每个单词有多大可能性跟input word同时出现。举个栗子,如果我们向神经网络模型中输入一个单词“Soviet“,那么最终模型的输出概率中,像“Union”, ”Russia“这种相关词的概率将远高于像”watermelon“,”kangaroo“非相关词的概率。因为”Union“,”Russia“在文本中更大可能在”Soviet“的窗口中出现。
我们将通过给神经网络输入文本中成对的单词来训练它完成上面所说的概率计算。下面的图中给出了一些我们的训练样本的例子。我们选定句子“The quick brown fox jumps over lazy dog”,设定我们的窗口大小为2(window_size = 2),也就是说我们仅选输入词前后各两个词和输入词进行组合。下图中,蓝色代表input word,方框内代表位于窗口内的单词。
模型将会从每队单词出现的次数中习得统计结果,模型可能会得到更多的(’soviet’, ‘union’)样本对,而(soviet, dog)这样的组合看到的很少。因此,当模型训练完成后,给定一个单词 soviet,输出结果中union 或者russia会比dog有更高的概率。
输入
常用做法是用训练文档构建词汇表,然后再对单词进行0ne-hot编码。
编码后的向量,形如dog = [0, 0, 1, 0, …0], 如果词汇表大小为10000, 那这个向量包含了10000的概率,即为当前词为输入的概率
下图是神经网络结构:
我们基于成对的单词来对神经网络进行训练, 训练样本是(input word, output word)这样的单词对,input word 和 output word都是one-hot编码的向量,最终的模型输出是一个概率分布。
隐层
如果我们想要用300个特征来表示一个词(即每个词是300维的向量),即隐层有300个神经元,隐层的权重为10000 * 300的矩阵,下图中的左右两个图代表了不同角度看隐层权重,左图中每列代表一个10000维的词向量与隐层单个神经元的连接权重,右图每行代表了一个单词的词向量。
我们最终的目标就是学习这个隐层权重矩阵。
输入被one-hot编码后,实际上只有一个位置不为0,所以这个向量相当稀疏,那如果我们将1 10000的向量与10000 300的矩阵相乘,相当消耗计算资源,为了高效计算,仅仅会选择矩阵中对应的向量中纬度为1的索引行
即实际不会进行矩阵乘法计算,而是根据输入向量中不为0 的维度去索引。这样模型中的隐层权重矩阵便成了一个查找表(lookup table),输出就是输入单词的嵌入词向量
输出层
隐层的输出是一个1*300的向量,而输出层是一个softmax回归分类器,他的每个结点将会输出一个0-1之间的值(概率),而结点的概率之和为1.
我们会发现Word2Vec模型是一个超级大的神经网络(权重矩阵规模非常大)。
举个栗子,我们拥有10000个单词的词汇表,我们如果想嵌入300维的词向量,那么我们的输入-隐层权重矩阵和隐层-输出层的权重矩阵都会有 10000 x 300 = 300万个权重,在如此庞大的神经网络中进行梯度下降是相当慢的。更糟糕的是,你需要大量的训练数据来调整这些权重并且避免过拟合。百万数量级的权重矩阵和亿万数量级的训练样本意味着训练这个模型将会是个灾难(太凶残了)。
Word2Vec的作者在它的第二篇论文中强调了这些问题,下面是作者在第二篇论文中的三个创新:
事实证明,对常用词抽样并且对优化目标采用“negative sampling”不仅降低了训练过程中的计算负担,还提高了训练的词向量的质量。
word pairs and phases
一些单词组合的含义和拆开以后具有完全不同的意义,比如 New York,单独的New 和York无法表达这个词组的含义。因此,应该把New York作为一个单独的词组来生成其词向量。
对高频词抽样
对于高频词,如 the ,按上面的处理方式会有两个问题:
如果直接删除掉这些高频词,会有两个问题
1.删除后,the这个单词永远也不会出现在我们的上下文窗口
2.训练样本会减少
所以word2vec 采用抽样的方式来解决这种高频词问题。他的基本思想是:对于我们在训练原始文本中遇到的每一个单词,他们都有一定概率被我们从文本中删除掉,而这个被删除的概率与单词的频率有关。
wi 是一个单词,Z(wi)是这个单词在所有预料中出现的频次。P(wi)是被保留的概率。
负采样
训练一个神经网络意味着要输入训练样本并且不断的调整神经元的权重,不断提高对目标的准确预测。而vocabulary的大小决定了skip-gram神经网络将拥有大规模的权重矩阵,所有的这些权重需要通过我们数以亿计的样本来训练调整,非常消耗计算资源,并且实际中会非常慢。
负采样解决了这个问题,不同于原本每个训练样本更新所有权重,负采样每次让一个训练样本仅仅更新一部分权重,减小计算量。
对于训练样本(fox,quick),都是经过one-hot编码的,当vocabulary的大小为10000时,我们期望输出对应的quick单词的那个神经元的输出是1,其余9999个都是0,这9999个输出为0的神经元所对应的单词称为negative word
隐层-输出层拥有300 10000的权重,而负采样时,我们仅仅更新quick 和我们选择的其他5个negative word的结点对应的权重,共6个神经元,300 6 = 1800 个权重,相当于只计算了0.06%的权重,计算效率大大提高。
其中f(wi)代表每个单词出现的频次,p(wi)代表被选中的概率。
负采样的C语言实现非常的有趣。unigram table有一个包含了一亿个元素的数组,这个数组是由词汇表中每个单词的索引号填充的,并且这个数组中有重复,也就是说有些单词会出现多次。那么每个单词的索引在这个数组中出现的次数该如何决定呢,由公式P(wi) * table_size,也就是说计算出的负采样概率*1亿=单词在表中出现的次数。
有了这张表以后,每次去我们进行负采样时,只需要在0-1亿范围内生成一个随机数,然后选择表中索引号为这个随机数的那个单词作为我们的negative word即可。一个单词的负采样概率越大,那么它在这个表中出现的次数就越多,它被选中的概率就越大。
Word2Vec原理详解
自然语言是一套用来表达含义的复杂系统。在这套系统中,词是表义的基本单元。顾名思义,词向量是用来表示词的向量,也可被认为是词的特征向量或表征。把词映射为实数域向量的技术也叫词嵌入(word embedding)。近年来,词嵌入已逐渐成为自然语言处理的基础知识。
跳字模型假设基于某个词来生成它在文本序列周围的词。举个例子,假设文本序列是“the” “man” “loves” “his” “son”。以“loves”作为中心词,设背景窗口大小为2。如图1所示,跳字模型所关心的是,给定中心词“loves”,生成与它距离不超过2个词的背景词“the” “man” “his” “son”的条件概率,即
假设给定中心词的情况下,背景词的生成是相互独立的,那么上式可以改写成
虽然开篇说了one-hot不行,但是我们不要忽略一个事实,计算机没办法识别“字符”,所有的数据必须转化成二进制的编码形式。
大家已经注意到,我们已经到了Hidden Layer到Output Layer这一层了,简单来看就是隐藏层和输出层进行全连接,然后是一个softmax,输出概率。过程比较简单,一个Forward Propagation,一个Backward Propagation。
在跳字模型中,每个词被表示成两个 维向量,用来计算条件概率。假设这个词在词典中索引为 ,当它为中心词时向量表示为 ,而为背景词时向量表示为 。设中心词 在词典中索引为 ,背景词 ,在词典中索引为 ,给定中心词生成背景词的条件概率可以通过对向量内积做softmax运算而得到:
其中词典索引集 。假设给定一个长度为 的文本序列,设时间步 的词为 。假设给定中心词的情况下背景词的生成相互独立,当背景窗口大小为 时,跳字模型的似然函数即给定任一中心词生成所有背景词的概率
这里小于1和大于 的时间步可以忽略。
这样就可以计算出每个中心词推断背景词的概率,而我们在输入的时候给出了背景词的向量,此时只需要最大化背景词的输出概率即可。 基于这样的想法,我们会想到极大化似然估计的方式。但是一个函数的最大值往往不容易计算,因此,我们可以通过对函数进行变换,从而改变函数的增减性,以便优化。这等价于最小化以下损失函数:
最小化损失函数,我们最容易想到的就是梯度下降法。在使用梯度下降法之前,我们要把我们的损失函数定义出来,毕竟上面的式子是一个概率,下面把softmax的计算结果带入得到:
损失函数已经得到了,我们的目标就是最小化它,优化它之前我们要搞清楚我们的参数是谁?每错,我们的参数是中心词和背景词,那对于这样的一个函数显然是非凸函数,因此,我们要做一个假设,假设在对中心词权重更新时,背景词的权重是固定的,然后在以同样的方式来更新背景词的权重。
这里就计算出来了中心词的梯度,可以根据这个梯度进行迭代更新。对于背景词的更新是同样的方法,
当 时,即通过中心词 我们可以正确预测上下文词 时,不需要调整 ,反之,则相应调整 。
但是要注意背景词的个数不是唯一的,所以更新的时候要逐个更新,幅图辅助理解。
连续词袋模型与跳字模型类似。与跳字模型最大的不同在于,连续词袋模型假设基于某中心词在文本序列前后的背景词来生成中心词。在同样的文本序列“the” “man” “loves” “his” “son”里,以“loves”作为中心词,且背景窗口大小为2时,连续词袋模型关心的是,给定背景词“the” “man” “his” “son”生成中心词“loves”的条件概率(如图2所示),也就是
因为连续词袋模型的背景词有多个,我们将这些背景词向量取平均,然后使用和跳字模型一样的方法来计算条件概率。设 和 分别表示词典中索引为 的词作为背景词和中心词的向量(注意符号的含义与跳字模型中的相反,假设输入向量为 ,输出向量为 )。设中心词 在词典中索引为 ,背景词 在词典中索引为 ,那么给定背景词生成中心词的条件概率
为了让符号更加简单,我们记 ,且 ,那么上式可以简写成
给定一个长度为 的文本序列,设时间步t的词为 ,背景窗口大小为 。连续词袋模型的似然函数是由背景词生成任一中心词的概率
训练连续词袋模型同训练跳字模型基本一致。连续词袋模型的最大似然估计等价于最小化损失函数
注意到
通过微分,我们可以计算出上式中条件概率的对数有关任一背景词向量 的梯度
中心词的梯度同理可得,
同跳字模型不一样的一点在于,我们一般使用连续词袋模型的背景词向量作为词的表征向量。
Word2vec原理详细解读
Softmax函数:
哈夫曼树(Huffman Tree)
从图1可以看出Skip-gram就是用当前中心词 (banking)预测附近的词,图1中将窗口大小设为2,即需要预测左边的2个词和右边的2个词。
对于每个位置 ,预测窗口大小为 的上下文,设当前中心词为 ,那么目标为最大化:
(1)
其中 为模型的参数。
为了将最大化转为最小化,可对 取负数,为了简化计算,可取对数:
(2)
现在问题的关键是如何计算 ,我们使用两个向量表示: 为中心词的表示, 为上下文词的表示。那么,计算中心词 c 和上下文词 o 的出现概率为:
(3)
其中,V为整个词表大小, 为中心词向量表示。其实式3就是softmax函数。
图2展示了Skip-gram的计算过程,从图中可以看出Skip-gram预测的是 , , ,由于只预测前后两个单词,因此窗口大小为2。
输入层到隐藏层 :输入层的中心词 用one-hot向量表示(维度为V*1,V为整个词表大小),输入层到隐藏层的权重矩阵为中心词矩阵W(维度为V*d,d为词向量维度),设隐含向量为 (维度为d*1),那么:
(4)
隐藏层到输出层: 隐藏层到输出层的上下文权重矩阵为U(维度为d*V),输出层为y(维度为V*1),那么:
(5)
注意 ,输出层的向量 y 与输出层的向量 虽然维度一样,但是 y 并不是one-hot向量,并且向量 y 的每一个元素都是有意义的。如,假设训练样本只有一句话”I like to eat apple”,此时我们正在使用eat去预测to,输出层结果如图3所示。
向量y中的每个元素表示用 I、like、eat、apple 四个词预测出来的词是对应的词的概率,比如是like的概率为0.05,是to的概率是0.80。由于我们想让模型预测出来的词是to,那么我们就要尽量让to的概率尽可能的大,所以我们将式子(1)作为最大化函数。
Continuous Bag-of-Words(CBOW),的计算示意图如图4所示。从图中可以看出,CBOW模型预测的是 ,由于目标词 只取前后的两个词,因此窗口大小为2。假设目标词 前后各取 个词,即窗口大小为 ,那么CBOW模型为:
(6)
输入层到隐藏层: 如图4所示,输入层为4个词的one-hot向量表示,分别为 , , , (维度都为V*1,V为整个词表大小),记输入层到隐藏层的上下文词的权重矩阵为W(维度为V*d,d是词向量维度),隐藏层的向量h(维度为d*1),那么:
(7)
这里就是把各个上下文词的向量查找出来,再进行简单的加和平均。
隐藏层到输出层: 记隐藏层到输出层的中心词权重矩阵为U(维度d*V),输出层的向量y(维度V*1),那么:
(8)
注意 ,输出层的向量 与输入层的 虽然维度一样,但是 并不是one-hot向量,并且向量 的每个元素都是有意义的。CBOW的目标是最大化函数:
(9)
由于softmax的分母部分计算代价很大,在实际应用时,一般采用层次softmax或者负采样替换掉输出层,降低计算复杂度。
层次softmax(Hierarchical Softmax)是一棵哈夫曼树,树的叶子节点是训练文本中所有的词,非叶子节点是一个逻辑回归二分类器,每个逻辑回归分类器的参数都不同,分别用 表示,假定分类器的输入为向量h,记逻辑回归分类器输出的结果为 将向量h传递给节点的左孩子概率为 ,否则传递给节点的右孩子概率为 。重复这个传递流程直到叶子节点。
从图5和图6可以看出,我们就是将隐藏层的向量h直接传递到了层次softmax,层次softmax的复杂度为O(log(V)),层次softmax采样到每个词的概率如下:
对于CBOW或者skip-gram模型,如果要预测的词是to,那么我们就让 尽量大,所以我们将任务转换成训练V-1个逻辑分类器。CBOW模型和skip-gram模型训练目标函数和之前形式一样,为:
(10)
(11)
负采样实际上是采样负例来帮助训练的手段,其目的与层次softmax一样,是用来提升模型的训练速度。我们知道,模型对正例的预测概率是越大越好,模型对负例的预测概率是越小越好。负采样的思路就是根据某种负采样的策略随机挑选一些负例,然后保证挑选的这部分负例的预测概率尽可能小。所以,负采样策略是对模型的效果影响很大,word2vec常用的负采样策略有均匀负采样、按词频率采样等等。
以“I like to eat apple”为例子,假设窗口的大小是2,当中心词为like时,即我们会用 I to 来预测like,所以在这里我们就认为(I,like)和(to,like)都是正例,而(I,apple)、(to,apple)就是负例,因为(I,apple)、(to,apple)不出现在当前正例中。用NEG(w)表示负样本,有:
(12)
(13)
这里的 是词*的中心词向量表示,h为隐藏层的输出向量。我们只需要最大化目标函数:
(14)
这个损失函数的含义就是让正例概率更大,负例的概率更小。
以“I like to eat apple”为例子,假设窗口的大小是1,即我们会用 like 来预测 I to,所以在这里我们就认为(like,I)和(like,to)都是正例,而(like,apple)就是负例,因为(like,apple)不会出现在正例中。那么,对于给定的正样本(w,context(w))和采样出的负样本(w,NEG(w)),有:
(15)
(16)
这里的 是词*的中心词向量表示,h为隐藏层的输出向量。我们只需要最大化目标函数:
(17)
word2vec常用的负采样策略有均匀负采样、按词频率采样等等。比较常用的采样方法是一元分布模型的3/4次幂。该方法中,一个词被采样的概率,取决于这个词在语料中的词频 ,其满足一元分布模型(Unigram Model).
(18)
其中V为整个词表大小, 为词 的词频。
至于为什么选择3/4呢?其实是由论文作者的经验所决定的。
假设由三个词,,”我“,”和平“,”觊觎“ 权重分别为 0.9 ,0.01,0.003;经过3/4幂后:
我: 0.9^3/4 = 0.92
和平:0.01^3/4 = 0.03
觊觎:0.003^3/4 = 0.012
对于”觊觎“而言,权重增加了4倍;”和平“增加3倍;”我“只有轻微增加。
可以认为:在保证高频词容易被抽到的大方向下,通过权重3/4次幂的方式, 适当提升低频词、罕见词被抽到的概率 。如果不这么做,低频词,罕见词很难被抽到,以至于不被更新到对应的Embedding。
QuestionAnswer
Question1: 如图7中,skip-gram模型中,从隐藏层到输出层,因为使用权值共享,所以会导致输出的几个上下文词向量总是完全一样,但网络的目的是要去预测上下文会出现的词,而实际中给定中心词的情况下上下文的词会五花八门。怎么解释skip gram的这种输出形式?
Answer1: 网络的目的不是要预测上下文会出现啥词,这只是一个fake task。实际上这个loss就是降不下来的,所以本来就不能用于真正预测上下文,而初衷也不是用于预测上下文,只是利用上下文信息去实现嵌入。
如果你的100W个句子都是”I really love machine learning and deep learning“,加上权值共享,结果就是给定machine以后,它输出really,love,learning,and这四个词的概率完全相同,这就意味着这四个词的词向量也是差不多的。正因为这样,语义相近的词,他们在空间上的映射才会接近。
Question2 : Word2Vec哪个矩阵是词向量?
Answer2: 如图7所示,中心词矩阵W,上下文矩阵W' 可以任意选一个作为词向量矩阵。但是,如果采用优化后(层次softmax)的模型,那么将不存在W',这种情况下只能选矩阵W。
三千多字,码字不易,如果大家发现我有地方写得不对或者有疑问的,麻烦评论, 我会回复并改正 。对于重要问题,我会持续更新至 QuestionAnswer。
参考:
[1] skip-gram的关键术语与详细解释
[2] 一篇浅显易懂的word2vec原理讲解
[3] CS224n:深度学习的自然语言处理(2017年冬季)1080p
[4] Stanford CS224N: NLP with Deep Learning | Winter 2019 | Lecture 2 – Word Vectors and
Word Senses
[5] 关于skip gram的输出?
[6] Le, Quoc V , and T. Mikolov . "Distributed Representationsof Sentences and Documents." (2014).
[7] Mikolov, T. . "Distributed Representations of Words andPhrases and their Compositionality." Advances in Neural InformationProcessing Systems 26(2013):3111-3119.
[8] Mikolov, Tomas , et al."Efficient Estimation of Word Representations in Vector Space." Computerence (2013).
[9] Goldberg, Yoav , and O. Levy . "word2vec Explained:deriving Mikolov et al.'s negative-sampling word-embedding method." arXiv(2014).