零基础进行神经网络语言建模

更多深度文章,请关注:https://yq.aliyun.com/cloud


零基础进行神经网络语言建模

语言模型是自然语言处理领域的基础问题,其在词性标注、句法分析、机器翻译、信息检索等任务中起到了重要作用。简而言之,统计语言模型表示为:在词序列中,给定一个词和上下文中所有词,这个序列出现的概率。例如:你手机上键盘上方正显示的三个字,系统试图预测你要输入的下一个字词就是语言建模的用途之一。在下面所示的情况下,语言模型预测“from”“on”“it”在给定句子中具有很高的下一个单词的可能性。其实输入法系统内部,语言模型都会计算词汇中的每个单词的出现的概率,但是用户只能看到前三个最可能的单词。

零基础进行神经网络语言建模

语言模型是许多系统的基本部分,它试图解决机器翻译和语音识别等自然语言处理任务。目前,所有的最先进的语言模型都是神经网络。

这篇文章的第一部分提供了一个简单的前馈神经网络来解决这个任务。在帖子的第二部分,我们将通过添加一个循序神经网络(RNN)来改进简单的神经网络模型。最后一部分将讨论两种最近提出的改进基于RNN的语言模型的正则化技术。

一个简单的模型

作为开始,我们将建立一个简单的模型,给出一个单词,然后尝试预测其后的单词。

零基础进行神经网络语言建模

我们使用one-hot向量来表示单词:我们让词汇表中单词任意排序,然后将该n词表示为词汇量为(N)大小的向量。其中绝大多数标记为0,只有一个标记为 1,代表当前的词。

该模型可以分为两部分:

我们从编码输入字开始。通过取代表输入字的one-hot矢量(c在图中),并将其乘以(N,200)我们称为输入embeddingU)的大小矩阵。通过该乘法产生一个大小为200的向量,这也被称为词嵌入。该嵌入是当前输入字的密集式表征(dense representation)。该表示的大小要小于表示相同单词的单热矢量,而且它还具有一些其他有趣的属性。例如,虽然由one-hot向量表示的每两个词之间的距离总是相同的,但是这些密集式表征却具有这样的属性,即在意义上接近的词具有在嵌入空间中接近密集式表征。

第二个组件可以看作是一个解码器。在编码步骤之后,我们有输入字的表示方式。我们将它乘上一个大小的矩阵(200,N),我们称之为输出embeddingV)。所得到的矢量大小为N然后通过softmax函数,将其归一化为概率分布(意味着每个值都在01之间,并且它们的和1)。

解码器是一个简单的函数,它接受输入单词的表征,并返回一个模型表示对下一个单词的预测的分布:该模型显示每个单词成为序列中下一个单词的概率。

为了训练这个模型,我们需要一对输入和目标输出字。对于(input, target-output),我们使用Penn Treebank数据集,其中包含来自新闻文章的约40K个句子,并且具有10,000常用词汇。为了生成模型学习的单词对,我们将从文本中获取每对相邻单词,并将第一个作为输入单词,将第二个单词作为目标输出单词。因此,例如,对于句子“The cat is on the mat”:我们将提取下列词对(The, cat)(cat, is)(is, on)等等。

我们使用随机梯度下降来更新训练中的模型,所用的损失是交叉熵损失。这种损失测量了模型预测的输出分布与每次迭代的目标分布之间的差距。每次迭代的目标分布是表示当前目标字的one-hot矢量。

用于表示语言模型性能的度量标准是测试集的困惑度。最佳困惑度为1,而简单模型的困惑度为183但,我们可以通过更好的办法来提升其性能。

使用RNN来提高性能

简单模型的最大问题是,为了预测句子中的下一个单词,它只使用单个前一个单词。如果我们可以建立一个能够记住前面几句话的模型,那么它的性能应该会有所提高。我们用一个例子来理解我们为什么这样做!想想下面的例子:词语是什么?你可能会说咖啡啤酒苏打水有可能是它后面的词。如果我告诉你这个词序列实际上是奶牛喝,那么你就会完全改变你的答案。

我们可以通过使用循环神经网络RNN)来增加我们模型的记忆,如下所示。

零基础进行神经网络语言建模

该模型与简单的模型类似,只是在对当前输入字进行编码之后,我们将所得到的大小为200矢量式提供给两层LSTM,然后输出一个也是大小为200的向量(在每个时间步长内LSTM也会接收到一个向量表示其以前的状态,这在图中未表示出)。然后,我们使用解码器将这个输出向量转换成概率值的向量。(LSTM只是一个更好地记住过去爱好的RNN,它的“API”RNN“API”相同,每个时间步长内的LSTM接收到一个输入及其以前的状态,并使用这两个输入计算输出向量。)

现在我们有一个模型,在每个时间步骤内不仅获得当前的单词表示,而且还获取了上一个时间步长中LSTM的状态,并使用它来预测下一个单词。LSTM的状态是以前看到的单词的表示(注意,我们最近看到的单词对这个状态的影响比我们以前看到的有更大的影响)。

