首页 > 解决方案 > 将时间序列数据提供给有状态 LSTM 的正确方法?

问题描述

假设我有一个整数序列:

0,1,2, ..

并希望在给定最后 3 个整数的情况下预测下一个整数,例如:

[0,1,2]->5, [3,4,5]->6, 等

假设我像这样设置我的模型:

batch_size=1
time_steps=3
model = Sequential()
model.add(LSTM(4, batch_input_shape=(batch_size, time_steps, 1), stateful=True))
model.add(Dense(1))

据我了解,模型具有以下结构(请原谅粗图):

在此处输入图像描述

第一个问题:我的理解正确吗?

注意我已经绘制了C_{t-1}, h_{t-1}进入图片的先前状态,因为这是在指定时暴露的stateful=True。在这个简单的“下一个整数预测”问题中,性能应该通过提供这些额外信息来提高(只要前一个状态来自前 3 个整数)。

这让我想到了我的主要问题: 似乎标准做法(例如参见这篇文和TimeseriesGenerator keras 预处理实用程序)是在训练期间向模型提供一组交错的输入。

例如:

batch0: [[0, 1, 2]]
batch1: [[1, 2, 3]]
batch2: [[2, 3, 4]]
etc

这让我很困惑,因为这似乎需要第一个 Lstm 单元的输出(对应于第一个时间步)。看这个图:

从张量流文档

stateful:布尔值(默认为 False)。如果为 True,则批次中索引 i 处每个样本的最后状态将用作下一批中索引 i 的样本的初始状态。

似乎这种“内部”状态不可用,所有可用的都是最终状态。看这个图:

所以,如果我的理解是正确的(显然不是),我们不应该在使用时向模型提供不重叠的样本窗口stateful=True吗?例如:

batch0: [[0, 1, 2]]
batch1: [[3, 4, 5]]
batch2: [[6, 7, 8]]
etc

标签: pythontensorflowmachine-learningkeraslstm

解决方案


答案是:取决于手头的问题。对于您的一步预测的情况 - 是的,您可以,但您不必这样做。但无论你是否这样做,都会对学习产生重大影响。


批处理与样本机制(“参见 AI”=参见“附加信息”部分)

所有模型都将样本视为独立示例;一批 32 个样品就像一次喂 1 个样品,32 次(有差异 - 见 AI)。从模型的角度来看,数据分为批量维度batch_shape[0]和特征维度batch_shape[1:]——两者“不说话”。两者之间的唯一关系是通过梯度(参见 AI)。


重叠与无重叠批次

也许理解它的最好方法是基于信息的。我将从时间序列二进制分类开始,然后将其与预测联系起来:假设您有 10 分钟的 EEG 记录,每个记录有 240000 个时间步长。任务:扣押还是不扣押?

  • 由于 240k 对 RNN 来说太多了,我们使用 CNN 进行降维
  • 我们可以选择使用“滑动窗口”——即一次输入一个子段;让我们使用 54k

取 10 个样品,定型(240000, 1)。如何喂养?

  1. (10, 54000, 1),包括所有样品,切片为sample[0:54000]; sample[54000:108000]...
  2. (10, 54000, 1),包括所有样品,切片为sample[0:54000]; sample[1:54001]...

以上两个你选哪个?如果 (2),您的神经网络将永远不会混淆这 10 个样本的癫痫发作与非癫痫发作。但它也会对任何其他样本一无所知。即,它会大量过拟合,因为它每次迭代看到的信息几乎没有什么不同(1/54000 = 0.0019%)——所以你基本上是连续多次喂它同一批。现在假设(3):

  1. (10, 54000, 1),包括所有样品,切片为sample[0:54000]; sample[24000:81000]...

更合理;现在我们的窗口有 50% 的重叠,而不是 99.998%。


预测:重叠不好?

如果您正在进行一步预测,那么信息格局现在会发生变化:

  • 很有可能,您的序列长度从 240000 开始,因此任何类型的重叠都不会受到“同一批次多次”的影响
  • 预测从根本上不同于分类,因为您输入的每个子样本的标签(下一个时间步长)都不同;分类对整个序列使用一个

