机器学习中的 Seq2Seq 模型

2025年6月24日 | 阅读 11 分钟

序列到序列(seq2seq)模型在机器学习中已成为深度学习在具有顺序数据固有结构的任务中的基本方法,例如语言翻译、文本摘要和语音识别。最常见的 seq2seq 模型类型采用编码器-解码器处理,它是一种应用于输入序列的 RNN,其输出是在相同或不同预定义目标序列中的目标输出。编码器-解码器模型通常假设一个上下文向量,该向量作为输入的一种抽象表示形式,对编码器而言,并负责使输出符合输入要求,对解码器而言。

编码器所做的唯一工作是将输入编码为上下文向量,这意味着仅用一个向量来总结其语义。此最终隐藏状态将传递给解码器,解码器一次生成一个目标序列。直接将编码器连接到解码器,上下文向量被馈送到解码器,这确保了解码器从一个逻辑起点开始,并拥有有关输入的所有必要信息。由于解码器无法直接访问输入信息,因此它会根据这些上下文向量和隐藏状态来预测单词。Teacher forcing(教师强制)旨在帮助训练:它有时会将模型的一个预测结果作为目标词传递给网络,以便在模型训练时不会累积错误。在推理时,解码器会生成单词,直到生成序列结束标记。然后,将此模型的性能与实际输出进行评估,从而随着时间的推移改进模型的状态。

我们将使用 PyTorch 来实现模型,并利用 TorchText 协助我们进行必要的预处理。此外,我们将使用 spaCy 来帮助进行数据分词。

代码

输出

Seq2Seq Model in Machine Learning

代码

输出

Seq2Seq Model in Machine Learning

此外,我们可以打印一个示例,确保源句子已反转。

代码

输出

 
{'vi_no_accents': ['mieu', 'ta', 'khoa', 'hoc', 'dau', 'tien', 'nam', '1928', '.'], 'vi': ['miêu_tả', 'khoa_học', 'đầu_tiên', 'năm', '1928', '.']}   

周期始于德语(源)句子,这似乎是可以接受的。现在,我们为源语言和目标语言构建词汇表。词汇表中的每个标记都被分配一个唯一的索引(整数);然后,对其应用独热编码。在此向量中,除标记位置(标记为 1)外,所有位置均设置为零。请注意,源语言和目标语言的词汇表是分开的。我们通过考虑至少出现两次的最小频率阈值来过滤标记以构建词汇表。出现一次的任何标记都将被替换为一个表示未知词的标记。在构建词汇表时,一个重要的考虑因素是它必须仅从训练数据集中派生,而不包括验证集和测试集:这将避免信息泄露,其中模型在验证或测试中的分数由于学习了不应该在训练期间看到的数据而被人为地提高。

代码

输出

Seq2Seq Model in Machine Learning

数据准备的最后附加部分是创建迭代器,这将使我们能够以有效的方式输入数据批次。返回批次中的两个重要键是:`the_SRC`,它们是包含数值化源句子的 PyTorch 张量,以及 `the_TRG`,包含数值化目标句子。基本上,数值化意味着原始的可读标记序列已被转换为对应于词汇表索引的序列。另一个重要的步骤是定义 `torch.device`,它使我们能够指定计算是在 GPU 还是 CPU 上进行。我们通过调用 `torch` 中的函数 `torch.cuda.is_available()` 来检查是否具有 GPU,并据此设置迭代器上的设备。为了处理批次,源句子和目标句子在批次中长度相同非常重要;因此,需要进行填充,以便所有句子都填充到批次中最长句子的长度。幸运的是,TorchText 迭代器会自动执行此操作。我们使用 BucketIterator 而不是普通 Iterator,它通过将长度相似的句子分组来更好地处理批次。这最小化了所需的填充量,从而实现了更高效的处理和更快的性能,尤其是在处理大型数据集时。

构建 Seq2Seq 模型

序列到序列模型包含三个主要组成部分:编码器、解码器和统一它们的 Seq2Seq 包装器。这种设计允许输入和输出与编码器和解码器无缝通信,同时高效地处理顺序输入和输出数据。

编码器

要构建的下一个组件是编码器。编码器应用于输入序列,定位其各个部分,并将其转换为一个压缩机制。在我们的例子中,使用了 2 层 LSTM,而在原始论文中,它基本上应该是 4 层 LSTM。基本上,我们可以通过计算能力和任务的复杂性轻松改变层数。多层 RNN 以顺序方式接受输入。第一层(底层)接收输入句子并生成隐藏状态序列。然后将隐藏状态馈送到其上方的层,从而在层之间进行更深层次的特征提取。更深的层不断地完善从输入中学到的表示。除了每个时间步的隐藏状态外,编码器还跟踪单元状态,因为 LSTM 会添加另一个单元状态以提高记忆保持能力。LSTM 架构在层之间跟踪隐藏状态和单元状态,而不是仅跟踪隐藏状态,以保留长期依赖关系。初始隐藏状态和初始单元状态在序列开始时均设置为零。当整个序列都被馈送到编码器后,最终状态被统称为上下文向量,该向量捕获了输入序列中应最终提供给解码器进行进一步处理的所有信息。

代码

解码器

此外,Seq2Seq 模型的第二个关键组成部分是解码器,它在给定编码的上下文向量的情况下生成目标序列。解码器是一个 2 层长短期记忆(LSTM)网络,与编码器类似;然而,原始论文推荐使用 4 层 LSTM。解码器一次生成一个输出标记,根据前一个词和隐藏状态生成下一个词。虽然编码器一次处理整个输入序列,但解码器会逐步工作,一次预测一个标记。初始状态隐藏,其中一个单元状态取自编码器的最终状态。解码器接收先前预测的词作为(Ground Truth Target Word During Training)输入,并将其输入到 LSTM 层以更新状态。

代码

Seq2Seq 模型是编码器和解码器的有效组合,通过上下文向量和教师强制来生成输出序列。该模型学习在训练过程中通过前向方法执行良好的翻译序列,这取决于提供的监督级别。

代码

模型实现后,我们就可以进行训练了。我们必须首先初始化模型。几年前,人们发现输入/输出的嵌入大小与词汇表的大小相对应。相比之下,编码器和解码器的嵌入维度和 dropout 率可以不同,而层数以及隐藏和单元状态的大小应保持不变。

代码

输出

Seq2Seq Model in Machine Learning

此外,我们定义了一个函数来确定模型包含多少可训练参数。

代码

输出

 
The model has 20,330,651 trainable parameters   

在训练循环中,我们使用定义的优化器来更改参数。要了解更多关于各种优化器的信息,请阅读这篇帖子。这里将使用 Adam。

代码

输出

Seq2Seq Model in Machine Learning