NLP学习路线第三章-----了解一些经典神经网络语言模型

本片文章为一些博文加上自己的一些理解总结而成,如有侵权,联系删除。希望可以和大家共同进步。

一、LSTM

       假如现在有一任务,需要预测“ I grew up in France...I speak fluent French" 最后的词 ”French“。
       当前建议下一个词可能是一种语言的名字,若需弄清楚就需要前文提到的France,而相关信息和当前预测位置之间的间隔很大。不幸的是,在这个间隔不断增大时,RNN会丧失学习连接到如此远的信息的能力。即RNN在反向传播时会面临梯度消失问题,而梯度是用来更新权值的(新权值=旧权值-梯度*学习率),进而导致权值几乎不更新,较早的学习器停止学习。
        因此RNN会忘记它在较长序列中以前的内容,只具有短时记忆。而LSTM可在一定程度上解决梯度消失和梯度爆炸问题(本质上都是梯度反向传播的连乘效应),从而具有长期记忆,能够解决长期依赖问题。
        LSTM是一种RNN特殊的类型,和基线RNN并没有特别大的结构不同,但用了不同的函数来计算隐状态。LSTM中重复的模块包含四个交互的层(三个sigmoid层和一个tanh层)。


LSTM的核心思想:
(1)LSTM关键就是细胞状态C,直接在模型上方整个链条上传输,只有少量线性交互,使得有效信息长期传递变得容易。
(2)LSTM有通过精心设计称作”门“的结构来给细胞丢弃或增加信息的能力。

(1)遗忘门,决定我们会从细胞状态中丢弃什么信息。向量  的值在(0,1)之间,1表示完全保留,0表示完全丢弃。
(2)输入门。sigmoid层决定我们需要更新的信息,tanh层创建一个新的候选记忆,会被加入到细胞状态(记忆)中。通俗来讲就是,新细胞记忆 = 旧细胞记忆*丢弃需要丢弃的信息 + 候选记忆*需要更新的信息。即    。
(3)输出门。基于细胞状态,确定最终输出什么值,可以看成是一个过滤后的版本。具体来说就是把得到的细胞状态(记忆)通过tanh处理(得到一个位于(-1,1)之间的值),再将它和sigmoid门得到的输出相乘。


总结: 
遗忘门:决定什么信息需要从记忆细胞中删除——0:将(过去的记忆)的值删除,1:保留的值;
输入门:决定输入的哪些新信息(输入信息通过候选记忆细胞传入)需要增加至记忆细胞中;
输出门:决定从记忆细胞中选出哪些信息进行输出。


        LSTM 的核心概念在于细胞状态以及“门”结构。细胞状态相当于信息传输的路径,让信息能在序列连中传递下去——即网络的“记忆”。理论上讲,细胞状态能够将序列处理过程中的相关信息一直传递下去。因此,即使是较早时间步的信息也能携带到较后时间步的细胞中来,这克服了短时记忆的影响(RNN可能会因为指数项的累积,变得越来越小或大到“面目全非”,LSTM将累积下来的影响由指数运算转化为了加法运算与参数学习控制去留)。信息的添加和移除我们通过“门”结构来实现,“门”结构在训练过程中会去学习该保存或遗忘哪些信息。

二、 NNLM

        NNLM(Neural Network Language Model)神经网络语言模型于2003年被提出。该模型使用前n-1个词来预测第n个词,计算概率 P(w_{n}|w_{1},w_{2},...,w_{n-1}) 。

       首先将前n-1个词用one-hot表示,然后使用投影矩阵降维,再将降维后的n-1个词的表示拼接起来,输入到单层使用tanh激活的神经网络中,得到一个富含输入信息的hidden state向量,或者说是context向量,再经过一个线性层得到字典中词的预测分值,经过softmax后得到每个词的概率,其中概率最大的就是模型的预测词。

模型如图所示。

模型输入:w_{t-n+1},...,w_{t-2},w_{t-1},即输入的是w_{t}的前n-1个单词。

