word2vec原理(二) 基于Hierarchical Softmax的模型

    word2vec原理(一) CBOW与Skip-Gram模型基础html

    word2vec原理(二) 基于Hierarchical Softmax的模型git

    word2vec原理(三) 基于Negative Sampling的模型github

    在word2vec原理(一) CBOW与Skip-Gram模型基础中,咱们讲到了使用神经网络的方法来获得词向量语言模型的原理和一些问题,如今咱们开始关注word2vec的语言模型如何改进传统的神经网络的方法。因为word2vec有两种改进方法,一种是基于Hierarchical Softmax的,另外一种是基于Negative Sampling的。本文关注于基于Hierarchical Softmax的改进方法,在下一篇讨论基于Negative Sampling的改进方法。算法

1. 基于Hierarchical Softmax的模型概述

    咱们先回顾下传统的神经网络词向量语言模型,里面通常有三层,输入层(词向量),隐藏层和输出层(softmax层)。里面最大的问题在于从隐藏层到输出的softmax层的计算量很大,由于要计算全部词的softmax几率,再去找几率最大的值。这个模型以下图所示。其中$V$是词汇表的大小,网络

 

    word2vec对这个模型作了改进,首先,对于从输入层到隐藏层的映射,没有采起神经网络的线性变换加激活函数的方法,而是采用简单的对全部输入词向量求和并取平均的方法。好比输入的是三个4维词向量:$(1,2,3,4), (9,6,11,8),(5,10,7,12)$,那么咱们word2vec映射后的词向量就是$(5,6,7,8)$。因为这里是从多个词向量变成了一个词向量。函数

    第二个改进就是从隐藏层到输出的softmax层这里的计算量个改进。为了不要计算全部词的softmax几率,word2vec采样了霍夫曼树来代替从隐藏层到输出softmax层的映射。咱们在上一节已经介绍了霍夫曼树的原理。如何映射呢?这里就是理解word2vec的关键所在了。post

    因为咱们把以前全部都要计算的从输出softmax层的几率计算变成了一颗二叉霍夫曼树,那么咱们的softmax几率计算只须要沿着树形结构进行就能够了。以下图所示,咱们能够沿着霍夫曼树从根节点一直走到咱们的叶子节点的词$w_2$。优化

 

    和以前的神经网络语言模型相比,咱们的霍夫曼树的全部内部节点就相似以前神经网络隐藏层的神经元,其中,根节点的词向量对应咱们的投影后的词向量,而全部叶子节点就相似于以前神经网络softmax输出层的神经元,叶子节点的个数就是词汇表的大小。在霍夫曼树中,隐藏层到输出层的softmax映射不是一会儿完成的,而是沿着霍夫曼树一步步完成的,所以这种softmax取名为"Hierarchical Softmax"。编码

    如何“沿着霍夫曼树一步步完成”呢?在word2vec中,咱们采用了二元逻辑回归的方法,即规定沿着左子树走,那么就是负类(霍夫曼树编码1),沿着右子树走,那么就是正类(霍夫曼树编码0)。判别正类和负类的方法是使用sigmoid函数,即:$$P(+) = \sigma(x_w^T\theta) = \frac{1}{1+e^{-x_w^T\theta}}$$url

    其中$x_w$是当前内部节点的词向量,而$\theta$则是咱们须要从训练样本求出的逻辑回归的模型参数。

    使用霍夫曼树有什么好处呢?首先,因为是二叉树,以前计算量为$V$,如今变成了$log_2V$。第二,因为使用霍夫曼树是高频的词靠近树根,这样高频词须要更少的时间会被找到,这符合咱们的贪心优化思想。

    容易理解,被划分为左子树而成为负类的几率为$P(-) =  1-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$, 使训练样本达到最大似然。那么如何达到最大似然呢?

2. 基于Hierarchical Softmax的模型梯度计算

   咱们使用最大似然法来寻找全部节点的词向量和全部内部节点$\theta$。先拿上面的$w_2$例子来看,咱们指望最大化下面的似然函数:$$\prod_{i=1}^3P(n(w_i),i) = (1- \frac{1}{1+e^{-x_w^T\theta_1}})(1- \frac{1}{1+e^{-x_w^T\theta_2}})\frac{1}{1+e^{-x_w^T\theta_3}}$$

    对于全部的训练样本,咱们指望最大化全部样本的似然函数乘积。

    为了便于咱们后面通常化的描述,咱们定义输入的词为$w$,其从输入层词向量求和平均后的霍夫曼树根节点词向量为$x_w$, 从根节点到$w$所在的叶子节点,包含的节点总数为$l_w$, $w$在霍夫曼树中从根节点开始,通过的第$i$个节点表示为$p_i^w$,对应的霍夫曼编码为$d_i^w \in \{0,1\}$,其中$i =2,3,...l_w$。而该节点对应的模型参数表示为$\theta_i^w$, 其中$i =1,2,...l_w-1$,没有$i =l_w$是由于模型参数仅仅针对于霍夫曼树的内部节点。

    定义$w$通过的霍夫曼树某一个节点j的逻辑回归几率为$P(d_j^w|x_w, \theta_{j-1}^w)$,其表达式为:

