我有两个预测器
A
和 B
,目标是使用多层 ANN 预测目标 (y) C
。我的输入是时间序列的二维组合,使用 1 小时的 A
和 30 分钟的 B
进行预测。
假设我们在时间 t = 0 时预测
C
,则输入 (x) 如下:
x0 = [A(t=-60), A(t=-59) ... A(t=0), B(t=-30), B(t=-29) ... B(t=0)]
那么对于 t = 1,
x1 = [A(t=-59), A(t=-58) ... A(t=1), B(t=-29), B(t=-28) ... B(t=1)]
如您所见,输入 0 和 1 具有重叠的时间历史,因此,当分成训练集、测试集和验证集时,会出现数据泄漏,如下所示:
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=test_split, random_state=64, shuffle=True)
x_val, x_test, y_val, y_test = train_test_split(x_test, y_test, test_size=val_split, random_state=64, shuffle=True)
解决此问题的一个明确方法是在分割数据集时制作
shuffle=False
,然后在数据加载器中对训练集进行洗牌,我在转换为火炬张量后在此处执行此操作:
# training data loading
train_data = TensorDataset(x_train_tensor, y_train_tensor)
train_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True)
# validation data loading
val_data = TensorDataset(x_val_tensor, y_val_tensor)
val_loader = DataLoader(val_data, batch_size=batch_size, shuffle=True)
问题是,当我不在训练/测试/拆分中洗牌时,我的模型很糟糕。糟糕得令人怀疑(例如测试集的相关系数为-0.02)。我说可疑是因为我知道我的预测变量与我的目标在统计上相关,即使模型表现不佳,我仍然会得到比我所看到的更好的指标。
由于我在分割过程中不会打乱数据,因此我怀疑稍后的测试集中会有我的模型在训练中需要的重要信息。我不知道。它似乎表现得太差了,我认为有一个我没有看到的问题。有没有更好的方法来分割我的数据集以保留时间历史并防止重大数据泄漏?
编辑:我还应该补充一点,我通过超参数调整脚本运行模型,以便数据集可以使用各种参数进行训练。结果始终很糟糕。
您可以做的是将数据分成
n 子集,每个子集之间都有时间间隔。间隙必须至少为 1 小时以避免重叠。尽管实际上您应该考虑 A、B 和 C 的自相关时间尺度之类的东西,以确定什么可能导致数据泄漏。
我会做类似以下的事情:选择连续段的长度。比如说5个小时。在您的数据集中,这将对应于 300 个样本。
选择间隙的长度。至少 1 小时 - 但最好通过 A/B/C 的自相关来了解。比如说2小时。
选择您的数据子集。例如,如果您的数据位于数组中:
n_segments = len(x) // (300 + 120)
segments = [x[i*300 + i*120 : i*300 + i*120 + 300] for i in range(n_segments)
对于每个段和间隙周期(2 小时 - 120 分钟),这应该只产生 5 小时(300 分钟)。然后你只需要把它们分配给训练/验证/测试,你应该能够通过随机样本来做到这一点,因为现在你不应该有数据泄漏的问题。尽管您显然必须将它们连接回单个数组而不是列表中的当前子数组。