模型输出:根据已知的n-1个词预测下一个词 w_{t} 。

上图中:

- 矩阵C---输入层到隐藏层之间的矩阵,大小为V x m。V表示语料中的总词数,m为词向量的维度。

- C(w)指w所对应的词向量,即在C中取w对应的一行。

¥¥网络的第一层(即输入层):输入n-1 个用one-hot表示的词向量与输入层到隐藏层之间的矩阵C相乘得到 C(w_{t-n+1}),...,C(w_{t-2}),C(w_{t-1}) 。再将 C(w_{t-n+1}),...,C(w_{t-2}),C(w_{t-1}) 这n-1个向量首尾拼接起来形成一个 m*(n-1)的向量。

¥¥网络的第二层(即隐藏层):首先使用一个全连接层:Hx + d计算得到(H表示对应向量的权重,d表示偏置)。通过全连接层后再使用tanh激活函数进行激活。

¥¥网络的第三层(即输出层):本质上这也是个全连接层(权重为U,偏置为d)。一共有V个结点,每个输出结点yi(其中i为索引)表示下一个词语为i的log概率,最后使用softmax激活函数将输出的yi进行归一化处理。

¥¥整个合起来就是:y=softmax\: [log(U*tanh(d+Hx)+Wx+b)]

其中W是可选参数,主要是将输入层的数据结果也放到输出层进行计算的线性变换,称为直连边(若不需要直连边,则令W=0)。

NNLM损失函数使用交叉熵损失函数,即  CEL(p,q)=-\sum_{x\in X}^{}\; p(x)log\: q(x)  。

其中X为x的取值范围,多分类任务中代表类别。一个x的真实模型,一个是构造的模型,我们希望构造的模型尽量接近真实模型。交叉熵越小,表示两个概率分布越靠近。p(x)为x的真实概率分布,q(x)为构造模型的概率分布。

因此,NNLM的优化目标为 loss=min(-\sum_{t=1}^{T}log\: p(w_{t}|w_{t-n+1},w_{t-n+2},....,w_{t-1})) ,待优化的参数为:b,d,W,H,C, U。对于一个输入样本w_{t-n+1},...,w_{t-2},w_{t-1}来说,真实概率为one-hot编码值(one-hot也可看作总和为1的完美的概率分布),而模型预测的概率分布为P。

注:NNLM只能处理定长的序列。

下面举个例子。

NNLM的优缺点。

优点:由于NNLM模型使用低维紧凑的词向量对上文进行表示,这解决了词袋模型带来的数据稀疏、语义鸿沟等问题。

缺点:模型在神经网络层参数量巨大。

三、 word2vector

word2vector的工作原理基于神经网络语言模型,是一种将词语表示为向量的技术。它可以将每个词语映射到一个固定长度的向量空间,并学习语料库中词汇之间的相关性和语义关系。

word2vector工具主要包含两个模型:skip-gram(跳字模型)和 CBOW(连续词袋模型),以及两种高效训练的方法:负采样和层序softmax(hierarchical softmax)。

1. CBOW

CBOW(Continuous Bag of Word),又称连续词袋模型,是一个三层神经网络。该模型的特点是输入已知上下文,输出对当前单词的预测

计算步骤:

(1)输入层:上下文单词的one-hot。(假设单词向量空间维度为V,上下文单词个数为C)

(2)所有one-hot分别乘以共享的输入权重矩阵W(W为VxN矩阵,N为自己设定的数,需要初始化权重矩阵W)。

(3)所得的向量(即one-hot向量乘以矩阵的结果)相加求平均作为隐层向量,size为1xN。

(4)乘以输出权重矩阵W'(NxV)。

(5)得到的向量(1xV)经激活函数处理后得到维度为V的概率分布,概率最大的index所指示的单词为预测出的中间词。

(6)与true label的one-hot(看作总和为1的概率分布)作比较,误差越小越好。

