WEBKT

时间序列数据的交叉验证:陷阱、技巧与最佳实践

4 0 0 0

为什么不能直接用k折交叉验证?

时间序列交叉验证的正确姿势

1. 前向链式验证 (Forward Chaining)

2. 时间序列分割 (TimeSeriesSplit)

3. 阻塞式时间序列交叉验证 (Blocked Cross-Validation)

4. 自定义验证集

时间序列交叉验证的注意事项

总结

在机器学习中,交叉验证是评估模型泛化能力的重要手段。它通过将数据集划分为多个子集,轮流使用其中一部分进行训练,另一部分进行测试,从而减少模型评估的偏差。然而,当处理时间序列数据时,标准的交叉验证方法(如k折交叉验证)可能会失效,甚至导致错误的结论。这是因为时间序列数据具有内在的时间依赖性,过去的数据会影响未来的数据。今天我们就来深入聊聊时间序列数据的交叉验证,看看有哪些坑需要避免,又有哪些技巧可以帮助我们构建更可靠的模型。

为什么不能直接用k折交叉验证?

想象一下,你正在预测明天的股票价格。如果你用未来的数据(比如后天的股票价格)来训练模型,然后再用今天的数据来测试,这显然是不合理的。因为在现实世界中,你不可能预知未来。这就是时间序列数据交叉验证的核心问题:数据泄露

标准的k折交叉验证会随机打乱数据,这破坏了时间序列数据的时间顺序。例如,一个5折交叉验证可能会将数据集分成如下几部分:

  • 折1:第2、4、6、8、10天的数据
  • 折2:第1、3、5、7、9天的数据
  • ...

如果用折1的数据训练,折2的数据测试,就会出现用未来的数据预测过去的情况,导致模型评估结果过于乐观。这种乐观的评估结果会误导我们,让我们误以为模型具有很好的预测能力,但实际上它在真实场景中可能表现很差。

时间序列交叉验证的正确姿势

为了解决这个问题,我们需要使用专门针对时间序列数据的交叉验证方法。这些方法的核心思想是:始终使用过去的数据训练模型,使用未来的数据测试模型。 几种常见的时间序列交叉验证方法如下:

1. 前向链式验证 (Forward Chaining)

前向链式验证,也叫滚动式交叉验证,是时间序列交叉验证最常用的方法之一。它的思路非常简单:

  1. 初始训练集只包含最早期的少量数据。
  2. 使用这个训练集训练模型,并在紧随其后的时间段上进行测试。
  3. 将测试集加入训练集,形成一个更大的训练集。
  4. 重复步骤2和3,直到所有数据都被用于测试。

这种方法就像一个时间滑块,不断向未来滑动,每次滑动都用过去的所有数据训练,用未来的数据测试。 如下图所示:

Fold 1: Training [1], Test [2]
Fold 2: Training [1 2], Test [3]
Fold 3: Training [1 2 3], Test [4]
Fold 4: Training [1 2 3 4], Test [5]
Fold 5: Training [1 2 3 4 5], Test [6]

这种方法可以保证数据的时间顺序,避免数据泄露。同时,它也充分利用了所有的数据,既用于训练,又用于测试。

2. 时间序列分割 (TimeSeriesSplit)

TimeSeriesSplitscikit-learn库中专门用于时间序列交叉验证的类。它的用法非常简单,与KFold类似。 最大的区别在于,TimeSeriesSplit不会打乱数据,而是按照时间顺序进行划分。

from sklearn.model_selection import TimeSeriesSplit
import numpy as np
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]]) # 假设这是时间序列数据
y = np.array([1, 2, 3, 4, 5, 6])
tscv = TimeSeriesSplit(n_splits=3)
for train_index, test_index in tscv.split(X):
print("TRAIN:", train_index, "TEST:", test_index)
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
# 在这里进行模型的训练和评估

输出结果:

TRAIN: [0 1 2] TEST: [3]
TRAIN: [0 1 2 3] TEST: [4]
TRAIN: [0 1 2 3 4] TEST: [5]

可以看到,TimeSeriesSplit将数据按照时间顺序划分成了多个训练集和测试集,每次测试集都在训练集之后,保证了时间顺序。

3. 阻塞式时间序列交叉验证 (Blocked Cross-Validation)

在某些情况下,时间序列数据可能存在一些相关性较强的块(例如,同一台机器产生的多个连续测量值)。为了避免同一块中的数据同时出现在训练集和测试集中,可以使用阻塞式时间序列交叉验证。

阻塞式时间序列交叉验证将数据分成多个连续的块,然后按照时间顺序进行划分。这种方法可以减少块内相关性对模型评估的影响。 这种方法在金融数据中很常见,因为金融市场经常存在一些周期性的波动。

4. 自定义验证集

有时候,你可能需要更精细地控制验证过程。比如你已经有了明确的训练周期,验证周期,测试周期. 比如, 你想用2020-2022年的数据训练, 2023年1-6月的数据验证, 2023年7-12月的数据进行最终测试. 这种情况下,你可以手动划分数据集,完全自定义你的验证集。

时间序列交叉验证的注意事项

  • 数据平稳性:时间序列数据的平稳性对模型评估有很大影响。如果数据不平稳(例如存在趋势或季节性),需要先进行差分或分解等预处理操作,使数据平稳化,然后再进行交叉验证。否则,模型可能只学习到了数据的趋势或季节性,而没有学习到真正的规律。
  • 特征工程:时间序列数据的特征工程非常重要。需要根据数据的特点,提取合适的特征,例如滞后特征、滑动窗口统计量、时间特征等。好的特征可以提高模型的预测能力。
  • 评估指标:选择合适的评估指标也很重要。对于回归问题,常用的评估指标有均方误差(MSE)、均方根误差(RMSE)、平均绝对误差(MAE)等。对于分类问题,常用的评估指标有准确率、精确率、召回率、F1值等。需要根据具体的问题选择合适的评估指标。
  • 超参数调整: 在时间序列的交叉验证中进行超参数调整时, 也要注意不能使用未来的数据. 也就是说, 超参数的搜索空间, 也需要基于时间序列进行划分.
  • 计算成本:时间序列交叉验证通常比标准的k折交叉验证计算成本更高,因为它需要训练更多的模型。如果数据集很大,或者模型训练时间很长,需要考虑计算成本。

总结

时间序列数据的交叉验证是模型评估的关键步骤。通过使用正确的方法,可以避免数据泄露,得到更可靠的模型评估结果。希望这篇文章能让你对时间序列数据的交叉验证有更深入的理解。记住,实践出真知,多尝试不同的方法,才能找到最适合你的问题的解决方案。别怕麻烦,多动手,你会发现时间序列分析的乐趣!

如果你觉得这篇文章有用, 欢迎点赞, 分享, 让更多的人了解时间序列分析的奥秘! 我也会持续分享更多关于数据科学, 机器学习的内容, 欢迎关注!

数据挖掘机 时间序列交叉验证机器学习

评论点评

打赏赞助
sponsor

感谢您的支持让我们更好的前行

分享

QRcode

https://www.webkt.com/article/8789