关于“理解 Keras LSTM”的疑问

Doubts regarding `Understanding Keras LSTMs`

我是 LSTM 的新手,正在经历 and had some silly doubts related to a beautiful answer by Daniel Moller

以下是我的一些疑惑:

  1. Achieving one to many 部分指定了 2 种方法,其中写道我们可以使用 stateful=True 循环获取一步的输出并将其作为输入下一步(需要output_features == input_features)。

    One to many with repeat vector 图中,重复向量在所有时间步中作为输入提供,而在 One to many with stateful=True 中,输出在下一个时间步中作为输入提供。那么,我们不是通过使用 stateful=True 来改变层的工作方式吗?

    在构建 RNN 时,应遵循上述两种方法中的哪一种(使用重复向量或将前一个时间步输出作为下一个输入)?

  2. One to many with stateful=True部分,改变one to many的行为,在手动循环预测的代码中,我们如何知道steps_to_predict变量因为我们事先不知道输出序列长度。

    我也不明白整个模型是如何使用last_step output生成next_step ouput的。它让我对 model.predict() 函数的工作感到困惑。我的意思是,model.predict() 不会一次同时预测整个输出序列,而不是循环生成 no. of output sequences(我仍然不知道其值)并执行 model.predict() 到预测给定迭代中的特定时间步长输出?

  3. 我无法理解整个 Many to many 案例。任何其他 link 都会有所帮助。

  4. 我知道我们使用 model.reset_states() 来确保新批次独立于前一批次。但是,我们是手动创建序列批次,以便一个批次跟随另一批次,还是 Keras in stateful=True 模式自动将序列分成这样的批次。

    如果手动完成,那么为什么会有人将数据集分成这样的批次,其中序列的一部分在一个批次中,另一个在下一批次中?

  5. 最后,实际的实现是什么,或者examples/use-cases 哪里会用到stateful=True(因为这似乎有些不寻常)?我正在学习 LSTM,这是我第一次在 Keras 中被介绍 stateful

任何人都可以帮助我解释我的愚蠢问题,以便我可以清楚地了解 Keras 中的 LSTM 实现吗?

编辑:要求其中一些人澄清当前答案,并要求一些人解决剩余的疑问

A。所以,基本上有状态让我们 keep OR reset 每批之后的内部状态。那么,如果我们在每批训练后不断地重置内部状态,模型将如何学习呢?重置真的意味着重置参数(用于计算隐藏状态)吗?

B。在 If stateful=False: automatically resets inner state, resets last output step 行中。重置最后一个输出步骤是什么意思?我的意思是,如果每个时间步长都产生自己的输出,那么重置最后一个输出步长意味着什么,也只是最后一个输出步长?

C。针对 Question 2Question 4 的第二点,我仍然没有得到你的 manipulate the batches between each iterationstateful 的需要((Question 2 的最后一行)这只会重置状态)。我的意思是我们不知道在一个时间步长中生成的每个输出的输入。

所以,你将序列分成 only one-step 的序列,然后使用 new_step = model.predict(last_step) 但是你怎么知道你需要多长时间一次又一次地这样做(必须有一个循环的停止点)?另外,请解释 stateful 部分(在 Question 2 的最后一行)。

D。在One to many with stateful=True下的代码中,似乎for循环(手动循环)用于预测下一个单词只是在测试时使用。模型是否在训练时合并了那个东西本身,或者我们 manually 是否也需要在训练时使用这个循环?

E。假设我们正在做一些 机器翻译 工作,我认为序列的中断将在整个输入(要翻译的语言)被输入到输入时间步长然后生成输出之后发生(翻译的语言)在每个时间步长将通过 manual loop 发生,因为现在我们完成了输入并开始使用迭代在每个时间步长产生输出。我做对了吗?

F。由于 LSTM 的默认工作需要答案中提到的 3 件事,因此在序列中断的情况下,current_inputprevious_output 被馈送相同的向量,因为在没有当前输入可用的情况下它们的值是一样吗?

G。在 many to many with stateful=True 下的 Predicting: 部分,代码如下:

predicted = model.predict(totalSequences)
firstNewStep = predicted[:,-1:]

因为finding the very next word in the current sequence的手动循环到现在都没用过,我怎么知道model.predict(totalSequences)预测的时间步长count ] 以便 predicted(predicted[:,-1:]) 的最后一步稍后将用于生成其余序列?我的意思是,我怎么知道manual for loop之前的predicted = model.predict(totalSequences)(后面用到)

已经产生了多少序列

编辑 2:

。在 D 的回答中,我仍然不明白我将如何训练我的模型?我知道使用手动循环(在训练期间)可能会非常痛苦,但如果我不使用它,模型将如何在 we want the 10 future steps, we cannot output them at once because we don't have the necessary 10 input steps 的情况下进行训练?只需使用 model.fit() 就能解决我的问题吗?

IID 答案的最后一段,You could train step by step using train_on_batch only in the case you have the expected outputs of each step. But otherwise I think it's very complicated or impossible to train.

你能详细解释一下吗?