说明:W是输入层到隐藏层的权重矩阵,维度是VxN,W'是隐藏层到输出层的权重矩阵,维度是NxV。

        Loss function 一般使用交叉熵损失函数,采用梯度下降法更新W和W'。训练完毕后,输入层的每个单词与矩阵W相乘所得的向量就是我们想要的向量(word embedding),这个矩阵(所有单词的word embedding)也叫做look up table,任何一个单词的one-hot乘以这个矩阵都将得到自己的词向量。有了look up table就可以免去训练过程直接查表得到单词的词向量。

        再假如我们的训练样本有100个词,设置词向量的维度为10,即词向量矩阵V大小是[100, 10]。现在有一个训练集 “有力促进了同心县与全国其他地方一道迈向全面小康”,这句话分词结果是 ['有力', '促进', '了', '同心县', '与', '全国', '其他', '地方', '一道', '迈向', '全面', '小康']。

        以label为“地方”为例,前四个词加后四个词组成的输入是['同心县', '与', '全国', '其他', '一道', '迈向', '全面', '小康']。根据每个词的索引,在V中取出相应的词向量X(大小是[8, 10])。通过神经网络计算和softmax输出后会得到一个对应100个词的概率输出,loss就是这个输出和表示实际label的one-hot的交叉熵损失,然后根据loss去调节神经网络参数和输入X(X属于词向量矩阵V,因此本质上就是更新V)。在该次训练中即会同时更新['同心县', '与', '全国', '其他', '一道', '迈向', '全面', '小康']八个词的词向量,虽然“地方”对应的词向量没有被更新,但是在其他输入含有“地方的”样本参与训练的过程中,会被更新。

       这里我们可以发现:CBOW虽然是使用2n个词预测一个词,但是在训练过程中却是使用一个词去同时调节2n个词的过程(理解这句话很重要)。从整个训练过程我们可以发现,word2vector的训练过程,训练的不仅仅是神经网络中间层的参数,还有输入层X的参数。因此,词向量实际上是模型训练过程中的副产品

2. skip-gram

skip-gram的特点是根据当前已知词语,预测上下文

 

        以句子”The quick brown fox jumps over lazy dog“为例,我们设定skip-window的参数为2,代表我们仅选前后各两个词和输入词进行组合。如下图所示,蓝色方框代表input word,窗口内其余的单词即为我们要预测的词。

       假如skip-window参数为1,训练样本取【The,quick】。这句话一共包含九个不同词,它们被编码成one-hot后,The 是[1,0,0,0,0,0,0,0,0],quick是[0,1,0,0,0,0,0,0,0]。因此输入是1*9的one-hot向量乘以9*5的权重矩阵W(位于输入层和隐藏层之间,9是单词个数,5是自定义的),得到1*5维的隐藏层神经元向量,该神经元向量再乘以5*9的权重矩阵(位于隐藏层和输出层之间),得到1*9的向量经过softmax函数运算后得到另一个1*9的概率分布向量。

        这个向量也就是The这个词经过训练得到的输出,向量中的每个概率值代表着对应词汇表中9个单词的概率分布,理想情况是这个向量等于quick的one-hot,但由于softmax函数的特性,这种情况永远达不到,所以只能通过反向传播的过程让他们不断逼近。上述的训练过程可以不断调整输入层到隐藏层之间的权重矩阵W。

小结:无论是CBOW还是skip-gram,最终我们需要的是训练出来的输入层到隐藏层的权重矩阵W,W每行对应每个词的词向量。    

       继续上面的例子:“有力促进了同心县与全国其他地方一道迈向全面小康”,中心词依然取“地方”,n依然取4,则8个训练样本为:
['地方', '同心县'],['地方', '与']['地方', '全国']['地方', '其他']['地方', '一道']['地方', '迈向']['地方', '全面']['地方', '小康']
        整个计算过程和上述差别不大,因为输入仅为一个词向量,所以第一步的平均处理就不再需要了。这里我们可以发现,在训练过程中2n个样本都是一样的,并不会因为谁距离中心词更近或者更远而有不同。虽然Skip-Gram是使用一个词判断前后2n个词,但是根据反向传播和梯度下降机制,在Skip-Gram中是使用前后2n个词来调节一个中心词。所以一般在数据量允许的情况下,使用Skip-Gram会更好。


