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

How to use return_sequences option and TimeDistributed layer in Keras?

我有一个像下面这样的对话语料库。我想实现一个预测系统动作的 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)

所以我要实现的是"many to many (2)"模型。当我的模型接收到用户输入时,它必须输出系统操作。 但是我无法理解 LSTM 之后的 return_sequences 选项和 TimeDistributed 层。实现"many-to-many (2)"、return_sequences==True,在LSTM后加个TimeDistributed?如果您能对它们进行更多描述,我将不胜感激。

return_sequences: Boolean. Whether to return the last output in the output sequence, or the full sequence.

TimeDistributed: This wrapper allows to apply a layer to every temporal slice of an input.

2017/03/13 更新17:40

我想我可以理解 return_sequence 选项。但我仍然不确定 TimeDistributed。如果我在LSTMs后面加一个TimeDistributed,模型和下面的"my many-to-many(2)"一样吗?所以我认为每个输出都应用了密集层。

LSTM 层和 TimeDistributed 包装器是获得所需 "many to many" 关系的两种不同方式。

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

如你所见,两者的区别在于 LSTM“通过序列传播信息,它会吃掉一个词,更新它的状态,return它与否。然后它会去继续处理下一个单词,同时仍然携带前一个单词的信息……就像在 TimeDistributed 中一样,单词将以相同的方式自行处理,就好像它们在筒仓中一样,同一层适用于每个单词他们。

所以你不必连续使用 LSTM 和 TimeDistributed,你可以做任何你想做的事,只要记住它们各自的作用即可。

我希望它更清楚?

编辑:

在您的例子中,时间分布对 LSTM 输出的每个元素应用了一个致密层。

举个例子:

您有一系列 n_words 个嵌入 emb_size 维度的单词。所以你的输入是一个二维张量 (n_words, emb_size)

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

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

是不是更清楚了? :-)

    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 的包装层。该层将帮助我们保持输出的形状,以便我们最终可以实现一个序列作为输出。