使用LSTM预测时间序列的多个前向时间步长

时间:2017-12-01 13:49:13

标签: time-series keras lstm prediction forward

我想预测每周可预测的某些值(低SNR)。我需要预测一年中形成的一年的整个时间序列(52个值 - 图1)

Figure 1: Year time series by week

我的第一个想法是使用Keras over TensorFlow开发多对多LSTM模型(图2)。我用52输入层(前一年的给定时间序列)和52预测输出层(明年的时间序列)训练模型。 train_X的形状是(X_examples,52,1),换言之,要训练的X_examples,每个1个特征的52个时间步长。据我所知,Keras会将52个输入视为同一域的时间序列。 train_Y的形状是相同的(y_examples,52,1)。 我添加了一个TimeDistributed层。我的想法是算法会将值预测为时间序列而不是孤立值(我是否正确?)

Keras的模型代码是:

y = y.reshape(y.shape[0], 52, 1)
X = X.reshape(X.shape[0], 52, 1)
# design network
model = Sequential()
model.add(LSTM(n_neurons, input_shape=(X.shape[1], X.shape[2]), return_sequences=True))
model.add(TimeDistributed(Dense(1)))
model.compile(loss='mean_squared_error', optimizer='adam')
# fit network
model.fit(X, y, epochs=n_epochs, batch_size=n_batch, verbose=2)

Figure 2: Many-to-many LSTM architecture

问题是算法没有学习这个例子。它预测的值非常类似于属性'值。我是否正确建模了问题?

第二个问题: 另一个想法是使用1输入和1输出训练算法,但是在测试期间如何在不查看 1输入的情况下预测整个2015时间序列?测试数据的形状与训练数据不同。

3 个答案:

答案 0 :(得分:19)

分享关于数据太少的相同问题,你可以这样做。

首先,将值保持在-1和+1之间是个好主意,所以我先将它们标准化。

对于LSTM模型,您必须确保使用return_sequences=True 您的模型没有“错误”,但可能需要更多或更少的层或单元来实现您的需求。 (虽然没有明确的答案)。

训练模型以预测下一步:

您只需将Y作为移位的X传递:

entireData = arrayWithShape((samples,52,1))
X = entireData[:,:-1,:]
y = entireData[:,1:,:]

使用这些训练模型。

预测未来:

现在,为了预测未来,由于我们需要使用预测元素作为更多预测元素的输入,我们将使用循环并创建模型stateful=True

创建一个与前一个相同的模型,并进行以下更改:

  • 所有LSTM图层必须为stateful=True
  • 批输入形状必须为(batch_size,None, 1) - 这允许可变长度

复制先前训练过的模型的权重:

newModel.set_weights(oldModel.get_weights())

一次仅预测一个样本,并且在开始任何序列之前永远不要忘记调用model.reset_states()

首先用您已经知道的序列进行预测(这将确保模型正确地准备其状态以预测未来)

model.reset_states()
predictions = model.predict(entireData)

通过我们训练的方式,预测的最后一步将是未来的第一个元素:

futureElement = predictions[:,-1:,:]

futureElements = []
futureElements.append(futureElement)

现在我们创建一个循环,其中此元素是输入。 (由于有状态,模型将理解它是前一序列的新输入步骤而不是新序列)

for i in range(howManyPredictions):
    futureElement = model.predict(futureElement)
    futureElements.append(futureElement)

此链接包含一个完整的示例,用于预测两个功能的未来:https://github.com/danmoller/TestRepo/blob/master/TestBookLSTM.ipynb

答案 1 :(得分:2)

  

我有10年的数据。如果我的训练数据集是:4周的值来预测第5个并且我继续移动,我可以有近52个例子来训练模型,52个预测(去年)

这实际上意味着您只有9个训练样本,每个示例包含52个特征(除非您想训练高度重叠的输入数据)。无论哪种方式,我都认为这几乎不值得培训LSTM

我建议尝试一个更简单的模型。您的输入和输出数据具有固定大小,因此您可以尝试sklearn.linear_model.LinearRegression每个训练示例处理多个输入要素(在您的情况下为52),以及多个目标(也为52)。

更新:如果必须使用LSTM,请查看LSTM Neural Network for Time Series PredictionKeras LSTM实施,支持通过将每个预测作为输入反馈,一次或迭代地进行多个未来预测。根据您的评论,这应该是您想要的。

此实现中的网络架构是:

model = Sequential()

model.add(LSTM(
    input_shape=(layers[1], layers[0]),
    output_dim=layers[1],
    return_sequences=True))
model.add(Dropout(0.2))

model.add(LSTM(
    layers[2],
    return_sequences=False))
model.add(Dropout(0.2))

model.add(Dense(
    output_dim=layers[3]))
model.add(Activation("linear"))

但是,我仍然建议运行线性回归或者可能是一个带有一个隐藏层的简单前馈网络,并将精度与LSTM进行比较。特别是如果你一次预测一个输出并将其作为输入反馈,你的错误很容易累积,从而进一步给你做出非常糟糕的预测。

答案 2 :(得分:1)

我想补充这个问题

  

我添加了一个TimeDistributed层。我的想法是该算法会将值预测为一个时间序列,而不是孤立的值(我正确吗?)

因为我本人很难理解Keras TimeDistributed层背后的功能。

我认为您的动机是正确的,隔离时间序列预测的计算。在预测其未来形状时,您明确地不要将所有系列的特征和相互依存联系在一起。

但是,这与TimeDistributed Layer的用途完全相反。它用于隔离每个时间步的计算。您可能会问,为什么这很有用?对于完全不同的任务,例如序列标签,其中您有一个顺序输入(i1, i2, i3, ..., i_n),旨在分别为每个时间步输出标签(label1, label2, label1, ..., label2)

我想最好的解释可以在此postKeras Documentation中找到。

基于这个原因,我认为,对于添加直观的TimeDistributed层而言,对于时间序列预测来说可能永远不是一个好主意。开放,很高兴听到其他有关此的意见!