了解 Seq2Seq 模型

Posted

技术标签:

【中文标题】了解 Seq2Seq 模型【英文标题】:Understanding Seq2Seq model 【发布时间】:2018-03-03 11:57:08 【问题描述】:

这是我对基本序列到序列 LSTM 的理解。假设我们正在处理问答设置。

你有两组 LSTM(下面的绿色和蓝色)。每组分别共享权重(即 4 个绿色单元格中的每一个都具有相同的权重,并且与蓝色单元格相似)。第一个是多对一LSTM,总结了在最后一个隐藏层/cell memory的问题。

第二组(蓝色)是多对多 LSTM,其权重与第一组 LSTM 不同。输入只是答案句子,而输出是同一个句子移位了。

问题有两个方面: 1. 我们是否将最后一个隐藏状态作为初始隐藏状态传递给蓝色 LSTM。或者它是最后一个隐藏状态和细胞记忆。 2. 有没有办法在 Keras 或 Tensorflow 中设置初始隐藏状态和单元内存?如果有参考?

(图片取自 suriyadeepan.github.io)

【问题讨论】:

我对你的问题有很多疑问...... 1 - “每组分别共享权重”是什么意思? -- 2- 你对细胞记忆和细胞状态的理解是什么? -- 3 -- 如果图片说它以“思想向量”作为输入,为什么蓝色是多对多的? -- 4 -- 为什么蓝色得到答案并输出一个偏移的答案?疑问句从何而来? ---- 我可以说的一件事是:只有“输出”从一层传递到另一层。 1.在上面的括号中回答。 2. 我想我的意思是细胞状态(根据 colah 的博客,基本上是从 LSTM 传递出来的两件事之一)。 3.我不理解思想向量(这是整个问题的意义所在),但没有它,它是多对多的。看看输出如何循环回输入。 4.这只是训练时间,在测试期间你只需要最高概率的输出(或光束搜索) 【参考方案1】:
    我们是否仅将最后一个隐藏状态作为初始隐藏状态传递给蓝色 LSTM。或者它是最后的隐藏状态和单元记忆。

隐藏状态h 和单元内存c 都被传递给解码器。

TensorFlow

在seq2seq source code,你可以在basic_rnn_seq2seq()找到如下代码:

_, enc_state = rnn.static_rnn(enc_cell, encoder_inputs, dtype=dtype)
return rnn_decoder(decoder_inputs, enc_state, cell)

如果您使用LSTMCell,则从编码器返回的enc_state 将是一个元组(c, h)。如您所见,元组直接传递给解码器。

Keras

在 Keras 中,为 LSTMCell 定义的“状态”也是一个元组 (h, c)(注意顺序与 TF 不同)。在LSTMCell.call(),您可以找到:

    h_tm1 = states[0]
    c_tm1 = states[1]

要获取从LSTM 层返回的状态,您可以指定return_state=True。返回值是一个元组(o, h, c)。张量o 是该层的输出,除非您指定return_sequences=True,否则它将等于h

    有没有办法在 Keras 或 Tensorflow 中设置初始隐藏状态和单元内存?如果有参考?

TensorFlow

调用时只需将初始状态提供给LSTMCell。比如在official RNN tutorial:

lstm = tf.contrib.rnn.BasicLSTMCell(lstm_size)
...
    output, state = lstm(current_batch_of_words, state)

对于诸如tf.nn.static_rnn 之类的函数,还有一个initial_state 参数。如果您使用 seq2seq 模块,请将状态提供给rnn_decoder,如问题 1 的代码所示。

Keras

在 LSTM 函数调用中使用关键字参数initial_state

out = LSTM(32)(input_tensor, initial_state=(h, c))

您实际上可以在the official documentation 上找到这种用法:

关于指定 RNN 初始状态的注意事项

您可以通过以下方式象征性地指定 RNN 层的初始状态 使用关键字参数initial_state 调用它们。的价值 initial_state 应该是张量或张量列表,代表 RNN 层的初始状态。


编辑:

现在 Keras (lstm_seq2seq.py) 中有一个示例脚本,展示了如何在 Keras 中实现基本的 seq2seq。该脚本还介绍了如何在训练 seq2seq 模型后进行预测。

