如何在有状态的 RNN 中设计批次

数据挖掘 深度学习 张量流 lstm rnn
2021-09-20 03:48:26

我正在使用 TF Eager 来训练有状态的 RNN (GRU)。

我有几个大约 1 分钟长的可变长度时间序列,我将它们分成长度为 1s 的窗口。

在 TF Eager 中,就像在 Keras 中一样,如果stateful=True,“批次中索引 i 处的每个样本的最后状态将用作下一批中索引 i 的样本的初始状态。” 来源

因此,我应该如何设计我的批次?我显然不能从随机序列中采样随机窗口。我也不能将一个序列拆分成多个窗口并将相邻的窗口放在同一个批次中(例如batch 1 = [[seq1 0-1s], [seq 1 1-2s], [seq1 2-3s], ...]),因为来自前一个窗口的状态不会传递到下一个窗口,就像有状态 RNN 的要点一样。

我正在考虑在同一批次中混合序列:

batch 1 = [[seq1 0-1s], [seq2 0-1s], [seq3 0-1s], ...]
batch 2 = [[seq1 1-2s], [seq2 1-2s], [seq3 1-2s], ...]
...

但是,问题在于序列的长度不同,因此有些序列会先于其他序列完成。

那么实现这一点的最佳方法是什么?

(仅供参考,我在学术文献或博客中找不到任何讨论这个的东西,所以参考文献会很棒)

谢谢!

1个回答

您的具体情况

在批次索引处[seq1 0-1s](长序列的第 1 秒)之后,批次seq1索引(相同序列的第 2 秒,这正是我们设置时所需要的0b[seq1 1-2s]seq10b+1stateful=True

请注意,每批内的样本必须具有相同的长度,如果正确完成,则(不是内部)批次之间的序列长度差异不会导致问题。也就是说,当批次中的所有样本b都处理完毕后,将处理下一批样本b+1,以此类推。

一个普遍的例子

作为一般示例,对于stateful=Truebatch_size=2,数据集如

seq1: s11, s12, s13, s14
seq2: s21, s22, s23
seq3: s31, s32, s33, s34, s35
seq4: s41, s42, s43, s44, s45, s46

其中sij表示第 j 个时间步,必须像这样构造

    batch 1         batch 2         batch 3         batch 4  

0   s21, s22        s23, <pad>      s31, s32, s33   s34, s35, <pad>   ...
1   s11, s12        s13, s14        s41, s42, s43   s44, s45, s46

或类似(有重叠)

    batch 1         batch 2         batch 3         

0   s21, s22        s22, s23        s23, <pad>    ...
1   s11, s12        s12, s13        s13, s14   

其中,例如,长序列s21, s22, s23(3 个时间步长)被分解为两个子序列s21, s22s23, <pad>此外,如您所见,可以有具有不同序列长度的批次(通过使用自定义批次生成器)。

请注意,<pad>(填充值)应该被屏蔽以防止 RNN 将它们视为实际值(更多信息在这篇文章中)。我们还可以通过选择batch_size=1可能过于严格的填充值来避免使用填充值(更多信息在这篇文章中)。

以下是具有 5 个时间步长的序列的两个示例:

            s11   s12   s13   s14   s15

example 1   23,   25,   27,   24,    28     # 5 temperature readings for t to t+4

example 2   I,    like, LSTM, very,  much   # 5 128-dim word embeddings

一些资源

  1. 您可能会发现这篇关于有状态与无状态 LSTM 的文章很有帮助。文章中的一些引用:

    具有相同配置的无状态 LSTM 在这个问题上的表现可能比有状态版本更好。

    当使用大批量时,可以使用无状态 LSTM 模拟有状态 LSTM。

  2. Philippe Remy 撰写的关于 Keras 中的 Stateful LSTM 的博客

  3. Keras github上的一些意见,像这样