用于 LSTM-RNN 训练的填充时间序列子序列
Padding time-series subsequences for LSTM-RNN training
我有一个时间序列数据集,我将其用作 LSTM-RNN 的输入以进行动作预测。时间序列包含 30 fps 的 5 秒时间(即 150 个数据点),数据表示面部特征 position/movement。
我从我的数据集中采样了更小长度的额外子序列,以便在数据集中添加冗余并减少过度拟合。在这种情况下,我知道子序列的开始和结束帧。
为了批量训练模型,所有时间序列需要具有相同的长度,并且根据文献中的许多论文,padding 不应影响网络的性能。
示例:
原始序列:
1 2 3 4 5 6 7 8 9 10
子序列:
4 5 6 7
8 9 10
2 3 4 5 6
考虑到我的网络正在尝试预期一个动作(这意味着一旦 P(action) > threshold 从 t = 0 到 T = tmax,它将预测该动作)填充的位置重要吗?
选项 1:用零替换原始值
0 0 0 4 5 6 7 0 0 0
0 0 0 0 0 0 0 8 9 10
0 2 3 4 5 6 0 0 0 0
选项 2:末尾全为零
4 5 6 7 0 0 0 0 0 0
8 9 10 0 0 0 0 0 0 0
2 3 4 5 0 0 0 0 0 0
此外,一些时间序列缺少一些帧,但不知道它们是哪些 - 这意味着如果我们只有 60 帧,我们不知道它们是否是从 0 到2 秒,从 1 到 3 秒,等等。这些甚至需要在拍摄子序列之前填充。在这种情况下填充的最佳做法是什么?
提前致谢。
一般而言,LSTM 和 RNN 最强大的属性是它们的参数在时间范围内共享(参数 在时间范围内重复)但参数共享依赖于假设相同的参数可以用于不同的时间步长,即前一个时间步长和下一个时间步长之间的关系 不 取决于 t ,如 here in page 388, 2nd paragraph.[=11 所解释的=]
简而言之,在末尾填充零,理论上 不应改变模型的准确性。我在理论上使用副词 因为在每个时间步长 LSTM 的决定取决于它的细胞状态以及其他因素,而这个细胞状态是对过去帧的简短总结。据我了解,您的情况可能缺少过去的帧。我认为你在这里有一点权衡。
我宁愿在末尾补零,因为它与RNNs的基本假设不完全冲突,而且更便于实现和跟踪。
在实现方面,我知道一旦你给它每个样本的序列和实际序列大小,tensorflow 就会计算损失函数(例如,对于 4 5 6 7 0 0 0 0 0 0 你还需要给它实际大小(此处为 4)假设您正在实施选项 2。不过,我不知道选项 1 是否有实施。
最好一开始就用零填充,正如本文所建议的那样Effects of padding on LSTMs and CNNs,
Though post padding model peaked it’s efficiency at 6 epochs and started to overfit after that, it’s accuracy is way less than pre-padding.
检查table 1,其中pre-padding(开头补零)的准确率在80%左右,但是对于post-padding(最后补零),它只有50%左右
如果你有可变长度的序列,pytorch
提供一个效用函数 torch.nn.utils.rnn.pack_padded_sequence。使用此功能的一般工作流程是
from torch.nn.utils.rnn import pack_padded_sequence, pad_packed_sequence
embedding = nn.Embedding(4, 5)
rnn = nn.GRU(5, 5)
sequences = torch.tensor([[1,2,0], [3,0,0], [2,1,3]])
lens = [2, 1, 3] # indicating the actual length of each sequence
embeddings = embedding(sequences)
packed_seq = pack_padded_sequence(embeddings, lens, batch_first=True, enforce_sorted=False)
e, hn = rnn(packed_seq)
可以通过
收集每个标记的嵌入
e = pad_packed_sequence(e, batch_first=True)
使用这个函数比自己填充要好,因为torch
会限制RNN只检查实际序列并在填充的token之前停止。
我有一个时间序列数据集,我将其用作 LSTM-RNN 的输入以进行动作预测。时间序列包含 30 fps 的 5 秒时间(即 150 个数据点),数据表示面部特征 position/movement。
我从我的数据集中采样了更小长度的额外子序列,以便在数据集中添加冗余并减少过度拟合。在这种情况下,我知道子序列的开始和结束帧。
为了批量训练模型,所有时间序列需要具有相同的长度,并且根据文献中的许多论文,padding 不应影响网络的性能。
示例:
原始序列:
1 2 3 4 5 6 7 8 9 10
子序列:
4 5 6 7
8 9 10
2 3 4 5 6
考虑到我的网络正在尝试预期一个动作(这意味着一旦 P(action) > threshold 从 t = 0 到 T = tmax,它将预测该动作)填充的位置重要吗?
选项 1:用零替换原始值
0 0 0 4 5 6 7 0 0 0
0 0 0 0 0 0 0 8 9 10
0 2 3 4 5 6 0 0 0 0
选项 2:末尾全为零
4 5 6 7 0 0 0 0 0 0
8 9 10 0 0 0 0 0 0 0
2 3 4 5 0 0 0 0 0 0
此外,一些时间序列缺少一些帧,但不知道它们是哪些 - 这意味着如果我们只有 60 帧,我们不知道它们是否是从 0 到2 秒,从 1 到 3 秒,等等。这些甚至需要在拍摄子序列之前填充。在这种情况下填充的最佳做法是什么?
提前致谢。
一般而言,LSTM 和 RNN 最强大的属性是它们的参数在时间范围内共享(参数 在时间范围内重复)但参数共享依赖于假设相同的参数可以用于不同的时间步长,即前一个时间步长和下一个时间步长之间的关系 不 取决于 t ,如 here in page 388, 2nd paragraph.[=11 所解释的=]
简而言之,在末尾填充零,理论上 不应改变模型的准确性。我在理论上使用副词 因为在每个时间步长 LSTM 的决定取决于它的细胞状态以及其他因素,而这个细胞状态是对过去帧的简短总结。据我了解,您的情况可能缺少过去的帧。我认为你在这里有一点权衡。
我宁愿在末尾补零,因为它与RNNs的基本假设不完全冲突,而且更便于实现和跟踪。
在实现方面,我知道一旦你给它每个样本的序列和实际序列大小,tensorflow 就会计算损失函数(例如,对于 4 5 6 7 0 0 0 0 0 0 你还需要给它实际大小(此处为 4)假设您正在实施选项 2。不过,我不知道选项 1 是否有实施。
最好一开始就用零填充,正如本文所建议的那样Effects of padding on LSTMs and CNNs,
Though post padding model peaked it’s efficiency at 6 epochs and started to overfit after that, it’s accuracy is way less than pre-padding.
检查table 1,其中pre-padding(开头补零)的准确率在80%左右,但是对于post-padding(最后补零),它只有50%左右
如果你有可变长度的序列,pytorch
提供一个效用函数 torch.nn.utils.rnn.pack_padded_sequence。使用此功能的一般工作流程是
from torch.nn.utils.rnn import pack_padded_sequence, pad_packed_sequence
embedding = nn.Embedding(4, 5)
rnn = nn.GRU(5, 5)
sequences = torch.tensor([[1,2,0], [3,0,0], [2,1,3]])
lens = [2, 1, 3] # indicating the actual length of each sequence
embeddings = embedding(sequences)
packed_seq = pack_padded_sequence(embeddings, lens, batch_first=True, enforce_sorted=False)
e, hn = rnn(packed_seq)
可以通过
收集每个标记的嵌入e = pad_packed_sequence(e, batch_first=True)
使用这个函数比自己填充要好,因为torch
会限制RNN只检查实际序列并在填充的token之前停止。