祝大家有美好的一天!
我们再次为修订后的“
数据科学家”课程开辟了新
渠道 :另一位
优秀的老师 ,基于更新的稍有改进的程序。 好吧,像往常一样,有趣的
公开课和有趣的资料集。 今天,我们将开始分析Tensor Flow中的seq2seq模型。
走吧
正如
RNN教程中已经讨论过的(建议您在阅读本文之前先熟悉它),可以教递归神经网络对语言进行建模。 随之而来的是一个有趣的问题:是否有可能在某些数据上训练网络以产生有意义的答案? 例如,我们可以教一个神经网络将英语翻译成法语吗? 事实证明,我们可以做到。
本指南将向您展示如何创建和培训这种端到端系统。
从GitHub复制
Tensor Flow核心存储库和
TensorFlow模型存储库 。 然后,您可以通过启动翻译程序开始:
cd models/tutorials/rnn/translate python translate.py --data_dir [your_data_directory]

她将从
WMT'15网站上下载数据,将其从英语翻译为法语,
以备培训和培训之用。 这将需要大约20GB的硬盘驱动器,并且需要大量的时间进行下载和准备,因此您可以立即开始该过程并继续阅读本教程。
该手册将访问以下文件:
档案文件 | 里面有什么? |
---|
tensorflow /张量流/ python / ops / seq2seq.py | 用于创建序列到序列模型的库 |
模型/教程/ rnn /翻译/ seq2seq_model.py | 序列到序列的神经翻译模型 |
模型/教程/ rnn /翻译/ data_utils.py | 用于准备翻译数据的辅助功能 |
模型/教程/rnn/translate/translate.py | 训练和运行翻译模型的二进制文件 |
序列到序列的基础知识Cho et al。,2014 (
pdf )提出的基本序列到序列模型由两个递归神经网络(RNN)组成:处理输入数据的编码器(encoder)和生成数据的解码器(decoder)输出。 基本架构如下所示:

上图中的每个矩形代表RNN中的一个单元,通常是一个GRU单元-一个受控的递归块或一个LSTM单元-长期短期记忆(请阅读
RNN教程以了解更多信息)。 编码器和解码器可以具有相同的权重,或更常见的是,使用不同的参数集。 多层细胞已成功用于序列到序列模型中,例如,翻译
Sutskever等人,2014 (
pdf )。
在上述基本模型中,必须将每个输入编码为固定大小的状态向量,因为这是唯一传输到解码器的内容。 为了使解码器更直接地访问输入数据,
Bahdanau等人(2014年 )引入了一种注意力机制(
pdf )。 我们将不涉及注意力机制的细节(为此,您可以在这里熟悉自己的工作); 可以说,它允许解码器在每个解码步骤中查看输入数据。 具有LSTM单元和解码器中的注意机制的多层序列到序列网络如下:
TensorFlow库seq2seq从上面可以看到,有不同的序列到序列模型。 它们都可以使用不同的RNN单元,但是它们都接受编码器输入数据和解码器输入数据。 这是TensorFlow seq2seq库接口(tensorflow / tensorflow / python / ops / seq2seq.py)的基础。 这种基本的RNN,编解码器,序列到序列模型的工作原理如下。
outputs, states = basic_rnn_seq2seq(encoder_inputs, decoder_inputs, cell)
在上面的调用中,
encoder_inputs
是代表编码器输入数据的张量列表,对应于上图中的字母A,B,C。 类似地,
decoder_inputs
是表示解码器输入数据的张量。 从第一张图片开始GO,W,X,Y,Z。
cell
参数是
tf.contrib.rnn.RNNCell
类的实例,该类确定将在模型中使用哪个单元格。 您可以使用现有的单元格,例如
GRUCell
或
LSTMCell
,也可以编写自己的单元格。 另外,
tf.contrib.rnn
提供了用于创建多层单元的外壳,为单元输入和输出或其他转换添加了例外。 查看
RNN教程中的示例。
basic_rnn_seq2seq
调用返回两个参数:
outputs
和
states
。 它们都表示与
decoder_inputs
输入相同长度的张量列表。
outputs
对应于每个时间步长的解码器输出数据,在第一张图片中是W,X,Y,Z,EOS。 返回的
states
表示每个时间步解码器的内部状态。
在使用序列到序列模型的许多应用中,时间t处的解码器输出在时间t +1处被传输回输入到解码器。 在测试过程中,在序列解码过程中,这就是构造新序列的方式。 另一方面,在训练期间,习惯上在每个时间步长将正确的输入数据发送到解码器,即使先前解码器被弄错了。
seq2seq.py
函数通过
feed_previous
参数支持两种模式。 例如,考虑以下对嵌套RNN模型的使用。
outputs, states = embedding_rnn_seq2seq( encoder_inputs, decoder_inputs, cell, num_encoder_symbols, num_decoder_symbols, embedding_size, output_projection=None, feed_previous=False)
在
embedding_rnn_seq2seq
模型中,所有输入数据(
decoder_inputs
输入和
decoder_inputs
输入)都是反映离散值的整数张量。 它们将嵌套在一个紧密的表示形式中(有关附件的详细信息,请参见“
向量视图指南” ),但是要创建这些附件,您需要指定最大离散字符数:在编码器端为
num_decoder_symbols
,在解码器端为
num_decoder_symbols
。
在上面的调用中,我们将
feed_previous
设置为False。 这意味着解码器将以提供它们的形式使用解码器
decoder_inputs
张量。 如果将
feed_previous
设置为True,则解码器将仅使用第一个
decoder_inputs
元素。 列表中的所有其他张量将被忽略,而将使用解码器输出的先前值代替。 这用于解码翻译模型中的翻译,但也可以在训练过程中使用,以提高模型对其错误的稳定性。 大致与
Bengio et al。,2015 (
pdf )相同。
上面使用的另一个重要参数是
output_projection
。 无需澄清,嵌入式模型的结论将为张量,其形式为每
num_decoder_symbols
训练样本的数量,因为它们表示每个生成符号的对数。 当训练具有大输出字典的模型(例如,具有大
num_decoder_symbols
,存储这些大张量变得不切实际。 相反,最好返回较小的张量,随后将使用
output_projection
将其投影到较大的张量上。 这使我们可以使用seq2seq模型和采样的softmax损失,如
Jean等人所述。 等人,2014年 (
pdf )。
除了
basic_rnn_seq2seq
和
embedding_rnn_seq2seq
之外,
basic_rnn_seq2seq
还有更多的序列到序列模型。 注意他们。 它们都具有相似的界面,因此我们将不深入研究它们的细节。 对于下面的翻译模型,请使用
embedding_attention_seq2seq
。
待续。