背景
我正在尝试构建一个聊天机器人,并通过阅读以下内容对tensorflow Sequence2Sequence API有基本的了解: https://www.tensorflow.org/tutorials/seq2seq/
我还阅读了相关的神经翻译论文,编码/解码过程中的注意机制等。
RNN翻译代码取自此处: HTTP @ S://github.com/tensorflow/models/blob/master/tutorials/rnn/translate/seq2seq_model.py
从这里选择Bucketing / Attention机制代码: HTTP @ S://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/legacy_seq2seq/python/ops/seq2seq.py
在我的训练期间(注意机制,GRU细胞),我把我的水桶给了[(2,2),(4,4),(6,6),(,8,8),(10,10) ]
问题
在解码过程中,如果我在同一输入上强制使用bucket_index,那么在第一步时我会得到完全不同的输出。例如:
输入:你好吗? 铲斗指数:1
输出:NAME UNK NAME
输入:你好吗? 铲斗指数:2
输出:你好NAME到
观察
我可以使用波束搜索修复每个时间步的坏输出。但是,为什么我在解码过程中第一次获得不同的字作为输出?小桶输出不应该是更大桶输出的子集吗?
我尝试过在线搜索,并且提到参数在各个存储桶之间共享。铲斗用于训练效率,而不用于模型调整。我还验证了我的训练参数在所有桶中都很常见。
我可以在各种存储桶的编码器输入之间看到的最大区别是一开始就有额外的填充。我们正在对encoded_states进行注意机制,并且在训练期间已经为那些编码状态学习了softmax权重。因此,那些额外填充输入的softmax权重是否会导致在解码的第一个时间段内导致不同输出的足够差异?
其他人是否也遇到过上述问题?任何帮助解决上述错误都将非常感激。
我也在这里打开了一个问题,因为我不确定它是否是一个bug(github上的文件),或者我的误解(Stackoverflow): https://github.com/tensorflow/tensorflow/issues/7561
答案 0 :(得分:0)
我不确定你是否已找到答案。我想对此发表评论以防其他人想要这个想法。
我相信这是预期的行为。如果在TensorFlow中检查model_with_buckets函数的源实现,则大致可以看到以下代码行:
for j, bucket in enumerate(buckets):
with variable_scope.variable_scope(
variable_scope.get_variable_scope(), reuse=True if j > 0 else None):
bucket_outputs, _ = seq2seq(encoder_inputs[:bucket[0]],
decoder_inputs[:bucket[1]])
outputs.append(bucket_outputs)
如果你使用5个桶,那么上面的输出列表将包含5个子列表。在每个子列表中,它包含每个桶的decoder_output。将返回此输出,并将用于训练和预测。您可以看到不同存储桶中的每个decoder_output(单数形式)通常是不同的,因为它们经过训练可生成与不同存储桶的不同目标匹配的输出(尽管不同存储桶中的变量被重复使用)。
你可以做的一个有趣的测试是:在你的训练集中增加一对简短的问题,但是答案很长(确保你的模型足够大,几乎可以记住每个训练样本)。这意味着,这对将在训练中使用更大的桶,但在预测中使用更小的桶。您还需要一种机制来以字符串格式键入填充令牌,例如 pad 。训练模型后,执行此类预测测试。输入原始答案,您很可能会得到完全不同/无意义的答案。但是,然后输入您的问题,然后输入一些 pad ,直到输入句子足够长,以便可以选择所需的存储桶。然后,您很可能会在新的训练对中获得相同的答案。
希望这种解释有意义。