LSTM非常擅长处理序列,但我们需要一对而不是一个LSTM。我们将构建一个模块化的架构,称为编码-解码架构。
编码-解码架构的前半部分是序列编码器,该网络将序列(如自然语言文本)转换为较低维的表示形式(如思想向量),这样就已经构建了序列到序列模型的前半部分。
编码-解码架构的后半部分是序列解码器,序列解码器设计成将向量重新转换回人类可读的文本。
LSTM作为可变长度文本的编码器非常有效,构建它们是为了捕捉自然语言文本的语义和情感,LSTM通过内部表示(一个思想向量)捕获了这个含义。我们只需要从LSTM模型汇总的状态(记忆元胞)里提取该思想向量。可以在Keras的LSTM模型中设置return_state=True,以便输出包含隐藏层状态,这个状态向量称为编码器的输出和解码器的输入。
解码思想
假设要研发一个翻译模型将文本从英语翻译成德语,我们希望将字符序列或词序列映射到另一个字符序列或词序列。直接使用LSTM将一种语言映射到另一种语言会很容易遇到问题。对于单个LSTM,需要输入序列和输出序列具有相同的序列长度,而对于翻译任务这种情况往往很少。
上图展示了这个问题。英语和德语句子长度不同,这使得英语输入和预期输出之间的映射更加复杂。英语短语“is playing”(现在进行时)被翻译成德语的现在时态“spielt”。但是这里的“spielt”只能根据输入“is”进行预测,而我们在这个时刻还没有输入“playing”。下一步“playing”会被映射为“FuBball”。当然网络可以学习这些映射,但学到的表示只能针对特定的输入,这样会获得一个更通用的语言模型对我们来说就做不到了。
序列到序列网络架构,有时缩写为seq2seq,通过创建一个思想向量形式的输入表示来解除这个限制。然后,序列到序列模型使用该思想向量(有时称为上下文向量)作为第二个网络的起点,第二个网络接收不同的输入集来生成输出序列。
序列到序列网络由两个模块化的循环网络组成,它们之间有一个思想向量(如下图)。编码器在其输入序列的末尾输出一个思想向量。解码器接收这个向量并输出一个词条序列。
第一个网络称为编码器,将输入文本(如用户向聊天机器人发送的消息)转换为思想向量。思想向量有两部分,每一部分都是一个向量:编码器隐藏层的输出(经过了激活函数)和这个输入样本LSTM元胞的记忆状态。
然后思想向量成为第二个网络即解码器网络的输入。其生成的状态(思想向量)将作为解码器网络的初始状态。然后,第二个网络使用初始状态和一种特殊的输入:初始词条。有了这些信息,第二个网络就能学习生成目标序列的第一个元素(如字符和词)。
在这种特殊的结构中,训练阶段和推理阶段的处理是不同的。在训练期间,我们将初始文本传递给编码器,并将预期的文本作为输入传递给解码器。我们让解码器网络学习,在给定初始状态和“开始”按键的情况下,它就可以生成一系列词条。解码器的第一个输入是初始词条,第二个输入应该是第一个预期的或要被预测的词条,它会反过来促使网络生成第二个预期的词条。
然而在推理阶段,我们没有预期的文本,那么除状态之外,可以使用通用的初始词条,然后使用第一个生成的元素,该元素将在下一时刻成为解码器的输入,以生成下一个元素,以此类推。这个过程重复进行,直到达到序列元素的最大数量,或者生成一个终止词条。
通过这种端到端(end-to-end)训练,解码器将把一个思想向量转换为对初始输入序列(如用户问题)的全解码回复。将解决方案分割成两个网络,其中思想向量作为结合组件(绑定两个网络),允许我们将输入序列映射到不同长度的输出序列:
编码-解码方法
自编码器对学习神经网络而言是一种常见的编码-解码结构,它们是一种重复博弈的神经网络,经过训练,能够将输入信息反刍出来出来,这使得寻找训练数据变得很容易,几乎任何一组高维张量、向量或序列都可以。
与任何编码-解码结构一样,自编码器在编码器和解码器之间存在信息瓶颈,这里将其用作输入数据的低维表示。任何具有信息瓶颈的网络都可以在编码-解码架构中用作编码器,即使该网络直接收了改写或重复表述输入的训练。
虽然自编码器与编码器-解码器具有相同的结构,但是它们是为不同的任务而训练的。自编码器被训练来寻找输入数据的向量表示,这样输入就可以由网络的解码器以最小的误差重构。编码器和解码器互为伪逆过程。该网络的目的是找到输入数据(如图像或文本)的稠密向量表示,从而允许解码器以最小的误差重构它。在训练阶段,输入数据和预期输出是相同的。因此,如果目标是找到数据的稠密向量表示,而不是为语言翻译生成思想向量或为给定的问题寻找回复,那么自编码器是一个不错的选择。
t-SNE模型生成一个嵌入作为它的输出,所以在某种意义上,我们可以把它看作一个编码器。PCA也是一样,然而这些模型是无监督的,因此它们不能针对特定的输出或任务。这些算法主要是用于特征提取和可视化。它们创建了非常紧密的瓶颈以输出非常低维的向量(通常是二维或三维)。它们不是涉及用来输出任意长度的序列的。这就是编码器的区别。所以LSTM是用于从序列中提取特征和嵌入的最先进技术。
序列到序列对话
对话引擎问题和机器翻译之间其实非常相似,在聊天机器人的对话中生成回复与在机器翻译系统总生成英文语句的德语翻译没有什么不同。
翻译和对话任务都需要模型将一个序列映射到另一个序列。将英语词条序列映射到德语序列非常类似于将对话中的自然语言语句映射到对话引擎的预期回复语句。我们可以把机器翻译引擎想象成一个精神分裂的双语对话引擎。
但是,我们希望机器人有合适的回复,而不是只是一个回音室。因此,我们的模型需要引入希望聊天机器人谈论的领域的附加信息。我们的NLP模型需要学习一个从问题到回复的复杂映射,而不是回声或翻译,这需要更多的训练数据和更高维度的思想向量,因为它必须包含对话引擎需要了解的领域的所有信息。LSTM模型中增加思想向量的维数,可以增加其信息容量。如果想把翻译机器变成对话机器,还需要获得足够多的合适数据。
给定一组词条,我们可以训练机器学习流水线来模拟一个对话回复序列,我们需要足够多的对话语句对合在思想向量中足够大的信息空间来理解所有这些映射。一旦我们有了一个数据集,其中包含了足够多的从问题到回复的“翻译”对,我们就可以使用和机器翻译相同的网络来训练对话引擎。
Keras使用一种称为编码-解码模型的模块化架构,为构建序列到序列网络提供模块。它提供了一个API来访问LSTM网络的所有内部组件,我们需要这些组件来解决翻译、会话甚至基因型-表现型的问题。
LSTM
已知LSTM如何为循环网络提供方法来选择性地记住和遗忘它们在样本文档中“看到”的词条模式:每个时刻的输入词条都经过遗忘门和更新门,乘以权重和掩码,然后存储在记忆元胞中,各个时刻(词条)的网络输出不单单由输入词条决定,而是由输入词条和记忆单元当前的状态一起决定的。
重要的是,LSTM在文档之间共享词条模式识别器,因为遗忘门和更新门具有在读取多个文档后训练的权重。因此,LSTM不必为每个新文档重新学习英语拼写和语法。我们学习了如何激活存储在LSTM记忆元胞的权重中的这些词条模式,从而根据一些种子词条预测之后的词条及处罚序列的生成。(如下图)
通过预测一个个的词条,我们可以根据网络建议的可能的后续词条的概率分布来选择下一个词条,从而生成一些文本。虽然说不上完美,但还是很有趣的。
还有一种方法,就是引入LSTM模型,以一种随机性更弱、更可控的方式解码记忆元胞中的模式。使用LSTM在分类任务中创建的思想向量,然后使用生成的向量作为输入传递给第二个完全不同的LSTM,这个LSTM只试图逐个预测各个词条,这种方法提供了一种将输入序列映射到一个截然不同的输出序列的方法。