关于“理解 Keras LSTMs”的疑问
Posted
技术标签:
【中文标题】关于“理解 Keras LSTMs”的疑问【英文标题】:Doubts regarding `Understanding Keras LSTMs` 【发布时间】:2019-05-26 01:49:42 【问题描述】:我是 LSTM 的新手,并且正在浏览 Understanding Keras LSTMs,并且对 Daniel Moller 的漂亮答案有一些愚蠢的疑问。
以下是我的一些疑问:
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 时应遵循上述两种方法中的哪一种(使用重复向量或将前一个时间步长输出作为下一个输入)?
在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()
来预测特定的时间步长在给定的迭代中输出?
我无法理解整个Many to many
案例。任何其他链接都会有所帮助。
我了解我们使用model.reset_states()
来确保新批次独立于前一批。但是,我们是否手动创建序列批次,以便一个批次跟随另一批次,或者Keras
在stateful=True
模式下自动将序列划分为这样的批次。
如果是手动完成,为什么会有人将数据集分成这样的批次,其中一个序列的一部分在一个批次中,另一个在下一个批次中?
最后,stateful=True
将被使用的实际实现或示例/用例是什么(因为这似乎很不寻常)?我正在学习 LSTM,这是我第一次被介绍给 Keras 中的stateful
。
谁能帮我解释一下我的愚蠢问题,以便我可以清楚地了解 Keras 中的 LSTM 实现吗?
编辑:询问其中一些是为了澄清当前的答案,还有一些是为了解决剩余的疑问
一个。所以,基本上有状态让我们keep OR reset
每批之后的内部状态。那么,如果我们在每批训练后一次又一次地重置内部状态,模型将如何学习?重置真的意味着重置参数(用于计算隐藏状态)吗?
B。在If stateful=False: automatically resets inner state, resets last output step
行中。重置最后一个输出步骤是什么意思?我的意思是,如果每个时间步都产生自己的输出,那么重置最后一个输出步骤意味着什么?也只有最后一个?
C。针对Question 2
和Question 4
的第二点,我仍然没有得到你的manipulate the batches between each iteration
和stateful
((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_input
和 previous_output
是否提供相同的向量,因为它们在没有当前输入可用的情况下的值是相同的?
G。在 Predicting: 部分下的 many to many with stateful=True 下,代码如下:
predicted = model.predict(totalSequences)
firstNewStep = predicted[:,-1:]
由于finding the very next word in the current sequence
的手动循环到现在都没有用过,我怎么知道model.predict(totalSequences)
已经预测的时间步长的count
,以便预测的最后一步(predicted[:,-1:]
) 稍后将用于生成其余的序列?我的意思是,我怎么知道predicted = model.predict(totalSequences)
在manual for loop
之前已经产生了多少个序列(后面用到)。
编辑 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()
就能解决我的问题吗?
二。 D
答案的最后一段,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
的情况,因为后者将有许多输入向量可供选择(用作单个重复向量)?您将如何将repeat vector
用于many to many
案例?
【问题讨论】:
请查看更新后的答案。 【参考方案1】:问题 3
理解问题3是理解其他问题的关键,所以,让我们先尝试一下。
Keras 中的所有循环层都执行隐藏循环。这些循环对我们来说是完全不可见的,但我们可以在最后看到每次迭代的结果。
不可见的迭代次数等于time_steps
维度。因此,LSTM 的循环计算发生在步骤上。
如果我们通过 X 步传递输入,将会有 X 次不可见的迭代。
LSTM 中的每次迭代都需要 3 个输入:
此步骤的输入数据的相应切片 图层的内部状态 最后一次迭代的输出因此,以下面的示例图像为例,我们的输入有 5 个步骤:
Keras 在一次预测中会做什么?
步骤 0: 采取输入的第一步,input_data[:,0,:]
一个形状为(batch, 2)
的切片
取内部状态(此时为零)
执行最后一个输出步骤(第一步不存在)
将计算传递给:
更新内部状态
创建一个输出步骤(输出 0)
第 1 步:
进行下一步的输入:input_data[:,1,:]
获取更新的内部状态
取上一步生成的输出(输出0)
通过相同的计算:
再次更新内部状态
再创建一个输出步骤(输出 1)
第 2 步:
拍下input_data[:,2,:]
获取更新的内部状态
取输出 1
通过:
更新内部状态
创建输出 2
依此类推,直到第 4 步。
最后:
如果stateful=False
:自动重置内部状态,重置最后一个输出步骤
如果stateful=True
:保持内部状态,保持上一步输出
您不会看到任何这些步骤。它看起来只是一次通过。
但您可以选择:
return_sequences = True
:返回每个输出步骤,形状(batch, steps, units)
这正是多对多。输出中的步数与输入中的步数相同
return_sequences = False
:只返回最后一个输出步骤,形状(batch, units)
这是多对一。您为整个输入序列生成单个结果。
现在,这回答了您问题 2 的第二部分:是的,predict
将在您不注意的情况下计算所有内容。但是:
输出步数将等于输入步数
问题 4
现在,在进行第 2 题之前,让我们先看看第 4 题,这实际上是答案的基础。
是的,批次划分应该手动完成。 Keras 不会更改您的批次。那么,我为什么要划分一个序列?
1、序列太大,一批放不下电脑或GPU的内存 2,您想做问题 2 上发生的事情:在每一步迭代之间操作批次。问题 2
在问题 2 中,我们正在“预测未来”。那么,输出步数是多少?嗯,这是您想要预测的数字。假设您试图根据过去预测您将拥有的客户数量。您可以决定预测未来 1 个月或 10 个月。您的选择。
现在,您认为predict
会立即计算整个事情是正确的,但请记住上面我所说的问题 3:
输出步数等于输入步数
还要记住,第一个输出步骤是第一个输入步骤的结果,第二个输出步骤是第二个输入步骤的结果,依此类推。
但我们想要的是未来,而不是与前面的步骤一一匹配。我们希望结果步骤遵循“最后”步骤。
所以,我们面临一个限制:如果我们没有各自的输入,如何定义固定数量的输出步骤? (遥远未来的输入也是未来,所以不存在)
这就是为什么我们将序列分解为只有一步的序列。所以predict
也会输出只有一步。
当我们这样做时,我们就有能力在每次迭代之间操纵批次。而且我们有能力将输出数据(我们以前没有)作为输入数据。
有状态是必要的,因为我们希望这些步骤中的每一个都连接为一个序列(不要丢弃状态)。
问题 5
我所知道的stateful=True
的最佳实际应用是问题2的答案。我们想要在步骤之间操作数据。
这可能是一个虚拟示例,但另一个应用程序是,例如,如果您要从 Internet 上的用户接收数据。用户每天使用您的网站,您都会向模型多提供一步数据(并且您希望以相同的顺序继续该用户以前的历史记录)。
问题 1
那么,最后是问题1。
我想说:除非您需要它,否则请始终避免使用stateful=True
。
您不需要它来构建一对多网络,因此,最好不要使用它。
请注意,stateful=True
示例与 预测未来 示例相同,但您从一个步骤开始。这很难实现,由于手动循环,它的速度会更差。但是您可以控制输出步骤的数量,这在某些情况下可能是您想要的。
计算也会有所不同。在这种情况下,如果一个比另一个更好,我真的无法回答。但我不相信会有很大的不同。但网络是某种“艺术”,测试可能会带来有趣的惊喜。
编辑答案:
一个
我们不应将“状态”与“权重”混淆。它们是两个不同的变量。
权重:可学习的参数,它们永远不会重置。 (如果你重置权重,你会失去模型学到的所有东西) 状态:当前一批序列的记忆(与我现在在序列上的哪个步骤以及我“从这批中的特定序列”到这一步所学到的知识有关)。想象你正在看一部电影(一个序列)。每一秒都会让你建立起记忆,比如角色的名字,他们做了什么,他们的关系是什么。
现在想象一下,您拿到了一部以前从未看过的电影,然后开始观看电影的最后一秒。你不会明白电影的结局,因为你需要这部电影的前一个故事。 (各州)
现在,您已看完整部电影。现在您将开始观看新电影(新序列)。你不需要记住你看过的上一部电影中发生了什么。如果你试图“加入电影”,你会感到困惑。
在这个例子中:
权重:理解和解释电影的能力,记住重要名称和动作的能力 状态:在暂停的电影中,状态是从开始到现在发生的事情的记忆。因此,状态是“未学习的”。状态是“计算的”,关于批次中的每个单独序列逐步构建。这就是为什么:
重置状态意味着从第 0 步开始新序列(开始新电影) 保持状态意味着继续上一步的相同序列(继续暂停的电影,或观看该故事的第 2 部分)状态正是使循环网络像具有“过去步骤的记忆”一样工作的原因。
B
在 LSTM 中,最后一个输出步骤是“状态”的一部分。
一个 LSTM 状态包含:
通过计算每一步更新的内存矩阵 最后一步的输出所以,是的:每一步都产生自己的输出,但每一步都使用最后一步的输出作为状态。这就是 LSTM 的构建方式。
如果你想“继续”相同的序列,你需要记忆最后一步的结果 如果您想“开始”一个新序列,您不希望记忆最后一步的结果(如果您不重置状态,这些结果将继续存储)C
你想停就停。你想预测未来多少步?那是你的停止点。
假设我有一个包含 20 个步骤的序列。我想预测未来的 10 步。
在标准(非有状态)网络中,我们可以使用:
一次输入19步(从0到18) 一次输出 19 步(从 1 到 19)这是“预测下一步”(注意 shift = 1 步)。我们可以这样做,因为我们拥有所有可用的输入数据。
但是当我们想要 10 个未来的步骤时,我们不能一次输出它们,因为我们没有必要的 10 个输入步骤(这些输入步骤是未来的,我们需要模型先预测它们)。
因此,我们需要根据现有数据预测未来的一个步骤,然后将此步骤用作下一步的输入。
但我希望这些步骤都是相互关联的。如果我使用stateful=False
,模型会看到很多“长度为 1 的序列”。不,我们想要一个长度为 30 的序列。
D
这是一个非常好的问题,你得到了我......
有状态的一对多是我在写这个答案时的一个想法,但我从未使用过这个。我更喜欢“重复”选项。
只有在每个步骤都有预期输出的情况下,您才能使用train_on_batch
逐步训练。但除此之外,我认为训练非常复杂或不可能。
E
这是一种常见的方法。
使用网络生成压缩向量(该向量可以是结果,也可以是生成的状态,或两者兼而有之) 将此压缩向量用作另一个网络的初始输入/状态,手动逐步生成,并在模型生成“句末”单词或字符时停止。也有没有手动循环的固定尺寸模型。您假设您的句子的最大长度为 X 个单词。比这更短的结果句子用“句子结尾”或“空”字/字符完成。 Masking
层在这些模型中非常有用。
F
您只提供输入。其他两件事(最后的输出和内部状态)已经存储在有状态层中。
我之所以输入=最后一个输出,只是因为我们的特定模型预测下一步。这就是我们希望它做的事情。对于每个输入,下一步。
我们在训练中使用移位序列来教授这一点。
G
没关系。我们只想要最后一步。
序列数由第一个:
保存。
-1:
只考虑最后一步。
但如果你想知道,你可以打印predicted.shape
。在此模型中,它等于totalSequences.shape
。
编辑 2
我
首先,我们不能使用“一对多”模型来预测未来,因为我们没有这方面的数据。如果您没有序列步骤的数据,就不可能理解“序列”。
因此,这种类型的模型应该用于其他类型的应用程序。正如我之前所说,我对这个问题真的没有很好的答案。最好先有一个“目标”,然后我们决定哪种模型更适合该目标。
二
“逐步”是指手动循环。
如果你没有后面步骤的输出,我认为是不可能训练的。它可能根本不是一个有用的模型。 (但我不是什么都知道的人)
如果您有输出,是的,您可以使用 fit
训练整个序列,而无需担心手动循环。
III
关于 III,你是对的。您不会在多对多中使用重复向量,因为您有不同的输入数据。
“一对多”和“多对多”是两种不同的技术,各有优缺点。一种适用于某些应用程序,另一种适用于其他应用程序。
【讨论】:
又一个精彩的答案,但在阅读您的答案后,我在 EDIT 下提出了一些问题。 1+ 此答案应作为短论文提交:) @DanielMöller 更多问题在另一个 EDIT 部分下。 @DanielMöller 所以,在C
中,它仅仅意味着在不同的手动迭代中使用model.predict()
和stateful=False
将仅仅意味着我们使用不同的独立序列作为输入(我们不这样做'不希望 bcz 它只是遵循相同的序列)所以我们使用stateful=True
使模型将每个输入视为同一序列的一部分。这是否正确理解?嘿,等着这个!!
是的。正是这样。以上是关于关于“理解 Keras LSTMs”的疑问的主要内容,如果未能解决你的问题,请参考以下文章