【问题标题】:LSTM forecasted a straight lineLSTM 预测出一条直线
【发布时间】:2019-10-15 16:35:35
【问题描述】:

我在 Keras 中构建了一个 LSTM。它读取 9 个时间滞后的观察结果,并预测下一个标签。出于某种原因,我训练的模型预测的东西几乎是一条直线。 造成如此糟糕的回归结果的模型架构可能存在什么问题?

输入数据:每小时金融时间序列,有明显上升趋势 1200+ 条记录

输入数据维度:
- 原来:

X_train.shape (1212, 9)

- 为 LSTM 重塑:

Z_train.shape (1212, 1, 9)


array([[[0.45073171, 0.46783444, 0.46226164, ..., 0.47164819,
         0.47649667, 0.46017738]],

       [[0.46783444, 0.46226164, 0.4553289 , ..., 0.47649667,
         0.46017738, 0.47167775]],

目标数据:y_train

69200    0.471678
69140    0.476364
69080    0.467761
       ...   
7055     0.924937
7017     0.923651
7003     0.906253
Name: Close, Length: 1212, dtype: float64

type(y_train)
<class 'pandas.core.series.Series'>

LSTM 设计:

my = Sequential()
my.add(LSTM((20),batch_input_shape=(None,1,9), return_sequences=True))
my.add(LSTM(20, return_sequences=True))
my.add(LSTM(20, return_sequences=True))
my.add(LSTM(1))

9 个节点的输入层。 3 个隐藏层,每层 20 个单元。 1 个单元的 1 个输出层。

Keras 默认是 return_sequences=False

使用mse loss 和adamsgd 优化器编译模型。

curr_model.compile(optimizer=optmfunc, loss="mse")

模型以这种方式拟合。 Batch是32,shuffle可以是True/False

curr_model.fit(Z_train, y_train,
                           validation_data=(Z_validation,y_validation),
                           epochs=noepoch, verbose=0,
                           batch_size=btchsize,
                           shuffle=shufBOOL)

配置和权重保存到磁盘。由于我正在训练多个模型,因此我会在之后加载它们以测试某些性能指标。

spec_model.model.save_weights(mname_trn)
mkerascfg = spec_model.model.to_json()
    with open(mname_cfg, "w") as json_file:
        json_file.write(mkerascfg)


当我训练一个 MLP 时,我在验证集上得到了这个结果:

我已经训练了几个 LSTM,但验证集的结果如下所示:

第二个图(LSTM 图)是验证数据。这是 y_validation 与 Z_validation 的预测。它们是各自数组中的最后 135 条记录。这些是从完整数据(即验证)中拆分出来的,并且具有与 Z_train 和 y_train 相同的类型/属性。 x 轴只是索引的 0 到 134 编号,y 轴是 y_validation 或预测的值。单位在两个数组中都进行了归一化。所以所有的单位都是一样的。 “直线”是预测。

对于为什么会发生这种情况,您有什么建议? - 我改变了批量大小。类似的结果。 - 我尝试过更改return_sequences,但它会导致后续图层的形状出现各种错误等。

有关 MSE 损失的 LSTM 进展的信息

一共训练了 4 个模型,当然都是相同的问题。 我们只关注上面定义的 3 个隐藏层,每层 20 个单元,LSTM。(Mini-批量大小为 32,并且 shuffle 被禁用。但启用并没有改变)。

这是第一个模型(亚当优化器)损失进程的略微放大图像

从我通过弄乱索引可以看出,损失值的反弹(这会产生厚区域)在 500 年代之后开始。

【问题讨论】:

  • 你如何定义y_train,图的横轴单位是什么?包含涵盖您提供的 sn-ps 中使用的所有变量的代码会有所帮助。
  • 为验证集和训练目标添加了数据类型/形状信息。
  • 尝试绘制损失图,看看你在每次迭代中学到了多少。
  • 我理解正确吗:输入 = 9 个时间步,输出 = 第 10 个时间步。 Z_train = 9 个时间步的 1212 个样本,y_train = “第 10 个时间步”的 1212 个样本
  • 谢谢。我认为这将是过去发生任何问题的地方。我已经绘制了这个。它像人们预期的那样向下倾斜并逐渐变小。

标签: python keras lstm forecasting


【解决方案1】:

您的代码有一个关键问题:维度改组。 LSTM 期望输入的形状为(batch_size, timesteps, channels)(或(num_samples, timesteps, features))——而您正在输入具有九个通道的一个时间步。甚至从未发生过时间的反向传播。

修复:将输入重塑为(1212, 9, 1)


建议:阅读this answer。它很长,但可以为您节省数小时的调试时间;此信息在其他地方无法以如此紧凑的形式获得,我希望在开始使用 LSTM 时已经拥有它。

回复related question 也可能有用 - 但之前的链接更重要。

【讨论】:

  • =)。我实际上有一两个 S.O.与可训练参数计数相关的问题,涉及到这一点。从我读到的内容和我得到的帮助来看,似乎 (1,1,9) 是为这个问题设置的正确方法。事情又发生了翻天覆地的变化。我明白了它的要点:一个样本中有 9 个时间步长,与具有那么多通道/特征的样本不同。是时候修一条直线了。谢谢。
  • @VISQL 如果问题解决了,考虑采纳答案
【解决方案2】:

OverLordGoldDragon 是对的:问题在于输入的维度。

正如您在Keras documentation 中看到的,所有循环层都期望输入是具有形状的 3D 张量:(batch_size, timesteps, input_dim)

在你的情况下:

  • 输入有9个时间延迟需要依次馈送到LSTM,所以它们是timesteps
  • 时间序列仅包含一种金融工具,因此input_dim 为 1

因此,重塑它的正确方法是:(1212, 9, 1)

此外,请确保遵守将数据馈送到 LSTM 的顺序。对于预测问题,最好将滞后从最古老的到最近的,因为我们要预测最近的值之后的下一个值。

由于 LSTM 从左到右读取输入,这 9 个值应从左到右排序为:x_t-9, x_t-8, ...., x_t-1,即输入和输出张量应如下所示:

Z = [[[0], [1], [2], [3], [4], [5], [6], [7], [8]],
     [[1], [2], [3], [4], [5], [6], [7], [8], [9]],
     ...
    ]
y = [9, 10, ...]

如果它们不是这样定向的,您始终可以设置 LSTM 标志 go_backwards=True 以使 LSTM 从右到左读取。

另外,请确保传递 numpy 数组而不是 pandas 系列作为 Xy,因为 Keras 有时会被 Pandas 混淆。

有关使用 Keras 进行时间序列预测的完整示例,请查看 this notebook

【讨论】:

  • 太棒了!我也担心时间步顺序,并尝试构建一个较小的示例来测试它。不知道go_backwards 标志。以后会派上用场的。
猜你喜欢
  • 1970-01-01
  • 2022-07-05
  • 2020-08-25
  • 2021-06-30
  • 1970-01-01
  • 2018-02-16
  • 2018-04-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多