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

asc*_*ter 15 python lstm keras 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线程,比如了解Keras LSTMKeras - 有状态的vs无状态LSTM,但是并没有完全解释我正在寻找的东西.


我的问题

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

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

Input shape = (1000, 600, 8)

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

Output shape = (1000, 600, 1)


什么是批次?

从[ 4 ]:

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

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

[...]

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

这听起来像是一个"批处理"将沿着timesteps-dimension 分割数据.

但是,[ 3 ]指出:

换句话说,无论何时训练或测试LSTM,首先必须建立批量大小分割的输入X形状矩阵.例如,如果和,则表示您的模型将接收64个样本的块,计算每个输出(无论每个样本的时间步数是多少),平均梯度并传播它以更新参数向量.nb_samples, timesteps, input_dimnb_samplesnb_samples=1024batch_size=64

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

结论

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

了解了batch_size的原则 - 但是仍然不知道batch_size的值是多少.以及如何确定它


有状态

KERAS文件告诉我们

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

如果我将我的时间序列分成几个samples(如[ 1 ]和[ 4 ] 的例子中所示),那么我想要建模的依赖关系跨越几个批次,或者批量跨越样本以其他方式与每个批次相关联另外,我可能需要一个有状态网,否则不需要.这是正确而完整的结论吗?

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

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)
Run Code Online (Sandbox Code Playgroud)

lsm*_*mor 14

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

所以假设你有以下系列: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 - > sample3

等等...

通过这样做,您将以一个形状矩阵结束(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)))
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

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

  • 所以你有1000个独立系列,每个系列长600步,你将根据101个时间步长训练你的lstm.所以,最后你会得到`(500个样本x 101长度,每个x 1000系列)` (2认同)
  • 好吧,也许我们这里没有说同样的话.假设我有3个系列:最高温度,最低温度和纽约360天的污染量.我想研究三个系列之间的关系,以便预测污染.你的小朋友将在过去的30天里学习.所以你的尺寸将是`(330个样本×每个x 3个系列30个步骤).希望能帮助到你 (2认同)
  • 好吧,我想我明白了。现在让我们说,不仅对于纽约,而且对于总共1000个城市,我都希望拥有相同的模型,并希望拟合适用于所有城市的模型。当然,实际上,那时我将需要的不仅仅是这3个系列,但为简单起见,我们假设其中包含所有相关信息以进行预测。因此,在这种情况下,我将得到`(1000 x 330个样本x每个30个时间步长x 3个系列)。请确认我的假设。 (2认同)
  • 好的!我现在明白了。是的,对于您的情况,您最终会得到这样的维度。我不明白您在许多情况下都有相同的系列。这里的术语很复杂哈哈。问候 (2认同)
  • 好答案。为我澄清了术语,但仍然有一个问题。为什么建议不要使用有状态? (2认同)
  • @马库斯哇。这是相当古老的。Stateful 不适合我的解决方案,因为批次 `n + 1` 的样本 `i` 不会是批次 `n` 的样本 `i` 的“延续”,这是有状态的原因。我并不是说您实际上不能为了使用 Stateful LSTM 而洗牌您的样本。我的意图是“如果您使用我的解决方案,请不要使用有状态”。此外,我已经测试了有状态 LSTM 并且我没有得到更多的改进(有些人这样做了!!)但是使批次正常的努力很大,我认为这取决于您当前的事件受非常旧的事件影响的程度。 (2认同)