step by step是什么意思?如果我 没有 后面序列的输出,这将如何影响我的训练?在训练期间我还需要手动循环吗?如果不是,那么 model.fit() 功能是否会按预期工作?

III。我将 "repeat" option 解释为使用 repeat vector。使用重复向量不会只适用于 one to many 情况而不适合 many to many 情况,因为后者将有许多输入向量可供选择(用作单个重复向量) ?在 many to many 案例中,您将如何使用 repeat vector

问题 3

理解问题 3 是理解其他问题的关键,所以,让我们先尝试一下。

Keras 中的所有循环层执行 隐藏 循环。这些循环对我们来说是完全不可见的,但是我们可以在最后看到每次迭代的结果。

不可见迭代次数等于time_steps维度。因此,LSTM 的循环计算发生在这些步骤上。

如果我们用 X 步传递一个输入,就会有 X 次不可见的迭代。

LSTM 中的每次迭代将采用 3 个输入:

  • 这一步输入数据的相应切片
  • 层的内部状态
  • 最后一次迭代的输出

所以,以下面的示例图像为例,我们的输入有 5 个步骤:

Keras 在一次预测中会做什么?

  • 第0步:
    • 采取输入的第一步,input_data[:,0,:] 切片形状为 (batch, 2)
    • 取内部状态(此时为零)
    • 采取最后的输出步骤(第一步不存在)
    • 将计算传递给:
      • 更新内部状态
      • 创建一个输出步骤(输出0)
  • 第一步:
    • 进行下一步的输入:input_data[:,1,:]
    • 获取更新后的内部状态
    • 取上一步生成的输出(输出0)
    • 通过相同的计算:
      • 再次更新内部状态
      • 再创建一个输出步骤(输出 1)
  • 第二步:
    • input_data[:,2,:]
    • 获取更新后的内部状态
    • 取输出 1
    • 通过:
      • 更新内部状态
      • 创建输出 2
  • 依此类推,直到第 4 步。

  • 最后:

    • 如果stateful=False:自动重置内部状态,重置最后的输出步骤
    • 如果stateful=True:保持内部状态,保持最后的输出步骤

您不会看到这些步骤中的任何一个。它看起来就像一个单程。

但您可以选择:

  • return_sequences = True:每输出一步返回,形状(batch, steps, units)
    • 这正好是多对多。您在输出中得到的步数与在输入中得到的步数相同
  • return_sequences = False:只返回最后一步输出,形状(batch, units)
    • 这是多对一的。您为整个输入序列生成一个结果。

现在,这回答了问题 2 的第二部分:是的,predict 会在您不注意的情况下计算所有内容。但是:

The number of output steps will be equal to the number of input steps

问题 4

现在,在进入问题 2 之前,让我们先看一下 4,它实际上是答案的基础。

是的,批处理应该手动完成。 Keras 不会更改您的批次。那么,为什么我要划分一个序列呢?

  • 1,序列太大,一批不适合计算机或GPU的内存
  • 2,您想执行 问题 2 中发生的事情:在每个步骤迭代之间操作批次。

问题 2

第2题,我们是"predicting the future"。那么,输出步数是多少?好吧,这就是您要预测的数字。假设您正试图根据过去预测您将拥有的客户数量。您可以决定预测未来一个月或 10 个月。你的选择。

现在,您认为 predict 会立即计算整个事情是对的,但请记住上面 问题 3 我说的地方:

The number of output steps is equal to the number of input steps

还要记住,第一个输出步骤是第一个输入步骤的结果,第二个输出步骤是第二个输入步骤的结果,依此类推。

但我们要的是未来,而不是一个接一个地跟前面的步骤相匹配的东西。我们希望结果步骤遵循 "last" 步骤。

所以,我们面临一个限制:如果我们没有各自的输入,如何定义固定数量的输出步骤? (遥远未来的输入也是未来,所以,它们不存在)

这就是为什么我们将序列分解为 只有一个步骤 的序列。所以predict也只会输出一步

当我们这样做时,我们有能力在每次迭代之间操纵批次。而且我们有能力将输出数据(我们以前没有)作为输入数据。

有状态是必要的,因为我们希望这些步骤中的每一个都连接为一个序列(不要丢弃状态)。

问题 5

我所知道的stateful=True最好的实际应用是问题2的答案。我们想要在步骤之间操作数据。

这可能是一个虚拟示例,但另一个应用程序是,如果您正在从 Internet 上的用户接收数据。用户每天使用您的网站,您都会向您的模型提供更多数据步骤(并且您希望以相同的顺序继续该用户之前的历史记录)。

问题 1

然后,终于是第1题了

我会说:总是避免stateful=True,除非你需要它
您不需要它来构建一对多网络,因此最好不要使用它。

请注意,此 stateful=True 示例与 预测未来 示例相同,但您从一步开始。它很难实现,因为手动循环,速度会更差。但是您可以控制输出步骤的数量,这在某些情况下可能是您想要的。

计算也会有差异。在这种情况下,我真的无法回答一个比另一个好。但我不相信会有很大的不同。但是网络是某种 "art",测试可能会带来有趣的惊喜。

