如何处理keras中多元LSTM中的多步时间序列预测

Posted

技术标签:

【中文标题】如何处理keras中多元LSTM中的多步时间序列预测【英文标题】:How to deal with multi step time series forecasting in multivariate LSTM in keras 【发布时间】:2018-04-04 17:03:20 【问题描述】:

我正在尝试在 Keras 中使用多元 LSTM 进行多步时间序列预测。具体来说,我最初为每个时间步长有两个变量(var1 和 var2)。遵循在线教程here,我决定使用时间(t-2)和(t-1)的数据来预测时间步t var2的值。如示例数据表所示,我使用前 4 列作为输入,Y 作为输出。我开发的代码可以看到here,但是我有三个问题。

   var1(t-2)  var2(t-2)  var1(t-1)  var2(t-1)  var2(t)
2        1.5       -0.8        0.9       -0.5     -0.2
3        0.9       -0.5       -0.1       -0.2      0.2
4       -0.1       -0.2       -0.3        0.2      0.4
5       -0.3        0.2       -0.7        0.4      0.6
6       -0.7        0.4        0.2        0.6      0.7
    Q1:我已经用上面的数据训练了一个 LSTM 模型。这个模型做 很好地预测了时间步 t 的 var2 的值。然而,什么 如果我想在时间步 t+1 预测 var2。我觉得很难 因为模型无法告诉我 var1 在时间步 t 的值。如果我想做,我应该如何修改code来构建模型? Q2:我看到这个问题问了很多,但我还是很困惑。在 我的例子,[样本,时间中的正确时间步长应该是多少? 步骤、特点] 1还是2? Q3:我刚开始学习 LSTM。我有 阅读here,LSTM 的最大优势之一是它 自己学习时间依赖性/滑动窗口大小,然后 为什么我们必须总是将时间序列数据转换为像 上表?

更新:LSTM 结果(蓝线是训练序列,橙线是ground truth,绿色是预测)

【问题讨论】:

var1 和 var2 是否相互独立?您只想预测 var 2 吗?你不想预测 var 1 吗? 他们是独立的。只需将它们视为降水和土壤水分。是的,我只想预测 var1。 土壤水分不依赖于降水...你有完整的降水值序列要输入吗? 是的,我知道有一些相关性,也许是一个不好的例子。只是想简化案例。我之前的评论有错别字,我只想预测 var2。是的,我在这里有完整的月度数据序列:github.com/Yongyao/enso-forcasting/blob/master/preprocessed/… 但是 var 2 依赖于 var 1,对吧? (如果是这样,您也必须预测 var 1)。 【参考方案1】:

实际上,您不能只输入原始时间序列数据,因为网络无法自然适应它。 RNN 的当前状态仍然需要您输入多个“特征”(手动或自动导出),才能正确学习有用的东西。

通常需要的先前步骤是:

    去趋势 去季节化 缩放(标准化)

一个重要的信息来源是来自微软研究员的this post,他通过 LSTM 网络赢得了时间序列预测比赛。

还有这个帖子:CNTK - Time series Prediction

【讨论】:

【参考方案2】:

问题一:

从您的表格中,我看到您在单个序列上有一个滑动窗口,用 2 个步骤制作了许多较小的序列。

为了预测 t,您将表格的第一行作为输入 为了预测 t+1,您将第二行作为输入。

如果您不使用表格:请参阅问题 3

问题2:

假设您使用该表作为输入,显然它是一个滑动窗口案例,需要两个时间步作为输入,您的 timeSteps 为 2。

您可能应该将var1var2 视为相同顺序的特征:

input_shape = (2,2) - 两个时间步长和两个特征/变量。

问题3:

我们不需要制作这样的桌子或构建滑动窗口案例。这是一种可能的方法。

您的模型实际上能够学习并决定此窗口本身的大小。

如果一方面您的模型能够学习长时间依赖,允许您不使用窗口,另一方面,它可以学习识别序列开始和中间的不同行为。在这种情况下,如果您想使用从中间开始的序列(不包括开头)进行预测,您的模型可能会像开头一样工作并预测不同的行为。使用窗户可以消除这种长期的影响。我猜哪个更好可能取决于测试。

不使用窗口:

