简单神经网络

简单神经网络

1.文本表示

(1).one-hot

one-hot即独立热词,词语被表示成一个维度为词表大小的向量,这个向量中只有一个维度是1其他位置都是0.假如词表中只有四个个词“奥巴马”、“特朗普”、“宣誓”、“就职”,那么他们将被表示为:

one-hot表示的优点是简单易用,但是有着致命的缺点:

  • 如果一个词表有十万个单词,那么就需要十万维的向量来表示每一个单词,而每个向量只有一位是1,在储存上造成大量浪费,在深度学习场景中容易受到维度灾难的困扰。
  • 奥巴马和特朗普都是美国总统,而one-hot表示出的两个向量是正交向量,也就是他们之间毫无关系,这显然是丢失了相关语义信息。
    因此我们需要更好的表示方法。

实例例举

word2vec

word2vec就是将词表征为实数值向量的一种高效的算法模型,其利用深度学习的思想,可以通过训练,把对文本内容的处理简化为 K 维向量空间中的向量运算,而向量空间上的相似度可以用来表示文本语义上的相似。当我们在说word2vec算法或模型的时候,其实指的是其背后用于计算word vector的CBoW模型和Skip-gram模型。很多人以为word2vec指的是一个算法或模型,这也是一种谬误。

  • 引子Distributed representation词向量表示

    低维实数向量。向量的距离可以用最传统的欧氏距离来衡量,也可以用 cos 夹角来衡量。它的思路是通过训练,将每个词都映射到一个较短的词向量上来。所有的这些词向量就构成了向量空间,进而可以用普通的统计学的方法来研究词与词之间的关系。这个较短的词向量维度是多大呢?这个一般需要我们在训练时自己来指定。

  • Word2vec 使用的词向量不是我们上述提到的One-hot Representation那种词向量,而是 Distributed representation 的词向量表示方式。其基本思想是 通过训练将每个词映射成 K 维实数向量(K 一般为模型中的超参数),通过词之间的距离(比如 cosine 相似度、欧氏距离等)来判断它们之间的语义相似度.其采用一个 三层的神经网络 ,输入层-隐层-输出层。有个核心的技术是 根据词频用Huffman编码 ,使得所有词频相似的词隐藏层激活的内容基本一致,出现频率越高的词语,他们激活的隐藏层数目越少,这样有效的降低了计算的复杂度。而Word2vec大受欢迎的一个原因正是其高效性。这个三层神经网络本身是 对语言模型进行建模 ,但也同时 获得一种单词在向量空间上的表示 ,而这个副作用才是Word2vec的真正目标。

  • 输入是one-hot,,Hidden Layer没有激活函数,也就是线性的单元。Output Layer维度跟Input Layer的维度一样,用的是Softmax回归。当这个模型训练好以后,我们并不会用这个训练好的模型处理新的任务,我们真正需要的是这个模型通过训练数据所学得的参数,例如隐层的权重矩阵。

Word2Vec实际上是两种不同的方法:Continuous Bag of Words (CBOW) 和 Skip-gram。CBOW的目标是根据上下文来预测当前词语的概率。Skip-gram刚好相反:根据当前词语来预测上下文的概率(如下图所示)。这两种方法都利用人工神经网络作为它们的分类算法。起初,每个单词都是一个随机 N 维向量。经过训练之后,该算法利用 CBOW 或者 Skip-gram 的方法获得了每个单词的最优向量。

 取一个适当大小的窗口当做语境,输入层读入窗口内的词,将它们的向量(K维,初始随机)加和在一起,形成隐藏层K个节点。输出层是一个巨大的二叉 树,叶节点代表语料里所有的词(语料含有V个独立的词,则二叉树有|V|个叶节点)。而这整颗二叉树构建的算法就是Huffman树。这样,对于叶节点的 每一个词,就会有一个全局唯一的编码,形如”010011”,不妨记左子树为1,右子树为0。接下来,隐层的每一个节点都会跟二叉树的内节点有连边,于是 对于二叉树的每一个内节点都会有K条连边,每条边上也会有权值。

