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

时间:2017-10-24 02:43:00

标签: tensorflow deep-learning time-series keras lstm

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

import urllib2
import suds
from suds.transport.https import HttpAuthenticated
from suds.transport import TransportError

URL = 'https://example.com/ChangeRequest.do?WSDL'

class HttpHeaderModify(HttpAuthenticated):
    def open(self, request):
        try:
            url = request.url
            u2request = urllib2.Request(url, headers={'User-Agent': 'Mozilla'})
            self.proxy = self.options.proxy
            return self.u2open(u2request)
        except urllib2.HTTPError, e:
            raise TransportError(str(e), e.code, e.fp)

transport = HttpHeaderModify()
client = Client(URL, transport=transport, timeout=10)

# Subsequent requests' header needs to be set again here. The overridden transport
# class only handles opening of the client.
client.set_options(headers={'User-Agent': 'Mozilla'})
  1. Q1:我已经使用上述数据训练了LSTM模型。这个模型呢 很好地预测在时间步t的var2的值。但是,什么 如果我想在时间步t + 1预测var2。我觉得很难 因为模型不能告诉我在时间步t的var1的值。如果我想这样做,我该如何修改code来构建模型?
  2. Q2:我已经看到这个问题了很多,但我仍然感到困惑。在 我的例子,[样本,时间应该是正确的时间步骤 步骤,功能] 1或2?
  3. 问题3:我刚开始研究LSTM。我有 阅读here LSTM的最大优势之一就是它 然后,自己学习时间依赖性/滑动窗口大小 为什么我们必须始终将时间序列数据转换为格式 上面的表?
  4. 更新:LSTM结果(蓝线是训练序列,橙线是基础事实,绿色是预测) Enter image description here

2 个答案:

答案 0 :(得分:6)

问题1:

从你的表中,我看到你在一个序列上有一个滑动窗口,通过两个步骤制作许多较小的序列。

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

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

问题2:

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

您可能应该像var1var2一样,按照相同的顺序进行操作:

  • input_shape = (2,2) - 两个时间步和两个功能/变量。

问题3:

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

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

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

不使用Windows:

如果您的数据有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()为每个时代。 (使用手动循环训练并epochs=1
  • 从多个步骤预测时,仅将输出的最后一步作为所需结果。

答案 1 :(得分:0)

实际上,您不能只输入原始时间序列数据,因为网络自然不适合它。 RNN的当前状态仍然需要您输入多个功能。 (手动或自动派生),以便正确学习有用的东西。

通常需要的先前步骤是:

  1. 消除趋势
  2. Deseasonalize
  3. 缩放(标准化)
  4. 来自微软研究员的this post是一个很好的信息来源,它通过LSTM网络赢得了时间序列预测竞赛。

    此帖也是:CNTK - Time series Prediction