正如预期的那样,RNN模型的困惑度为114,性能有所提高,Tensorflow提供了此模型的实现以及详细的说明。

正则化的重要性

利用RNN虽然能够提高模型的性能,但是我们依然可以做得更好。在本节中,我将介绍一些改进RNN语言模型性能的最新进展。

Dropout

我们可以通过增加嵌入层和LSTM层来改进模型网络,但是随着层数的不断增加,很快就会停止增加性能,因为网络超出了训练数据的需求。通过规范模型来解决这个问题的一个方法是使用Dropout

Dropout是指在深度学习网络的训练过程中,对于神经网络单元,按照一定的概率将其暂时从网络中丢弃。关于Dropout的介绍:深度学习网络大杀器之Dropout——深入解析Dropout

下图是基于RNN模型的可视化,展示了三个时间步骤。x是输入序列和y输出序列,灰色框表示LSTM层。垂直箭头表示来自相同时间步长层的输入,水平箭头表示携带先前时间步长信息的连接。

零基础进行神经网络语言建模

我们可以在垂直(同一时间步)连接上应用Dropout

零基础进行神经网络语言建模

着色箭头代表我们应用Dropout的地方。某个层的缺陷掩码表示那个层被激活归零。在这种情况下,我们对不同的层使用不同的Dropout掩码(这由图中的不同颜色表示)。

Dropout应用于循环连接会损害性能,因此在初始使用Dropout时,我们仅在同一时间段内的连接上使用它。使用两个LSTM层,每层包含1500LSTM单元,我们实现了一个困惑度为78的模型创建。

最近引入的variational dropout 解决这个问题,并且通过在每个时间步长使用相同的dropout masks来提高模型的性能(模型困惑度75)。

零基础进行神经网络语言建模

Weight Tying权重绑定):

输入嵌入和输出嵌入有几个共同的属性。它们共同的第一个属性是它们都是相同的大小(在我们的具有DropoutRNN模型中,它们的大小都是(10000,1500))。

他们共有的第二个属性有点微妙。在输入嵌入中,具有相似含义的词由相似的向量(与余弦相似度相似)表示。这是因为该模型得知它需要以类似的方式对类似的单词做出反应(快速这个词之后的单词与极速一词相似)。

这个属性也出现在输出嵌入中。输出嵌入接收关于下一个输出字(RNN的输出),必须将其转换成概率分布。来自给定RNN的表征,解码器判断单词的概率主要取决于其在输出嵌入中的表示。因为模型想要提升RNN输出性能,就会将类似的概率值分配给类似的单词,类似的单词由相似的向量表示。(再者,如果给定一定的RNN输出,单词快速的概率相对较高,我们也预计单词极速的概率相对较高)。

这两个相似之处使我们最近提出了一个非常简单的方法:weight tying,以降低模型的参数并提高其性能。我们简单地把输入嵌入和输出嵌入联系在一起(即我们设置U = V,这意味着我们现在有一个单独的嵌入矩阵,既用作输入嵌入和有可以用作输出嵌入)。这使得使用DropoutRNN模型的困惑度降到了73

为什么weight tying权重绑定)可以起到作用?

变化的dropout RNN模型在测试集上的困惑度是75。相同的模型在训练集上实现了困惑度24的成绩。这意味着它已经开始记住仅在训练集中的某些模式或序列,并且不会让模型涉及到数据集不可见的数据。应对这种过度配合的一个方法就是通过降低模型的容量(参数数量)来降低模型的记忆能力。通过应用权重绑定(weight tying),我们删除了大量的参数。

除了权重绑定(weight tying)的正规化效果之外,我们提出了改进结果的另一个原因。那就是我们发现输出嵌入中的单词表示的质量远远高于无语言模型的输入嵌入中的表示。在一个权重绑定模型中,因为在每个训练迭代中绑定的嵌入参数更新与未解模型的输出嵌入的更新非常相似,所以绑定的嵌入与未解开的模型的输出嵌入相似。所以在绑定的模型中,我们在模型中使用单个高质量的嵌入矩阵。这有助于提高绑定模型性能(tied model)。

总结:这篇文章介绍了如何通过首先添加一个RNN,然后添加可变化的Dropout和权重绑定来改进一个非常简单的前馈神经网络语言模型。

近几个月来,我们已经看到RNN语言建模方面的最新进展。目前最新的结果由Melis等人最近的两篇论文。这些模型利用上面所示的大多数方法,并通过使用更好的优化技术,如新的正则化方法以及通过为现有模型找到更好的参数来扩展它们。这些方法中的一些将在本指南的第二部分中介绍。

本文由北邮@爱可可-爱生活老师推荐,@阿里云云栖社区组织翻译。

文章原标题《Neural-Language-Modeling-From-Scratch

作者:Ofir 目前作者正关注于自然语言处理领域。

博客:http://ofir.io

译者:袁虎 审阅:主题曲哥哥

文章为简译,更为详细的内容,请查看原文

上一篇:[PYTHON] 核心编程笔记之四-Python对象


下一篇:阿里云发布第七代云服务器ECS,整机算力提升160%