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

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



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

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

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

一个简单的模型

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

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

该模型可以分为两部分:

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

第二个组件可以看作是一个解码器。在编码步骤之后,我们有输入字的表示方式。我们将它乘上一个大小的矩阵(200,N),我们称之为输出embedding(V)。所得到的矢量大小为N,然后通过softmax函数,将其归一化为概率分布(意味着每个值都在0和1之间,并且它们的和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层,每层包含1500个LSTM单元,我们实现了一个困惑度为78的模型创建。

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

Weight Tying权重绑定):

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

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

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

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

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

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

时间: 2024-08-30 17:10:12

零基础进行神经网络语言建模的相关文章

零基础入门深度学习(5) - 循环神经网络

  在前面的文章系列文章中,我们介绍了全连接神经网络和卷积神经网络,以及它们的训练和使用.他们都只能单独的取处理一个个的输入,前一个输入和后一个输入是完全没有关系的.但是,某些任务需要能够更好的处理序列的信息,即前面的输入和后面的输入是有关系的.   比如,当我们在理解一句话意思时,孤立的理解这句话的每个词是不够的,我们需要处理这些词连接起来的整个序列:当我们处理视频的时候,我们也不能只单独的去分析每一帧,而要分析这些帧连接起来的整个序列.这时,就需要用到深度学习领域中另一类非常重要神经网络:循

零基础入门深度学习(3) - 神经网络和反向传播算法

   神经元   神经元和感知器本质上是一样的,只不过我们说感知器的时候,它的激活函数是阶跃函数:而当我们说神经元时,激活函数往往选择为sigmoid函数或tanh函数.如下图所示:       sigmoid函数的定义如下:     将其带入前面的式子,得到     sigmoid函数是一个非线性函数,值域是(0,1).函数图像如下图所示     sigmoid函数的导数是:     可以看到,sigmoid函数的导数非常有趣,它可以用sigmoid函数自身来表示.这样,一旦计算出sigmoi

零基础入门深度学习(三):卷积神经网络

投稿:Intelligent Software Development 团队介绍:团队成员来自一线互联网公司,工作在架构设计与优化.工程方法研究与实践的最前线,曾参与搜索.互联网广告.共有云/私有云等大型产品的设计.开发和技术优化工作.目前主要专注在机器学习.微服务架构设计.虚拟化/容器化.持续交付/DevOps等领域,希望通过先进技术和工程方法最大化提升软件和服务的竞争力.   在前面的文章中,我们介绍了全连接神经网络,以及它的训练和使用.我们用它来识别了手写数字,然而,这种结构的网络对于图像

零基础入门深度学习(4) - 卷积神经网络

在前面的文章中,我们介绍了全连接神经网络,以及它的训练和使用.我们用它来识别了手写数字,然而,这种结构的网络对于图像识别任务来说并不是很合适.本文将要介绍一种更适合图像.语音识别任务的神经网络结构--卷积神经网络(Convolutional Neural Network, CNN).说卷积神经网络是最重要的一种神经网络也不为过,它在最近几年大放异彩,几乎所有图像.语音识别领域的重要突破都是卷积神经网络取得的,比如谷歌的GoogleNet.微软的ResNet等,打败李世石的AlphaGo也用到了这

《C语言编程——零基础初学者指南(第3版)》一第2章 编写第一个C程序2.1 概述

第2章 编写第一个C程序 C语言编程--零基础初学者指南(第3版)本章内容 编写第一个程序使用main()函数识别数据类型本章将教你如何编写第一个C程序!如果无法理解本章的所有内容,请不要着急.放轻松些,你的目标是先熟悉C程序.经过本章的学习,你要学会识别所有C程序的共同元素. 2.1 概述 C语言编程--零基础初学者指南(第3版)本节将介绍一个简短但完整的C程序,并讨论附录B中的另一个程序--"Draw Poker扑克游戏".这两个程序都包含一些共同和不同的元素.第一个程序相当简单:

《C语言编程——零基础初学者指南(第3版)》一2.3 数据的种类

2.3 数据的种类 C语言编程--零基础初学者指南(第3版)C程序所使用的数据由数字.字符和单词组成.程序将数据处理为有意义的信息.在C程序设计中有各种不同类型的数据,最常见的三种数据类型是: 字符整型数浮点型数(也称为实数)提示 你也许会问:"我需要具备多少数学知识?!这不公平!"别急,轻松点,C语言会帮你处理数学的问题.不一定非要学会2+2才能写C程序.但是,你必须要理解数据类型,否则无法为自己的程序选择合适的类型. 2.3.1 C语言中的字符 C语言中的字符是计算机可以表示的任意

零基础入门深度学习(六):递归神经网络

递归神经网络是啥    因为神经网络的输入层单元个数是固定的,因此必须用循环或者递归的方式来处理长度可变的输入.循环神经网络实现了前者,通过将长度不定的输入分割为等长度的小块,然后再依次输入到网络中,从而实现了神经网络对变长输入的处理.   一个典型的例子是,当我们处理一句话时,我们可以把一句话看作是词组成的序列,然后,每次向循环神经网络输入一个词,如此循环直至整句话输入完毕,循环神经网络将产生对应的输出.如此,我们就能处理任意长度的句子了.如下图所示:     然而,有时候把句子看做是词的序列

零基础入门深度学习(二):神经网络和反向传播算法

投稿:Intelligent Software Development 团队介绍:团队成员来自一线互联网公司,工作在架构设计与优化.工程方法研究与实践的最前线,曾参与搜索.互联网广告.共有云/私有云等大型产品的设计.开发和技术优化工作.目前主要专注在机器学习.微服务架构设计.虚拟化/容器化.持续交付/DevOps等领域,希望通过先进技术和工程方法最大化提升软件和服务的竞争力.   在上一篇文章<零基础入门深度学习:感应器.线性单元和梯度下降>中,我们已经掌握了机器学习的基本套路,对模型.目标函

零基础易语言入门教程(二)之编程思路_易语言

易语言简介: 易语言是一门以中文作为程序代码编程语言.以"易"著称.创始人为吴涛.早期版本的名字为E语言.易语言最早的版本的发布可追溯至2000年9月11日.创造易语言的初衷是进行用中文来编写程序的实践.从2000年至今,易语言已经发展到一定的规模,功能上.用户数量上都十分可观. 上一篇跟大家讲了零基础易语言入门教程(一)编写第一个程序,然后接下来大家应该自己把支持库和易语言组件里面的控件全部认真的看一下,下面我直接跟大家分享下易语言简单编程思路. 方法和步骤如下所示: 1.易语言程序