这极大地改变了您的损失函数,以及将其最小化的“良好做法”:

  • 预测器必须对其初始样本具有鲁棒性,尤其是对于 LSTM - 因此我们通过滑动序列来训练每个这样的“开始”,如您所示
  • 由于标签在时间步之间存在差异,因此损失函数在时间步之间发生显着变化,因此过度拟合的风险要小得多

我应该怎么办?

首先,确保你理解了整篇文章,因为这里没有什么是真正“可选的”。然后,这是关于每批次重叠与不重叠的关键:

  1. 一个样本移位:模型学习更好地预测每个起始步骤的前一步 - 含义:(1)LSTM 对初始细胞状态的鲁棒性;(2) LSTM 对任何领先一步的预测都很好,因为落后 X 步
  2. 许多样本,在后面的批次中转移:模型不太可能“记住”训练集和过度拟合

你的目标:平衡两者;1 相对于 2 的主要优势是:

  • 2 可以通过让它忘记看到的样本来阻碍模型
  • 1允许模型通过检查多个开始和结束(标签)的样本来提取质量更好的特征,并相应地平均梯度

我应该在预测中使用(2)吗?

  • 如果您的序列长度很长,并且您可以负担得起其长度约为 50% 的“滑动窗口”,则可能,但这取决于数据的性质:信号(EEG)?是的。股票,天气?怀疑。
  • 多对多预测;更常见的是(2),每个更长的序列。

LSTM 有状态:实际上可能对您的问题完全没用。

当 LSTM 无法一次处理整个序列时使用有状态的,因此它被“拆分” - 或者当反向传播需要不同的梯度时。对于前者,想法是——LSTM 在评估后者时考虑前一个序列:

  • t0=seq[0:50]; t1=seq[50:100]说得通; t0逻辑上导致t1
  • seq[0:50] --> seq[1:51]没有意义; t1没有因果关系源自t0

换句话说:不要在有状态的不同批次中重叠。同一批是可以的,同样,独立性 - 样本之间没有“状态”。

何时使用有状态:当 LSTM 在评估下一个批次时考虑前一批时受益。这可以包括一步预测,但前提是您不能一次提供整个序列:

  • 期望:100 个时间步长。可以做到:50。所以我们t0, t1按照上面的第一个项目符号进行设置。
  • 问题:以编程方式实现并不简单。您需要找到一种在不应用梯度的情况下提供给 LSTM 的方法 - 例如冻结重量或设置lr = 0

LSTM 何时以及如何在有状态的情况下“传递状态”?

  • 何时:仅批次到批次;样本完全独立
  • 如何:在 Keras 中,只有批样本到批样本stateful=True 需要您指定batch_shape而不是input_shape- 因为,Kerasbatch_size在编译时构建了 LSTM 的单独状态

根据上述,您不能这样做:

# sampleNM = sample N at timestep(s) M
batch1 = [sample10, sample20, sample30, sample40]
batch2 = [sample21, sample41, sample11, sample31]

这意味着21因果关系10- 并且会破坏训练。而是这样做:

batch1 = [sample10, sample20, sample30, sample40]
batch2 = [sample11, sample21, sample31, sample41]

批次与样品:附加信息

“批次”是一组样本 - 1 个或更大(假设此答案总是后者)。迭代数据的三种方法:批量梯度下降(一次整个数据集)、随机 GD(一次一个样本)和 Minibatch GD(中间)。(然而,在实践中,我们也称最后一个 SGD 并且只区分 vs BGD - 假设这个答案是这样。)差异:

  • SGD 从未真正优化过训练集的损失函数——只是它的“近似值”;每个批次都是整个数据集的一个子集,计算的梯度仅与最小化该批次的损失有关。批量越大,它的损失函数越接近训练集。
  • 以上可以扩展到拟合批次与样本:样本是批次的近似值 - 或者,数据集的近似值较差
  • 首先拟合 16 个样本,然后再拟合 16 个样本与一次拟合 32 个样本不同 - 因为权重在两者之间更新,所以后半部分的模型输出会改变
  • 实际上,选择 SGD 而不是 BGD 的主要原因不是计算限制——而是它在大多数情况下更优越。简单解释:使用 BGD 更容易过度拟合,并且 SGD 通过探索更多样化的损失空间来收敛到更好的测试数据解决方案。

奖金图



推荐阅读