【问题标题】:Experiment shows that LSTM does worse than Random Forest... Why?实验表明 LSTM 比随机森林做得更差……为什么?
【发布时间】:2019-02-08 17:00:35
【问题描述】:

LSTM 应该是捕捉时间序列数据中路径依赖性的正确工具。

我决定进行一个简单的实验(模拟)来评估 LSTM 在多大程度上能够理解路径依赖。

设置非常简单。我只是模拟了来自 4 个不同数据生成过程的一堆(N=100)路径。其中两个过程代表真实增加和真实减少,而另外两个趋势最终恢复为零。

下图显示了每个类别的模拟路径:

候选机器学习算法将获得路径的前 8 个值([1,8] 中的 t),并将被训练以预测最后 2 步的后续移动。

换句话说:

  • 特征向量为X = (p1, p2, p3, p4, p5, p6, p7, p8)

  • 目标是y = p10 - p8

我将 LSTM 与具有 20 个估计器的简单随机森林模型进行了比较。以下是使用 Keras 和 scikit-learn 对两个模型的定义和训练:

# LSTM
model = Sequential()
model.add(LSTM((1), batch_input_shape=(None, H, 1), return_sequences=True))
model.add(LSTM((1), return_sequences=False))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])
history = model.fit(train_X_LS, train_y_LS, epochs=100, validation_data=(vali_X_LS, vali_y_LS), verbose=0)
# Random Forest
RF = RandomForestRegressor(random_state=0, n_estimators=20)
RF.fit(train_X_RF, train_y_RF);

样本外结果由以下散点图汇总:

如您所见,随机森林模型明显优于 LSTM。后者似乎无法区分趋势。

您有什么想法可以解释为什么会发生这种情况吗?

您将如何修改 LSTM 模型以使其更好地解决这个问题?

一些备注:

  • 数据点除以 100 以确保梯度不会爆炸
  • 我尝试增加样本量,但没有发现任何差异
  • 我尝试增加 LSTM 训练的 epoch 数,但没有发现任何差异(经过一堆 epoch 后,损失变得停滞不前)
  • 你可以找到我用来运行实验的代码here

更新:

感谢SaTa的回复,我改变了模型,得到了更好的结果:

# Updated LSTM Model
model = Sequential()
model.add(LSTM((8), batch_input_shape=(None, H, 1), return_sequences=False))
model.add(Dense(4))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])

不过,随机森林模型做得更好。关键是 RF 似乎understand 认为,以类别为条件,较高的 p8 预测较低的结果 p10-p8 反之亦然,因为添加噪声的方式。 LSTM 似乎在这方面失败了,因此它可以很好地预测类,但我们在最终散点图中看到了类内向下倾斜的模式。

有什么改进的建议吗?

【问题讨论】:

  • 您使用多少样本进行训练?结果显示的是训练结果还是测试结果?
  • @SaTa:我正在使用 N=100 个数据样本。我试图将它增加到 1,000 和 10,000,但结果是一样的。结果在测试集上是样本外的,但它们在样本内看起来是一样的,因为数据是以同质方式模拟的

标签: python machine-learning lstm random-forest


【解决方案1】:

我不希望 LSTM 在与传统方法的所有战斗中获胜,但我确实希望它能够很好地解决您提出的问题。您可以尝试以下几件事:

1) 增加第一层隐藏单元的数量。

model.add(LSTM((32), batch_input_shape=(None, H, 1), return_sequences=True))

2) LSTM 层的输出默认为 tanh,这将输出限制为 (-1, 1),如右图中所示。我建议要么添加一个密集层,要么在输出上使用带有线性激活的 LSTM。像这样:

model.add(LSTM((1), return_sequences=False, activation='linear'))

或者

model.add(LSTM((16), return_sequences=False))
model.add(Dense(1))

使用您拥有的 10K 样本尝试上述方法。

【讨论】:

  • 好点,谢谢!我更新了模拟并获得了更好的结果(请参阅更新)
  • 酷。你的训练和测试错误是什么?您是否尝试过使用更多隐藏单元使其稍微变大,直到它开始过度拟合?
  • 也许用 LSTM 层替换中间的 Dense 层,这样你就有了两个堆叠的 LSTM 层和一个最终的 Dense 层。看看有没有帮助。
猜你喜欢
  • 2018-04-04
  • 2014-11-01
  • 2018-06-13
  • 2020-03-16
  • 2019-04-11
  • 2018-06-22
  • 1970-01-01
  • 2016-01-24
  • 2013-05-06
相关资源
最近更新 更多