【讨论】:

你能把链接放到你在 tensorflow 上找到 seq2seq enc_state 信息的部分吗?只是有一种感觉,你正在通过它的外观看源头。非常感谢,写得很好! 是的,我查看了它的源代码。我已经添加了代码的链接。这些行来自basic_rnn_seq2seq() 函数(这是官方教程中使用的函数)。如果执行rnn.static_rnn() 行,返回的enc_state 将是LSTMStateTuple(c=..., h=...)【参考方案2】:

(编辑:此答案不完整,未考虑状态转移的实际可能性。请参阅已接受的答案)。

Keras 的角度来看,该图片只有两层。

绿色组是一个 LSTM 层。 蓝色组是另一个 LSTM 层。

除了传递输出之外,绿色和蓝色之间没有任何通信。所以,1 的答案是:

    只有思想向量(该层的实际输出)被传递到另一层。

内存和状态(不确定它们是否是两个不同的实体)完全包含在单个层中,并且最初不打算与任何其他层看到或共享。

该图像中的每个单独块在 keras 中完全不可见。它们被认为是“时间步长”,仅以输入数据的形式出现。很少担心它们(除非非常高级的用法)。

在keras中是这样的:

很容易,您只能访问外部箭头(包括“思想向量”)。 但是可以访问每个步骤(图片中的每个单独的绿色块)并不是一件暴露的事情。所以...

    在 Keras 中也不希望将状态从一层传递到另一层。你可能不得不破解一些东西。 (见:https://github.com/fchollet/keras/issues/2995)

但是考虑到一个足够大的思想向量,你可以说它会学会一种携带本身重要的东西的方法。

您从这些步骤中得到的唯一概念是:

你必须输入形状像(sentences, length, wordIdFeatures)的东西

考虑到长度维度中的每个切片是每个绿色块的输入,将执行这些步骤。

您可以选择使用单个输出(sentences, cells),这样您就完全忘记了步骤。或者……

(sentences, length, cells) 这样的输出,您可以从中通过长度维度了解每个块的输出。

一对多还是多对多?

现在,第一层是多对一的(但如果您愿意,也没有什么能阻止它成为多对多)。

但是第二个......这很复杂。

如果思想向量是由多对一构成的。您将不得不管理一种创建一对多的方式。 (这在 keras 中并非微不足道,但您可以考虑重复预期长度的思想向量,使其成为所有步骤的输入。或者用零或一填充整个序列,仅保留第一个元素作为思想向量) 如果思想向量是由多对多构成的,则可以利用这一点并保持简单的多对多,前提是您愿意接受输出与输入具有完全相同的步数。

Keras 没有针对 1 到多个案例的现成解决方案。 (从单个输入预测整个序列)。

【讨论】:

but nothing prevents it from being many to many too if you want。这实际上是错误的。您可能正在考虑尝试预测下一个单词,这不是我在这里尝试做的。我想总结最后一个单元状态/隐藏层中的问题,然后将其传递给答案 LSTM。这严格来说是多对多。我认为你应该在回答这个问题之前先看看 tensorflow seq2seq 文档。 哇,你至少不能对丹尼尔没有礼貌,他花了一些时间给你写了一个很好的答案。据我所知,您可以使用many to manyone to many。这取决于您是否希望将绿色 LSTM 层中每个时间步的结果馈送到蓝色 LSTM 层 我真的很抱歉这么直率,并不是故意听起来粗鲁。不是我对最初的 +1 投了反对票。我真的很感谢您为做出这个答案所付出的时间和精力。再次,对不起,我是个混蛋。 嗯,看来我的回答根本不值得。查看已接受的答案,我的答案是完全错误的。

以上是关于了解 Seq2Seq 模型的主要内容,如果未能解决你的问题,请参考以下文章

[翻译] 可视化神经网络机器翻译模型(Seq2Seq模型的注意力机制)

深度学习之seq2seq模型以及Attention机制

seq2seq聊天模型—— attention 模型

seq2seq聊天模型

闲聊机器人seq2seq模型的原理

多标签文本分类代码详解Seq2Seq模型