基于注意力的神经机器翻译

在 TensorFlow.org 上查看 在 Google Colab 运行 在 GitHub 上查看源代码 下载此 notebook

Note: 我们的 TensorFlow 社区翻译了这些文档。因为社区翻译是尽力而为, 所以无法保证它们是最准确的,并且反映了最新的 官方英文文档。如果您有改进此翻译的建议, 请提交 pull request 到 tensorflow/docs GitHub 仓库。要志愿地撰写或者审核译文,请加入 docs-zh-cn@tensorflow.org Google Group

此笔记本训练一个将西班牙语翻译为英语的序列到序列(sequence to sequence,简写为 seq2seq)模型。此例子难度较高,需要对序列到序列模型的知识有一定了解。

训练完此笔记本中的模型后,你将能够输入一个西班牙语句子,例如 "¿todavia estan en casa?",并返回其英语翻译 "are you still at home?"

对于一个简单的例子来说,翻译质量令人满意。但是更有趣的可能是生成的注意力图:它显示在翻译过程中,输入句子的哪些部分受到了模型的注意。

spanish-english attention plot

请注意:运行这个例子用一个 P100 GPU 需要花大约 10 分钟。

下载和准备数据集

我们将使用 http://www.manythings.org/anki/ 提供的一个语言数据集。这个数据集包含如下格式的语言翻译对:

May I borrow this book? ¿Puedo tomar prestado este libro?

这个数据集中有很多种语言可供选择。我们将使用英语 - 西班牙语数据集。为方便使用,我们在谷歌云上提供了此数据集的一份副本。但是你也可以自己下载副本。下载完数据集后,我们将采取下列步骤准备数据:

  1. 给每个句子添加一个 开始 和一个 结束 标记(token)。
  2. 删除特殊字符以清理句子。
  3. 创建一个单词索引和一个反向单词索引(即一个从单词映射至 id 的词典和一个从 id 映射至单词的词典)。
  4. 将每个句子填充(pad)到最大长度。

限制数据集的大小以加快实验速度(可选)

在超过 10 万个句子的完整数据集上训练需要很长时间。为了更快地训练,我们可以将数据集的大小限制为 3 万个句子(当然,翻译质量也会随着数据的减少而降低):

创建一个 tf.data 数据集

编写编码器 (encoder) 和解码器 (decoder) 模型

实现一个基于注意力的编码器 - 解码器模型。关于这种模型,你可以阅读 TensorFlow 的 神经机器翻译 (序列到序列) 教程。本示例采用一组更新的 API。此笔记本实现了上述序列到序列教程中的 注意力方程式。下图显示了注意力机制为每个输入单词分配一个权重,然后解码器将这个权重用于预测句子中的下一个单词。下图和公式是 Luong 的论文中注意力机制的一个例子。

attention mechanism

输入经过编码器模型,编码器模型为我们提供形状为 (批大小,最大长度,隐藏层大小) 的编码器输出和形状为 (批大小,隐藏层大小) 的编码器隐藏层状态。

下面是所实现的方程式:

attention equation 0 attention equation 1

本教程的编码器采用 Bahdanau 注意力。在用简化形式编写之前,让我们先决定符号:

以及伪代码:

每个步骤中所有向量的形状已在代码的注释中阐明:

定义优化器和损失函数

检查点(基于对象保存)

训练

  1. 输入 传送至 编码器,编码器返回 编码器输出编码器隐藏层状态
  2. 将编码器输出、编码器隐藏层状态和解码器输入(即 开始标记)传送至解码器。
  3. 解码器返回 预测解码器隐藏层状态
  4. 解码器隐藏层状态被传送回模型,预测被用于计算损失。
  5. 使用 教师强制 (teacher forcing) 决定解码器的下一个输入。
  6. 教师强制 是将 目标词 作为 下一个输入 传送至解码器的技术。
  7. 最后一步是计算梯度,并将其应用于优化器和反向传播。

翻译

请注意:对于一个输入,编码器输出仅计算一次。

恢复最新的检查点并验证

下一步