递归神经网络教程请签收!

点击上方关注,All in AI中国

作者——William Koehrsen

使用递归神经网络撰写专利摘要

当我第一次尝试研究递归神经网络时,我犯了一个错误,我试图先学习LSTM和GRU之类的理论。在研究线性代数方程的几天之后,我在Python的深度学习中偶然发现了下面这段话(https://www.manning.com/books/deep-learning-with-python):

总之,你不需要了解LSTM单元的所有具体架构;作为一个人,理解它不应该是你的工作。请记住LSTM单元的作用:允许过去的信息在以后重新注入。

递归神经网络教程请签收!

这是深度学习专家Keras(Francois Chollet的作者),他告诉我,我不需要了解基础层面的所有内容!我意识到我的错误是从理论开始的底层开始的,而不仅仅是试图构建一个递归的神经网络。

此后不久,我改变了策略,决定尝试最有效的学习数据科学技术的方法:找到问题并解决它!

通过这种方式,我能够弄清楚在此过程中我需要知道什么,当我重新研究概念时,我就有了一个框架,我可以适应每个想法。在这种心态中,我决定不再担心细节,完成一个递归的神经网络项目。

本文将介绍如何在Keras中构建和使用递归神经网络来编写专利摘要。这篇文章很清楚这个理论,但是当你完成这个项目时,你会发现你在过程中会学到你需要知道的东西。最终结果是,你可以构建一个有用的应用程序,并弄清楚自然语言处理的深度学习方法是如何工作的。

(完整代码在GitHub上作为一系列Jupyter笔记本提供https://github.com/WillKoehrsen/recurrent-neural-networks。我还提供了所有预先训练好的模型https://github.com/WillKoehrsen/recurrent-neural-networks/tree/master/models,因此你不必自己训练几个小时!要尽快开始并研究模型,请参阅快速开始递归神经网络(https://github.com/WillKoehrsen/recurrent-neural-networks/blob/master/notebooks/Quick%20Start%20to%20Recurrent%20Neural%20Networks.ipynb,有关深入解释,请参阅深入到递归神经网络https://github.com/WillKoehrsen/recurrent-neural-networks/blob/master/notebooks/Deep%20Dive%20into%20Recurrent%20Neural%20Networks.ipynb)

递归神经网络

在开始实施之前,至少理解一些基础知识是有帮助的。在高层次上,递归神经网络(RNN)处理序列——无论是每日股票价格、句子还是传感器测量——一次只处理一个元素,同时保留之前在序列中所存在的记忆(称为状态)。

递归意味着当前时间步的输出成为下一个时间步的输入。在序列的每个元素上,模型不仅考虑当前输入,还考虑它对前面元素的记忆。

递归神经网络教程请签收!

RNN概述(来源:https://www.manning.com/books/deep-learning-with-python)

该记忆网络允许网络学习序列中的长期依赖性,这意味着它可以在进行预测时考虑整个上下文,无论是句子中的下一个单词,情感分类还是下一个温度测量。RNN旨在模仿人类处理序列的方式:我们在形成响应是应该考虑整个句子,而不是单词本身。例如,请考虑以下句子:

"演唱会在乐队热身前的15分钟里很无聊,但随后就非常令人兴奋。"

如果机器学习模型只考虑单独的单词,可能会得出结论,这句话是否定的。相比之下,RNN应该能够看到单词"但"和"非常令人兴奋"并且意识到句子从否定变为了肯定,因为它查看了整个序列。读取整个序列为我们提供了处理其含义的背景,这是一种在递归神经网络中编码的概念。

RNN的核心是由记忆网络单元构成的层。目前最流行的单元是长短期记忆网络(LSTM:https://en.wikipedia.org/wiki/Long_short-term_memory),它可以保持单元状态以及进位,以确保在处理序列时信号(梯度形式的信息:https://stats.stackexchange.com/questions/185639/how-does-lstm-prevent-the-vanishing-gradient-problem)不会丢失。在每个时间步中,LSTM都会考虑当前单词、进位和单元状态。

递归神经网络教程请签收!

LSTM(长短期记忆网络)

LSTM有3个不同的门和权重向量:有一个"遗忘"门用于丢弃无关信息;一个"输入"门用于处理当前输入,以及用于在每个时间步产生预测的"输出"门。然而,正如Chollet指出的那样,尝试为单元中的每个元素指定特定含义是徒劳的。

每个单元元素的特性最终由训练期间学习的参数(权重)决定。随意标记每个单元部分,但这并不是有效使用的必要条件!回想一下,递归神经网络对序列学习的好处是它维持整个序列的记忆,防止先前信息丢失。(https://machinelearningmastery.com/sequence-prediction-problems-learning-lstm-recurrent-neural-networks/)

问题制定

我们可以通过多种方式制定训练RNN编写文本的任务,在本文示例中是专利摘要。但是,我们会选择将其作为多对一序列映射器进行训练。也就是说,我们输入一系列单词并训练模型以预测下一个单词。在传递到LSTM层之前,将使用嵌入矩阵(预先训练的或可训练的)将单词映射到整数然后映射到向量。

当我们去写一个新的专利时,我们传入一个单词的起始序列,对下一个单词进行预测,更新输入序列,进行另一个预测,将单词添加到序列中,然后继续生成任意数量的单词。

该方法的步骤概述如下:

  1. 将字符串列表中的摘要转换为整数列表(序列)
  2. 从序列中创建特性和标签
  3. 使用嵌入层,LSTM和密集层构建LSTM模型
  4. 加载预先训练好的嵌入
  5. 训练模型以按顺序预测下一步工作
  6. 通过传递起始序列进行预测

请记住,这只是问题的一个表述:我们还可以使用字符级模型或对序列中的每个单词进行预测。与机器学习中的许多概念一样,没有一个正确的答案,但这种方法在实践中很有效。

数据准备

即使具有神经网络强大的表示能力,获得高质量、干净的数据集也是至关重要的。该项目的原始数据来自USPTO PatentsView(http://www.patentsview.org/querydev/),你可以在其中搜索有关在美国申请的任何专利的信息。我搜索了"神经网络"这个术语并下载了最终的专利摘要——总共3500个。我发现最好是在狭窄的领域上进行训练,但可以尝试使用不同的专利。

递归神经网络教程请签收!

专利摘要数据

我们将从专利摘要作为字符串列表开始。我们模型的主要数据准备步骤是:

  1. 删除标点符号并将字符串拆分为单个单词列表
  2. 将单个单词转换为整数

这两个步骤都可以使用Keras (https://keras.io/preprocessing/text/#tokenizer)、Tokenizer(https://keras.io/preprocessing/text/#tokenizer)类完成。 默认情况下,这将删除所有标点符号、小写单词,然后将单词转换为整数序列。Tokenizer首先适合于字符串列表,然后将此列表转换为整数列表列表。如下所示:

递归神经网络教程请签收!

第一个单元格的输出显示原始摘要,第二个单元格的输出显示标记化序列。每个摘要现在都表示为整数。

我们可以使用经过训练的tokenizer的idx_word属性来确定每个整数的含义:

递归神经网络教程请签收!

如果你仔细观察,你会注意到Tokenizer已经删除了所有标点并小写化了所有单词。如果我们使用这些设置,那么神经网络将无法学习正确的英语!我们可以通过将过滤器更改为Tokenizer来调整这一点,以避免删除标点符号。

递归神经网络教程请签收!

请参阅笔记本中的不同实现,但是,当我们使用预先训练的嵌入时,我们必须删除大写,因为嵌入中没有小写字母。在训练我们自己的嵌入时,我们不必担心这个问题,因为模型将学习不同的大小写表示形式。

特性和标签

上一步将所有摘要转换为整数序列。下一步是创建一个用于训练网络的监督机器学习问题。你可以通过多种方式为文本生成设置递归神经网络任务,但我们将使用以下方法:

为网络提供一系列单词并训练它以预测下一个单词。

单词数留作参数;我们将使用50表示这里显示的示例,这意味着我们为网络提供50个单词,并对其进行训练以预测第51个单词。训练网络的其他方法是让它预测序列中每个点的下一个词——对每个输入词进行预测,而不是对整个序列进行一次预测——或者使用单个字符训练模型。这里使用的实现不一定是最优的(没有公认的最佳解决方案)但它运作良好!

创建特性和标签相对简单,对于每个摘要(表示为整数),我们创建多组特性和标签。我们使用前50个单词作为特性,第51个单词作为标签,然后使用2-51个单词作为特性并预测第52个单词等等。这为我们提供了更多的训练数据,这是有益的,因为网络的性能与它在训练期间看到的数据量成比例(https://research.google.com/pubs/archive/35179.pdf)。

创建功能和标签的实现如下:

递归神经网络教程请签收!

这些特性最终以shape(296866,50)结束,这意味着我们有近300,000个序列,每个序列有50个标签。在递归神经网络的语言中,每个序列具有50个时间步长,每个具有1个特性。

我们可以将标签保留为整数,但是当标签是独热编码时,神经网络能够最有效地训练。我们可以使用以下内容快速对numpy的标签进行独热编码:

递归神经网络教程请签收!

要查找与label_array中的行对应的单词,我们使用:

递归神经网络教程请签收!

在将所有特性和标签格式化后,我们希望将它们分成训练和验证集(有关详细信息,请参阅笔记本)。这里的一个重点是要同时对特性和标签进行调整,这样相同的摘要就不会全部集中在一起。

建立一个递归神经网络

Keras是一个令人难以置信的库:它允许我们用几行可理解的Python代码构建最先进的模型。虽然其他神经网络库可能更快或允许更大的灵活性(https://deepsense.ai/keras-or-pytorch/),但在开发时间和易用性方面,没有什么能够超越Keras。

下面是一个简单LSTM的代码,其解释如下:

递归神经网络教程请签收!

递归神经网络教程请签收!

递归神经网络教程请签收!

我们正在使用Keras序列API,这意味着我们一次构建一个网络层。层次如下:

  • 将每个输入字映射到100维向量的嵌入。嵌入可以使用我们在权重参数中提供的预训练权重。如果我们不想更新嵌入,可以将trainable设置为False。
  • 一个屏蔽层,用于屏蔽任何没有经过预训练嵌入的单词,这些单词将被表示为零。在训练嵌入时不应使用此层。
  • 网络的核心:一层LSTM单元,具有防止过度拟合的特性(https://machinelearningmastery.com/dropout-regularization-deep-learning-models-keras/)。由于我们只使用一个LSTM层,因此不返回序列,如果使用两个或更多层,请确保返回序列。
  • 具有relu激活的完全连接的密集层。这为网络增加了额外的表示能力。
  • Dropout层可防止过度拟合训练数据。
  • 密集的全连接输出层。这使用softmax激活产生词汇中每个单词的概率。

该模型使用Adam优化器(随机梯度下降的一种变体)编译,并使用categorical_crossentropy损失进行训练。在训练期间,网络将尝试通过调整可训练参数(权重)来最小化损失。与往常一样,参数的梯度使用反向传播计算并使用优化器进行更新(http://neuralnetworksanddeeplearning.com/chap2.html)。由于我们使用的是Keras,因此我们不必担心在幕后如何发生这种情况(https://machinelearningmastery.com/5-step-life-cycle-neural-network-models-keras/),只需要正确设置网络即可。

递归神经网络教程请签收!

LSTM网络布局

在不更新嵌入的情况下,在网络中需要训练的参数更少。LSTM层的输入是(None,50,100),这意味着对于每个批次(第一个维度),每个序列具有50个时间步长(单词),每个序列在嵌入后具有100个特性。LSTM图层的输入始终具有(batch_size,timesteps,features)形状。

构建此网络的方法有很多种,笔记本中还包含其他几种方法(https://github.com/WillKoehrsen/recurrent-neural-networks/blob/master/notebooks/Deep%20Dive%20into%20Recurrent%20Neural%20Networks.ipynb)。例如,我们可以使用两个堆叠在一起的LSTM层,一个双向LSTM层,用于处理来自两个方向的序列,或更多的密集层。

预训练嵌入

一旦建立了网络,我们仍然必须为其提供预先训练好的嵌入词。你可以在不同的语料库上在线搜索大量嵌入(http://ahogrammer.com/2017/01/20/the-list-of-pretrained-word-embeddings/)。我们将使用的那些可以从斯坦福获得的,并且有100,200或300维度(我们将坚持100)。这些嵌入来自GloVe(https://nlp.stanford.edu/projects/glove/)算法,并在维基百科上进行了训练。

即使预先训练好的嵌入包含400,000个单词,但我们的词汇中也会包含一些单词。当我们用嵌入来表示这些单词时,它们将具有全零的100-d向量。可以通过训练我们自己的嵌入或通过将嵌入层的可训练参数设置为True(并移除屏蔽层)来解决此问题。

我们可以快速加载来自磁盘的预训练嵌入,并使用以下代码制作嵌入矩阵:

递归神经网络教程请签收!

递归神经网络教程请签收!

这样做是为词汇中的每个单词分配一个100维向量。如果单词没有预先训练的嵌入,则该向量将全为零。

递归神经网络教程请签收!

为了探索嵌入,我们可以使用余弦相似性来找到嵌入空间中最接近给定查询字的单词:

递归神经网络教程请签收!

嵌入是学习的(https://towardsdatascience.com/neural-network-embeddings-explained-4d028e6f0526),这意味着表示只适用于一个任务。当使用预先训练的嵌入时,我们希望嵌入式学习的任务足够接近我们的任务,因此嵌入是有意义的。如果这些嵌入是通过推文进行训练的,我们可能不会期望它们能够很好地工作,但由于它们接受过维基百科数据的训练,因此它们通常适用于一系列语言处理任务。

如果你有大量数据和时间,通常最好为特定任务学习自己的嵌入。在笔记本中我采用了两种方法,学习嵌入的性能稍好一些。

训练模型

通过准备训练和验证数据,构建网络以及加载嵌入,我们几乎可以为我们的模型学习如何编写专利摘要。但是,在训练神经网络时要采取的最好步骤是以Keras回调的形式使用ModelCheckpoint和EarlyStopping(https://keras.io/callbacks/):

  • 模型检查点:将最佳模型(通过验证丢失测量)保存在磁盘上以使用最佳模型
  • 早期停止:当验证损失不再减少时停止训练

使用早期停止意味着我们不会过度使用训练数据并浪费时间去训练那些不会提高性能的额外时期。模型检查点意味着我们可以访问最佳模型,如果我们的训练在1000个时期中断,我们将不会失去所有进展!

递归神经网络教程请签收!

然后可以使用以下代码训练模型:

递归神经网络教程请签收!

在亚马逊p2.xlarge实例上(https://aws.amazon.com/ec2/instance-types/p2/),这只花了1个多小时就完成了。训练完成后,我们可以加载最佳保存模型并评估验证数据的最终时间。

递归神经网络教程请签收!

总体而言,使用预先训练的单词嵌入的模型实现了23.9%的验证准确性。作为一个人,我发现很难预测这些摘要中的下一个词! 对最常用词("the")的猜测产生的准确率约为8%。笔记本中所模式的指标如下所示:

递归神经网络教程请签收!

最好的模型使用预先训练的嵌入和如上所示的相同架构。我鼓励任何人尝试使用不同模式的训练!

专利摘要生成

当然,虽然高指标很好,但重要的是网络是否可以产生合理的专利摘要。使用最佳模型,我们可以探索模型生成能力。如果你想在自己的硬件上运行它,你可以在这里找到笔记本(https://github.com/WillKoehrsen/recurrent-neural-networks/blob/master/notebooks/Exploring%20Model%20Results.ipynb),预先训练好的模型在GitHub上(https://github.com/WillKoehrsen/recurrent-neural-networks/tree/master/models)。

为了产生输出,我们使用从专利摘要中选择的随机序列为网络播种,使其预测下一个单词,将预测添加到序列中,并继续对我们想要的许多单词进行预测。一些结果如下所示:

递归神经网络教程请签收!

输出的一个重要参数是预测的多样性。我们不是使用具有最高概率的预测词,而是将多样性注入到预测中,然后选择具有与更多样化预测成比例的概率的下一个词。多样性过高,生成的输出就会显得随机,而多样性太低,网络就会进入递归的输出循环。

递归神经网络教程请签收!

输出也不错!有些时候很难确定哪个是计算机生成的,哪个来自机器。部分原因在于专利摘要的性质,大多数时候,这听起来并不像是人类写的。

网络的另一个用途是用我们自己的起始序列播种它。我们可以使用我们想要的任何文本,并查看网络所在的位置:

递归神经网络教程请签收!

同样,结果并不完全可信,但它们确实类似于英语。

人或机器?

作为递归神经网络的最终测试,我创建了一个游戏来猜测是模型还是人类产生了输出。这是第一个示例,其中两个选项来自计算机,一个来自人类:

递归神经网络教程请签收!

你怎么猜?答案是第二个是一个人写的实际摘要(嗯,这实际上是抽象的。我不确定这些摘要是由人写的)。这是另一个:

递归神经网络教程请签收!

这一次,第三个是人写的。

我们可以使用其他步骤来解释模型,例如找出不同的输入序列会激活哪些神经元。我们还可以查看学习到的嵌入(或使用Projector工具将其可视化)。

结论

重要的是要认识到递归神经网络没有语言理解的概念。它实际上是一种非常复杂的模式识别机器。尽管如此,与马尔可夫链或频率分析等方法不同,RNN基于序列中元素的排序进行预测。从哲学角度讲,你可以说人类只是极端的模式识别机器,因此递归神经网络只是像人类机器一样运作。

递归神经网络的使用远远超出了文本生成、机器翻译、图像字幕和作者身份识别。虽然我们在这里介绍的这个应用程序不会取代任何人类,但可以想象,通过更多的训练数据和更大的模型,神经网络将能够合成新的、合理的专利摘要。

递归神经网络教程请签收!

双向LSTM单元

人们很容易陷入细节或复杂技术背后的理论,但学习数据科学工具的一种更有效的方法是深入研究并构建应用程序。一旦你知道一种技术的能力以及它在实践中的运作方式,你就可以回过头来再研究这个理论。我们大多数人不会设计神经网络,但学习如何有效地使用它们是值得的。

递归神经网络教程请签收!

相关推荐