了解Keras LSTM:批量大小和有状态的作用

时间:2018-01-28 21:53:13

标签: python keras lstm recurrent-neural-network

来源

有几个来源解释有状态/无状态LSTM以及我已经读过的batch_size的作用。我稍后会在帖子中提及它们:

[1] https://machinelearningmastery.com/understanding-stateful-lstm-recurrent-neural-networks-python-keras/

[2] https://machinelearningmastery.com/stateful-stateless-lstm-time-series-forecasting-python/

[3] http://philipperemy.github.io/keras-stateful-lstm/

[4] https://machinelearningmastery.com/use-different-batch-sizes-training-predicting-python-keras/

Ans还有其他SO线程,例如Understanding Keras LSTMsKeras - stateful vs stateless LSTMs,但并未完全解释我正在寻找的内容。

我的问题

我仍然不确定有关状态和确定batch_size的任务的正确方法是什么。

我有大约1000个独立时间序列(samples),每个时间序列的长度大约为600天(timesteps)(实际上是可变长度,但我考虑将数据修剪为一个恒定的时间范围)每个时间步长有8个特征(或input_dim)(某些特征与每个样本相同,每个样本一些)。

Input shape = (1000, 600, 8)

其中一个特征是我想要预测的特征,而其他特征(应该是)支持预测这一个“主要特征”。我会为1000个时间序列中的每一个都这样做。什么是模拟这个问题的最佳策略?

Output shape = (1000, 600, 1)

什么是批次?

来自[4]:

  

Keras使用快速符号数学库作为后端,例如TensorFlow和Theano。

     

使用这些库的缺点是,无论您是在训练网络还是进行预测,数据的形状和大小都必须预先定义并保持不变。

     

[...]

     

当您希望进行的预测少于批量大小时,这确实会成为一个问题。例如,您可以获得批量较大的最佳结果,但需要在时间序列或序列问题等方面一次预测一次观察。

这听起来像“批处理”会将数据沿timesteps维分开。

但是,[3]声明:

  

换句话说,无论何时训练或测试LSTM,首先必须建立形状X的输入矩阵nb_samples, timesteps, input_dim,其中批量大小除以nb_samples。例如,如果nb_samples=1024batch_size=64,则意味着您的模型将接收64个样本的块,计算每个输出(无论每个样本的时间步数是多少),平均渐变并将其传播到更新参数向量。

当深入研究[1]和[4]的例子时,杰森总是将他的时间序列分成几个只包含1个时间步长的样本(在他的例子中完全确定的前身)序列中的下一个元素)。所以我认为批次实际上是沿着samples - 轴分开的。 (然而他的时间序列分裂方法对我来说对于长期依赖性问题没有意义。)

结论

所以我要说我选择batch_size=10,这意味着在一个纪元期间,权重更新1000/10 = 100次,随机选取10个完整的时间序列,包含600 x 8值,当我后来想要制作时使用该模型进行预测时,我将始终必须提供10个完整时间序列的批次(或使用来自[4]的解决方案3 ,将权重复制到具有不同batch_size的新模型)。

了解了batch_size的原则 - 但是仍然不知道什么是对于batch_size的好价值。以及如何确定它

有状态

KERAS documentation告诉我们

  

您可以将RNN图层设置为“有状态”,这意味着在一个批次中为样本计算的状态将重新用作下一批样本的初始状态。

如果我将时间序列 分成多个samples(例如[1]和[的示例] 4])以便我想要建模的依赖关系跨越多个批次,或批处理跨度样本相互关联,我可能需要有状态网,否则不是。这是一个正确而完整的结论吗?

所以对于我的问题,我想我不需要有状态网。我将训练数据构建为形状(samples, timesteps, features)的3D数组,然后使用batch_size调用model.fit来确定。示例代码可能如下所示:

model = Sequential()
model.add(LSTM(32, input_shape=(600, 8)))   # (timesteps, features)
model.add(LSTM(32))
model.add(LSTM(32))
model.add(LSTM(32))
model.add(Dense(1, activation='linear'))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(X, y, epochs=500, batch_size=batch_size, verbose=2)

1 个答案:

答案 0 :(得分:9)

让我通过一个例子解释一下:

所以,假设你有以下系列:1,2,3,4,5,6,...,100。您必须决定您的lstm将学习多少次步骤,并重新调整您的数据。如下所示:

如果您决定time_steps = 5,则必须以这种方式将时间序列重塑为样本矩阵:

  

1,2,3,4,5 - > sample1

     

2,3,4,5,6 - > SAMPLE2

     

3,4,5,6,7 - >样本3

     

等...

通过这样做,您将以形状矩阵(96个样本x 5个步骤)结束

此矩阵应重新形成为(96 x 5 x 1),表示您只有1个时间序列的Keras。如果你有更多的时间序列并行(如你的情况),你在每个时间序列上做同样的操作,所以你将以n个矩阵(每个时间序列一个)结束每个形状(96个样本x 5个时间步长)。

为了争论,让我们说你3个时间序列。您应该将所有三个矩阵连接成一个单个张量的形状(96个样本x 5个时间步长x 3个时间序列)。这个例子的lstm的第一层是:

    model = Sequential()
    model.add(LSTM(32, input_shape=(5, 3)))

32作为第一个参数完全取决于你。这意味着在每个时间点,您的3个时间序列将变为32个不同的变量作为输出空间。将每个时间步骤视为具有3个输入和32个输出但具有与FC层不同的计算的完全连接层更容易。

如果您要堆叠多个lstm图层,请使用return_sequences = True参数,这样图层将输出整个预测序列,而不仅仅是最后一个值。

你的目标应该是你想要预测的系列中的下一个值。

总而言之,假设你有以下时间序列:

时间序列1(主):1,2,3,4,5,6,...,100

时间序列2(支持):2,4,6,8,10,12,...,200

时间序列3(支持):3,6,9,12,15,18,...,300

创建输入和目标张量

x     -> y
     

1,2,3,4,5 - > 6

     

2,3,4,5,6 - > 7

     

3,4,5,6,7 - > 8

     

重新格式化剩余的时间序列,但忘记目标,因为你不想预测那些系列

创建模型

    model = Sequential()
    model.add(LSTM(32, input_shape=(5, 3), return_sequences=True)) # Input is shape (5 timesteps x 3 timeseries), output is shape (5 timesteps x 32 variables) because return_sequences  = True
    model.add(LSTM(8))  # output is shape (1 timesteps x 8 variables) because return_sequences = False
    model.add(Dense(1, activation='linear')) # output is (1 timestep x 1 output unit on dense layer). It is compare to target variable.

编译并训练。良好的批量大小为32.批量大小是您的样本矩阵被拆分以便更快计算的大小。只是不要使用statefull