Keras LSTM预测时间序列被压扁并转移

时间:2017-12-30 14:01:19

标签: python machine-learning time-series keras lstm

我想在节日期间亲身体验Keras的经验,我想我会从时间序列预测库存数据的教科书示例开始。所以我要做的是给出最后48小时的平均价格变化(自上次以来的百分比),预测未来一小时的平均价格差异。

然而,当针对测试集(或甚至训练集)进行验证时,预测序列的幅度偏离,有时会转变为总是正的或总是负的,即偏离0%的变化我觉得这种事情是正确的。

我想出了以下最小例子来说明问题:

df = pandas.DataFrame.from_csv('test-data-01.csv', header=0)
df['pct'] = df.value.pct_change(periods=1)

seq_len=48
vals = df.pct.values[1:] # First pct change is NaN, skip it
sequences = []
for i in range(0, len(vals) - seq_len):
    sx = vals[i:i+seq_len].reshape(seq_len, 1)
    sy = vals[i+seq_len]
    sequences.append((sx, sy))

row = -24
trainSeqs = sequences[:row]
testSeqs = sequences[row:]

trainX = np.array([i[0] for i in trainSeqs])
trainy = np.array([i[1] for i in trainSeqs])

model = Sequential()
model.add(LSTM(25, batch_input_shape=(1, seq_len, 1)))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
model.fit(trainX, trainy, epochs=1, batch_size=1, verbose=1, shuffle=True)

pred = []
for s in trainSeqs:
    pred.append(model.predict(s[0].reshape(1, seq_len, 1)))
pred = np.array(pred).flatten()

plot(pred)
plot([i[1] for i in trainSeqs])
axis([2500, 2550,-0.03, 0.03])

正如您所看到的,我创建了训练和测试序列,通过选择最近48小时,然后进入元组的下一步,然后提前1小时,重复该过程。该模型是一个非常简单的1 LSTM和1个密集层。

我原本预计个别预测点的图可以很好地重叠训练序列的图(毕竟这是他们训练过的相同集),以及测试序列的匹配类型。但是,我在培训数据

上得到以下结果
  • 橙色:真实数据
  • 蓝色:预测数据

enter image description here

知道可能会发生什么吗?我误解了什么吗?

更新:为了更好地显示移位和压扁的含义,我还通过将其移回以匹配实际数据并乘以匹配幅度来绘制预测值。

plot(pred*12-0.03)
plot([i[1] for i in trainSeqs])
axis([2500, 2550,-0.03, 0.03])

enter image description here

正如你所看到的那样,预测非常适合真实的数据,它只是被压扁并以某种方式偏移,我无法弄清楚原因。

4 个答案:

答案 0 :(得分:8)

我认为你过度拟合,因为数据的维数是1,而25个单位的LSTM对于这样的低维数据集来说似乎相当复杂。这是我要尝试的一系列事项:

  • 减少LSTM维度。
  • 添加某种形式的正规化以对抗过度拟合。例如,dropout可能是一个不错的选择。
  • 培训更多时代或改变学习率。该模型可能需要更多的纪元或更大的更新才能找到合适的参数。

更新。让我总结一下我们在评论部分讨论过的内容。

为了澄清,第一个图不显示验证集的预测序列,但是针对训练集。因此,我的第一个过度拟合解释可能不准确。我认为一个恰当的问题是:实际上是否有可能从这样的低维数据集中预测未来的价格变化?机器学习算法并不神奇:它们只有在数据存在的情况下才会在数据中找到模式。

如果仅过去价格变化确实没有提供未来价格变动的信息,那么:

  • 您的模型将学会预测价格变化的平均值(可能是0左右),因为这是在没有信息功能的情况下产生最低损失的价值。
  • 预测可能会略微变动"因为时间步长t + 1的价格变化与时间步长t的价格变化略有相关(但仍然,预测接近0的东西是最安全的选择)。这确实是我作为一个不熟练的人能够观察到的唯一模式(即时间步长t + 1的值有时与时间步长t的值相似)。

如果在时间步长t和t + 1的值一般更加相关,那么我假设模型对这种相关性更有信心,并且预测的幅度会更大。

答案 1 :(得分:2)

  1. 增加时代数量。您可以使用EarlyStopping来避免过度拟合。
  2. 您的数据如何缩放?时间序列对数据中的异常值非常敏感。试试MinMax((0.1,0.9)),然后RobustScaler也是一个不错的选择。
  3. 在您拥有大量数据之前,我不确定LSTM(seq_len)是否真的有必要。为什么不试试较小的尺寸?
  4. 尝试所有这些并尝试过度拟合(mse应该在真实数据集上大约为零)。然后应用正规化。

    更新

    让我解释一下你为什么选择

    plot(pred*12-0.03)
    

    很合适。

    好的,我们将LSTM图层视为黑盒而忘记它。它返回了25个值 - 这就是全部。 该值前进到Dense图层,我们将其应用于25个值函数的向量:

    y = w * x + b
    

    这里 w b - 由NN定义并且在开头的向量通常接近于零。 x - LSTM图层后的值和 y - 目标(单个值)。

    虽然您只有1个纪元:w和b根本不适合您的数据(实际上它们大约为零)。但是,如果你申请

    怎么办?
    plot(pred*12-0.03)
    

    到你的预测值?您(某种程度上)适用于目标变量 w b 。现在 w b 是单个值,而不是矢量,它们应用于单个值。但它们(几乎)与密集层完成相同的工作。

    因此,增加时代数量以获得更好的拟合。

    UPDATE2 顺便说一下,我在数据中看到了一些异常值。您也可以尝试将MAE用作损失/准确度指标。

答案 2 :(得分:0)

这周我遇到了同样的问题,并且找到了解决方案。唯一对我有用的方法是使用如下所述的窗口标准化方法:

https://www.altumintelligence.com/articles/a/Time-Series-Prediction-Using-LSTM-Deep-Neural-Networks

(检查有关sp500预测的部分)

祝你有美好的一天:)

答案 3 :(得分:0)

因为我在这一点上以及增加batch_size有助于SimpleRNN完全修复LSTM问题,relu,elu作为激活,学习率必须从默认增加,并尝试配置一些SmoteRNN的灵魂以获得更多过去的数据,或者更改行之间的时间段以获取更多数据供模型查找模式,似乎对我有用,atm,仍在尝试将准确度提高到 80% 以上, 准确率 = (mean_abosule_error / test.mean()) * 100

相关问题