编辑答案:

一个

我们不应该将 "states" 误认为是 "weights"。它们是两个不同的变量。

  • 权重:可学习的参数,它们永不重置。 (如果你重置权重,你会失去模型学到的一切)
  • States: current memory of a batch of sequences(关系到我现在在sequence上的第几步,到这一步我学到了什么"from the specific sequences in this batch") .

假设您正在看电影(连续镜头)。每一秒都会让你建立记忆,比如角色的名字,他们做了什么,他们的关系是什么。

现在假设您看到一部从未看过的电影,然后开始观看电影的最后一秒。你不会理解电影的结尾,因为你需要这部电影的前一个故事。 (各州)

想象一下,你看完了一整部电影。现在您将开始观看一部新电影(一个新序列)。您无需记住上一部电影中发生的事情。如果你尝试 "join the movies",你会感到困惑。

在这个例子中:

  • 权重:你理解和解释电影的能力记住重要名字和动作的能力
  • 状态:在暂停的电影中,状态是记忆从开始到现在发生的事情。

所以,状态是 "not learned"。状态是 "calculated",针对批次中的每个单独序列逐步构建。这就是为什么:

  • 重置状态意味着从第 0 步开始新序列(开始新电影)
  • 保持状态意味着从最后一步继续相同的序列(继续播放暂停的电影,或观看该故事的第 2 部分)

状态正是使循环网络像有 "memory from the past steps" 一样工作的原因。

B

在 LSTM 中,最后的输出步骤是 "states" 的一部分。

一个 LSTM 状态包含:

  • 通过计算每一步更新的记忆矩阵
  • 最后一步的输出

所以,是的:每一步都会产生自己的输出,但每一步都使用最后一步的输出作为状态。这就是 LSTM 的构建方式。

  • 如果你想"continue"相同的序列,你要记忆最后一步的结果
  • 如果你想 "start" 一个新的序列,你不需要最后一步结果的记忆(如果你不重置状态,这些结果将保持存储)

C

想停就停。您想预测未来多少步?那是你的停止点。

假设我有一个包含 20 个步骤的序列。我想预测未来的 10 个步骤。

在标准(无状态)网络中,我们可以使用:

  • 一次输入19步(从0到18)
  • 一次输出19步(从1到19)

这是 "predicting the next step"(注意移位 = 1 步)。我们可以这样做,因为我们拥有所有可用的输入数据。

但是当我们想要10个未来的步骤时,我们不能一次输出它们,因为我们没有必要的10个输入步骤(这些输入步骤是未来的,我们需要模型先预测它们)。

所以我们需要根据现有数据预测未来的一步,然后将这一步作为输入为下一步。

但我希望这些步骤都相互关联。如果我使用 stateful=False,模型会看到很多 "sequences of length 1"。不,我们想要一个长度为 30 的序列。

D

这是一个非常好的问题,你让我明白了....

有状态的一对多是我在写那个答案的时候想到的,但是我从来没有用过这个。我更喜欢 "repeat" 选项。

只有在每个步骤都有预期输出的情况下,您才可以使用 train_on_batch 逐步训练。但除此之外,我认为训练起来非常复杂或不可能。

E

这是一种常见的方法。

  • 用网络生成压缩向量(这个向量可以是结果,或者生成的状态,或者两者兼而有之)
  • 使用此压缩向量作为另一个网络的初始input/state,手动逐步生成并在模型生成"end of sentence"个单词或字符时停止。

还有没有手动循环的固定尺寸模型。你假设你的句子有 X 个单词的最大长度。比这短的结果句用"end of sentence"或"null"words/characters补全。 Masking 层在这些模型中非常有用。

F

您只提供输入。另外两件事(最后的输出和内部状态)已经存储在有状态层中。

我输入 = 最后一个输出只是因为我们的特定模型预测下一步。这就是我们想要它做的。对于每个输入,下一步。

我们在训练中用移位的顺序来教这个。

G

没关系。我们只需要最后一步。

  • 序列数由第一个:保留。
  • 并且-1:只考虑了最后一步。

但是如果你想知道,你可以打印predicted.shape。在此模型中等于 totalSequences.shape

编辑 2

首先,我们不能使用 "one to many" 模型来预测未来,因为我们没有这方面的数据。如果您没有序列步骤的数据,则无法理解 "sequence"。

因此,此类模型应该用于其他类型的应用程序。正如我之前所说,对于这个问题我真的没有很好的答案。最好先有一个"goal",然后我们决定哪种模型更适合那个目标。

与"step by step"我的意思是手动循环。

如果你没有后面步骤的输出,我认为是不可能训练的。它可能根本不是一个有用的模型。 (但我不是什么都懂的人)

如果你有输出,是的,你可以用 fit 训练整个序列而不用担心手动循环。

关于 III,你是对的。您不会在多对多中使用重复向量,因为您有不同的输入数据。

"One to many" 和 "many to many" 是两种不同的技术,各有优缺点。一种适用于某些应用,另一种适用于其他应用。