LSTM 预测了一条直线
LSTM forecasted a straight line
我在 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 个输出层。
The Keras default is return_sequences=False
模型编译时带有 mse
损失和 adam
或 sgd
优化器。
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 相同的 type/properties。 x 轴只是索引的编号 0 到 134,y 轴是 y_validation 或预测的值。两个数组中的单位都已归一化。所以所有的单位都是一样的。 "straight" 行是预测。
对于为什么会发生这种情况,您有什么建议?
- 我改变了批量大小。类似的结果。
- 我试过更改 return_sequences,但它会导致后续层的形状等出现各种错误。
MSE损失的LSTM进展信息
训练了 4 个模型,当然都有同样的问题。 我们只关注 3 个隐藏层,每层 20 个单元,定义为 LSTM上面。(小批量大小为 32,混洗被禁用。但启用没有任何改变)。
这是第一个模型(adam 优化器)的损失进程的略微放大图像
据我所知,通过弄乱指数,损失值的反弹(形成厚区域)在 500 年代之后开始。
您的代码有一个严重问题:维数改组。 LSTM 期望输入的形状为 (batch_size, timesteps, channels)
(或 (num_samples, timesteps, features)
)——而您正在用九个通道提供 one 时间步长。甚至从未发生过时间反向传播。
Fix:将输入重塑为 (1212, 9, 1)
。
建议:阅读。它很长,但可以节省您数小时的调试时间;此信息在其他地方无法以如此紧凑的形式获得,我希望我在开始使用 LSTM 时已经掌握了它。
对 的回答也可能有用 - 但以前的 link 更重要。
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
系列作为 X
和 y
,因为 Keras 有时会被 Pandas 混淆。
有关使用 Keras 进行时间序列预测的完整示例,请查看 this notebook
我在 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 个输出层。
The Keras default is return_sequences=False
模型编译时带有 mse
损失和 adam
或 sgd
优化器。
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 相同的 type/properties。 x 轴只是索引的编号 0 到 134,y 轴是 y_validation 或预测的值。两个数组中的单位都已归一化。所以所有的单位都是一样的。 "straight" 行是预测。
对于为什么会发生这种情况,您有什么建议? - 我改变了批量大小。类似的结果。 - 我试过更改 return_sequences,但它会导致后续层的形状等出现各种错误。
MSE损失的LSTM进展信息
训练了 4 个模型,当然都有同样的问题。 我们只关注 3 个隐藏层,每层 20 个单元,定义为 LSTM上面。(小批量大小为 32,混洗被禁用。但启用没有任何改变)。
这是第一个模型(adam 优化器)的损失进程的略微放大图像
据我所知,通过弄乱指数,损失值的反弹(形成厚区域)在 500 年代之后开始。
您的代码有一个严重问题:维数改组。 LSTM 期望输入的形状为 (batch_size, timesteps, channels)
(或 (num_samples, timesteps, features)
)——而您正在用九个通道提供 one 时间步长。甚至从未发生过时间反向传播。
Fix:将输入重塑为 (1212, 9, 1)
。
建议:阅读
对
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
系列作为 X
和 y
,因为 Keras 有时会被 Pandas 混淆。
有关使用 Keras 进行时间序列预测的完整示例,请查看 this notebook