如果您的数据有 800 个步骤,请一次性输入所有 800 个步骤以进行训练。

在这里,我们需要分离两个模型,一个用于训练,另一个用于预测。在训练中,我们将利用参数return_sequences=True。这意味着对于每个输入步骤,我们都会得到一个输出步骤。

为了以后的预测,我们只需要一个输出,然后我们将使用return_sequences= False。如果我们要将预测输出用作后续步骤的输入,我们将使用stateful=True 层。

培训:

将您的输入数据设置为(1, 799, 2),1 个序列,从 1 到 799 的步骤。两个变量的序列相同(2 个特征)。

将目标数据 (Y) 的形状也设为 (1, 799, 2),采用相同的步骤,从 2 变为 800。

使用return_sequences=True 构建模型。您可以使用timeSteps=799,但也可以使用None(允许步数可变)。

model.add(LSTM(units, input_shape=(None,2), return_sequences=True))
model.add(LSTM(2, return_sequences=True)) #it could be a Dense 2 too....
....
model.fit(X, Y, ....)

预测:

为了预测,创建一个类似的模型,现在使用return_sequences=False

复制权重:

newModel.set_weights(model.get_weights())

例如,您可以输入长度为 800 的输入(形状:(1,800,2))并预测下一步:

step801 = newModel.predict(X)

如果你想预测更多,我们将使用stateful=True 层。再次使用相同的模型,现在使用 return_sequences=False(仅在最后一个 LSTM 中,其他保持 True)和 stateful=True(全部)。将input_shape 更改为batch_input_shape=(1,None,2)

#with stateful=True, your model will never think that the sequence ended  
#each new batch will be seen as new steps instead of new sequences
#because of this, we need to call this when we want a sequence starting from zero:
statefulModel.reset_states()

#predicting
X = steps1to800 #input
step801 = statefulModel.predict(X).reshape(1,1,2)
step802 = statefulModel.predict(step801).reshape(1,1,2)
step803 = statefulModel.predict(step802).reshape(1,1,2)
    #the reshape is because return_sequences=True eliminates the step dimension   

实际上,您可以使用单个 stateful=Truereturn_sequences=True 模型完成所有操作,只需处理两件事:

训练时,reset_states() 用于每个 epoch。 (使用手动循环训练和epochs=1) 从多个步骤进行预测时,仅将输出的最后一步作为所需结果。

【讨论】:

谢谢!这很有帮助。 (1) 对于 Q1 和 Q2,如果我使用滑动窗口并且在这种情况下 input_shape = (2,2),这是否意味着我告诉 LSTM t 步骤仅与前两个步骤相关 - t-1 和 t -2、这被称为经典的滑动窗口效应? (2)如果我接受你最后一次手动循环训练的建议,我可以重复调用 model.fit() 吗? 是的...如果使用具有 2 个步骤的滑动窗口,您的 LSTM 将只能学习 2 个步骤,而不能学习其他任何东西。 --- 在最后一个建议中,是的,model.fit(longSequence,longPrediction, epochs=1),但最好使用model.train_on_batch(),不要忘记为每个循环重置状态。 我刚开始使用 LSTM。如果内存静止是由窗口大小决定的,那就意味着我不能同时拥有长内存和短内存,但是LSTM是长短期内存的缩写,是不是很奇怪? ....等等....什么??哈哈哈……我不喜欢推拉窗套……我几乎没用过。我喜欢 Q3 之类的方法。他们确实利用了 LSTM 功能。 刚刚尝试了您的建议,1) 结果表明 Keras 不支持 input_shape=(None,2) 。有人说只有 TensorFlow 支持变量输入。 2)另一件事是,如果我理解正确, stateful=True 不会影响预测(每个新预测都不会被视为新步骤),对吧?

以上是关于如何处理keras中多元LSTM中的多步时间序列预测的主要内容,如果未能解决你的问题,请参考以下文章

如何为LSTM Keras中的多步和多变量准备时间序列数据

Keras 中的多步多元时间序列分类

Keras每一步的多步LSTM批量训练分类

Keras 如何处理单元格和隐藏状态(RNN、LSTM)的初始值以进行推理?

Tensorflow / Keras:规范化训练/测试/实时数据或如何处理现实?

如何处理多元线性回归中的误差维度?