将时间序列数据正确地输入到有状态LSTM中的方法是什么?

24

假设我有一个整数序列:

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))

据我所知,该模型具有以下结构(请原谅粗略的绘图):

enter image description here

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

请注意,由于指定了stateful=True,因此我已经将先前的状态C_{t-1},h_{t-1}绘制在图中。在这个简单的“下一个整数预测”问题中,通过提供这个额外的信息(只要前一个状态是由前3个整数得出的),性能应该会有所提高。

这就带来了我的主要问题:似乎标准做法(例如参见这篇博客文章TimeseriesGenerator keras预处理工具)是在训练过程中向模型提供一组错开的输入。

例如:

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

这让我感到困惑,因为它似乎需要输出第一个Lstm单元(对应于第一个时间步)的输出。请参见此图:

来自tensorflow docs:

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

似乎这个“内部”状态不可用,只有最终状态是可用的。请参见此图:

所以,如果我的理解是正确的(显然不是),当使用stateful=True时,我们不应该将非重叠的样本窗口馈送给模型吗?例如:

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

正如我预测的那样,这是两个问题。简要回答你的第一个问题:很可能是的。更重要的是你认为这个图像描绘了什么 - 但要点是准确的:LSTM在隐藏状态之间传递信息,并且只传递一个特征张量给Dense进行预测(多对一)。 - OverLordGoldDragon
你所说的“你认为这张图片描绘了什么?”是什么意思?你是指它在概念上是准确的,但是它所表现出来的比我所画的还要多吗? - rmccabe3701
1
我想说的是这是一个非常高级别的表示,LSTM 内部有很多内容 - 例如 kernelrecurrent 权重,每个门的作用以及信息在时间步之间如何流动。 - OverLordGoldDragon
1个回答

43
答案是:取决于手头的问题。对于你这种一步预测的情况-是,你可以这样做,但不一定要这样做。但你是否这样做将显著影响学习。

批量和样本机制("查看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):

  • (10, 54000, 1),包含所有样本,切片为sample[0:54000]; sample[24000:81000]...
  • 现在更加合理了;现在我们的窗口有50%的重叠,而不是99.998%。


    预测:重叠区域不好?

    如果你正在进行一步预测,信息情景已经发生了改变:

    • 很有可能,你的序列长度远远不到240000,因此任何形式的重叠都不会遭受“同一批次多次”效果的影响
    • 预测从根本上与分类不同,因为每个子样本所提供的标签(下一个时间步)都不同;而分类则使用整个序列的一个标签

    这极大地改变了你的损失函数以及最小化它所需的“良好实践”:

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

    我该怎么做?

    首先,确保你完全理解了这篇文章,因为这里没有什么是“可选的”。然后,关于overlap vs no-overlap,在每个batch中有一个关键点:

    1. 一个样本被移位:模型学习更好地预测每个起始步骤向前一步 - 意味着:(1) LSTM对初始细胞状态具有鲁棒性;(2) LSTM对给定X步之前的任何步骤都能很好地预测。
    2. 许多样本,在稍后的batch中移位:模型不太可能‘记住’训练集并过拟合。

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

    • 2会使模型受到影响,使其‘忘记’已经看到的样本
    • 1允许模型通过检查样本的几个起始和结束(标签),并根据此平均梯度来提取更好质量的特征。

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

    • 如果你的序列长度非常长,并且你能够承担“滑动窗口”w/ ~50%的长度,也许可以,但这取决于数据的性质:信号(EEG)?是的。股票、天气?怀疑。
    • 许多对多预测;在更大的长序列中看到(2)更为常见。

    LSTM状态保存(Stateful):实际上对于你的问题可能完全没有用处。

    当LSTM无法一次处理整个序列时,就会使用状态保存功能(Stateful),因此它会被“分割” - 或者当需要从反向传播中得到不同的梯度时。对于前者,其思想是 - LSTM在评估后续内容时考虑先前的序列:

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

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

    何时使用状态保存:当LSTM从先前的批次中受益于评估下一个批次时。这可能包括单步预测,但仅限于您无法一次输入整个序列的情况下:

    • 期望值:100个时间步骤。可行:50个。因此我们设置t0,t1,如上面第一个项目符号。
    • 问题:在编程实现中不太直观。您需要找到一种方法,以输入LSTM而不应用梯度 - 例如冻结权重或设置lr = 0

    LSTM在stateful模式下何时以及如何“传递状态”?

    • 何时:仅限于批次之间;样本完全独立
    • 如何:在Keras中,只能够批次-样本之间进行传递:stateful=True 需要您指定batch_shape而不是input_shape - 因为Keras在编译时构建了batch_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个或更多(对于此答案始终假设为后者)。有三种方法可以迭代数据:批量梯度下降(一次处理整个数据集),随机梯度下降(每次处理一个样本)和小批量梯度下降(介于两者之间)。 (实际上,我们也称最后一种为SGD,并且只区分它与BGD - 对于此答案也是如此。)区别:

    • SGD实际上从未优化训练集的损失函数 - 只有其“近似值”;每个批次都是整个数据集的子集,并且计算的梯度仅涉及最小化该批次的损失。 批次大小越大,则其损失函数越类似于训练集。
    • 上述内容可以扩展到拟合批次与样本:样本是批次的近似值 - 或者说是数据集的较差近似值
    • 首先拟合16个样本,然后再拟合16个不同的样本与一次性拟合32个是不同的 - 因为在这两个过程中,权重会被更新,因此后一半的模型输出将会改变
    • 选择SGD而不是BGD的主要原因实际上不是计算限制,而是因为它通常更优。简单地解释:使用BGD很容易过拟合,并且SGD通过探索更多样化的损失空间收敛于更好的测试数据解决方案。

    额外的图表:



    2
    我还在消化这个精彩的答案(感谢您),但是我仍然不清楚我的后两个图中哪一个是“正确”的:当stateful=True时,“最终”LSTM状态(对应于给定整个样本时间序列的输出)是否会传递到下一批次?还是某个中间状态? - rmccabe3701
    1
    哇,你的第一个“奖励图”正是我所问的。看起来我的第二个图(将“最终”状态馈送到下一批)是最准确的(你的图更清晰)。我差不多准备把这个问题标记为已解决。但在此之前:如果输入是交错的,通过这种方式传递状态的有效性仍然不清楚。我完全理解你的激励示例,说明为什么交错输入很有用,但我的困惑在于在这种情况下传递状态的算法似乎不一致。 - rmccabe3701
    @rmccabe3701,你说得很对;据你所知,我已经移动了一些部分,并鼓励你仔细检查是否已经阅读了所有部分——因为你的问题在“LSTM stateful”下的粗体字中得到了回答。 - OverLordGoldDragon
    @rmccabe3701 不用谢 - 很高兴你觉得有用。如果你能负担得起,我会很感激这个答案的最低赏金 - 因为我花了相当多的时间和精力在里面。祝你的深度学习好运。 - OverLordGoldDragon
    @rmccabe3701 不确定您所指的是什么,或者它与这个问题有什么关系,但我已在聊天中回复了。如果涉及数据输入管道,那又是一个完整的问题 - 幸运的是,我为各种方式的时间序列数据提供/预处理编写了几乎整个API,尽管它尚未发布,我可能会有答案。 - OverLordGoldDragon
    显示剩余6条评论

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接