大家好!
我们在几周前发布了翻译的第二部分,以准备启动
“数据科学家”课程的第二部分。 未来是另一种有趣的材料,也是一个公开的课程。
同时,我们进一步深入了模型的丛林。
神经翻译模型虽然序列到序列模型的核心是由
tensorflow/tensorflow/python/ops/seq2seq.py
的函数创建的,但在
models/tutorials/rnn/translate/seq2seq_model.py
,我们的翻译模型中仍使用了一些技巧值得一提。
采样的softmax和输出投影如上所述,我们希望使用采样的softmax处理大型输出字典。 要从中解码,您必须跟踪输出的投影。 采样的softmax损耗和输出投影都是由
seq2seq_model.py
的以下代码生成的。
if num_samples > 0 and num_samples < self.target_vocab_size: w_t = tf.get_variable("proj_w", [self.target_vocab_size, size], dtype=dtype) w = tf.transpose(w_t) b = tf.get_variable("proj_b", [self.target_vocab_size], dtype=dtype) output_projection = (w, b) def sampled_loss(labels, inputs): labels = tf.reshape(labels, [-1, 1])
首先,请注意,只有在样本数(默认为512)小于目标字典大小的情况下,我们才创建样本softmax。 对于小于512的字典,最好使用标准softmax损失。
然后,创建输出的投影。 这是一对由权重矩阵和位移向量组成的对。 当使用rnn单元格时,返回按
size
排列的训练样本数的形状矢量,而不是按
target_vocab_size
返回训练样本数的形状向量。 要恢复logit,您需要将其乘以权重矩阵并添加一个偏移量,这发生在
seq2seq_model.py
中的第124-126行中。
if output_projection is not None: for b in xrange(len(buckets)): self.outputs[b] = [tf.matmul(output, output_projection[0]) + output_projection[1] for ...]
桶装和填充除了采样的softmax之外,我们的翻译模型还使用了
bucketing(存储桶)功能 ,该方法可让您有效地管理不同长度的句子。 首先,说明问题。 从英语翻译成法语时,我们在入口处使用长度为L1的英语句子,在出口处使用长度为L1的法语句子。 由于英语句子是作为
encoder_inputs
传输的,而法语句子则是作为
decoder_inputs
(带有GO符号前缀)显示的,因此有必要为英语和法语句子的每对长度(L1,L2 + 1)创建一个seq2seq模型。 结果,我们得到了一个包含许多相似子图的巨大图。 另一方面,我们可以用特殊的PAD字符“填充”每个句子。 然后,对于“打包”长度,我们只需要一个seq2seq模型。 但是,这样的模型在短句子中将无效-您必须编码和解码许多无用的PAD字符。
在为每对长度创建一个图和填充为单个长度之间的折衷方案中,我们使用一定数量的存储桶,并将每个句子填充至上述组的长度。 默认情况下,在
translate.py
我们使用以下组。
buckets = [(5, 10), (10, 15), (20, 25), (40, 50)]
因此,如果一个带有3个标记的英语句子到达输入,而对应的法语句子在输出处包含6个标记,则它们将进入第一组,并在编码器的输入处填充为长度5,在解码器的输入处填充为长度10。 如果英语报价中有8个令牌,而对应的法语18中,则不会落入组(10、15)中,而是将其转移到组(20、25)中,即英语报价将增加到20个令牌,而法语报价将增加到25个令牌。
请记住,在创建解码器输入时,我们会在输入中添加特殊的
GO
字符。 这发生在
get_batch()
中的
get_batch()
函数中,该函数还会翻转英语句子。 输入的翻转有助于改善
Sutskever等人(2014)(pdf)的神经翻译模型的结果
。 为了弄清楚,想像一下有一个句子“ I go”。在输入处,将其分解为标记
["I", "go", "."]
,在输出处则是一个句子“ Je vais。”,将其分解为标记
["Je", "vais", "."]
。 它们将以输入编码器
[PAD PAD "." "go" "I"]
形式添加到组(5,10)中
[PAD PAD "." "go" "I"]
[PAD PAD "." "go" "I"]
和解码器输入
[GO "Je" "vais" "." EOS PAD PAD PAD PAD PAD]
[GO "Je" "vais" "." EOS PAD PAD PAD PAD PAD]
。
运行它要训练上述模型,您将需要一个大型的英法军团。 为了进行培训,我们将使用来自
WMT'15网站的10 ^ 9法语-英语军,并将来自同一站点的新闻作为工作样本进行测试。 当运行下一个命令时,两个数据集都将被加载到
train_dir
。
python translate.py --data_dir [your_data_directory] --train_dir [checkpoints_directory] --en_vocab_size=40000 --fr_vocab_size=40000
您将需要18GB的硬盘空间和几个小时来准备培训大楼。 对该案例进行解压缩,在
data_dir,
中创建字典文件
data_dir,
然后对该案例进行标记并转换为整数标识符。 请注意负责字典大小的参数。 在上面的示例中,40,000个最常用词之外的所有词都将转换为代表未知词的UNK令牌。 因此,当更改字典的大小时,二进制文件将通过令牌ID重新更改外壳。 数据准备培训开始之后。
默认情况下,
translate
中指定的值非常高。 长时间学习的大型模型显示出良好的效果,但是可能会花费太多时间或GPU内存过多。 您可以指定一个较小的模型锻炼,如下例所示。
python translate.py --data_dir [your_data_directory] --train_dir [checkpoints_directory] --size=256 --num_layers=2 --steps_per_checkpoint=50
上面的命令将训练模型分为两层(默认为3层),每层有256个单位(默认为1024个),每50步带有一个检查点(默认为200个)。 尝试使用这些选项,以查看哪种尺寸模型适合您的GPU。
在训练过程中,
steps_per_checkpoin
t二进制文件的每个步骤都会提供有关过去步骤的统计信息。 使用默认参数(3层,大小为1024),第一条消息如下:
global step 200 learning rate 0.5000 step-time 1.39 perplexity 1720.62 eval: bucket 0 perplexity 184.97 eval: bucket 1 perplexity 248.81 eval: bucket 2 perplexity 341.64 eval: bucket 3 perplexity 469.04 global step 400 learning rate 0.5000 step-time 1.38 perplexity 379.89 eval: bucket 0 perplexity 151.32 eval: bucket 1 perplexity 190.36 eval: bucket 2 perplexity 227.46 eval: bucket 3 perplexity 238.66
请注意,每个步骤花费的时间不到1.4秒,这使训练样本感到困惑,并使每个组的工作样本感到困惑。 经过大约3万步,我们看到了简短句子(第0组和第1组)的困惑如何变得清晰。 培训大楼包含约2200万个句子,一次迭代(一次运行的训练数据)大约需要34万步,训练样本的数量为64个。在此阶段,该模型可用于使用
--decode
选项将英语句子翻译为法语。
python translate.py --decode --data_dir [your_data_directory] --train_dir [checkpoints_directory] Reading model parameters from /tmp/translate.ckpt-340000 > Who is the president of the United States? Qui est le président des États-Unis ?
接下来是什么?上面的示例显示了如何端到端创建自己的英语-法语翻译器。 运行它,看看模型如何工作。 质量是可以接受的,但是无法使用默认参数获得理想的翻译模型。 这是您可以改进的几件事。
首先,我们使用原始标记化,即
basic_tokenizer
中
data_utils
的基本功能。
在WMT'15网站上可以找到更好的令牌生成器。 如果使用它和大型词典,则可以实现更好的翻译。
此外,转换模型的默认参数配置不完善。 您可以尝试更改学习速度,衰减,模型权重的初始化。 您还可以使用更高级的功能(例如
AdagradOptimizer
替换
seq2seq_model.py
的标准
GradientDescentOptimizer
。 尝试观察更好的结果!
最后,以上介绍的模型不仅可以用于翻译,还可以用于任何其他序列到序列的任务。 例如,即使您要将序列变成树,生成分析树,该模型也可以产生最新的结果,如
Vinyals&Kaiser等人,2014(pdf)所示 。 因此,您不仅可以创建翻译器,还可以创建解析器,聊天机器人或您想要的任何其他程序。 实验!
仅此而已!
我们在这里等待您的评论和问题,或者我们邀请您在
公开课中向他们的
老师提问。