对于语料库中的某个词w_t,对应着二叉树的某个叶子节点,因此它必然有一个二进制编码,如”010011”。在训练阶段,当给定上下文,要预测后 面的词w_t的时候,我们就从二叉树的根节点开始遍历,这里的目标就是预测这个词的二进制编号的每一位。即对于给定的上下文,我们的目标是使得预测词的二 进制编码概率最大。形象地说,我们希望在根节点,词向量和与根节点相连经过 logistic 计算得到 bit=1 的概率尽量接近 0,在第二层,希望其 bit=1 的概率尽量接近1,这么一直下去,我们把一路上计算得到的概率相乘,即得到目标词w_t在当前网络下的概率P(w_t),那么对于当前这个 sample的残差就是1-P(w_t),于是就可以使用梯度下降法训练这个网络得到所有的参数值了。显而易见,按照目标词的二进制编码计算到最后的概率 值就是归一化的。

  最先优化使用的数据结构是用霍夫曼树来代替隐藏层和输出层的神经元,霍夫曼树的叶子节点起到输出层神经元的作用,叶子节点的个数即为词汇表的小大,word2vec使用霍夫曼树来代替传统的DNN算法(因为DNN算法处理过程非常耗时)。 而内部节点则起到隐藏层神经元的作用。其实借助了分类问题中,使用一连串二分类近似多分类的思想。例如我们是把所有的词都作为输出,那么“桔 子”、“汽车”都是混在一起。给定w_t的上下文,先让模型判断w_t是不是名词,再判断是不是食物名,再判断是不是水果,再判断是不是“桔子”。

  但是在训练过程中,模型会赋予这些抽象的中间结点一个合适的向量,这个向量代表了它对应的所有子结点。因为真正的单词公用了这些抽象结点的向量,所 以Hierarchical Softmax方法和原始问题并不是等价的,但是这种近似并不会显著带来性能上的损失同时又使得模型的求解规模显著上升。

  没有使用这种二叉树,而是直接从隐层直接计算每一个输出的概率——即传统的Softmax,就需要对|V|中的每一个词都算一遍,这个过程时间复杂 度是O(|V|)的。而使用了二叉树(如Word2vec中的Huffman树),其时间复杂度就降到了O(log2(|V|)),速度大大地加快了。

  现在这些词向量已经捕捉到上下文的信息。我们可以利用基本代数公式来发现单词之间的关系(比如,“国王”-“男人”+“女人”=“王后”)。这些词向量可 以代替词袋用来预测未知数据的情感状况。该模型的优点在于不仅考虑了语境信息还压缩了数据规模(通常情况下,词汇量规模大约在300个单词左右而不是之前 模型的100000个单词)。因为神经网络可以替我们提取出这些特征的信息,所以我们仅需要做很少的手动工作。但是由于文本的长度各异,我们可能需要利用 所有词向量的平均值作为分类算法的输入值,从而对整个文本文档进行分类处理。

注:以下内容转载自网络

. 基于Hierarchical Softmax的模型概述

    我们先回顾下传统的神经网络词向量语言模型,里面一般有三层,输入层(词向量),隐藏层和输出层(softmax层)。里面最大的问题在于从隐藏层到输出的softmax层的计算量很大,因为要计算所有词的softmax概率,再去找概率最大的值。这个模型如下图所示。其中VV 是词汇表的大小,

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

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

    由于我们把之前所有都要计算的从输出softmax层的概率计算变成了一颗二叉霍夫曼树,那么我们的softmax概率计算只需要沿着树形结构进行就可以了。如下图所示,我们可以沿着霍夫曼树从根节点一直走到我们的叶子节点的词w2w2 。

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

    如何“沿着霍夫曼树一步步完成”呢?在word2vec中,我们采用了二元逻辑回归的方法,即规定沿着左子树走,那么就是负类(霍夫曼树编码1),沿着右子树走,那么就是正类(霍夫曼树编码0)。判别正类和负类的方法是使用sigmoid函数,即:

P(+)=σ(xTw**θ)=11+exTw**θP(+)=σ(xwTθ)=11+e−xwTθ

    其中x**wxw 是当前内部节点的词向量,而θθ 则是我们需要从训练样本求出的逻辑回归的模型参数。

    使用霍夫曼树有什么好处呢?首先,由于是二叉树,之前计算量为VV ,现在变成了log2Vlog2V 。第二,由于使用霍夫曼树是高频的词靠近树根,这样高频词需要更少的时间会被找到,这符合我们的贪心优化思想。

    容易理解,被划分为左子树而成为负类的概率为P(−)=1−P(+)P(−)=1−P(+) 。在某一个内部节点,要判断是沿左子树还是右子树走的标准就是看P(−),P(+)P(−),P(+) 谁的概率值大。而控制P(−),P(+)P(−),P(+) 谁的概率值大的因素一个是当前节点的词向量,另一个是当前节点的模型参数θθ 。

    对于上图中的w2w2 ,如果它是一个训练样本的输出,那么我们期望对于里面的隐藏节点n(w2,1)n(w2,1) 的P(−)P(−) 概率大,n(w2,2)n(w2,2) 的P(−)P(−) 概率大,n(w2,3)n(w2,3) 的P(+)P(+) 概率大。

    回到基于Hierarchical Softmax的word2vec本身,我们的目标就是找到合适的所有节点的词向量和所有内部节点θθ , 使训练样本达到最大似然。那么如何达到最大似然呢?

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

   我们使用最大似然法来寻找所有节点的词向量和所有内部节点θθ 。先拿上面的w2w2 例子来看,我们期望最大化下面的似然函数:

