【问题标题】:LSTM with Keras for mini-batch training and online testing带有 Keras 的 LSTM 用于小批量训练和在线测试
【发布时间】:2016-11-13 19:09:00
【问题描述】:

我想在 Keras 中实现一个 LSTM 用于流式时间序列预测——即在线运行,一次获取一个数据点。 This is explained well here,但正如人们所假设的那样,在线 LSTM 的训练时间可能非常慢。我想在小批量上训练我的网络,并在线测试(运行预测)。在 Keras 中执行此操作的最佳方法是什么?

例如,小批量可能是在连续时间步长出现的 1000 个数据值 ([33, 34, 42, 33, 32, 33, 36, ... 24, 23]) 的序列。为了训练网络,我指定了一个形状为(900, 100, 1) 的数组X,其中有900 个长度为100 的序列,以及一个形状为(900, 1) 的数组y。例如,

X[0] = [[33], [34], [42], [33], ...]]
X[1] = [[34], [42], [33], [32], ...]]
...
X[999] = [..., [24]]

y[999] = [23]

所以对于每个序列X[i],都有一个对应的y[i],它代表时间序列中的下一个值——我们想要预测的值。

在测试中,我想预测下一个数据值 1000 到 1999。我通过为从 1000 到 1999 的每一步输入一个形状为 (1, 100, 1) 的数组来做到这一点,其中模型试图预测下一步的值。

这是解决我的问题的推荐方法和设置吗?启用有状态可能是纯在线实现的方式,但在 Keras 中,这需要在训练和测试中保持一致的batch_input_shape,这不符合我在小批量训练然后在线测试的意图。或者有什么办法可以做到这一点?

更新:尝试按照@nemo 的建议实施网络

我在博客文章 "Time Series Prediction with LSTM Recurrent Neural Networks in Python with Keras" 的示例网络上运行了我自己的数据集,然后尝试将预测阶段实现为有状态网络。

两者的模型构建和训练是相同的:

# Create and fit the LSTM network
numberOfEpochs = 10
look_back = 30
model = Sequential()
model.add(LSTM(4, input_dim=1, input_length=look_back))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(trainX, trainY, nb_epoch=numberOfEpochs, batch_size=1, verbose=2)
# trainX.shape = (6883, 30, 1)
# trainY.shape = (6883,)
# testX.shape = (3375, 30, 1)
# testY.shape = (3375,)

批量预测是通过:

trainPredict = model.predict(trainX, batch_size=batch_size)
testPredict = model.predict(testX, batch_size=batch_size)

为了尝试有状态的预测阶段,我运行了与以前相同的模型设置和训练,但随后进行了以下操作:

w = model.get_weights()
batch_size = 1
model = Sequential()
model.add(LSTM(4, batch_input_shape=(batch_size, look_back, 1), stateful=True))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
trainPredictions, testPredictions = [], []
for trainSample in trainX:
    trainPredictions.append(model.predict(trainSample.reshape((1,look_back,1)), batch_size=batch_size))
trainPredict = numpy.concatenate(trainPredictions).ravel()
for testSample in testX:
    testPredictions.append(model.predict(testSample.reshape((1,look_back,1)), batch_size=batch_size))
testPredict = numpy.concatenate(testPredictions).ravel()

为了检查结果,下图以蓝色显示实际(标准化)数据,以绿色显示对训练集的预测,以红色显示对测试集的预测。

第一个数字来自使用批量预测,第二个来自有状态。任何想法我做错了什么?

【问题讨论】:

  • 在训练和在线测试期间都使用状态性。在训练期间,只需在每批后重置状态。它还使事情变得更容易,因为您将使用相同的结构来构建所有数据。
  • 对于其他想了解 keras 中的有状态 LSTM 的人,这里有一个教程:philipperemy.github.io/keras-stateful-lstm
  • model.set_weights(w) 在最后一个代码块中丢失。此外,正如 nemo 在评论中指出的那样,我观察了第二组结果,并且起伏与蓝线具有非常高的相关性。
  • @BoltzmannBrain:这段代码可靠吗? machinelearningmastery.com/…

标签: keras lstm


【解决方案1】:

如果我对您的理解正确,您是在询问您是否可以在训练后启用有状态。这应该是可能的,是的。例如:

net = Dense(1)(SimpleRNN(stateful=False)(input))
model = Model(input=input, output=net)

model.fit(...)

w = model.get_weights()
net = Dense(1)(SimpleRNN(stateful=True)(input))
model = Model(input=input, output=net)
model.set_weights(w)

之后,您可以以有状态的方式进行预测。

【讨论】:

  • 谢谢。我已经尝试实现这一点,但仍然存在一些问题。请参阅已编辑的问题。非常感谢您的帮助!
  • 两件事:你永远不会重置循环层的状态,数据看起来非常相似但缩放不同;例如,这可能是您绘图的简单缩放问题。无论如何,这个问题不再适合 SO。最好自己进行测试,将事情归结为更简短的问题:)
猜你喜欢
  • 1970-01-01
  • 2017-08-15
  • 2018-01-08
  • 2019-03-22
  • 2018-12-06
  • 1970-01-01
  • 2018-01-30
  • 2019-02-28
  • 1970-01-01
相关资源
最近更新 更多