当前位置: 首页 > 面试题库 >

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

姚兴安
2023-03-14
问题内容

资料来源

有很多资料解释了有状态/无状态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-有状态与无状态LSTM,它们并不能完全解释我在寻找什么。

我的问题

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

我有大约1000个独立的时间序列(samples),timesteps每个时间序列的长度约为600天()(实际上是可变长度,但是我考虑过将数据修剪到一个恒定的时间范围),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_dim``nb_samples``nb_samples=1024``batch_size=64

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

结论

假设我选择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.fitbatch_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)

问题答案:

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

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

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

1,2,3,4,5->样本1

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

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

等等…

这样,您将得到一个形状矩阵(96个样本x 5个时间步长)

该矩阵应重塑为(96 x 5 x
1),表示Keras您只有1个时间序列。如果您有更多并行的时间序列(如您的情况),则对每个时间序列执行相同的操作,因此将以每种形状(96个样本x
5个时间步长)的n个矩阵(每个时间序列一个)结束。

为了争辩,我们假设您有3个时间序列。您应该将所有三个矩阵合并为一个单一的张量形状(96个样本x 5 timeSteps x 3
timeSeries)。此示例的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



 类似资料:
  • 当编写器抛出异常时,我希望能够将步骤和作业状态设置为失败。在做了一些调试和检查Spring批处理源代码后,我注意到配置了一个,它认为是一个致命的异常,因此将作业状态设置为FAILED,所以我将代码包装在我的编写器中的一个try-get中,将包装在中,现在作业和步骤状态设置为FAILED,这是我想要的。我不确定这是否是正确的方法,因为我在任何地方都找不到它的文档,的留档也没有提到它。所以,问题是:这

  • 在阅读了Flink的文档并四处搜索后,我无法完全理解Flink的句柄在其窗口中的状态。假设我有一个每小时滚动的窗口,其中包含一个聚合函数,该函数将消息累积到某个java pojo或scala case类中。该窗口的大小将与一小时内进入该窗口的事件数量相关联,还是仅仅与POJO/Case类相关联,因为我将事件累加到该对象中。(例如,如果将10000个味精数成一个整数,大小会接近10000*味精大小还

  • 我使用JpaPagingItemReader和Spring批处理作业从数据库中读取数据。我有一个要求,我只能写10K记录到外部服务器在每次尝试。我将块大小和页面大小设置为10000。这是否有助于在每次尝试中只读取、处理和写入10K记录,直到JpaPagingItemReader以响应null耗尽并读取来自DB的所有数据为止?我混淆了Pagesize和setMaxItemCount值。哪种方法可以确

  • 我在我的JAVA应用程序中配置了Spring批处理作业,该应用程序在集群中运行。因此,相同的作业被执行两次,这是我不想要的。 所以我想在作业中配置一个步骤,它将检查CREATE_DATE是否在BATCH_JOB_EXECUTION表中存在,并将继续或故障转移。 如何在spring批处理步骤中进行配置?

  • 问题内容: 我在应用程序中使用Hibernate ORM和PostgreSQL,有时我使用批处理操作。最初,我不明白为什么在批处理大小为25的日志中,会生成25个查询,并且最初认为它无法正常工作。但是之后,我查看了pg驱动程序的源代码,并在PgStatement类中找到了以下几行: 并在PgPreparedStatement类中 我注意到,事实证明,如果批处理的大小达到25,则会发送25个带有附加

  • 我在我的应用程序中使用Hibernate ORM和PostgreSQL,有时我使用批处理操作。起初我不明白为什么在批处理大小=25的日志中,会生成25个查询,起初我认为它不能正常工作。但是在那之后,我查看了pg驱动程序的源代码,在Pg语句类中发现了以下几行: 在PgPreparedStatement类中 我注意到,如果批处理的大小变为25,则会发送25个查询并附带参数。 数据库日志证实了这一点,例

  • 我们的几个应用程序具有每天晚上聚合数据的批处理作业。这些批处理作业是Python脚本,使用Prometheus Pushgateway将度量值推送到Prometheus,我们有一些规则,当这些度量值变得无效(例如,超过某个阈值)时,会触发警报(在Alertmanager中)。 我们现在还想使用Prometheus指标来仔细检查批处理作业本身是否正确运行:例如,作业是否按时开始?有任何错误发生吗?这

  • 我最近使用。我对DB表进行了必要的更改,并对一些与参数API相关的微小代码进行了更改。 现在,当我运行应用程序时,它正在工作,但是如果一个步骤的退出状态为失败,则作业的存在状态设置为完成。这会导致一些问题,因为我们的应用程序代码将其视为成功执行。我通过在中添加一个代码片段来解决这个问题,在这里我检查列表并手动设置作业退出状态,但是Spring批处理框架不应该处理退出状态吗?