这里再另外提两点,不知道大家有没有疑问。

第一,因为我们拿的是前后2n个词去无序训练,那么在实际预测中,怎么判断每个词的顺序呢?其实,这个问题已经在前面回答过,在模型训练结束以后,我们需要的其实并不是模型本身,而是模型的副产品——词向量,然后拿词向量去做更多的事情(翻译、情感分类、评论分类、智慧客服等),所以一般我们不会使用这个模型去直接处理问题。

第二,在Skip-Gram中我们可以发现,一个样本对应了多个label(前后的2n个词),会不会导致无法收敛呢?其实,模型在训练过程中是一个综合调节的过程,模型的目的是为了得到词的特征表达,并不是模型本身,词向量的结果也和你的训练样本有关,通常来说,对于一些专业领域,往往会进行定制化的词向量训练。至于为什么这样处理得到的结果就可以表示每个词,甚至词之间的语义区别,和神经网络一样,目前也是不可解释的。

训练及优化

在第一部分讲解完成后,我们会发现word2vector模型是一个超级大的神经网络(权重矩阵规模非常大)。举个例子,我们拥有10000个单词的词汇表,我们如果想嵌入300维的词向量,那么我们的输入-隐层权重矩阵和隐层-输出层权重矩阵都会有10000x300=300万个权重,在如此庞大的神经网络中进行梯度下降是相当慢的。更糟糕的是,你需要大量的训练数据来调整这些权重并且避免过拟合。百万数量级的权重矩阵和亿万数量级的训练样本意味着训练这个模型将会是个灾难。

- 负采样,用来提高训练速度并且改善所得词向量的质量的一种方法。不同于原本每个训练样本更新所有的权重,负采样每次让一个训练样本仅仅更新一小部分权重,这样就会降低梯度下降过程中的计算量。

- 层序softmax,也是解决这个问题的一种方法。

四、fastText

        fastText是一种Facebook AI Research在16年开源的一个文本分类器。fastText专注于文本分类,在许多标准问题上实现当下最好的表现(例如文本倾向性分析或标签预测)。文本分类是许多应用程序的核心问题,例如垃圾邮件检测、情感分析或智能回复等。

与基于神经网络的分类算法相比有以下优点:

(1)fastText在保持高精度的情况下加快了训练速度和测试速度。

(2)fastText不需要预训练好的词向量,fastText会自己训练词向量。

(3)fastText两个重要的优化:Hierarchical Softmax、N-gram

层次少的好处不只在于运算速度快,而且更容易归因,定位重要特征以及估计对应的权重,不像深度网络的数据都散布在各层的结点之中。

         fastText方法包含三部分:模型架构、层次softmax和N-gram特征。fastText模型架构和word2vector中的CBOW模型很类似。不同之处在于fastText预测标签,而CBOW模型预测中间词

fastText词向量与word2vector对比

模型的输入层:word2vec的输入层是context window中的term;而fastText对应的整个sentence的内容,包括term,也包括n-gram的内容。

模型的输出层:word2vec的输出层,对应的是每一个term,计算某term的概率最大,而fastText的输出层对应的是分类的label。不过不管输出层对应的是什么内容,其对应的vector都不会被保留和使用。

两者本质的不同,体现在h-softmax的使用:

word2vec的目的是得到词向量,该词向量最终在输入层得到,输出层对应的h-softmax也会生成一系列的向量,但最终都会被抛弃,不会使用。

fastText则充分使用了h-softmax的分类功能,遍历分类树的所有叶结点,找到概率最大的label(一个或者N个)。

再一次强调fastText的重要优化是使用了 N-gram 和 Hierarchical Softmax 。接下来便来详细了解N-gram和Hierarchical Softmax 究竟带来了什么优化。

首先回顾下N-gram算法的特点。

- N-grams 提供了一种紧凑的文本表示方式,可以用于文本分类、信息检索等任务。通过将文本转换为 N-grams,可以将文本映射到一个固定长度的向量,从而方便输入到机器学习模型中。

