我想预测每周可预测的某些值(低信噪比)。我需要预测一年中由一周组成的整个时间序列(52个值-图1)
我的第一个想法是使用Keras over TensorFlow开发一个多对多LSTM模型(图2)。我正在用52个输入层(前一年的给定时间序列)和52个预测输出层(下一年的时间序列)训练模型。train_X的形状是(X_examples,52,1),换句话说,X_examples训练,52个时间步长各1个特征。我知道Keras将把52个输入视为同一领域的时间序列。train_Y形状相同(y_examples,52,1)。我添加了一个时间分布层。我的想法是,算法将预测值作为一个时间序列,而不是孤立的值(我是正确的吗?)
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)
问题是算法没有学习示例。它预测的值与属性的值非常相似。我对问题建模正确吗?
第二个问题:另一个想法是用1个输入和1个输出来训练算法,但是在测试过程中,我将如何预测整个2015年的时间序列,而不看“1个输入”?测试数据将具有不同于训练数据的形状。
对于数据太少也有同样的担忧,您可以这样做。
首先,将值保持在-1和1之间是一个好主意,因此我首先将它们标准化。
对于LSTM模型,必须确保使用的是return\u sequences=True
您的模型没有“错误”,但可能需要或多或少的层或单元才能实现您的愿望。(但对此没有明确的答案)。
培训模型以预测下一步:
您只需将Y作为移位的X传递:
entireData = arrayWithShape((samples,52,1))
X = entireData[:,:-1,:]
y = entireData[:,1:,:]
使用这些工具训练模型。
预测未来:
现在,为了预测未来,因为我们需要使用预测元素作为更多预测元素的输入,我们将使用一个循环,使模型stateful=True
。
创建与上一个模型相同的模型,并进行以下更改:
stateful=True
(批大小,无,1)
-这允许可变长度复制先前训练模型的权重:
newModel.set_weights(oldModel.get_weights())
一次只预测一个样本,永远不要忘记调用模型。在开始任何序列之前,重置状态()。
首先用你已经知道的序列进行预测(这将确保模型为预测未来正确准备其状态)
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
我想补充这个问题
我添加了一个时间分布层。我的想法是,算法将预测值作为一个时间序列,而不是孤立的值(我是正确的吗?)
因为我自己很难理解Keras时间分布层背后的功能。
我认为,你的动机是正确的,没有孤立的计算时间序列预测。在预测其未来形状时,您尤其不希望得到整个系列的特征和相互依赖性。
然而,这与时间分布式层的作用正好相反。它用于隔离每个时间步上的计算。你可能会问,这为什么有用?对于完全不同的任务,例如序列标记,其中您有一个顺序输入(i1,i2,i3,...,i_n)
,并针对每个时间步分别输出标签(label1,label2,label1,...,label2)
。
恕我直言,最好的解释可以在这篇文章和Keras文档中找到。
出于这个原因,我认为,与所有直觉相反,添加一个时间分布层对于时间序列预测来说可能永远都不是一个好主意。开诚布公,很高兴听到关于这一点的其他意见!
我有10年的数据。如果我的训练数据集是:从4周到预测第5周的值,并且我一直在变换,那么我可以有52 X 9个示例来训练模型和52个预测(去年)
这实际上意味着你只有9个训练示例,每个示例有52个特征(除非你想在高度重叠的输入数据上训练)。不管怎样,我不认为这足以值得训练一个LSTM
。
我建议尝试一个简单得多的模型。输入和输出数据的大小是固定的,因此可以尝试sklearn.linear_model。LinearRegression处理每个训练示例的多个输入特性(在您的示例中为52)和多个目标(也是52)。
更新:如果必须使用LSTM,请查看用于时间序列预测的LSTM神经网络,这是一种Keras
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进行精度比较。尤其是如果你一次预测一个输出,并将其作为输入反馈,你的错误很容易积累,给你带来非常糟糕的预测。