i=13P(n(w**i),i)=(1−11+exTw**θ1)(1−11+exTw**θ2)11+exTw**θ3∏i=13P(n(wi),i)=(1−11+e−xwTθ1)(1−11+e−xwTθ2)11+e−xwTθ3

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

    为了便于我们后面一般化的描述,我们定义输入的词为ww ,其从输入层词向量求和平均后的霍夫曼树根节点词向量为x**wxw , 从根节点到ww 所在的叶子节点,包含的节点总数为l**wlw , ww 在霍夫曼树中从根节点开始,经过的第ii 个节点表示为pwipiw ,对应的霍夫曼编码为dwi∈{0,1}diw∈{0,1} ,其中i=2,3,…l**wi=2,3,…lw 。而该节点对应的模型参数表示为θwiθiw , 其中i=1,2,…l**w−1i=1,2,…lw−1 ,没有i=l**wi=lw 是因为模型参数仅仅针对于霍夫曼树的内部节点。

    定义ww 经过的霍夫曼树某一个节点j的逻辑回归概率为P(dwj|x**w,θwj−1)P(djw|xw,θj−1w) ,其表达式为:

P(dwj|x**w,θwj−1)={σ(xTwθw**j−1)1−σ(xTwθw**j−1)dwj=0dwj=1P(djw|xw,θj−1w)={σ(xwTθj−1w)djw=01−σ(xwTθj−1w)djw=1

    那么对于某一个目标输出词ww ,其最大似然为:

j=2lwP(dwj|x**w,θwj−1)=∏j=2l**w[σ(xTwθw**j−1)]1−dwj[1−σ(xTwθw**j−1)]dwj∏j=2lwP(djw|xw,θj−1w)=∏j=2lw[σ(xwTθj−1w)]1−djw[1−σ(xwTθj−1w)]djw

    在word2vec中,由于使用的是随机梯度上升法,所以并没有把所有样本的似然乘起来得到真正的训练集最大似然,仅仅每次只用一个样本更新梯度,这样做的目的是减少梯度计算量。这样我们可以得到ww 的对数似然函数LL 如下:

L=logj=2lwP(dwj|x**w,θwj−1)=∑j=2l**w((1−dwj)log[σ(xTwθw**j−1)]+dwjlo**g[1−σ(xTwθw**j−1)])L=log∏j=2lwP(djw|xw,θj−1w)=∑j=2lw((1−djw)log[σ(xwTθj−1w)]+djwlog[1−σ(xwTθj−1w)])

    要得到模型中ww 词向量和内部节点的模型参数θθ , 我们使用梯度上升法即可。首先我们求模型参数θwj−1θj−1w 的梯度:

Lθwj−1=(1−dwj)(σ(xTwθw**j−1)(1−σ(xTwθw**j−1)σ(xTwθw**j−1)x**wdwj(σ(xTwθw**j−1)(1−σ(xTwθw**j−1)1−σ(xTwθw**j−1)x**w=(1−dwj)(1−σ(xTwθw**j−1))x**wdwj**σ(xTwθw**j−1)x**w=(1−dwjσ(xTwθw**j−1))x**w(1)(2)(3)(1)∂L∂θj−1w=(1−djw)(σ(xwTθj−1w)(1−σ(xwTθj−1w)σ(xwTθj−1w)xw−djw(σ(xwTθj−1w)(1−σ(xwTθj−1w)1−σ(xwTθj−1w)xw(2)=(1−djw)(1−σ(xwTθj−1w))xw−djwσ(xwTθj−1w)xw(3)=(1−djw−σ(xwTθj−1w))xw

    如果大家看过之前写的逻辑回归原理小结,会发现这里的梯度推导过程基本类似。

    同样的方法,可以求出x**wxw 的梯度表达式如下:

Lx**w=∑j=2l**w(1−dwjσ(xTwθw**j−1))θwj−1∂L∂xw=∑j=2lw(1−djw−σ(xwTθj−1w))θj−1w

    有了梯度表达式,我们就可以用梯度上升法进行迭代来一步步的求解我们需要的所有的θwj−1θj−1w 和x**wxw 。

3. 基于Hierarchical Softmax的CBOW模型

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

    首先我们要定义词向量的维度大小MM ,以及CBOW的上下文大小2c2c ,这样我们对于训练样本中的每一个词,其前面的cc 个词和后面的cc 个词作为了CBOW模型的输入,该词本身作为样本的输出,期望softmax概率最大。

    在做CBOW模型前,我们需要先将词汇表建立成一颗霍夫曼树。

    对于从输入层到隐藏层(投影层),这一步比较简单,就是对ww 周围的2c2c 个词向量求和取平均即可,即:

x**w=12ci=12cxixw=12c∑i=12cxi

    第二步,通过梯度上升法来更新我们的θwj−1θj−1w 和x**wxw ,注意这里的x**wxw 是由2c2c 个词向量相加而成,我们做梯度更新完毕后会用梯度项直接更新原始的各个x**i(i=1,2,,,,2c)xi(i=1,2,,,,2c) ,即:

θwj−1=θwj−1+η(1−dwjσ(xTwθw**j−1))x**wθj−1w=θj−1w+η(1−djw−σ(xwTθj−1w))xw

x**i=x**i+ηj=2l**w(1−dwjσ(xTwθw**j−1))θwj−1(i=1,2..,2c)xi=xi+η∑j=2lw(1−djw−σ(xwTθj−1w))θj−1w(i=1,2..,2c)

    其中ηη 为梯度上升法的步长。

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

    输入:基于CBOW的语料训练样本,词向量的维度大小MM ,CBOW的上下文大小2c2c ,步长ηη

    输出:霍夫曼树的内部节点模型参数θθ ,所有的词向量ww

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

    2. 随机初始化所有的模型参数θθ ,所有的词向量ww

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

      a) e=0, 计算x**w=12ci=12cxixw=12c∑i=12cxi

      b) for j = 2 to l**wlw , 计算:

f=σ(xTwθw**j−1)f=σ(xwTθj−1w)

g=(1−dwjf)ηg=(1−djw−f)η

e=e+gθw**j−1e=e+gθj−1w

θwj−1=θwj−1+gxwθj−1w=θj−1w+gxw

    c) 对于context(w)context(w) 中的每一个词向量x**ixi (共2c个)进行更新:

x**i=x**i+exi=xi+e

      d) 如果梯度收敛,则结束梯度迭代,否则回到步骤3继续迭代。

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

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

    我们对于训练样本中的每一个词,该词本身作为样本的输入, 其前面的cc 个词和后面的cc 个词作为了Skip-Gram模型的输出,,期望这些词的softmax概率比其他的词大。

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

    在做CBOW模型前,我们需要先将词汇表建立成一颗霍夫曼树。

    对于从输入层到隐藏层(投影层),这一步比CBOW简单,由于只有一个词,所以,即x**wxw 就是词ww 对应的词向量。

    第二步,通过梯度上升法来更新我们的θwj−1θj−1w 和x**wxw ,注意这里的x**wxw 周围有2c2c 个词向量,此时如果我们期望P(x**i|x**w),i=1,2…2cP(xi|xw),i=1,2…2c 最大。此时我们注意到由于上下文是相互的,在期望P(x**i|x**w),i=1,2…2cP(xi|xw),i=1,2…2c 最大化的同时,反过来我们也期望P(x**w|x**i),i=1,2…2cP(xw|xi),i=1,2…2c 最大。那么是使用P(x**i|x**w)P(xi|xw) 好还是P(x**w|x**i)P(xw|xi) 好呢,word2vec使用了后者,这样做的好处就是在一个迭代窗口内,我们不是只更新x**wxw 一个词,而是x**i,i=1,2…2cxi,i=1,2…2c 共2c2c 个词。这样整体的迭代会更加的均衡。因为这个原因,Skip-Gram模型并没有和CBOW模型一样对输入进行迭代更新,而是对2c2c 个输出进行迭代更新。

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

    输入:基于Skip-Gram的语料训练样本,词向量的维度大小MM ,Skip-Gram的上下文大小2c2c ,步长ηη

    输出:霍夫曼树的内部节点模型参数θθ ,所有的词向量ww

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

    2. 随机初始化所有的模型参数θθ ,所有的词向量ww ,

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

      a) for i =1 to 2c:

        i) e=0

        ii)for j = 2 to l**wlw , 计算:

f=σ(xTiθw**j−1)f=σ(xiTθj−1w)

g=(1−dwjf)ηg=(1−djw−f)η

e=e+gθw**j−1e=e+gθj−1w

θwj−1=θwj−1+gxiθj−1w=θj−1w+gxi iii)

x**i=x**i+exi=xi+e

      b)如果梯度收敛,则结束梯度迭代,算法结束,否则回到步骤a继续迭代。

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

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

    在源代码中,基于Hierarchical Softmax的CBOW模型算法在435-463行,基于Hierarchical Softmax的Skip-Gram的模型算法在495-519行。大家可以对着源代码再深入研究下算法。

    在源代码中,neule对应我们上面的ee , syn0对应我们的x**wxw , syn1对应我们的θij−1θj−1i , layer1_size对应词向量的维度,window对应我们的cc 。

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