- 由于 N-grams 只考虑连续的 N 个项,相比于考虑整个文本的全局信息,它们的计算效率较高。这对于处理大规模文本数据是一个优点。

- N-grams 考虑了文本中相邻的单元,因此保留了一定的上下文信息。这使得它对于语言模型和序列建模任务很有用,因为它可以捕捉到单词之间的关联性。

        以上特点使得fastText的性能变得更好,且由于能考虑词序关系和上下文信息,因此fastText在文本分类或情感分析中能够实现更高的准确率。例如“你礼貌吗”和“礼貌你吗”的子词构成是一样的,顺序不同,在语义或情感上就有很大差别。

接下来介绍Hierarchical Softmax。

        softmax函数常在神经网络输出层充当激活函数,目的就是将输出层的值归一化到(0,1)区间构造成概率分布,下图展示了softmax函数对于输出值z1=3、z2=1,z3=-3的归一化映射过程。

        在标准的softmax中,当计算一个类别的softmax概率时,我们需对所有类别概率做归一化,这在类别很多情况下非常耗时,因此提出了Hierarchical Softmax,思想是根据类别的频率构造哈夫曼树来代替标准softmax(即根据统计词频,构建词库哈夫曼树,叶子节点数量就是词库大小),通过分层softmax可以将复杂度从N降低到logN。我们把所有都要计算的从输出softmax层的概率计算变成了一颗二叉哈夫曼树(频率高的词路径更短),那么我们的softmax概率计算只需要沿着树形结构进行就可以了。

       下图给出了分层softmax的示例。例如“足球”,沿着根节点走(路径为1001)即可到达,换句话说,通过四个二分类模型即可得到输出“足球”。可以发现,在哈夫曼树中,隐藏层到输出层的softmax映射不是一下子完成的,而是沿着哈夫曼树结构一步步完成的,因此这种softmax取名为"Hierarchical Softmax",也叫层级softmax。

        怎么构建这个含有多个二分类模型的哈夫曼树模型呢?这个时候,你是不是想到了某个经典的二分类模型呢?没错,就是逻辑回归,逻辑回归的好处就是模型简单,并且求导方便。到这里,你应该已经明白了Hierarchical Softmax实际上就是训练多个逻辑回归二分类模型的过程

        对于Hierarchical Softmax本身,目标就是找到合适的所有节点的词向量和所有内部节点θ, 使所有训练样本达到最大似然。在层次softmax模型中,叶子结点的词没有直接输出的向量,而非叶子结点在模型的训练过程中都有相应的输出。通过哈夫曼编码,构造了一颗庞大的哈夫曼树,同时会给非叶子节点赋予向量。我们要计算的是目标词w的概率,这个概率的具体含义是指从根节点开始随机走,走到目标词w的概率。

综上所述,Hierarchical Softmax 为fastText带来的优化是解决了原始神经网络计算成本非常高昂的问题。

# 最后再补充一个前文所提到过的训练优化方法------负采样。

        前文已经介绍了Hierarchical Softmax可以有效解决原始神经网络计算成本高的问题,我们可以发现,虽然针对高频词(靠近根节点的词)计算少了,但对于低频词(距离根节点较远的词)依然需要多次计算才行,尤其是当我们的语料库非常大的时候。

        词库的数量一般都非常大,导致最后的多分类任务计算复杂,主要原因是因为我们一次计算的负例太多(除了目标词,其他词都是负例),那么在计算时我们是不是可以减少负例的数量呢?负采样(Negative Sampling)就是这么一种优化训练(比如应用在求解word2vector模型中)的方法,它摒弃了Hierarchical Softmax中构造层级二分类的做法。
        假设我们的词库大小是十万,计算时除了一个是正例外,其它99999个都是负例,负采样(Negative Sampling)的做法是不再把这99999个负例都拿来参与计算,因为大多数都和当前词没什么关系,只取其中的neg个负例参与计算。利用这一个正例和neg个负例,我们进行二元逻辑回归,得到负采样对应每个词对应的模型参数θ和每个词的词向量,从而降低计算量(实际上就是训练neg+1个二分类模型)。从上面描述可以看出,Negative Sampling由于没有采用哈夫曼树,每次只是通过采样neg个不同的中心词做负例,就可以训练模型,因此整个过程要比Hierarchical Softmax简单。

