使用 Tensorflow 进行 LSTM 一步预测
LSTM one-step-ahead prediction with Tensorflow
我正在使用 Tensorflow 的 GRUCell
+ MultiRNNCell
+ dynamic_rnn
组合来生成多层 LSTM 来预测元素序列。
在我见过的几个例子中,比如字符级语言模型,一旦训练阶段完成,生成似乎是通过一次只提供一个 'character'(或任何元素)来完成的获得下一个预测,然后根据第一个预测获得以下 'character' 等
我的问题是,由于 Tensorflow 的 dynamic_rnn
将 RNN 图展开为任意数量的步骤,无论输入的序列长度是多少,一次只输入一个元素有什么好处,一次预测正在逐步构建出来?在每个预测步骤中逐渐收集更长的序列并将其重新输入到图表中不是更有意义吗? IE。在生成第一个预测后,反馈一个包含 2 个元素的序列,然后是 3 个,等等?
我目前正在尝试预测阶段,首先输入 15 个元素的序列(实际历史数据),获取预测的最后一个元素,然后用该预测值替换原始输入中的一个元素,在 N 个预测步骤的循环中依此类推。
与一次只提供一个元素相比,这种方法的缺点是什么?
这是一个很好的问题,我问了一些非常相似的问题 here。
这个想法不是跨时间共享权重(如您所描述的那样一次一个元素),每个时间步都有自己的一组权重。
我认为一步一步训练有几个原因,主要是计算复杂度和训练难度。对于每个时间步,您需要训练的权重数量呈线性增长。您需要一些非常运动的硬件来训练长序列。此外,对于长序列,您将需要一个 非常 大数据集来训练所有这些权重。但是恕我直言,我仍然乐观地认为,对于正确的问题,只要有足够的资源,它就会有所改善。
我不确定你的方法是否真的在做你想做的事情。
假设我们有一个训练有素的 LSTM 网络来生成字母表。现在,为了让网络生成一个序列,我们从一个干净的状态 h0
开始并输入第一个字符 a
。网络输出一个新状态 h1
及其预测 b
,我们将其附加到输出中。接下来,我们希望网络根据当前输出预测下一个字符,ab
。如果我们在这一步将状态 h1
提供给网络 ab
,它的感知序列将是 aab
,因为 h1
是在第一个 a
之后计算的],现在我们放入另一个 a
和一个 b
。或者,我们可以将 ab
和一个干净的状态 h0
馈入网络,这将提供适当的输出(基于 ab
),但我们会对整个序列执行不必要的计算,除了b
,因为我们已经计算出网络读取序列a
对应的状态h1
,所以为了得到下一个预测和状态,我们只需要输入下一个字符, b
.
所以回答你的问题,一次向网络提供一个字符是有意义的,因为网络只需要看到每个字符一次,而多次提供同一个字符只是不必要的计算。
我正在使用 Tensorflow 的 GRUCell
+ MultiRNNCell
+ dynamic_rnn
组合来生成多层 LSTM 来预测元素序列。
在我见过的几个例子中,比如字符级语言模型,一旦训练阶段完成,生成似乎是通过一次只提供一个 'character'(或任何元素)来完成的获得下一个预测,然后根据第一个预测获得以下 'character' 等
我的问题是,由于 Tensorflow 的 dynamic_rnn
将 RNN 图展开为任意数量的步骤,无论输入的序列长度是多少,一次只输入一个元素有什么好处,一次预测正在逐步构建出来?在每个预测步骤中逐渐收集更长的序列并将其重新输入到图表中不是更有意义吗? IE。在生成第一个预测后,反馈一个包含 2 个元素的序列,然后是 3 个,等等?
我目前正在尝试预测阶段,首先输入 15 个元素的序列(实际历史数据),获取预测的最后一个元素,然后用该预测值替换原始输入中的一个元素,在 N 个预测步骤的循环中依此类推。
与一次只提供一个元素相比,这种方法的缺点是什么?
这是一个很好的问题,我问了一些非常相似的问题 here。
这个想法不是跨时间共享权重(如您所描述的那样一次一个元素),每个时间步都有自己的一组权重。
我认为一步一步训练有几个原因,主要是计算复杂度和训练难度。对于每个时间步,您需要训练的权重数量呈线性增长。您需要一些非常运动的硬件来训练长序列。此外,对于长序列,您将需要一个 非常 大数据集来训练所有这些权重。但是恕我直言,我仍然乐观地认为,对于正确的问题,只要有足够的资源,它就会有所改善。
我不确定你的方法是否真的在做你想做的事情。
假设我们有一个训练有素的 LSTM 网络来生成字母表。现在,为了让网络生成一个序列,我们从一个干净的状态 h0
开始并输入第一个字符 a
。网络输出一个新状态 h1
及其预测 b
,我们将其附加到输出中。接下来,我们希望网络根据当前输出预测下一个字符,ab
。如果我们在这一步将状态 h1
提供给网络 ab
,它的感知序列将是 aab
,因为 h1
是在第一个 a
之后计算的],现在我们放入另一个 a
和一个 b
。或者,我们可以将 ab
和一个干净的状态 h0
馈入网络,这将提供适当的输出(基于 ab
),但我们会对整个序列执行不必要的计算,除了b
,因为我们已经计算出网络读取序列a
对应的状态h1
,所以为了得到下一个预测和状态,我们只需要输入下一个字符, b
.
所以回答你的问题,一次向网络提供一个字符是有意义的,因为网络只需要看到每个字符一次,而多次提供同一个字符只是不必要的计算。