逐步解释和可视化的循环神经网络
应用于机器翻译
循环神经网络(RNN)是能够按顺序操作的神经网络。虽然它们不像几年前那样受欢迎,但它们代表了深度学习的重要发展,并且是前馈网络的自然扩展。
在本文中,我们将涵盖以下内容:
- 从前馈到循环网络的步骤
- 多层循环网络
- 长短期记忆网络(LSTM)
- 顺序输出(“文本输出”)
- 双向性
- 自回归生成
- 应用于机器翻译(对Google Translate 2016模型架构的高级理解)
本文的目的不仅是解释RNN的工作原理(有很多文章可以做到这一点),而是通过插图探讨其设计选择和高级直观逻辑。我希望本文不仅能为您掌握这个特定的技术主题提供一些独特的价值,而且还能更普遍地提高深度学习设计的灵活性。
循环神经网络(1985)的设计基于如下两个关于理想模型(如人类阅读文本)如何处理顺序信息的观察:
- 通过MINILLM揭示人工智能的潜力:深入探讨从更大的语言模型到更小的对应模型的知识蒸馏
- 使用Google Cloud构建推荐系统
- 通过一种新的人工智能模型,在蛋白质设计方面突破界限,能够理解与任何种类的分子的相互作用
- 它应该追踪到目前为止“学到”的信息,以便将新信息与以前看到的信息联系起来。为了理解“快速棕色狐狸跳过懒狗”的句子,我需要记住“快速”和“棕色”这些单词,以便以后理解它们适用于“狐狸”这个词。如果我没有在我的“短期记忆”中保留任何此类信息,我将无法理解信息的顺序意义。当我在“懒狗”上完成句子时,我会将这个名词与我之前遇到的“快速棕色狐狸”联系起来。
- 尽管后面的信息总是在早期的信息的上下文中阅读,但我们希望以类似的方式处理每个单词(标记),而不考虑它的位置。我们不应该因为某种原因系统地将第三个位置的单词与第一个位置的单词不同,即使我们可能根据前者阅读后者。请注意,之前提出的方法——将所有标记的嵌入堆叠在一起并同时呈现给模型——不具备这种属性,因为不能保证与第一个单词相对应的嵌入与与第三个单词相对应的嵌入使用的规则相同。这个一般属性也被称为位置不变性。
一个循环神经网络的核心是由循环层组成。循环层和前馈层一样,是一组可学习的数学变换。事实证明,我们可以近似理解循环层为多层感知机。
循环层的“短期记忆”称为它的隐藏状态。这是一个向量——只是一组数字——它传达了有关网络到目前为止学到的关键信息。然后,对于标准化文本中的每个标记,我们将新信息合并到隐藏状态中。我们使用两个多层感知机(MLP)来实现这一点:一个MLP变换当前嵌入,另一个MLP变换当前隐藏状态。这两个MLP的输出被相加以形成更新后的隐藏状态,或“更新的短期记忆”。
然后我们对下一个标记重复这个过程——嵌入被传递到一个MLP中,更新后的隐藏状态被传递到另一个MLP中;两者的输出被相加。这对于序列中的每个标记都重复一遍:一个MLP将输入转换为适合合并到短期记忆(隐藏状态)中的形式,而另一个MLP则准备好更新短期记忆(隐藏状态)。这满足我们的第一个要求——我们希望在旧信息的上下文中阅读新信息。此外,这两个MLP在每个时间步骤上都是相同的。也就是说,我们使用相同的规则来合并当前隐藏状态和新信息。这满足我们的第二个要求——我们必须在每个时间步骤上使用相同的规则。
这两个MLP通常只实现为一层深:也就是说,它只是一个大型的逻辑回归堆栈。例如,下图演示了MLP A的架构可能会是什么样子,假设每个嵌入是八个数字长,而隐藏状态也包括八个数字。这是一个简单但有效的转换,将嵌入向量映射为适合与隐藏状态合并的向量。
当我们将最后一个令牌加入隐藏状态后,循环层的工作就完成了。它产生了一个向量——一系列数字,代表了顺序读取一系列令牌所积累的信息。然后我们可以将这个向量通过第三个多层感知机(MLP),学习“内存当前状态”与预测任务之间的关系(在这种情况下,股票价格是上涨还是下跌)。
更新权重的机制太复杂,无法在本书中详细讨论,但它类似于反向传播算法的逻辑。额外的复杂性是跟踪每个参数重复作用于其自身输出的复合效应(因此是模型的“循环”性质),这可以在数学上通过一种修改的算法称为“时间反向传播”来解决。
循环神经网络是一种相当直观的方法来处理序列数据的建模。它是另一种复杂的线性回归模型排列的情况,但它非常强大:它允许我们系统地处理困难的序列学习问题,如语言。
为了方便绘图和简化,您经常会看到循环层仅表示为一个块,而不是作用于一系列输入的扩展单元。
这是文本的最简单的循环神经网络:标准化的输入令牌被映射到嵌入中,然后输入到循环层中;循环层的输出(“最近的内存状态”)由MLP处理并映射到预测目标。
复杂的循环网络变体
循环层允许网络处理序列问题。然而,我们当前的循环神经网络模型存在一些问题。为了了解循环神经网络如何在实际应用中用于建模困难问题,我们需要添加一些更多的内容。
其中之一是缺乏深度:循环层只是一遍地经过文本,因此仅获得表面级别的粗略阅读内容。考虑哲学家伊曼纽尔·康德的句子“幸福不是理性的理想,而是想象的理想”。为了真正理解这个句子的深度,我们不能简单地一遍地经过这些单词。相反,我们阅读这些词,然后——这是关键步骤——我们阅读我们的思想。我们评估我们对句子的直接解释是否有意义,并可能修改它以使其更深入。我们甚至可能阅读我们关于我们思想的思想。这一切都发生得非常快速,通常没有我们的知觉,但这是一种从文本内容中提取多个深度的过程。
因此,我们可以添加多个循环层以增加理解的深度。虽然第一个循环层从文本中获取表面级别的信息,但第二个循环层阅读第一个循环层的“思想”。第二层的双重通知的“最新内存状态”然后被用作MLP的输入,做出最终决定。或者,我们可以添加多个循环层。
为了具体说明这个叠加机制的工作原理,请参阅以下图:与其仅将每个隐藏状态传递以进行更新,我们还将此输入状态给下一个循环层。虽然第一个输入到第一个循环层是嵌入,但第二个输入到第二个循环层是“第一个循环层关于第一个输入的想法”。
几乎所有用于实际语言建模问题的循环神经网络都使用多个循环层的堆栈,而不是单个循环层,因为它增加了理解和语言推理的深度。对于大型循环层堆栈,我们通常使用循环残差连接。回想一下残差连接的概念,即先前版本的信息添加到后续版本的信息中。类似地,我们可以在每个层的隐藏状态之间放置残差连接,以便层可以引用各种“思考深度”。
虽然递归模型在短而简单的句子中表现良好,例如“联邦宣布经济衰退”,但金融文件和新闻文章通常比几个词长得多。对于更长的序列,标准递归模型会遇到持久的长期记忆丧失问题:通常,序列中早期单词的信号或重要性被后来的单词所淡化和掩盖。由于每个时间步骤都会对隐藏状态产生影响,因此它部分破坏了早期信息。因此,在序列的末尾,大多数开始的信息都变得无法恢复。递归模型具有狭窄的注意力/记忆窗口。如果我们想要制作一个模型,它可以像人类一样查看和分析具有可比理解和深度的文档,我们需要解决这个记忆问题。
长短期记忆(LSTM)(1997)层是一个更复杂的递归层。它的具体机制太复杂了,无法在本书中准确或完整地讨论,但我们可以大致理解为试图将“长期记忆”与“短期记忆”分开。当“阅读”序列时,两个组件都是相关的:我们需要长期记忆来跟踪时间上的大距离信息,但也需要短期记忆来专注于具体的局部信息。因此,LSTM层不仅存储单个隐藏状态,还使用“单元状态”(表示“长期记忆”)。
每个步骤,输入以与标准递归层相同的方式与隐藏状态合并。然后,又来了三个步骤:
- 长期记忆清理。长期记忆是珍贵的;它保存着我们将在整个时间内保留的信息。当前短期记忆状态用于确定不再需要的长期记忆的部分,并“剪切”以腾出新的内存空间。
- 长期记忆更新。现在已经在长期记忆中清除了空间,短期记忆用于更新(添加到)长期记忆,从而将新信息提交给长期记忆。
- 短期记忆通知。此时,长期记忆状态相对于当前时间步骤完全更新。因为我们希望长期记忆通知短期记忆功能,所以长期记忆有助于切除和修改短期记忆。理想情况下,长期记忆会更好地监督哪些内容对于保留在短期记忆中是重要的和不重要的。
因此,短期记忆和长期记忆(请记住,两者都是数字列表)在每个时间步骤与彼此和输入进行交互,以一种允许进行近距离阅读而不会造成灾难性遗忘的方式读取输入序列。这个三步骤的过程在下图中以图形方式表示。 +
表示信息添加,而x
表示信息移除或清洗。(加法和乘法是实现这些思想的数学运算。例如,如果隐藏状态的当前值为10,则将其乘以0.1,它就变成1-因此,我已经“削减”隐藏状态中的信息。)
使用带有残差连接的LSTM堆栈,我们可以构建强大的语言解释模型,这些模型能够阅读(如果您喜欢,则为“理解”)段落甚至整篇文章的文本。除了用于金融分析以浏览大量财务和新闻报告之外,这些模型还可以用于预测社交媒体帖子和消息中潜在的自杀或恐怖主义个人,根据他们之前的产品评论向客户推荐可能购买的新产品以及在在线平台上检测有毒或骚扰性评论和帖子。
这些应用迫使我们批判性地思考它们的材料哲学含义。政府有强烈的兴趣检测潜在的恐怖分子,而最近的大屠杀枪手经常被证明具有令人不安的公共社交媒体记录-但悲剧在于他们没有在海量互联网信息中发现。递归模型等语言模型,如您自己所见,纯粹以数学方式运作:它们试图找到最好地建模输入文本和输出文本之间关系的权重和偏差。但是,只要这些权重和偏差具有某种含义,它们就可以以有效且极快的方式“阅读”信息-比人类读者更快,甚至可能更有效。这些模型可能允许政府在恐怖分子采取行动之前检测、跟踪和停止潜在的恐怖分子。当然,这可能会以隐私的代价为代价。此外,我们已经看到语言模型-尽管能够在数据中机械地追踪模式和关系-但实际上只是能够犯错误的数学算法。模型错误地将个人标记为潜在的恐怖分子应该如何调和?
社交媒体平台面临来自用户和政府的压力,希望减少在线论坛上的骚扰和毒性。从概念上讲,这似乎是一个欺骗性的简单任务:将一组社交媒体评论标记为有毒或无毒,然后训练语言模型来预测特定文本样本的毒性。但是,直接的问题是,由于依赖于快速变化的参考(表情包)、内部笑话、巧妙的讽刺和先决上下文知识,数字话语变得非常具有挑战性。然而,更有趣的哲学问题是,是否可以并且应该真正训练一个数学模型(一个“客观”模型)来预测像毒性这样看似“主观”的目标。毕竟,对于一个人来说有毒的东西可能并不会对另一个人有毒。
随着我们涉足越来越个人化的数据模型,语言成为我们沟通和吸收几乎所有知识的小猪AI,我们发现思考和努力回答这些问题变得更加重要。如果您对这条研究路线感兴趣,您可能需要研究对齐、陪审团学习、宪法AI、RLHF和价值多元主义。
神经机器翻译
概念:多输出循环模型,双向性,注意力
机器翻译是一项令人难以置信的技术:它允许以前在没有重大困难的情况下无法进行沟通的个人进行自由对话。印地语使用者可以通过点击“翻译此页面”按钮阅读用西班牙语编写的网站,反之亦然。看俄语电影的英语使用者可以启用实时翻译的字幕。在法国的中国游客可以通过获得基于照片的菜单翻译来点餐。机器翻译以非常文字的方式将语言和文化融合在一起。
在深度学习崛起之前,机器翻译的主要方法是基于查找表。例如,在中文中,“我”翻译为“我”,“开车”翻译为“开”,“汽车”翻译为“车”。因此,“我开车”将逐字逐句地翻译为“我开车”。然而,任何双语使用者都知道这个系统的缺点。许多拼写相同但意思不同的词。一种语言可能有多个在另一种语言中被翻译为一个单词的词。此外,不同的语言具有不同的语法结构,因此翻译后的单词本身需要重新排列。在像西班牙语和法语这样的性别语言中,英语中的文章有多种不同的上下文相关翻译。为了解决这些问题,许多巧妙的语言解决方案已经被设计出来,但是仅限于短而简单的句子。
另一方面,深度学习为我们提供了构建更深入理解语言的模型的机会,甚至更接近人类理解语言的方式,因此更有效地执行重要的翻译任务。在本节中,我们将介绍从深度语言建模中引入的多个其他想法,并以技术探索谷歌翻译的方式达到高潮。
文本输出循环模型
目前,构建可行的循环模型最明显的障碍是无法输出文本。先前讨论的循环模型可以“读取”但无法“写入”——输出是一个单一的数字(或一组数字,矢量)。为了解决这个问题,我们需要赋予语言模型输出整个文本序列的能力。
幸运的是,我们不必做太多的工作。回想一下之前介绍的循环层叠概念:与其仅在循环层运行整个序列后收集“记忆状态”,我们在每个时间步收集“记忆状态”。因此,为了输出序列,我们可以在每个时间步收集记忆状态的输出。然后,我们将每个记忆状态传递到指定的MLP中,该MLP预测在给定记忆状态的情况下要预测输出词汇表中的哪个单词(标记为“MLP C”)。选择具有最高预测概率的单词作为输出。
为了确切地了解如何将每个记忆状态转换为输出预测,请考虑以下图形的进展。
在第一个图中,第一个输出的隐藏状态(即在读取第一个词“the”之后导出的隐藏状态)被传递到MLP C中。 MLP C输出一个概率分布,覆盖了输出词汇表;也就是说,它为输出词汇表中的每个单词提供一个概率,表示在该时间选择该单词作为翻译的可能性有多大。这是一个前馈网络:我们实际上是在隐藏状态上执行逻辑回归,以确定给定词的可能性。理想情况下,具有最大概率的单词应该是“les”,因为这是“the”的法语翻译。
在循环层读取“the”和“machines”之后,得出的下一个隐藏状态再次传递到MLP C中。这次,最理想的情况是概率最高的单词应该是“machine”(这是“machines”在法语中的复数翻译)。
上一个时间步选择的最可能的单词应该是“gagnent”,这是特定时态下“win”的翻译。基于先前阅读的信息,模型应该选择“gagnent”,而不是“gagner”或者该单词的其他时态。这就是使用深度学习模型进行翻译的好处所在:能够掌握贯穿整个句子的语法规则。
实际上,我们通常希望将多个循环层叠加在一起,而不仅仅是一个单独的循环层。这样可以让我们开发多个层次的理解,首先“理解”输入文本的含义,然后用输出语言重新表达输入文本的“含义”。
双向性
请注意,循环层是按顺序进行的。当它读取文本“the machines win”时,它首先读取“the”,然后是“machines”,最后是“win”。尽管最后一个单词“win”是在“the”和“machines”之前的上下文中阅读的,但相反的情况并不成立:第一个单词“the”并没有在后面的“machines”和“win”中阅读。这是一个问题,因为语言通常是根据我们后面要说的话来说的。在法语这样的有性别的语言中,像“the”这样的冠词可以采用许多不同的形式——对于女性物品,是“la”;对于男性物品,是“le”;对于复数物品,是“les”。我们不知道要翻译哪个版本的“the”。当然,一旦我们阅读了整个句子——“the machines”——我们就知道这个物品是复数,我们应该使用“les”。这是一个情况,早期的文本部分受到后期部分的影响。更一般地说,当我们重新阅读一句话时——我们经常不自觉地做到这一点——我们会根据起始部分的上下文来阅读它。尽管语言是按顺序阅读的,但它通常必须被“非顺序”地解释(也就是说,不是严格地从头到尾单向阅读)。
为了解决这个问题,我们可以使用双向性——一种对循环模型进行简单修改的方法,使层能够“正向”和“反向”阅读。双向循环层实际上是两个不同的循环层。一个层向前按时间顺序读取,而另一个层向后按时间顺序读取。在两者都完成阅读后,它们在每个时间步的输出被加在一起。
双向性使模型能够以一种使得过去在未来的上下文中阅读的方式阅读文本,从而使未来也能在过去的上下文中阅读(循环层的默认功能)。请注意,每个时间步的双向循环层的输出都受到整个序列的影响,而不仅仅是之前的所有时间步。例如,在一个10个时间步的序列中,时间步t=3受到一个“内存状态”的影响,该状态已经阅读了序列[t=0]→[t=1]→[t=2]→[t=3],以及另一个“内存状态”,该状态已经阅读了序列[t=9]→[t=8]→[t=7]→[t=6]→[t=5]→[t=4]→[t=3]。
这个简单的修改使语言理解深度大幅提升。
自回归生成
我们目前工作中的翻译模型是一个大型的(双向)循环层堆栈。然而,存在一个问题:当我们将一些文本 A 翻译成其他文本 B 时,我们不仅仅是在参考 A 来写 B,我们还是在参考 B 本身来写 B。
我们无法直接将俄语中复杂的句子“Грузовик внезапно остановился потому что дорогу переходила курица”直译成英文中的“The truck suddenly stopped because a chicken was crossing the road”,如果我们按照俄语中的单词顺序直接逐字翻译,我们会得到“Truck suddenly stopped because road was crossed by chicken”。在俄语中,对象是放在名词后面的,但是在英语中保留这种形式虽然可读,但不够流畅,也不是最优的。关键是:为了获得可理解和可用的翻译,我们不仅需要确保翻译忠实于原始文本,还需要忠实于自身(自洽)。
为了做到这一点,我们需要一种不同的文本生成称为自回归生成。这使得模型可以将每个单词翻译成原始文本的关系,但也翻译成模型已经翻译的内容。自回归生成不仅是神经翻译模型的主导范式,也是所有现代文本生成模型(包括先进的聊天机器人和内容生成器)的主导范式。
我们从一个“编码器”模型开始。编码器模型在这种情况下可以表示为一堆循环层。编码器读取输入序列并派生出一个输出,即编码表示。这个单一的数字列表以定量形式表示输入文本序列的“本质”——如果您愿意的话,它的“通用/实际含义”。编码器的目标是将输入序列浓缩成这个基本含义的数据包。
一旦获得了这个编码表示,我们就开始解码的任务。解码器与编码器类似——我们可以将其视为接受序列并产生输出的另一堆循环层。在这种情况下,解码器接受编码表示(即编码器的输出)和一个特殊的“开始标记”(表示为</s>)。开始标记表示一个句子的开头。解码器的任务是预测给定句子中的下一个单词;在这种情况下,它给出了一个“零词句子”,因此必须预测第一个词。在这种情况下,没有先前的翻译内容,因此解码器完全依赖于编码表示:它预测第一个词“The”。
接下来是关键的自回归步骤:我们将解码器的先前输出插回到解码器中。现在我们有了一个“一个单词的句子”(开始标记后跟单词“The”)。两个标记都被传递到解码器中,以及编码表示——与之前相同,由编码器输出——现在解码器预测下一个单词“truck”。
然后将该标记视为另一个输入。在这里,我们可以更清楚地意识到为什么自回归生成是文本生成的有用算法支架:已知当前工作的句子为“The truck”,这限制了我们如何完成它。在这种情况下,下一个单词很可能是一个动词或副词,我们“知道”这是一个语法结构。另一方面,如果解码器只能访问原始俄语文本,它将无法有效地限制可能性集。在这种情况下,解码器能够参考先前已经翻译的内容和原始俄语句子的含义,以正确地预测下一个单词为“suddenly”。
这个自回归生成过程继续进行:
最后,为了结束一个句子,解码器模型会预测一个指定的“结束标记”(表示为</e>)。在这种情况下,解码器将会与编码表示进行“匹配”,以确定翻译是否令人满意并停止句子生成过程。
2016年的谷歌翻译
到现在为止,我们已经涉及了很多内容。我们现在已经掌握了大部分必要的元素,以便对谷歌翻译的模型设计有一个相对全面的理解。我需要说的话很少,对于像谷歌翻译这样的模型的重要性不言自明:即使粗略地,一种准确且易于使用的神经机器翻译系统也能消除许多语言障碍。对于我们来说,这个特殊的模型有助于将我们所讨论的许多概念统一到一个连贯的应用程序中。
这些信息摘自2016年《谷歌神经机器翻译论文》,该论文介绍了谷歌用于机器翻译的深度学习系统。虽然几年以来该模型几乎肯定已经发生了变化,但该系统仍然为神经机器翻译系统提供了一个有趣的案例研究。为了清晰起见,我们将称此系统为“谷歌翻译”,承认它可能不是最新的。
谷歌翻译使用了一个编码器-解码器自回归模型。也就是说,该模型包括编码器组件和解码器组件;解码器是自回归的(回想一下之前的内容:除了其他信息外,它还接受先前生成的输出作为输入,例如编码器的输出)。
编码器是由七个长短时记忆(LSTM)层堆叠而成。第一层是双向的(因此实际上有8层,因为双向层“算两个”),这使得它可以捕捉输入文本中的重要模式(底部图,左)。此外,该架构在每个层之间使用残差连接(底部图,右)。回想一下之前的讨论,递归神经网络中的残差连接可以通过将输入添加到递归层的输出中来实现,以使递归层最终学习应用于输入的最佳差异。
解码器也是由八个LSTM层堆叠而成。它以自回归方式接受先前生成的序列,从开始标记</s>
开始。然而,Google神经机器翻译架构同时使用了自回归生成和注意力机制。
为每个原始文本单词(由编码器中的隐藏状态表示,这些状态迭代地转换文本但仍然以位置方式表示)计算注意力分数。我们可以将注意力视为解码器和编码器之间的对话。解码器说:“到目前为止,我已经生成了[句子],我想预测下一个翻译的单词。原始句子中哪些单词与这个下一个翻译的单词最相关?”编码器回答:“让我看看你在想什么,我会将它与我已经学习到的有关原始输入的每个单词的信息进行匹配……啊,你应该注意[单词A],但不太需要关注[单词B]和[单词C],它们与预测下一个特定单词的相关性较小。”解码器感谢编码器:“我会考虑这些信息,以确定我如何生成,这样我确实会关注[单词A]。”将关于注意力的信息发送到每个LSTM层,使得这些注意力信息在所有生成的层面上都是已知的。
这代表了Google神经机器翻译系统的主要部分。该模型在大量的翻译任务数据集上进行训练:给出英文输入,例如,预测西班牙语输出。该模型学习了最佳的阅读方式(即编码器中的参数),最佳的注意力计算方式(即注意力计算),以及将关注的输入与西班牙语输出相关联的最佳方式(即解码器中的参数)。
随着后续工作的推进,神经机器翻译系统已经扩展到多语言能力,即一个模型可以用于多个语言对之间的翻译。这不仅在实际应用中是必要的 —— 为每一对语言训练和存储模型是不可行的 —— 而且还显示出可以提高任意两种语言之间的翻译。此外,GNMT 论文提供了有关训练的详细信息 —— 这是一个非常深层的架构,受硬件限制 —— 和实际部署 —— 大模型不仅训练缓慢,而且也很慢获取预测结果,但 Google 翻译用户不想等待超过几秒钟来翻译文本。
虽然 GNMT 系统肯定是计算语言理解中的里程碑,但几年后出现了一种新的、在某些方面彻底简化的方法,完全改变了语言建模的方式 —— 并且完全摆脱了曾经常见的循环层,我们曾经费尽心思去理解。请继续关注第二篇关于 Transformers 的文章!
感谢阅读!
在本文中,我们对循环神经网络进行了全面的调查:它们的设计逻辑、更复杂的特性和应用。
一些关键点:
- RNN 是前馈网络的自然扩展,可用于机器翻译。RNN 的设计是为了跟踪到目前为止所学到的信息,并将新信息与先前看到的信息联系起来,类似于人类处理序列信息的方式。
- RNN 使用循环层,其中隐藏状态表示短期记忆。
- 循环层可以堆叠以增加网络的理解和推理深度。
- 长短时记忆(LSTM)网络是一种更复杂的循环层类型,将长期记忆与短期记忆分离。LSTM 具有清除、更新和通知长期和短期记忆的机制。
- RNN 在金融分析、社交媒体分析、推荐系统和语言翻译等各个领域都有应用。
- RNN 在实际应用中的使用引发了有关隐私、模型错误以及对有害内容进行主观标注等哲学和伦理问题。
- 神经机器翻译是 RNN 的一个强大应用,可以实现不同语言之间的语言翻译,促进交流和文化交流。
所有照片由作者提供。