在逻辑回归中:

中心词正例(y=1,表示label为1,正例)应该满足:P(context(w_{0}),\; w_{i})=\sigma (x_{w_{0}}^{T}\: \theta ^{w_{i}}),\; y_{i}=1,\; i=0

负采样负例(y=0,表示label为0,负例)应该满足:

P(context(w_{0}),\; w_{i})=1-\sigma (x_{w_{0}}^{T}\: \theta ^{w_{i}}),\; y_{i}=0,\; i=1,2,...neg

对于一个训练样本,neg个负例的最大似然如下,同时我们期望最大化:

L=\prod_{i=0}^{neg}P(context(w_{0}),\; w_{i})=\sigma (x_{w_{0}}^{T}\: \theta ^{w_{i}})\prod_{i=1}^{neg}\: (1-\sigma (x_{w_{0}}^{T}\: \theta ^{w_{i}}))=\prod_{i=0}^{neg}\: \sigma (x_{w_{0}}^{T}\: \theta ^{w_{i}})^{y_{i}}(1-\sigma (x_{w_{0}}^{T}\: \theta ^{w_{i}}))^{1-y_{i}}

对数处理结果为:

L=\sum_{i=0}^{neg}\; y_{i}log(\sigma (x_{w_{0}}^{T}\: \theta ^{w_{i}}))+(1-y_{i})log(1-\sigma (x_{w_{0}}^{T}\: \theta ^{w_{i}}))

分别求导如下(求导过程利用sigmoid求导公式):

\frac{\partial L}{\partial \theta ^{w_{i}}}=y_{i}(1-\sigma (x_{w_{0}}^{T}\: \theta ^{w_{i}}))x_{w_{0}}-(1-y_{i})\sigma (x_{w_{0}}^{T}\: \theta ^{w_{i}})x_{w_{0}}=(y_{i}-\sigma (x_{w_{0}}^{T}\: \theta ^{w_{i}}))x_{w_{0}}

\frac{\partial L}{\partial x^{w_{0}}}=\sum_{i=0}^{neg}\; (y_{i}-\sigma (x_{w_{0}}^{T}\: \theta ^{w_{i}}))\theta ^{w_{i}}

根据上面偏导结合学习率,利用梯度上升法进行迭代就可以求解我们需要的词向量X和参数
        最后,我们还有一个遗留问题没有解决,就是怎么进行采样?如何从所有负例中选择出neg个负例?例如在word2vector模型中,假设词汇表的大小为V,那么我们就将一段长度为1的线段分成V份,每份对应词汇表中的一个词。当然每个词对应的线段长度是不一样的,高频词对应的线段长,低频词对应的线段短。每个词w的线段长度由其词频决定:

len(w)=\frac{count(w)}{\sum_{u\in vocab}^{}count(u)}

分子是该词在训练集中出现的次数,分母是训练集中所有词出现的次数和。在word2vec中,分子和分母都取了3/4次幂如下:

len(w)=\frac{count(w)^{3/4}}{\sum_{u\in vocab}^{}count(u)^{3/4}}

        在采样前,我们将这段长度为1的线段划分成M等份,这里M>>V。这样可以保证每个词对应的线段都会划分成对应的小块。而M份中的每一份都会落在某一个词对应的线段上。在采样的时候,我们只需要从M个位置中采样出neg个位置就行,此时采样到的每一个位置对应到的线段所属的词就是我们的负例词。可以发现,和Hierarchical Softmax一样,Negative Sampling也认为高频词被采样到的概率更大。当然,在采样过程中会避免出现重复采样的情况,或者可以认为是词库级别的不放回采样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值