$$P(d_j^w|x_w, \theta_{j-1}^w)=
\begin{cases}
 \sigma(x_w^T\theta_{j-1}^w)& {d_j^w=0}\\
1-  \sigma(x_w^T\theta_{j-1}^w) & {d_j^w = 1}
\end{cases}$$

    那么对于某一个目标输出词$w$,其最大似然为:$$\prod_{j=2}^{l_w}P(d_j^w|x_w, \theta_{j-1}^w) = \prod_{j=2}^{l_w} [\sigma(x_w^T\theta_{j-1}^w)] ^{1-d_j^w}[1-\sigma(x_w^T\theta_{j-1}^w)]^{d_j^w}$$

    在word2vec中,因为使用的是随机梯度上升法,因此并无把全部样本的似然乘起来获得真正的训练集最大似然,仅仅每次只用一个样本更新梯度,这样作的目的是减小梯度计算量。这样咱们能够获得$w$的对数似然函数$L$以下:

$$L= log \prod_{j=2}^{l_w}P(d_j^w|x_w, \theta_{j-1}^w) = \sum\limits_{j=2}^{l_w} ((1-d_j^w) log [\sigma(x_w^T\theta_{j-1}^w)]  + d_j^w log[1-\sigma(x_w^T\theta_{j-1}^w)])$$

    要获得模型中$w$词向量和内部节点的模型参数$\theta$, 咱们使用梯度上升法便可。首先咱们求模型参数$\theta_{j-1}^w$的梯度:

$$ \begin{align} \frac{\partial L}{\partial \theta_{j-1}^w} & = (1-d_j^w)\frac{(\sigma(x_w^T\theta_{j-1}^w)(1-\sigma(x_w^T\theta_{j-1}^w)}{\sigma(x_w^T\theta_{j-1}^w)}x_w - d_j^w \frac{(\sigma(x_w^T\theta_{j-1}^w)(1-\sigma(x_w^T\theta_{j-1}^w)}{1- \sigma(x_w^T\theta_{j-1}^w)}x_w  \\ & =  (1-d_j^w)(1-\sigma(x_w^T\theta_{j-1}^w))x_w -  d_j^w\sigma(x_w^T\theta_{j-1}^w)x_w \\& = (1-d_j^w-\sigma(x_w^T\theta_{j-1}^w))x_w \end{align}$$

    若是你们看过以前写的逻辑回归原理小结,会发现这里的梯度推导过程基本相似。

    一样的方法,能够求出$x_w$的梯度表达式以下:$$\frac{\partial L}{\partial x_w} = \sum\limits_{j=2}^{l_w}(1-d_j^w-\sigma(x_w^T\theta_{j-1}^w))\theta_{j-1}^w $$

    有了梯度表达式,咱们就能够用梯度上升法进行迭代来一步步的求解咱们须要的全部的$\theta_{j-1}^w$和$x_w$。

3. 基于Hierarchical Softmax的CBOW模型

    因为word2vec有两种模型:CBOW和Skip-Gram,咱们先看看基于CBOW模型时, Hierarchical Softmax如何使用。

    首先咱们要定义词向量的维度大小$M$,以及CBOW的上下文大小$2c$,这样咱们对于训练样本中的每个词,其前面的$c$个词和后面的$c$个词做为了CBOW模型的输入,该词自己做为样本的输出,指望softmax几率最大。

    在作CBOW模型前,咱们须要先将词汇表创建成一颗霍夫曼树。

    对于从输入层到隐藏层(投影层),这一步比较简单,就是对$w$周围的$2c$个词向量求和取平均便可,即:$$x_w = \frac{1}{2c}\sum\limits_{i=1}^{2c}x_i$$

    第二步,经过梯度上升法来更新咱们的$\theta_{j-1}^w$和$x_w$,注意这里的$x_w$是由$2c$个词向量相加而成,咱们作梯度更新完毕后会用梯度项直接更新原始的各个$x_i(i=1,2,,,,2c)$,即:

$$\theta_{j-1}^w = \theta_{j-1}^w + \eta  (1-d_j^w-\sigma(x_w^T\theta_{j-1}^w))x_w $$$$x_i= x_i +\eta  \sum\limits_{j=2}^{l_w}(1-d_j^w-\sigma(x_w^T\theta_{j-1}^w))\theta_{j-1}^w \;(i =1,2..,2c) $$

    其中$\eta$为梯度上升法的步长。

    这里总结下基于Hierarchical Softmax的CBOW模型算法流程,梯度迭代使用了随机梯度上升法:

    输入:基于CBOW的语料训练样本,词向量的维度大小$M$,CBOW的上下文大小$2c$,步长$\eta$

    输出:霍夫曼树的内部节点模型参数$\theta$,全部的词向量$w$

    1. 基于语料训练样本创建霍夫曼树。

    2. 随机初始化全部的模型参数$\theta$,全部的词向量$w$

    3. 进行梯度上升迭代过程,对于训练集中的每个样本$(context(w), w)$作以下处理:

      a)  e=0, 计算$x_w= \frac{1}{2c}\sum\limits_{i=1}^{2c}x_i$

      b)  for j = 2 to $ l_w$, 计算:$$f = \sigma(x_w^T\theta_{j-1}^w)$$$$g = (1-d_j^w-f)\eta$$$$e = e + g\theta_{j-1}^w$$$$\theta_{j-1}^w= \theta_{j-1}^w + gx_w$$

              c) 对于$context(w)$中的每个词向量$x_i$(共2c个)进行更新:$$x_i = x_i + e$$ 

      d) 若是梯度收敛,则结束梯度迭代,不然回到步骤3继续迭代。

