首页 文章

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

提问于
浏览
5

来源

有几个来源解释有状态/无状态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,首先必须构建形状为nb_samples,timesteps,input_dim的输入矩阵X,其中批量大小除以nb_samples . 例如,如果nb_samples = 1024且batch_size = 64,则表示您的模型将接收64个样本的块,计算每个输出(无论每个样本的时间步数是多少),平均梯度并传播它以更新参数向量 .

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

Conclusion

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

batch_size的原理被理解 - 但仍然不知道什么是 good value for batch_size. 以及如何确定它


有状态

KERAS documentation告诉我们

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

If I’m splitting my time series 进入了几个 samples (就像[1]和[4]的例子中那样),以便我想要建模的依赖关系跨越几个批次, or the batch-spanning samples are otherwise correlated 彼此,我可能 need a stateful net ,否则不是 . 这是正确而完整的结论吗?

所以对于我的问题,我想我不需要有状态网 . 我将我的训练数据构建为形状 (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 回答

  • 5

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

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

    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

相关问题