提问者:小点点

理解Keras LSTM:批处理大小和状态的作用


有几个来源解释了有状态/无状态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/

以及其他SO线程,如理解Keras LSTM和Keras-有状态vs无状态LSTM,这些线程并没有完全解释我正在寻找的内容。

关于状态性和确定批量大小,我仍然不确定我的任务的正确方法是什么。

我有大约1000个独立的时间序列(样本),每个序列的长度约为600天(时间步骤)(实际上是可变长度,但我考虑将数据修剪为恒定的时间帧),具有8个功能(或input_dim)为每个时间步(一些功能是相同的每个样本,一些个别的每个样本)。

Input shape=(1000600,8)

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

Output shape=(1000600,1)

从[4]:

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

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

[…]

当您希望做出比批次大小更少的预测时,这确实会成为一个问题。例如,您可以使用大批量获得最佳结果,但需要在时间序列或序列问题上一次对一个观察结果进行预测。

对我来说,这听起来像是批处理将沿着时间步骤-维度拆分数据。

然而,[3]指出:

换言之,无论何时培训或测试LSTM,您首先必须构建输入矩阵X,其形状为nb\u样本、时间步长、输入dim,其中批次大小划分nb\u样本。例如,如果nb_samples=1024batch_size=64,这意味着您的模型将接收64个样本的块,计算每个输出(无论每个样本的时间步数是多少),平均梯度并传播它以更新参数向量。

当深入研究[1]和[4]的示例时,Jason总是将其时间序列拆分为仅包含1个时间步长的多个样本(在他的示例中,前一个样本完全确定序列中的下一个元素)。因此,我认为批次实际上是沿着样本轴分割的。(然而,对于长期依赖性问题,他的时间序列分割方法对我来说没有意义。)

结论

比如说,我选择了批次大小=10,这意味着在一个历元中,权重会更新1000/10=100次,10个随机选择的完整时间序列包含600 x 8的值,当我以后想用模型进行预测时,我总是要给它提供10个完整时间序列的批次(或者使用[4]中的解决方案3,将权重复制到具有不同批次大小的新模型)。

batch_size理解的原则-但仍然不知道什么是好的价值batch_size

KERAS留档告诉我们

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

如果我要将我的时间序列拆分为几个样本(如[1]和[4]的示例中所示),以便我要跨多个批次建模的依赖关系,或者批次跨越样本以其他方式相互关联,我可能需要一个有状态的网络,否则就不需要。这是一个正确和完整的结论吗?

所以对于我的问题,我想我不需要一个有状态的网络。我将把我的训练数据构建成一个形状的3D数组(样本、时间步、特征),然后调用模型。使用尚未确定的批次大小安装。示例代码可能如下所示:

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个答案

匿名用户

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

假设你有以下系列:1,2,3,4,5,6,。。。,100.你必须决定你的lstm将学习多少时间步,并据此重塑你的数据。如下图所示:

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

1,2,3,4,5-

2,3,4,5,6-

3,4,5,6,7 -

这样,您将以形状矩阵结束(96个样本x 5个时间步)

这个矩阵应该重塑为(96 x 5 x 1),表明Keras只有1个时间序列。如果你有更多的时间序列并行(在你的情况下),你对每个时间序列做相同的操作,所以你将以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-

2,3,4,5,6-

3,4,5,6,7 -

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

创建您的模型

    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。Batch size是为加快计算而拆分样本矩阵的大小。只是不要使用statefull