4. 基于Hierarchical Softmax的Skip-Gram模型

    如今咱们先看看基于Skip-Gram模型时, Hierarchical Softmax如何使用。此时输入的只有一个词$w$,输出的为$2c$个词向量$context(w)$。

    咱们对于训练样本中的每个词,该词自己做为样本的输入, 其前面的$c$个词和后面的$c$个词做为了Skip-Gram模型的输出,,指望这些词的softmax几率比其余的词大。

    Skip-Gram模型和CBOW模型实际上是反过来的,在上一篇已经讲过。

    在作CBOW模型前,咱们须要先将词汇表创建成一颗霍夫曼树。

    对于从输入层到隐藏层(投影层),这一步比CBOW简单,因为只有一个词,因此,即$x_w$就是词$w$对应的词向量。

    第二步,经过梯度上升法来更新咱们的$\theta_{j-1}^w$和$x_w$,注意这里的$x_w$周围有$2c$个词向量,此时若是咱们指望$P(x_i|x_w), i=1,2...2c$最大。此时咱们注意到因为上下文是相互的,在指望$P(x_i|x_w), i=1,2...2c$最大化的同时,反过来咱们也指望$P(x_w|x_i), i=1,2...2c$最大。那么是使用$P(x_i|x_w)$好仍是$P(x_w|x_i)$好呢,word2vec使用了后者,这样作的好处就是在一个迭代窗口内,咱们不是只更新$x_w$一个词,而是$x_i, i=1,2...2c$共$2c$个词。这样总体的迭代会更加的均衡。由于这个缘由,Skip-Gram模型并无和CBOW模型同样对输入进行迭代更新,而是对$2c$个输出进行迭代更新。

    这里总结下基于Hierarchical Softmax的Skip-Gram模型算法流程,梯度迭代使用了随机梯度上升法:

    输入:基于Skip-Gram的语料训练样本,词向量的维度大小$M$,Skip-Gram的上下文大小$2c$,步长$\eta$

    输出:霍夫曼树的内部节点模型参数$\theta$,全部的词向量$w$

    1. 基于语料训练样本创建霍夫曼树。

    2. 随机初始化全部的模型参数$\theta$,全部的词向量$w$,

    3. 进行梯度上升迭代过程,对于训练集中的每个样本$(w, context(w))$作以下处理:

      a)  for i =1 to 2c:

        i) e=0

        ii)for j = 2 to $ l_w$, 计算:$$f = \sigma(x_i^T\theta_{j-1}^w)$$$$g = (1-d_j^w-f)\eta$$$$e = e + g\theta_{j-1}^w$$$$\theta_{j-1}^w= \theta_{j-1}^w+ gx_i$$

        iii) $$x_i = x_i + e$$

      b)若是梯度收敛,则结束梯度迭代,算法结束,不然回到步骤a继续迭代。

5. Hierarchical Softmax的模型源码和算法的对应    

    这里给出上面算法和word2vec源码中的变量对应关系。

    在源代码中,基于Hierarchical Softmax的CBOW模型算法在435-463行,基于Hierarchical Softmax的Skip-Gram的模型算法在495-519行。你们能够对着源代码再深刻研究下算法。

    在源代码中,neule对应咱们上面的$e$, syn0对应咱们的$x_w$, syn1对应咱们的$\theta_{j-1}^i$, layer1_size对应词向量的维度,window对应咱们的$c$。

    另外,vocab[word].code[d]指的是,当前单词word的,第d个编码,编码不含Root结点。vocab[word].point[d]指的是,当前单词word,第d个编码下,前置的结点。

  

    以上就是基于Hierarchical Softmax的word2vec模型,下一篇咱们讨论基于Negative Sampling的word2vec模型。

 

 (欢迎转载,转载请注明出处。欢迎沟通交流: liujianping-ok@163.com)