如何在 Keras 中使用 return_sequences 选项和 TimeDistributed 层?

Posted

技术标签:

【中文标题】如何在 Keras 中使用 return_sequences 选项和 TimeDistributed 层?【英文标题】:How to use return_sequences option and TimeDistributed layer in Keras? 【发布时间】:2017-08-03 00:11:30 【问题描述】:

我有一个如下的对话语料库。我想实现一个预测系统动作的 LSTM 模型。系统动作被描述为位向量。并且用户输入被计算为一个字嵌入,它也是一个位向量。

t1: user: "Do you know an apple?", system: "no"(action=2)
t2: user: "xxxxxx", system: "yyyy" (action=0)
t3: user: "aaaaaa", system: "bbbb" (action=5)

所以我想实现的是“多对多 (2)”模型。当我的模型接收到用户输入时,它必须输出系统操作。 但我无法理解 LSTM 之后的return_sequences 选项和TimeDistributed 层。要实现“多对多(2)”,return_sequences==True 并在 LSTM 之后添加TimeDistributed?如果您能提供更多关于它们的描述,我将不胜感激。

return_sequences:布尔值。是返回输出序列中的最后一个输出,还是返回完整序列。

TimeDistributed:此包装器允许将层应用于输入的每个时间切片。

2017/03/13 17:40 更新

我想我可以理解return_sequence 选项。但我仍然不确定TimeDistributed。如果我在 LSTM 之后添加TimeDistributed,模型是否与下面的“我的多对多(2)”相同?所以我认为每个输出都应用了密集层。

【问题讨论】:

TimeDistributed 是否应该用于“一对多”?如果我使用 TimeDistributed,return_sequences 必须为 True。我说的对吗? 我可以知道这些操作是否是有限和预定义的? 您的系统响应是否取决于之前用户的输入? 【参考方案1】:
    return_sequences=True parameter:

如果我们想要输出一个序列,而不是像我们在普通神经网络中所做的那样只是一个向量,那么我们有必要将 return_sequences 设置为 True。具体来说,假设我们有一个形状为 (num_seq, seq_len, num_feature) 的输入。如果我们不设置 return_sequences=True,我们的输出将具有形状 (num_seq, num_feature),但如果我们这样做,我们将获得形状 (num_seq, seq_len, num_feature) 的输出。

    TimeDistributed wrapper layer:

由于我们在 LSTM 层中设置了 return_sequences=True,因此输出现在是一个三维向量。如果我们将它输入到 Dense 层,它会引发错误,因为 Dense 层只接受二维输入。为了输入一个三维向量,我们需要使用一个名为 TimeDistributed 的包装层。该层将帮助我们保持输出的形状,以便我们最终实现一个序列作为输出。

【讨论】:

【参考方案2】:

LSTM 层和 TimeDistributed 包装器是获得所需“多对多”关系的两种不同方式。

    LSTM 会一个一个地吃掉你句子中的单词,你可以通过“return_sequence”选择在每一步(每个单词处理后)输出一些东西(状态),或者只在最后一个单词被吃掉后输出一些东西。所以当 return_sequence=TRUE 时,输出将是一个相同长度的序列,当 return_sequence=FALSE 时,输出将只是一个向量。 时间分布。此包装器允许您独立将一层(例如 Dense)应用于序列的每个元素。该层对于每个元素将具有完全相同的权重,将应用于每个单词的权重相同,并且它当然会返回独立处理的单词序列。

如你所见,两者的区别在于LSTM“通过序列传播信息,它会吃掉一个单词,更新它的状态并返回或不返回。然后它会继续下一个单词,而仍然携带来自以前的信息.... 就像在 TimeDistributed 中一样,单词将以相同的方式自行处理,就好像它们在孤岛中一样,并且相同的层适用于它们中的每一个。

所以你不必连续使用 LSTM 和 TimeDistributed,你可以做任何你想做的事,只要记住他们每个人都做了什么。

我希望它更清楚?

编辑:

在您的情况下,时间分布将密集层应用于 LSTM 输出的每个元素。

举个例子:

您有一个嵌入在 emb_size 维度中的 n_words 单词序列。所以你的输入是一个形状为(n_words, emb_size) 的二维张量

首先应用输出维度 = lstm_outputreturn_sequence = True 的 LSTM。输出仍将是一个序列,因此它将是一个形状为(n_words, lstm_output) 的二维张量。 所以你有长度为 lstm_output 的 n_words 向量。

现在您应用一个 TimeDistributed 密集层,其中 3 维输出作为密集的参数。所以时间分布(密集(3))。 这将应用 Dense(3) n_words 次,独立地应用于您序列中每个大小为 lstm_output 的向量......它们都将成为长度为 3 的向量。您的输出仍然是一个序列,所以现在是一个二维张量(n_words, 3) .

是不是更清楚了? :-)

【讨论】:

谢谢。我想我可以理解return_sequence。但我不清楚 TimeDistributed。你能检查我更新的问题吗? 谢谢。如果我只使用 Dense(3) 而不是 TimeDistributed(Dense(3)),有什么区别? 在这种情况下,这是一个特殊情况,但你会得到相同的结果...... ^^ 我知道这很令人困惑.. 如果你只想要 3 个输出,你必须像这样重塑 LSTM 的输出: Reshape( output_shape= (n_wordslstm_output,) ) 然后使用 Dense(3) 并且您的输出形状将从 (n_words, lstm_output) 更改为 (n_wordslstm_output,) 到 (3,) 好的。我得到了它。非常感谢。 如果我做 return_sequence=True 并应用一个简单的没有时间分布的 Dense,它和使用时间分布一样吗?

以上是关于如何在 Keras 中使用 return_sequences 选项和 TimeDistributed 层?的主要内容,如果未能解决你的问题,请参考以下文章

在较新版本的 Keras 中,LSTM 等效于 return_sequence = True

KERAS:使用 return_sequence = True 获取 SLICE 的 RNN 时间步长

如何在 Keras 中同时获取 LSTM 或 GRU 的最后输出和完整序列?

如何在 Keras 功能模型中添加 Dropout?

理解 LSTM 中的输入和输出形状 | tf.keras.layers.LSTM(以及对于return_sequences的解释)

Keras - 如何获取 GRU 单元状态?