k折交叉验证不适用于时间序列数据,以及
您可以用来替代的技术。
时间序列预测的目标是对未来做出准确的预测。
在机器学习中,我们所依赖的快速而强大的方法,例如使用训练-测试集分割和k折交叉验证,不适用于时间序列数据。这是因为它们忽略了问题中固有的时间成分。
在本教程中,您将学习如何使用Python评估时间序列数据上的机器学习模型。在时间序列预测领域,这被称为回测或后测。
完成本教程后,您将了解:
- 传统机器学习模型评估方法的局限性以及为什么需要对样本外数据进行模型评估。
- 如何在Python中创建时间序列数据的训练-测试集分割和多重训练-测试集分割,以进行模型评估。
- 步进式验证如何为时间序列数据上的机器学习模型提供最真实的评估。
通过我的新书《使用Python进行时间序列预测》**启动您的项目**,其中包括**分步教程**和**所有示例的Python源代码**文件。
让我们开始吧。
- 2019 年 4 月更新:更新了数据集链接。
- **2019年8月更新**:修复了步进式验证中使用的模型数量的一个小错字(感谢Eliav)。
- 2019年8月更新:更新了数据加载以使用新的API。

如何为时间序列预测回测机器学习模型
图片来自Nasa,保留部分权利。
模型评估
我们如何知道给定模型的好坏?
我们可以用用于训练它的数据来评估它。这将是无效的。它可能会提供对所选模型如何工作甚至如何改进的见解。但是,对这些数据的任何性能估计都将是乐观的,并且基于此性能做出的任何决策都将是有偏见的。
为什么?
把它推向极端是有帮助的
一个能记住每个观测的时间戳和值的模型
将实现完美的性能。
我们准备的所有真实模型都将报告这一结果的苍白版本。
在评估时间序列预测模型时,我们关注的是模型在未用于训练它的数据上的性能。在机器学习中,我们称之为未见过或样本外数据。
我们可以通过分割我们已有的数据来实现这一点。我们使用一部分数据来准备模型,并保留一部分数据,要求模型对该时期进行预测。对这些预测的评估将很好地近似模型在实际使用时的表现。
在应用机器学习中,我们通常将数据分为训练集和测试集:训练集用于准备模型,测试集用于评估模型。我们甚至可以使用k折交叉验证,它通过系统地将数据分成k组来重复此过程,每组都有机会成为保留模型。
这些方法不能直接用于时间序列数据。
这是因为它们假定观测值之间没有关系,每个观测值都是独立的。
这不适用于时间序列数据,因为观测值的时间维度意味着我们不能随机将它们分组。相反,我们必须将数据分割并尊重值被观测到的时间顺序。
在时间序列预测中,对历史数据上的模型评估称为回测。在某些时间序列领域,例如气象学,这被称为后测,而不是预测。
我们将介绍三种不同的方法,您可以用来回测时间序列问题上的机器学习模型。它们是:
- **训练-测试集分割**,它尊重观测值的时间顺序。
- **多重训练-测试集分割**,它尊重观测值的时间顺序。
- **步进式验证**,在每次接收到新数据时模型都可以更新。
首先,让我们看看一个小的单变量时间序列数据,我们将用它作为理解这三种回测方法的背景:太阳黑子数据集。
停止以**慢速**学习时间序列预测!
参加我的免费7天电子邮件课程,了解如何入门(附带示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
月太阳黑子数据集
该数据集描述了 230 多年(1749-1983 年)每月观测到的太阳黑子数量。
单位是计数,有2,820个观测值。数据集的来源被认为是Andrews & Herzberg (1985)。
以下是数据的前 5 行样本,包括标题行。
1 2 3 4 5 6 |
"月份","太阳黑子数" "1749-01",58.0 "1749-02",62.6 "1749-03",70.0 "1749-04",55.7 "1749-05",85.0 |
以下是整个数据集的图。

月太阳黑子数据集
该数据集显示出季节性,不同季节之间存在较大差异。
下载数据集并将其保存到当前工作目录中,文件名为“*sunspots.csv*”。
加载太阳黑子数据集
我们可以使用Pandas加载太阳黑子数据集。
1 2 3 4 5 6 7 |
# 加载太阳黑子数据 from pandas import read_csv from matplotlib import pyplot series = read_csv('sunspots.csv', header=0, index_col=0) print(series.head()) series.plot() pyplot.show() |
运行示例将打印数据的前5行。
1 2 3 4 5 6 7 |
月份 1749-01-01 00:00:00 58.0 1749-02-01 00:00:00 62.6 1749-03-01 00:00:00 70.0 1749-04-01 00:00:00 55.7 1749-05-01 00:00:00 85.0 名称:太阳黑子,数据类型:float64 |
数据集也已绘制。

太阳黑子数据集图
训练-测试集分割
您可以将数据集分成训练和测试子集。
您的模型可以在训练数据集上准备,并对测试数据集进行预测和评估。
这可以通过在观测值的有序列表中选择一个任意分割点并创建两个新数据集来完成。根据您可用数据的数量和所需数据的数量,您可以使用50-50、70-30和90-10的分割。
在Python中分割数据很简单。
将数据集作为Pandas Series加载后,我们可以提取数据值的NumPy数组。分割点可以计算为数组中的特定索引。所有达到分割点的记录都作为训练数据集,所有从分割点到观测值列表末尾的记录都作为测试集。
下面是使用66-34分割的Python示例。
1 2 3 4 5 6 7 8 |
from pandas import read_csv series = read_csv('sunspots.csv', header=0, index_col=0) X = series.values train_size = int(len(X) * 0.66) train, test = X[0:train_size], X[train_size:len(X)] print('观测值: %d' % (len(X))) print('训练观测值: %d' % (len(train))) print('测试观测值: %d' % (len(test))) |
运行示例将打印加载数据集的大小以及从分割创建的训练集和测试集的大小。
1 2 3 |
观测值:2820 训练观测值:1861 测试观测值:959 |
我们可以通过使用不同颜色绘制训练集和测试集来实现视觉化。
1 2 3 4 5 6 7 8 9 10 11 12 |
from pandas import read_csv from matplotlib import pyplot series = read_csv('sunspots.csv', header=0, index_col=0) X = series.values train_size = int(len(X) * 0.66) train, test = X[0:train_size], X[train_size:len(X)] print('观测值: %d' % (len(X))) print('训练观测值: %d' % (len(train))) print('测试观测值: %d' % (len(test))) pyplot.plot(train) pyplot.plot([None for i in train] + [x for x intest]) pyplot.show() |
运行示例会将训练数据集绘制为蓝色,测试数据集绘制为绿色。

太阳黑子数据集训练-测试集分割
使用训练-测试集分割方法评估机器学习模型是快速的。数据准备简单直观,并且只创建一个模型进行评估。
当您拥有大量数据时,它非常有用,这样训练集和测试集都能代表原始问题。
接下来,我们将探讨多次重复此过程。
多重训练-测试集分割
我们可以多次重复将时间序列分割成训练集和测试集的过程。
这将需要训练和评估多个模型,但是这种额外的计算开销将提供对所选方法和配置在未见数据上预期性能的更可靠估计。
我们可以通过使用不同的分割点重复上一节中描述的过程来手动完成此操作。
另外,scikit-learn库通过*TimeSeriesSplit*对象为我们提供了此功能。
您必须指定要创建的分割数量,并且*TimeSeriesSplit*将返回每个请求分割的训练和测试观测值的索引。
每次分割迭代(*i*)的总训练和测试观测值计算如下:
1 2 |
training_size = i * n_samples / (n_splits + 1) + n_samples % (n_splits + 1) test_size = n_samples / (n_splits + 1) |
其中*n_samples*是观测值的总数,*n_splits*是分割的总数。
我们通过一个例子来具体说明这一点。假设我们有100个观测值,并且我们想要创建2个分割。
对于第一次分割,训练和测试大小将计算如下:
1 2 3 4 5 6 7 |
train = i * n_samples / (n_splits + 1) + n_samples % (n_splits + 1) train = 1 * 100 / (2 + 1) + 100 % (2 + 1) train = 33.3 或 33 test = n_samples / (n_splits + 1) test = 100 / (2 + 1) test = 33.3 或 33 |
或者前33条记录用于训练,接下来的33条记录用于测试。
第二次分割计算如下:
1 2 3 4 5 6 7 |
train = i * n_samples / (n_splits + 1) + n_samples % (n_splits + 1) train = 2 * 100 / (2 + 1) + 100 % (2 + 1) train = 66.6 或 67 test = n_samples / (n_splits + 1) test = 100 / (2 + 1) test = 33.3 或 33 |
或者,前67条记录用于训练,其余33条记录用于测试。
你可以看到测试集的大小保持一致。这意味着在每个训练模型的预测上计算的性能统计数据将保持一致,并且可以组合和比较。它提供了公平的比较。
不同的是每次分割用于训练模型的记录数量,提供了越来越大的历史数据可供使用。这可能会成为结果分析的一个有趣方面。另外,这也可以通过保持用于训练模型的观测值数量一致,并且每次分割只使用训练数据集中相同数量的最新(最后)观测值来训练模型(在这个人为的例子中是33个)来控制。
让我们看看如何将TimeSeriesSplit应用于我们的太阳黑子数据。
数据集有2,820个观测值。让我们为数据集创建3个分割。使用与上述相同的算术,我们期望创建以下训练和测试分割:
- **分割1**:705个训练,705个测试
- **分割2**:1,410个训练,705个测试
- **分割3**:2,115个训练,705个测试
与之前的示例一样,我们将使用不同的颜色绘制训练和测试观测值。在这种情况下,我们将有3个分割,因此将有3个单独的数据图。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from pandas import read_csv from sklearn.model_selection import TimeSeriesSplit from matplotlib import pyplot series = read_csv('sunspots.csv', header=0, index_col=0) X = series.values splits = TimeSeriesSplit(n_splits=3) pyplot.figure(1) index = 1 for train_index, test_index in splits.split(X): train = X[train_index] test = X[test_index] print('观测值: %d' % (len(train) + len(test))) print('训练观测值: %d' % (len(train))) print('测试观测值: %d' % (len(test))) pyplot.subplot(310 + index) pyplot.plot(train) pyplot.plot([None for i in train] + [x for x intest]) index += 1 pyplot.show() |
运行示例将打印每个分割的训练集和测试集的数量和大小。
我们可以看到,每个分割中训练集和测试集中的观测值数量与使用上述简单算术计算出的预期值相符。
1 2 3 4 5 6 7 8 9 |
观测值:1410 训练观测值:705 测试观测值:705 观测值:2115 训练观测值:1410 测试观测值:705 观测值:2820 训练观测值:2115 测试观测值:705 |
该图还显示了3个分割以及每个后续图中不断增长的总观测值数量。

太阳黑子数据集多重训练-测试集分割
使用多个训练-测试集分割将导致训练更多模型,从而更准确地估计模型在未见数据上的性能。
训练-测试集分割方法的一个局限性是,训练好的模型在测试集中的每次评估中都保持不变。
这可能不切实际,因为模型可以随着新的每日或每月观测值的可用而重新训练。这个问题将在下一节中解决。
步进式验证
在实践中,我们很可能会在有新数据可用时重新训练模型。
这将使模型在每个时间步都有最好的机会做出良好的预测。我们可以根据这个假设评估我们的机器学习模型。
需要做出几个决定:
1. **最小观测值数量**。首先,我们必须选择训练模型所需的最小观测值数量。如果使用滑动窗口(见下一点),这可以被认为是窗口宽度。
2. **滑动或扩展窗口**。接下来,我们需要决定模型是将在所有可用数据上训练,还是仅在最近的观测值上训练。这决定了将使用滑动窗口还是扩展窗口。
在为您的测试设置选择合适的配置后,可以训练和评估模型。
- 从时间序列的开头开始,窗口中的最小样本数用于训练模型。
- 模型对下一个时间步进行预测。
- 预测被存储或与已知值进行评估。
- 窗口扩展以包含已知值,并重复该过程(转到步骤1)。
由于这种方法涉及一次一个时间步地沿着时间序列移动,因此通常被称为步进式测试(Walk Forward Testing)或步进式验证(Walk Forward Validation)。此外,由于使用滑动或扩展窗口来训练模型,因此该方法也称为滚动窗口分析(Rolling Window Analysis)或滚动预测(Rolling Forecast)。
此功能目前在scikit-learn中尚不可用,尽管您可以通过精心配置的TimeSeriesSplit来实现相同的效果。
下面是一个如何使用步进式验证方法将数据分割成训练集和测试集的示例。
1 2 3 4 5 6 7 8 9 |
from pandas import read_csv from matplotlib import pyplot series = read_csv('sunspots.csv', header=0, index_col=0) X = series.values n_train = 500 n_records = len(X) for i in range(n_train, n_records): train, test = X[0:i], X[i:i+1] print('训练集=%d, 测试集=%d' % (len(train), len(test))) |
运行示例只打印创建的训练集和测试集的大小。我们可以看到训练集在每个时间步都在扩展,而测试集固定为一个时间步。
循环中是您训练和评估模型的地方。
1 2 3 4 5 6 7 8 9 10 11 |
训练集=500,测试集=1 训练集=501,测试集=1 训练集=502,测试集=1 训练集=503,测试集=1 训练集=504,测试集=1 ... 训练集=2815,测试集=1 训练集=2816,测试集=1 训练集=2817,测试集=1 训练集=2818,测试集=1 训练集=2819,测试集=1 |
可以看到,创建了更多的模型。
这再次具有提供对所选建模方法和参数在实践中如何执行的更稳健估计的好处。这种改进的估计是以创建如此多模型的计算成本为代价的。
如果建模方法简单或数据集较小(如本例),这并不昂贵,但在大规模时可能会成为问题。在上述情况下,将创建和评估2,320(或2,820 – 500)个模型。
因此,需要仔细注意窗口宽度和窗口类型。可以调整这些参数,以便为您的项目设计一个计算成本显著降低的测试工具。
步进式验证是模型评估的黄金标准。它是时间序列领域的k折交叉验证,推荐用于您自己的项目。
进一步阅读
- sklearn.model_selection.TimeSeriesSplit API文档
- 时间序列模型的滚动窗口分析,了解更多关于滚动窗口的信息。
- 维基百科上的回测,了解更多关于回测的信息。
总结
在本教程中,您学习了如何使用 Python 对时间序列数据上的机器学习模型进行回测。
具体来说,你学到了:
- 关于评估模型在未见或样本外数据上的性能的重要性。
- 如何创建时间序列数据的训练-测试集分割,以及如何自动创建多个此类分割。
- 如何使用步进式验证为您的模型评估提供最真实的测试工具。
您对评估时间序列模型或本教程有任何疑问吗?
在下面的评论中提出你的问题,我会尽力回答。
Jason,
“进一步阅读”中的第二个链接应该指向mathworks.com而不是amathworks.com,后者找不到。
谢谢Michael,已修复!
非常感谢,简短而信息量大。
很高兴听到您觉得它有用。
对于步进式验证,在每次单次迭代后进行验证会消耗大量时间,而且每次迭代之间的结果也不会有太大差异。更好的方法是在每次迭代中增加h步,并以这种方式划分训练和测试数据。每次迭代的训练数据可以增加h步,测试数据也可以增加h步,而不是单个观测值。这只是我个人观点的一个建议。这里没有硬性规定。
嗨 Shreyak,
是的,那将是步进式验证的采样版本,一个子集。
如果我没理解错的话,这与 sklearn TimeSeriesSplit 对象中提供的多重训练-测试集分割非常相似。
嗨,Jason博士,
基于Shreyak简化WFV的想法,它要求您拥有一个共同的h步长因子,分别均匀地划分总观测值和最小训练样本。因此,将窗口宽度按共同因子扩展,同时在每次迭代中保持h步长的预测一致。
然而,这种方法的局限性在于,如果共同因子是1,甚至是2或3,并且您有大量的训练样本,它仍然会回退到传统的WFV,这很耗时。这就是TimeSeriesSplit对象发挥作用的地方——也就是说,拥有一组合理的分割,即使对于大型训练样本也具有相关性。
总之,可以通过扩展每个训练分割并重新训练模型,同时保持一致的测试分割来结合多重训练-测试分割方法和WFV技术。
贾森博士,您对此有何看法?
我的看法是,这很容易搞砸,初学者应该坚持简单的步进式验证。
听起来不错,只要一个人使用的方法对他们的问题有效。
谢谢!
你好Udeh,你能否补充更多关于你评论的参考文献?
当你说“Shreyak的想法”时,你指的是谁?
我的问题与步进式验证有关
假设一个时间序列预测模型用一组数据训练,并在time_range-1中通过测试集给出了良好的评估,模型生成了一个函数F1。对于time_range-2和另一组训练和测试数据,模型生成函数F2。类似地,对于time_range-N,模型生成函数FN。当不同的模型组合并实施时,如何根据局部模型的预测函数而不是所有时间范围模型的组合模型来预测结果,这可能会导致预测错误。
嗨 Saurabh,
抱歉,我不太理解你问题的最后一部分。你能否重新表述一下?
我正在阅读您关于时间序列的帖子。您是否有使用任何特定资源作为这些材料的参考?
主要是一些教科书 :)
嗨 Jason
非常感谢这篇深入的帖子。我的问题是:
我们应该使用哪种性能指标来选择模型?
例如,如果我在二元(1,0)分类问题中一次添加一个测试子集,准确率将是1或0。
在这种情况下,我应该如何选择模型?我应该使用其他指标吗?
我正在构建一个股票价格分类模型,其中1代表上涨,0代表下跌。我使用TimeSeriesSplit并将其划分为T(样本大小)-m(滚动窗口)+1。
非常感谢,我期待您的见解!
嗨 Ian,
这是一个特定于问题的问题。
也许样本外数据集上的分类准确率是您选择模型的好方法?
Jason,
非常感谢您的回复。
如果我们像您在步进式验证中演示的那样,每次向前走一步,这是否意味着测试数据集来自样本外?
希望这不会太具体化,再次提前感谢。
嗨 Ian,
步进式验证是一种估计模型在样本外数据上技能的方法。我们人为地制造样本外数据,并且随着我们“步进式”前进,每个时间步的一个样本外观测值都变为样本内。
只要每次收到新观测值时都执行步进式,我们就可以在操作中使用相同的模型。
这有道理吗?
感谢Jason提供的信息丰富的帖子!
如果时间序列非常长,例如10年的分钟值,那么训练将花费很长时间。据我理解,另一种方法是固定训练集的长度,例如2年,但只是移动它,如下所示:
分割1:第1+2年训练,第3年测试
分割2:第2+3年训练,第4年测试
…
分割8:第8+9年训练,第10年测试
这是正确和有效的吗?
对我来说听起来不错。
还要考虑旧数据对于拟合模型的价值。10年前的数据可能对今天没有预测性,当然这取决于具体问题。
那么这个分割代码呢?(8个分割)
嗯?它会怎么做?它的代码是什么?
分割数据集确实与数据集本身密切相关。
如果您需要Numpy数组入门帮助,也许可以从这里开始:
https://machinelearning.org.cn/index-slice-reshape-numpy-arrays-machine-learning-python/
那么我们应该使用哪种代码进行这种分割呢?
抱歉,我无法为您编写代码,您具体遇到了什么问题/错误?
感谢您的帖子,Jason。
我想问一下,如果我们有实施目的,我们将选择哪个模型。
实际上,例如,如果时间序列是3年的小时值,步进式可以这样应用:
分割1:第1年训练,第2年测试,我们将得到模型1,预测误差1
分割2:第1+2年训练,第3年测试,我们将得到模型2,预测误差2
那么我们应该选择哪个模型呢?
很好的问题。
选择最能代表您的应用程序所需性能/能力的模型。
Jason,
我想Marwa提到“模型”时,她指的是将相同的模型(如ARMA)应用于不同的数据(对应于扩展窗口)。
我认为步进式方法,就像k折交叉验证一样,会给出一系列指标,其平均值某种程度上对应于模型的真实技能。
我认为当评估这个平均值时,应该在整个数据集上训练模型(查看《使用R进行实用时间序列预测 - Shmueli》),就像使用K折交叉验证一样。
如果我错了,请纠正我。
此致
步进式验证将给出模型技能的平均估计。
步进式验证要求一部分数据用于拟合模型,一部分用于评估,并且随着我们“步进式”前进,用于评估的部分会逐步提供给训练。我们不会在整个训练数据集上进行训练,如果那样做并进行预测,我们将与什么进行比较以估计模型的技能呢?
嗨,Jason,
这里似乎有矛盾。问题是“如果我们要投入生产,应该选择哪个模型?”即要用于生产的模型。在您的文章:https://machinelearning.org.cn/train-final-machine-learning-model/中,您指出:“一旦我们获得了估计的技能,我们就完成了重采样方法。如果您使用训练-测试集分割,这意味着您可以丢弃分割的数据集和训练好的模型。它们已经完成了自己的使命,不再需要。这就是为什么我们倾向于在所有可用数据上训练最终模型。”
然而,这里您说:“选择最能代表您的应用程序所需性能/能力的模型。”
那么您建议我们如何将最终模型投入生产呢?除了在所有数据上重新训练模型之外,如何获得最终模型?
嗨 Katya...以下资源对于确定要在生产中使用的模型的最佳“性能”很重要
https://machinelearning.org.cn/model-prediction-versus-interpretation-in-machine-learning/
亲爱的 Jason,
非常感谢这篇深入的帖子。我的问题是:
如果我的时间序列是间断的(例如3月的两周和9月的两周),我应该如何划分数据集?
如果我将时间序列用作监督学习,它可能会导致一个样本包含3月和9月的数据。
这个问题困扰了我很久,我期待您的回复。
我没有一个好的答案。
也许尝试用0或nan填充缺失的时间。
也许尝试忽略缺失的块。
也许专注于以较低的尺度(按月)构建模型。
嘿Jason,你能评论一下Rob Hyndman的论文吗,该论文指出交叉验证实际上可以用于时间序列数据(https://robjhyndman.com/papers/cv-wp.pdf)?
作为后续问题,这段代码能在时间序列上下文中使用吗:https://machinelearning.org.cn/use-keras-deep-learning-models-scikit-learn-python/
提前感谢您的指导!
试试看吧。
我希望在我有空的时候能做到。
有没有办法存储模型拟合值,以便我们可以在每次迭代后更新模型,而不是完全重新创建一个新模型?
我的数据集有55,000个样本,我想运行5,000个测试集,但重新创建5,000个模型大约需要80个小时。谢谢。
是的,这里是如何保存模型的方法:
https://machinelearning.org.cn/save-arima-time-series-forecasting-model-python/
感谢您如此迅速的回复!假设我训练了一个模型,保存了它,在测试样本x1上运行它,然后迭代测试下一个测试样本x2。一旦我加载旧模型,我如何添加样本x1来更新模型,从而可能使其表现更好?
这样我就总是使用从0到n的训练集预测样本n+1,而不用总是为5000次迭代创建一个新模型。
您必须只在新数据上或新旧数据组合上拟合模型。
这可以通过使用新模型或更新现有模型来完成。
我没有ARIMA的例子,但我这里有LSTM的例子。
https://machinelearning.org.cn/update-lstm-networks-training-time-series-forecasting/
嗨,Jason
非常感谢您的这篇文章,我最近阅读了许多关于时间序列预测的博客文章,发现它信息量很大;尤其是关于时间序列特征工程的文章,以便可以用监督学习算法解决它。
现在,如果我有一个用于需求预测的时间序列数据,并且我对“日期”变量进行了大量的特征工程,以提取所有季节性,例如,日期、月份、星期几,如果那天是假日、季度、季节等。我还对目标变量进行了一些特征工程,以创建滞后特征、最小值、最大值、范围、平均值等。
我的问题是:我是否仍然需要使用回测/步进式验证?或者我可以使用简单的k折交叉验证,因为时间序列的顺序不再重要?
非常感谢。请继续做这项出色的工作。
Huzefa
这真的取决于您的数据。
在实践中,我确实建议在处理时间序列数据时使用步进式验证。这是确保您不会欺骗自己的好方法。
Jason,
感谢您的回复。是的,我同意您的看法。我意识到的另一件事是,我将滞后作为特征,如果在任何交叉验证折叠中使用了未来数据来预测过去,那么它将导致目标泄露!
祝好,
Huzefa
当然!
嗨 Jason
您的帖子真棒。我从阅读您的文章中学到了很多。如果您能帮我解决一个关于回测和将时间序列转换为监督学习的疑问,我将不胜感激。
我可以使用回测来确定将时间序列转换为监督学习的最佳滞后吗?
当然可以。
嗨,Jason,
非常感谢您的这篇帖子。
但是我有一个问题,可能看起来很愚蠢,但是……
这给了我现实(在训练集上)和我预测(在测试集上)的图形版本。但这并不是对我模型的评估……
我如何通过这些方法知道我的模型是好还是坏?
假设我想尝试一个ARIMA (5,2) 和一个ARIMA (6,3)。我如何选择最好的一个?我如何使用“步进式验证”评估每一个?
为了评估第一个模型,我可以计算每个分割的预测值和真实值之间的误差均值吗?
为了选择最佳模型,我可以比较这两个模型之间的均值吗?
这会是一个好的评估方法吗?
再次感谢您!
您可以将预测值与预期值进行比较,并计算误差分数。
这里有一些例子
https://machinelearning.org.cn/time-series-forecasting-performance-measures-with-python/
嗨,Jason,
我有一组从2000年到2015年的月度面板数据,我想预测未来的值。具体来说,我想通过使用固定窗口大小为5年的(汇总)滚动回归来预测提前一个月。 (我知道,面板数据有更好的替代方案,如带固定效应的回归,但在我的情况下,使用汇总OLS可以获得准确的预测。)回归模型如下所示:y_{i,t+1}= b0+ b1*x_{i,t} + b2*x2_{i,t} +… + x10_{i,t},其中t是当前月份,i是id。
此外,我通过动态模型选择在每一步中选择一个新模型。具体来说:
1. 取一个固定窗口大小为五年,并将其分成训练集和验证集。前58个月作为训练集,第59个月作为验证集。
2. 通过对训练集和验证集运行逐步回归进行模型选择,并以验证集的平均平方误差作为标准,选择解释变量或回归模型。
3. 取第60个月的数据和步骤2中的回归模型,对第61个月进行预测。
4. 返回步骤1,并将窗口向前滚动一个月。
我找不到任何关于在滚动回归的每一步中选择新的回归模型或新的解释变量的文献。您知道有什么相关的文献吗?
谢谢!
太棒了!
好问题。我一下子想不出好的来源,我会在应用统计书籍/论文中寻找,或者更有可能是在应用经济学著作中。
谢谢!
到目前为止,我还没有找到任何关于这种方法的资料,我查阅了几篇论文和书籍。我会继续寻找!:)
顺便问一下,这种方法对您来说有意义吗?
坚持住。
通常,没有一刀切的方法。你通常需要深入研究并尝试一些东西,看看什么适合问题/数据/项目。
如果我错了请纠正我,但在我看来,TimeSeriesSplit与步进式验证技术非常相似,除了(1)没有最小样本大小选项(或不一定是滑动窗口),以及(2)预测的范围更大。
PS. 非常感谢您的帖子!
它是一次性分割,而步进式验证则是从一个点开始到数据集末尾,在每个时间步进行分割。
这有帮助吗?
嗨,Jason,我不明白为什么TimeSeriesSplit要用如此“复杂”的公式来创建固定大小的测试集。我宁愿在第一次迭代时将其作为整个窗口的一部分,然后将该长度用于其余步骤。这正确吗?
是的,不错。你基本上描述了步进式验证的一种变体。
嗨,Jason,
我有一个关于时间序列步进式验证的疑问。假设我需要使用过去5年的数据(13年1月-17年12月)来预测未来3个月(18年1月-3月)。
原则上,我希望使用步进式验证,因为我想看看模型对未见数据的泛化能力。我会使用您的方法,即:
1) 设置最小观测值:12年1月-16年12月
2) 扩展测试窗口:整个2017年,这意味着在第一次迭代中,我将预测未来3个点(17年1月-3月),在下一次迭代中,17年1月成为训练集的一部分,我将预测17年2月-4月。我将对整个2017年进行此操作。
我的问题是,为什么每次添加1个数据点时都需要重新训练模型?为什么我不能假设我在ITR1之前训练的模型是最好的,然后只对接下来3个测试点进行评分呢?
我不能从步骤1中选择(比如说)前5个模型,计算它们所有测试样本(3个月窗口)的平均值,然后选择RMSE最小的模型吗?
急切等待您的回复!
你可以,但你离真实的观测值越远,模型技能就会变得越差。
这篇帖子会给你一些关于在不使用观测值作为输入的情况下进行多步预测的额外想法
https://machinelearning.org.cn/multi-step-time-series-forecasting/
嗨,Jason,
谢谢您的回复。
“你离真实观测值越远”是指我没有用真实数据重新训练我的模型吗?
我的意思是,预测的提前期越长——你预测的未来越远,结果就越不稳定/技能越差。
谢谢Jason。您确实做得非常出色。
谢谢。
嗨,Jason,
非常感谢您的帖子。我正在处理一个数千种产品的需求预测问题,我只有两年的销售数据。数据点单位可以是天,但目前我将其汇总成周。约60%的产品有很多零销售和一些爆发式销售周。其余产品在这些年中有更稳定的销售。我尝试了两种方法:
– 使用前4周的销售数据进行训练并预测下周的销售
– 使用第1年的销售数据预测下一整年的销售数据,模型不更新
我的问题
– 这些方法是否有任何理论错误?如果需要,我可以澄清更多事情
– 在这篇帖子中,您只谈论了一个时间序列。这能应用于我同时需要预测数千个时间序列的情况吗?
– 对于这类问题,哪种算法往往会给出最好的结果?像XGBoost这样的开箱即用算法能胜任吗?我浏览了一些论文,它们介绍了神经网络或贝叶斯方法等不同的方法,我还没有接触过。
谢谢。
这听起来是个很棒的问题。
我很乐意深入研究并提供一些建议,但这会占用我大量时间,我目前没有这个能力。我希望能尽快发布更多关于这个主题的帖子。
总的来说,我建议测试一系列建模方法和问题框架,以帮助您发现最适合您特定数据集的方法。
我渴望听到你的进展。
嗨 Jason
我是一名气象学家,目前正在处理时间序列验证问题。
我的同事们每天都进行预报,我希望评估他们的准确性。
我发现我们的预报和观测之间存在一些时间偏移。例如,我们认为明天早上5点会下雨。然而,雨在4点或6点发生。如果我们使用正常的验证方法,例如列联表,我们会得到一次漏报和一次虚警。然而,我认为这种评估方法在这种情况下是不合适的,因为4点和5点的天气状况并非独立,我们只是错过了这些数据的时间归属。您能给我一些关于如何评估这类时间序列数据的建议吗?
很好的问题。
我相信有很多关于天气预报验证的文献(我以前在这个领域工作过)。
这是一个很好的起点:
http://www.cawcr.gov.au/projects/verification/
嗨,Jason,
使用AIC进行预测是一种好方法吗?还是我应该在构建预测模型时使用交叉验证?
这真的取决于你的项目目标和你的具体数据。
如何在没有模型但只有两个序列y和yhat的情况下估计AIC和BIC?
你好,Chau……以下讨论可能对你感兴趣
https://stats.stackexchange.com/questions/509044/how-to-calculate-aic-and-bic
感谢您提供的信息系列。我可能需要重新阅读一遍,但如果您能纠正我,滑窗和回溯测试是否意味着相同的事情。从某种意义上说,您一次将窗口向前移动一步?
滑动窗口是指将时间序列构建为监督学习问题的一种方式。
回溯测试是对历史数据上的模型进行评估的通用术语。
尊敬的Jason博士,
对于那些在绘制来自网站 https://datamarket.com/data/set/22ti/zuerich-monthly-sunspot-numbers-1749-1983 的数据时遇到困难的人,以下内容在甚至使用Python之前可能有所帮助。
即使您从网站导入了文件作为CSV文件,问题在于电子表格底部有NaN值和多余的信息。这需要清理文件。否则,如果文件未清理,Python将产生错误消息。
.
(1) 将 sunspot.csv 文件用电子表格程序(例如MS Excel)打开
(2) 保留文件顶部的标题行。
(3) 滚动到数据文件的最末尾(向下2821行)。删除包含Nan和文本“Zuerich monthly sunspot numbers 1749-1983”的行。
(4) 将文件以CSV格式另存为 sunspot.csv
(3) 在Python中照常导入数据
从那时起一切都应该正常。
谢谢你,
悉尼的Anthony
我还在这里提供所有CSV格式的数据集
https://github.com/jbrownlee/Datasets
我想知道为什么来自 http://www.sidc.be/silso/datafiles 的每月太阳黑子数与
https://github.com/jbrownlee/Datasets/blob/master/monthly-sunspots.csv
的数据差异如此之大。
好问题,我不太确定具体原因。
我的数据源是帖子中链接的“数据市场”上的CSV文件。
你好 Jason,
您已成为机器学习的一站式网站。感谢您的所有努力!
我有点卡住了,想在这里验证我的方法,如果您能帮我的话。
我正在尝试使用多个时间序列预测股票市场指数:例如,除了目标指数本身之外的许多商品指数。这种方法是不是大错特错了?如果不是,您能否指点一个好的起点?我在这里真的非常卡住了。感谢您的想法。
谢谢。
这是我在这里回答的一个常见问题
https://machinelearning.org.cn/faq/single-faq/can-you-help-me-with-machine-learning-for-finance-or-the-stock-market
我之前评论的补充说明是,我正在尝试使用监督机器学习方法(例如随机森林或弹性网络)设计一个多时间序列问题。
嗨,Jason,
一如既往,谢谢。
请问我如何在“步进前向验证”方法循环中训练和评估我的模型?
在步进前向验证中,选择最小训练大小后,我创建了,例如:
训练范围到 len(records)
train, test = X_obs[0:i], X_obs[i:i+1]
# 拟合模型
history = model.fit(train_X, train_y, epochs=1000, batch_size=4192, validation_data= (test_X, test_y), verbose=0, shuffle=False)
# 评估模型
loss = model.evaluate(test_X, test_y, verbose=0)
print(loss)
model.save(‘lstm_model.h5’)
最后,我有10个不同的损失或验证分数。最后保存的模型是所有10个模型的平均值吗?我如何进行预测并计算平均模型的RMSE?
我仍在学习步进前向验证方法,如果您能指导我做正确的事情,我将不胜感激。
期待您的回复。
我建议在拟合模型时不要使用验证集。技能分数是根据步进前向验证循环中进行的预测计算的。
我使用了验证集,因为我想用modelcheckpoint监控验证损失值。因此,我将选择最佳模型,并查看它在新或独立测试集上的表现。
此外,我将使用该方法或方法进行超参数调整,以拟合最终模型,并将最终模型与modelcheckpoint中的模型进行比较。
你好,Jason,在这种情况下,我们如何在训练期间监控验证损失?以开发和诊断学习曲线。
这可能不是最好的监控指标。相反,也许可以跟踪预测误差。
那么,要检查我的模型是否过拟合,只需将训练误差与步进前向验证获得的误差进行比较就足够了吗?
好问题。
通常,您会希望检查测试集上的性能不会以牺牲训练集上的性能为代价。
有很多方法可以思考这个问题,这可能取决于您的具体问题/模型以及您如何构建问题。
嗨,Jason,
非常感谢您的帖子。您在“步进前向验证”部分说“在此情况下,将创建和评估2,820个模型。”这不是2,320个吗?因为我们使用了前500个观测值作为最小值。
谢谢。
是的。很棒的发现。
你好 Jason,
感谢这篇帖子。
问题是,在总共2320个模型中,应该选择哪个模型进行预测?
你需要一些指标来衡量和比较每个模型。这篇帖子中没有展示,但你可以在这里看到是如何做到的 https://machinelearning.org.cn/arima-for-time-series-forecasting-with-python/
AIC和BIC等指标就是例子。
嗨,Jason,
感谢这篇文章。我喜欢步进前向验证方法。我目前正在一个问题中使用相同的方法,有一个问题想和您讨论。
问:我们如何使用步进前向验证方法进行训练、验证和测试分割?我们通常将数据分成三部分,并保留一个单独的测试数据用于最终评估。如果我们使用宽度为w的窗口并将其向后滑动,我可以用它来调整超参数或最终验证分数。那测试分数和我们模型的泛化能力呢?
提前感谢!
好问题。
也许选择一个模型将进行预测的时期,不更新真实值,并且保留集可以用作模型调整的验证集?
Jason,
所以,我想知道如何将这些来自步进前向验证的折叠传递到 Python 管道中,或者作为 CV 对象传递到像 xgboost 这样的 sklearn 模型中。我以前使用过 GridSearchCV 来创建交叉验证折叠。我的工作项目有许多商店每周的销售数据。我正在创建一个模型,该模型将预测每个商店未来 4 周的销售额。目前,我最多有 80 周的数据。我打算从 52 周的最小训练量开始,并在接下来的 4 周进行测试。每个折叠将向前跳 4 周。在这里,n_train = 52,max_week = 80。我的代码和输出如下。非常感谢!
代码
for i in range(n_train, max_week)
if i % 4 == 0
train, test = df[(df.WeekCount_ID >= 1) & (df.WeekCount_ID i) & (df.WeekCount_ID <= i + 4)]
print('train=%d, test=%d' % (len(train), len(test)))
输出
train=3155, test=260
train=3415, test=260
train=3675, test=260
train=3935, test=260
train=4195, test=272
train=4467, test=282
train=4749, test=287
好问题。
我为时间序列编写了自己的验证和网格搜索过程,这也是我为了获得更多控制而提出的普遍建议。sklearn 工具不适合时间序列数据。
杰森,感谢您的快速回复。那么,对于正在同时学习所有这些(机器学习、时间序列、Python、SQL 等)且不确定如何编写自己的 Python 程序的人来说,您的这些自定义代码是否在您的任何书中都有介绍?如果没有,这是否是您可以分享或我可以在其他论坛上找到的内容?再次感谢。
我几乎在我提供的每一个时间序列示例中都给出了回溯测试自定义代码的示例。
我将在一两周内出版一本新书,其中包含许多此类示例。
嗨,Jason,
精彩教程!!!!!!!!
假设我有1-100期训练数据,我想预测101-120期。我应该预测101期的目标变量,然后将102期等作为输入数据集进行预测吗?
非常感谢
是的,如果真实观测值可用,你可以使用它,或者使用预测值作为输入。后者被称为递归模型。
https://machinelearning.org.cn/multi-step-time-series-forecasting/
说这是静态预测和动态预测之间的区别,即静态使用真实观测值进行预测,动态使用预测值进行进一步预测,这样对吗?
听起来合理。
嗨,Jason,
我可以问两个问题吗?
1. 如何在步进前向验证中应用早停法以选择每一步步进前向验证中的模型?
2. 我认为对于时间序列数据,我们可以将时间序列转换为监督学习问题。因此,每个样本都由过去的 timestep 数据作为输入和一个目标输出组成。现在每个样本都是独立的,在使用无状态 LSTM 进行训练时没有时间顺序。我们现在可以打乱所有样本,并像往常一样将数据拆分为训练集和验证集。如果我错了,请纠正我。
您可以在验证过程的每一步进行预测之前,对模型的拟合进行早停。
也许吧。这可能取决于您领域的具体情况。
谢谢你的回复。
如果模型是要预测分类问题。每一步的准确度将只有0或1,这不能用于基于验证的早停。
为什么不?
你的意思是我们可以像这样:如果10个epoch的准确率是1,那么就停止训练?但在这种情况下,如何比较两个在相同准确率=1的epoch中表现相同的模型呢?我的意思是,如果有很多样本用于验证,我可以通过Keras的检查点功能保存具有最高val_acc的最佳模型。
我不确定我是否理解。
时间序列的提前停止很难,但我认为这是可能的(乐于被证明是错误的)。需要仔细关注每一步中作为验证集使用的具体样本。
抱歉,我没有一个可行的例子。
嗨,Jason,
我是机器学习新手。我从理论上理解了机器学习主题。谈到实现情况,对我来说真的非常困难。通过您的网站,我做了一些实现工作。感谢您的帮助。
回到我的问题,
如何将机器学习二元分类概念应用于非平稳数据(例如:脑电图数据)?
目前,借助可用样本,我使用KV折交叉验证训练模型。
clf=ML-Classifcationmodel();
y_pred = cross_val_predict(clf,MyX,MyY,cv=10)
每次我都会得到相同的结果。
但如果我在训练前使用以下语法打乱样本,每次都会得到不同的结果。
from sklearn.utils import shuffle
mydataset = shuffle(df1)
在这些情况下如何找到最佳模型。
将交叉验证用于时间序列数据(无论是回归还是分类)都是无效的。
训练/测试数据必须以尊重时间顺序的方式进行划分,模型绝不能在未来的数据上进行训练,而只能在未来的数据上进行测试。
Rob Hyndman在这里发表了一篇论文,声称如果你的问题是一个纯粹的自回归问题(就像将机器学习问题构建为监督学习问题一样),那么在时间序列上使用K折交叉验证实际上是有效的,前提是模型产生的残差本身不相关。
论文可以在这里找到:https://pdfs.semanticscholar.org/b0a8/b26cb5c0836a159be7cbd574d93b265bc480.pdf
发现得好,谢谢。我得好好读读。
在这篇文章中,解释说时间序列问题可以重构为带有输入和输出的机器学习问题。在这种情况下,我们是否可以认为每一行都是一个独立的观测值,并使用交叉验证、嵌套交叉验证或任何其他方法进行超参数调整和验证?
差不多。问题在于,训练集中包含未来信息的行会使模型产生偏差。
亲爱的Jason,感谢您在这里的精彩工作,它对我帮助很大!我总是很高兴在我的搜索结果列表中看到machinelearningmastery.com。
一个问题
我想知道什么窗口大小最适合模型。
假设您的数据集有 2000 行,您开始使用 500 的窗口大小来拟合模型。这意味着我将得到 1500 个 RMSE 结果。
稍后在该循环中,我的窗口大小例如为 1200,我使用前 1200 个输入进行拟合,并且只得到 800 个 RMSE 结果。
比较两次运行的性能公平吗?
或者确保一个静态的“测试”长度会更好吗?
我有更多数据可用,但我想尽可能少地使用以获得高性能。
来自柏林的问候 😉
好问题。
我建议测试一系列窗口大小,以发现它对您特定数据集中的模型有何影响。
越大不一定越好。
抱歉回复,但我想我没明白重点;)。
一个更好的例子:一个拥有 10000 行的数据集,我们想知道哪个窗口大小表现最好。为了快速执行,我们只使用最后 N 个值来运行一些测试……
测试A)首先我们使用最后2000个数据点来测试不同的窗口大小(200,300,400)。我们第一次运行使用窗口大小200,我们在1:200上训练并在201:201+horizon上检查性能。我们收集每个“折叠&时间范围”的RMSE值,并继续一步一步(+1),直到我们达到索引>20004000。窗口大小越小(200),我剩下的数据就越多,如果窗口越大,例如1000,我测试的数据就越少。
我是否必须使用“固定”的测试区域长度才能获得可比较的结果,或者这里的经验法则是什么?
这真的让我很困惑,非常感谢……
模型在不同窗口大小(或您想改变的任何方案)上的评估应该在相同的样本外数据上进行。
我真的爱你,杰森 😉
一个解决方案是始终在例如索引1000处开始我的测试区域,并将拟合窗口扩展到过去。
1….[800:999]:wns200 >> 从1000到2000测试
1….[600:999]:wns400 >> 从1000到2000测试
你觉得怎么样?
你是最棒的,再次感谢……
当然,听起来不错。
嗨,Jason,
我非常感谢您的所有帖子;我从中学到了很多东西。
关于最后一个选项(即WFA方法),我希望能够非锚定窗口。我提出了以下列表推导方法
sliceListX = [arr[i: i + window] for i in range(len(arr) – (window-1))]
“window”是整数值。我已经成功地实现了非锚定窗口。但是,我无法插入另一个参数来控制窗口滚动数量,即能够移动窗口不仅一步,而是一步、两步或四步。我也在SO上发布了这个问题,因为我认为有一个解决方案会使许多其他人受益。
https://stackoverflow.com/questions/53797035/rolling-window-in-python-revisited-adding-window-rolling-quantity-as-a-paramet
有什么实现的想法吗?(不是直接要求代码)。
提前感谢,
抱歉,我不能提供好的即兴建议。
终于得到了一个可用的例子。你可以在上面的链接中查看锚定版本和非锚定版本。希望有所帮助!
干得好!
很棒的文章!帮了我大忙!
不过,我有一个问题。如果我使用sklearn的混洗分割函数,我的模型会受到强烈偏置,而且我觉得数据泄露发生了。
你能解释一下如何通过在时间点之前取训练集和在该时间点之后取测试集来防止这种情况吗?我没有完全理解其中的动态。
非常感谢!
我建议改用步进前向验证。
训练-测试分割,尊重观测的时间顺序。
然后只在训练数据集中进行训练洗牌,例如:np.random.shuffle(Train)
只在测试数据集中进行测试洗牌,例如:np.random.shuffle(Test)
这样可行吗?
听起来合理。
你好 Jason,感谢你精彩的文章。
我不确定我是否完全理解了步进前向验证的概念 :)
例如,我有一个包含3000行的时间序列数据集。我想进行步进前向验证。我从第500行开始,然后继续。最终,我将创建2500个模型,并获得相应的误差。
那么,我应该从这2500个模型中选择哪一个模型进行未来的预测呢?
谢谢!
您可能会或可能不会为每一步创建一个新模型。
您正在评估数据集中“模型创建策略”的平均效果,而不是某个特定模型。
一旦您选择了一种策略(例如模型类型和配置),您就可以在所有可用数据上进行拟合并开始进行预测。这称为创建最终模型,更多信息请参见
https://machinelearning.org.cn/train-final-machine-learning-model/
嗨,Jason,
我喜欢这个解释和提供的替代方案,但我对一件事很好奇。您将如何在时间序列数据中实现交叉验证方法,其中使用前一个时期的数据来预测未来(例如股票市场价格)?
步进前向验证将支持您所需的任何问题框架。
你好,很棒的帖子。我只有一个疑问。我们应该将时间序列数据分成训练集和测试集,然后进行所需的归一化吗?还是应该先归一化我们的序列,然后再进行分割?
这真的取决于问题的框架。
我必须设计一个测试框架,用于测试您期望使用模型的场景。
就像使用所有数据来拟合模型一样,您应该使用所有合理可用的数据来准备任何缩放,这适用于每个步进前向验证步骤。
感谢Jason您的工作。
当您使用滑动窗口的神经网络时,您在每个步骤都进行一次新的训练。以先前的神经网络权重作为新步骤的起点是否有意义,因为大部分训练样本可能相同?
如果是,您将如何在Python中实现?
此致。
您可以选择为每个窗口重新拟合,也可以不重新拟合。我通常不重新拟合。
我有很多例子,你可以从这里开始。
https://machinelearning.org.cn/start-here/#deep_learning_time_series
嗨,Jason,
感谢您这篇撰写精良且解释清晰的教程。如果您能回答我一个关于多次训练-测试分割的遗留问题,我将不胜感激。
所以据我理解,多次训练-测试分割是稍后为步进前向建模找到最佳窗口大小的好选择。您同意吗?
因为我们可以根据模型所拥有的观测值数量来检查性能……
谢谢!????
来自德国的问候
克里斯
是的,测试许多不同的输入窗口大小以查看哪种方法最适合您的特定数据集是个好主意。
酷!谢谢你的回复!:)
嗨,Jason,
感谢您的文章,对作为初学者的我帮助很大。我只是很好奇多重训练分割的公式,即分割训练集和测试集,为什么会形成那样的。如果您能告诉我从哪里获取更多信息,我将不胜感激。
谢谢!
此致。
你具体指的是什么?
我的意思是为什么公式是这样的:
training_size = i * n_samples / (n_splits + 1) + n_samples % (n_splits + 1)
test_size = n_samples / (n_splits + 1)
我可以在哪里找到它的推导过程吗?
谢谢您的回复。
也许可以查阅原始代码库?
明白了。非常感谢。
此致。
嗨,Jason,
感谢这篇精彩的教程。
您认为以不同方式进行多次训练-测试分割如何?
您在某个点将数据分割成训练集和测试集。
然后您使用bootstrap或“半”k折交叉验证,随机将训练集和测试集都分成k折,然后对k-1折训练集进行k次模型训练,并在k-1折测试集上评估模型。
您上面提出的多次训练-测试分割方法与此方法相比有哪些优势?
谢谢!!
Anat
通常,您不能将K折交叉验证用于时间序列数据。它会导致数据泄露。
但我并不是建议使用普通的k折交叉验证。我建议分别将训练集(过去的观测值)分成k折,并将测试集(在某个时间点之后的观测值)分成k折。这只是允许重复训练/评估过程k次以获得结果的显著性。
我想我明白了多次训练-测试分割的优势:它考虑了模型在不同时间窗口下的性能。我提出的解决方案没有……它只评估了模型在一个时间段内的性能。
嗨,Jason,
谢谢你的帖子。我计划对一年的时间序列数据使用监督学习方法(我有一家零售商的商店,周级别的销售信息)。你建议我如何处理?
谢谢,
阿迪亚
我建议遵循这个流程
https://machinelearning.org.cn/how-to-develop-a-skilful-time-series-forecasting-model/
这些教程将帮助您入门。
https://machinelearning.org.cn/start-here/#timeseries
如果我的模型不使用包含先前样本信息的特征,那么 k 折交叉验证如何“作弊”呢?如果任何折叠中的数据很可能在未来重复出现,那么为什么一个 10 折交叉验证中折叠 1 的测试结果(因此训练发生在折叠 2 到 10 上)是无效的呢?我能理解在 k 折交叉验证之前重新采样是有问题的(即消除了数据的时间性),但很难理解 k 折交叉验证不能应用于时间序列数据的说法——完全不能。您的断言总是正确的,还是取决于模型/特征?我很抱歉询问一些可能显而易见的事情。您的网站很棒,您的教学法也很到位。感谢所有帮助。
观测值按时间排序可能会导致问题,因为模型可能会访问它可能被要求预测的未来信息。
这有帮助吗?
我可以在高层次上理解它,并且从不考虑将 k 折交叉验证用于我的时间序列数据集/特征/模型配置。也就是说,随着我深入机器学习的兔子洞,我发现某些配置让我质疑这个断言。如果我不努力严格地向自己证明这一点,那么质疑它无疑会付出代价。
您能推荐一些专门解决时间/非时间数据问题并附带许多示例的书籍吗?请和谢谢。
并没有,对于文献而言,这有些不言自明(例如,使用关于未来的信息来预测未来是糟糕的消息)。
相反,或许可以搭建一个小型测试平台,使用线性模型并评估不同重采样方案下的技能。亲自证明数据泄露会导致模型性能的乐观评估。
更多关于数据泄露的信息在这里
https://machinelearning.org.cn/data-leakage-machine-learning/
我想我对数据类型有非常根本的误解。虽然我的一些数据是按时间采样的,但先前的样本并不能预测未来的结果。也就是说,我目前将数据视为“时间序列”数据,尽管不存在自相关。如果一组时间序列数据没有表现出自相关,那么在 k 折交叉验证中它仍然被认为是缺陷的吗?我希望我们之间有一个白板,这样你就可以在10秒内向我解释清楚。
如果数据是按顺序的(例如,按时间排序),那么 k 折交叉验证可能不是一个好主意。
你好,Jason,精彩的文章!
让我问您一个问题,我正在进行二元分类,以预测买入或卖出股票的最佳时机(-1代表卖出,1代表买入),所以我的目标假设这两个值。
我按照您说的做了,并在我的模型中实现了WFV,就像您做的那样,我取前500行进行训练,然后取接下来的进行测试,依此类推,直到序列结束。
在 for 循环的每次迭代中,我调用了 .fit() 函数,然后立即调用 .predict(),最后在每次迭代中保存了模型(希望在最后一次迭代中保存的模型具有正确的权重以完成任务),问题是:这个过程正确吗?我应该使用最后保存的模型来对新数据进行预测吗?
最后一件事,在每次迭代中,我将模型的测试准确度保存在一个列表中并计算其平均值,令人惊讶的是,模型获得了0.9362的平均准确度,我们能说这个模型能够预测新的传入数据吗?
提前感谢,来自巴西的问候!
一般来说,我不相信股市是可预测的。
https://machinelearning.org.cn/faq/single-faq/can-you-help-me-with-machine-learning-for-finance-or-the-stock-market
评估过程听起来不错。我建议在评估后,对所有可用数据拟合一个最终模型,然后进行预测。
这是一个不错的准确率,也许可以确认它在许多不同时间段(几十年)内都是可靠的。
谢谢你的回复,我会读你发的这篇文章。
假设我已经训练好了模型,它“准备好”投入使用了,所以我开始对新数据进行预测。例如:当市场在下午5点收盘时,我将获取最新的数据并输入到网络中,网络将预测-1或1。
1) 我应该每天用这些最新数据训练并保存模型吗?(我的意思是,如果这有助于保持性能并改进模型,那就值得!)
2) 假设模型已经做了10个预测(在训练/测试数据之外的数据),并且在我看来有些预测不正确,我应该修正预测并重新训练模型吗?处理这种情况最明智的方法是什么?
感谢您提供如此高质量的内容!
尝试重新训练并使用旧模型,然后比较结果,选择对您的数据集提供更好技能的策略。
也许使用一种朴素的方法,例如持久性作为您不信任实时模型时的备用方法?或者退回到前一天/周/月的模型?
事实上,我不会实时使用它。我将等待市场收盘,下载今天的价格,用模型进行预测,然后根据预测决定是做多还是做空。
“或许可以采用一种朴素的方法,例如当您不信任模型实时时,作为一种备用方法?或者回退到前一天/周/月的模型?” 我不理解这部分,这是第二个问题的答案吗?
简而言之,模型正在预测我第二天应该做什么。稍后我会尝试在这里发布一些预测的截图。再次感谢。
在运行 WFV 后,这是预测图:https://imgur.com/a/SUyOTzJ
如你所见,模型做出了一些错误的预测,你能帮我改进这个吗?你有什么建议?我正在考虑编辑我的目标并重新训练模型,希望那些有噪声的预测消失。
如果您正在使用神经网络,我这里有一些关于提高性能的建议。
https://machinelearning.org.cn/start-here/#better
我强烈推荐这个过程。
https://machinelearning.org.cn/how-to-develop-a-skilful-time-series-forecasting-model/
我明白了,如果你不是实时预测,你可以忽略我关于回退到另一个模型的评论。
是的,我正在使用 sklearn 的 MLPClassifier()。我也会尽快学习 RNN。感谢提供的链接!
你好 Jason,
在阅读了您几十篇关于时间序列的博客之后,我仍然有些困惑,这让我感到惊讶。
在我的案例中,我尝试使用LSTM进行单变量预测。
1. 我之前读过您的帖子“How to Convert a Time Series to a Supervised Learning Problem in Python”,并将数据集转换为几个序列进行监督学习。如果我想对我的模型应用回溯测试,我应该在原始数据上进行还是在转换后的序列上进行?
2. 在“多重训练-测试分割”部分,模型是否应该在最后一种情况(使用尽可能多的数据)中表现最好?
3. 将“时间序列转换为监督数据”与“步进前向验证”结合起来似乎有些模糊。根据我的理解,我应该首先使用监督学习数据训练我的LSTM模型,然后用每一份训练数据评估模型。
此致,
李
最简单的理解方式在这里
https://machinelearning.org.cn/start-here/#deep_learning_time_series
或者我的书。
或者一个完整的教程,比如这个
https://machinelearning.org.cn/how-to-develop-deep-learning-models-for-univariate-time-series-forecasting/
然而,
1. 回溯测试是在转换后的数据上进行的,例如,在缩放/差分等之后,将数据转换为监督学习问题。
2. 其目的是估计模型在新数据上进行预测时的性能,并通过与基线模型比较性能来确定其是否有能力。您选择的算法可能不会因为更多历史数据而表现更好。
3. 您可以选择在每一步之后更新模型,也可以不更新。我通常不更新,因为它计算成本太高了。
最后,LSTM在单变量时间序列预测方面表现糟糕。
https://machinelearning.org.cn/findings-comparing-classical-and-machine-learning-methods-for-time-series-forecasting/
请改用 SARIMA 或 ETS。
你好 Jason,
谢谢你的及时回复。
在我的案例中,我有一个非常长的时间序列,即一个庞大的数据集。它在我的双层LSTM中表现良好,数据量如此之大(希望它在实际操作中也能表现良好)。
我稍后会尝试其他方法。
此致,
李
太棒了!
打错了。
在问题2中:“with as much data as possible” -> “with as much training data as possible”
嘿,我想你在“步进前向验证”的最后一部分犯了一个小错误。
向我们展示如何应用模型(python 代码)之后,你说:“在上述情况下,将创建和评估 2,820 个模型。”,这是不正确的,很容易看出已经创建了 2320 个(2820 – 500)/[n_train:n_records] 模型。
此外,您在这里对一些直观的方法进行了令人满意的解释,这些方法用于替换经典机器学习中众所周知的“重采样方法”,以用于时间序列数据。
谢谢!
完全正确,谢谢!已修正。
你好 Jason,
在这里,当你说训练和测试时,你实际上是指训练和验证吗?因为交叉验证只在训练数据上进行,你将整个训练数据分成训练和验证。
提前感谢。
我指的是测试,但您也可以将验证用于相同的功能。
更多信息在这里
https://machinelearning.org.cn/difference-test-validation-datasets/
谢谢你,Jason。
所以如果我有一套模型,例如:线性回归、岭回归、Lasso等,并且我想评估每个模型的性能以选择我的最终模型,我可以这样做吗?
1- 将时间序列数据分为 80% 训练和 20% 测试
2- 对 80% 的训练数据进行步进前向验证
3- 对所有模型重复 (2)
4- 选择表现最好的模型,然后在 20% 的测试数据上进行评估?
提前感谢
听起来很棒!
谢谢Jason!您推荐嵌套交叉验证(内部实现步进前向验证)用于时间序列吗?
示例博客:https://towardsdatascience.com/time-series-nested-cross-validation-76adba623eb9
我通常不推荐任何技术,但如果你认为它适合你的问题,那就去做吧。
Brownlee 博士,
特别是在步进前向验证的情况下(但也可以用于多步预测),您能建议准备训练数据并将这些准备应用于测试集的基础方法吗?具体来说,我指的是异常值处理和归一化等准备工作。似乎您需要单独准备每个新的训练集,这在计算上可能非常昂贵。
谢谢,
乔丹
数据准备所需的系数(例如最小值/最大值)将来自初始训练集。
另一种方法是在每次步进前向之前使用所有可用观测值重新准备数据。
我一直在研究洪水预报任务,使用LSTMs/GRU甚至CNNs网络训练模型;我通常将数据分成三部分:训练集、验证集和测试集。模型总是过拟合。我尝试了许多方法来改进它,但都没有奏效。
然而,在我一次尝试改进模型时,我不小心随机分割了训练集和验证集,但测试集保留在未来;当我训练模型时,结果比以前更好,也没有过拟合,而且训练集和验证集都得到了同步改进,最后在测试集上进行评估时,我得到了与验证集一样好甚至更好的结果!
既然我做错了,为什么它会奏效?这是否表明某些时间段不相关,因此结果非常好而不是糟糕?我真的对结果感到困惑,因为我犯了一个错误。需要注意的是,在做错分割之前,数据已经是3D格式,这意味着观测值的顺序在批次中得到了保留。
这可能表明LSTM可能不合适,你可能把LSTM当成了MLP。
也许可以尝试一下MLP,然后比较结果?
使用时间序列分割
MPL模型 – 模型既不过拟合,也没有改进。训练和验证损失在每个epoch都波动,即上下起伏。
LSTM模型 – 与MLP情况相同。
混合模型(CONV-LSTM-DENSE) – 同样的情况。
随机分割
MPL模型 – 训练持续改进,验证也随之改善但有波动。模型过拟合。
LSTM模型 – 表现良好,训练和验证持续改进,验证损失有少量波动。验证性能在最后几个epoch下降,开始出现过拟合。
混合模型(CONV-LSTM-DENSE) – 模型表现非常好。训练和验证的损失持续下降。验证损失有一些波动。模型持续改进且不过拟合。
干得不错。
你是否在将时间序列数据集转换为监督学习之后,对训练集和测试集进行了洗牌?
嗨!如果我选择使用扩展窗口,我应该如何构建我的模型?我应该构建一个可以接受不同大小输入(如500,501,502…)的RNN,还是应该为序列的每个实例构建一个不同的模型?如果是这样,我如何比较这些模型?
好问题,我在这里详细介绍了这个问题。
https://machinelearning.org.cn/start-here/#deep_learning_time_series
嗨,当我使用滚动窗口时,我将如何准备我的测试集?
以同样的方式。一些训练集可能需要作为输入来预测测试集的前几个步骤。
将所有数据放在一起,转换它,然后分割它会更容易。
你好,Jason博士
我使用单向 LSTM RNN 构建了一个时间序列数据分类器(序列到标签分类)。起初,我使用“Holdout”方法将数据分为 70% 用于训练,30% 用于测试,结果良好(训练准确率 = 99%,测试准确率 = 98%)。然后我使用了 k 折交叉验证,这导致模型变弱(训练准确率 = 83%,测试准确率 = 83%),我意识到 k 折交叉验证不能用于时间序列数据,因为它会随机地将数据分成 k 次,这会影响它们的顺序。但是“Holdout”方法也随机分割数据,这也会影响数据的序列,但却给出了很好的结果。要知道我没有使用洗牌。
我搜索了很多,但没有找到这种差异的逻辑解释。
提前感谢您的帮助。
训练/测试分割和交叉验证不适用于序列数据!
您必须使用前向验证(如上所述)。
谢谢杰森博士
请解释一下 Holdout 方法的结果。
您具体指的是什么?您遇到了哪方面的问题?
我的问题是,我发现“Holdout”方法比上面提到的方法给出了更好的结果,即使它是一种交叉验证。
这是什么原因呢?
训练/测试分割和交叉验证与前向验证相比会更乐观。
交叉验证会随机打乱观测值,并给出预测过去(给定未来)的结果,这是一个糟糕的想法。
训练/测试分割更好,但可能无法充分测试模型。
非常感谢杰森博士
我搜索了很多,终于找到了一个逻辑解释。Holdout 方法(样本外 (OOS))随机分割数据,同时保留观测值的时间顺序。它能很好地处理实际时间序列。
https://www.researchgate.net/publication/322586715_A_Comparative_Study_of_Performance_Estimation_Methods_for_Time_Series_Forecasting
感谢分享。
Jason 博士您好
不客气。
杰森博士,我有一个简单的问题,在使用多重训练-测试分割方法时,我应该计算准确率的平均值吗?(例如,在 3 次分割的情况下,准确率 = (acc1 + acc2 + acc3)/3),还是我取最后一次分割的准确率?
提前感谢您的帮助。
是的。
非常感谢杰森博士
不客气。
谢谢。您能否写一篇关于时间序列中多步预测的文章?我对基本概念非常感兴趣……例如预测一年洗发水销量,一步预测和多步预测在前向验证中有什么区别?何时以及为何选择其中一种方法?
是的,有很多。您可以从这里开始
https://machinelearning.org.cn/faq/single-faq/how-do-you-use-lstms-for-multi-step-time-series-forecasting
使用线性模型非常容易,只需调用 forecast() 并指定所需的步数即可。
区别在于前向验证可以访问更多信息。
谢谢,我想我在这里有一些基本的连接问题:我阅读了您关于使用 SARIMA 以及指数平滑算法 (Holt Winters) 进行预测的帖子。
两者都包含一个根据月度值预测洗发水销量的示例。这两种算法/方法都属于您在这里描述的“4. 多输出策略”吗 https://machinelearning.org.cn/multi-step-time-series-forecasting/ ?从您的回答来看,我猜是,但不确定。
SARIMA 和指数平滑的两篇文章在其关于前向验证的部分中都提到了在交叉验证中进行多步预测的可能性。
我想知道这样做有什么好处/缺点?如何确定交叉验证中的步数(预测范围)?何时选择多步而不是单步前向验证?这应该反映我希望使用拟合模型进行预测的时间范围吗?
我有一个时间序列(4年的月度销售数据),我想预测接下来的12个月。目前我使用您关于指数平滑的帖子中描述的前向验证。它的预测范围是1个月。由于我想预测接下来的12个月,那么在交叉验证中将预测范围扩展到12个月会有益吗?
我希望我在这里遇到的各种信息连接问题已经说清楚了。您的博客对我非常有帮助。谢谢。
好问题。
是的,它们可以用于多输出模型,例如 model.forecast(steps=10)
是的,您可以将前向验证用于多步预测,您可以按步或跨所有步评估模型。
您预测数据集所需的步数,不多不少。预测未来越远,性能越差——预测未来很难!
是的。扩展到 12 个月,并按未来时间步或跨所有未来时间步或两者进行评估。
这有帮助吗?
是的,我想是这样。谢谢。
不客气。
嗨,我想知道我是否按月和年根据天气状况预测贷款预付款,这是否被视为时间序列?我的计划只是验证天气对贷款的影响
这听起来像时间序列。
嗨,Jason,
我有一个关于在有多个来源时分割时间序列数据的问题。在我的用例中,我有多个时间序列,我试图对它们使用相同的模型。例如,我正在为商店中某个部门的销售预测建模,并且我有每个部门的单独数据,我正在尝试创建一个中央模型,可以根据过去的销售情况预测任何给定部门的销售。我目前将此分为 70% 的部门作为训练序列,30% 作为测试序列。我认为本文中描述的等效方法是使用所有部门的前 70% 作为训练序列,所有部门的后 30% 作为测试序列。我计划尝试这两种方法,但我想知道您认为前者还是后者更可取?
谢谢!
听起来是个不错的开始。
这可能也会给你一些想法
https://machinelearning.org.cn/faq/single-faq/how-to-develop-forecast-models-for-multiple-sites
谢谢你!
嗨 Jason,
我有一个关于模型生命周期的问题。感谢本教程,我了解了如何使用 TimeSeriesSplit 对我的模型进行回溯测试。我通过创建一个 random_state=0 的 RandomForestClassifier 来进一步扩展这一点,以返回一致的结果。我循环保存基于准确性的最佳模型。然后我进行超参数调整并保存最佳模型。最后,当进行预测时,我会使用这个保存的模型,还是会实例化一个新的 RandomForestClassifier 而不带 random_state 来利用随机性的力量?如果选择后者,为什么我不选择经过超参数调整的最佳模型?
谢谢!
不,所有测试都用于找到模型/配置。这些模型被丢弃。然后,您使用最佳模型/配置在所有可用数据上拟合最终模型并开始进行预测。
我在这里解释了更多
https://machinelearning.org.cn/train-final-machine-learning-model/
哇,谢谢!只是为了确认:在训练/测试数据上拟合只是为了快速找出我们的机器学习算法是否适用于我们试图解决的问题。然后我们可以通过超参数调整来进一步找出模型的配置。最后,为了预测,我们使用从超参数调整中找到的那些配置设置一个新模型。
非常感谢。
是的,这就是这里概述的过程
https://machinelearning.org.cn/start-here/#process
嗨,Jason,
我有一个关于打乱训练数据的问题。从您的文章中,我完全理解并了解到(感谢您的分享),在分割时间序列数据之前打乱或应用交叉验证不是一个好主意。但是,如果在训练测试分割之后呢?在时间序列数据分割后,打乱训练集以避免序列偏差是否必要甚至可能是必不可少的?
提前感谢您的回答!
如果您分割数据,然后打乱训练集,那没问题——并且可能有助于无状态模型(如大多数机器学习模型)在滞后观测值上运行。
嗨,Jason,
我如何对季节性数据进行前向验证?我需要按季节迭代(春、夏、秋、冬)向前推进,每个季节包含数千行。
谢谢
大卫
没有区别。
在您期望使用的方案下测试模型。
你好 Jason,我想咨询一下,我正在写我的论文并应用时间序列。我有 20 年的月度历史数据,问题是我的数据已经分为训练和测试,我想使用前向验证,我如何应用它才能让它累积并重复这样做,例如如果我进行 10 次分割。
– Python 中用于分割、累积和进行前向验证的代码是什么样的?
– 我知道 WFV 只用于时间上的一个变量,或者可以在时间上有多个变量时同时评估它们,我如何在时间上有多个变量时应用 WFV,以及如何累积……
听起来是个很棒的项目。
博客上有很多前向验证的例子。也许可以找一个并将其应用于您的项目。
是的,它适用于多变量输出和多步输出。所有情况。
嗨,Jason!
感谢您的另一篇精彩帖子。
有些事情我完全不明白……
为什么我们不能把它变成经典的机器学习问题,其中每个样本输入都固定为 20 个时间戳(t-20 到 t0),响应(或目标)是下一个值(t1)或更晚(多步)?
当你这样分割数据时,你将能够使用 k 折吗?
如果模型基于未来样本学习并预测过去样本,则结果将是乐观且不可靠的。
很棒的教程!
我们如何在 R/Python 中打乱和代理时间序列数据。请为此制作一个教程。
在测试工具中打乱时间序列数据是无效的。
嗨,Jason!
关于洗牌问题,我不明白为什么要洗牌时间相关数据?那会让时间依赖性消失,对吧?
他们在这里这样做:https://tensorflowcn.cn/tutorials/structured_data/time_series
谢谢!
没错,这通常是一个糟糕的主意。
嗨,Jason!
感谢您的文章。我有一个关于前向验证采样版本的问题。假设我有一些时间序列数据,其中最新的可用数据条目(具有最新时间戳)对于测试数据上的预测更重要。有没有合理的方法来对再训练进行自动化超参数调整?🙁 我无法轻易地将训练数据分割以获取一些验证子集进行超参数调整。选择最新的数据作为验证数据可能会破坏模型性能。
谢谢!
通常,模型会捕捉这种关系,您可以通过将问题作为仅考虑最近滞后观测值的有监督学习问题来帮助解决。
https://machinelearning.org.cn/time-series-forecasting-supervised-learning/
关于使用前向验证进行网格搜索,请参阅此处
https://machinelearning.org.cn/how-to-grid-search-sarima-model-hyperparameters-for-time-series-forecasting-in-python/
嗨,Jason,
很棒的阅读。谢谢。
我想知道。我有一个集合中多个相关的单变量时间序列一个接一个,但每一行都有支持特征(关于手头时间序列的代理描述)。对于每个代理,我在行中生成了一些先前条目(7天)的滞后窗口,并且我还添加了诸如每天的均值和标准差成对值等统计数据,以便为模型提供更多属性进行处理。
既然我基本上将时间序列中的每个条目都变成了带有先前数据的一些“块”,那么 k 折交叉验证现在是一种正确的方法吗?
我读过不少论文通过时间窗的 MFCC 生成语音的时间块,然后使用 10 折交叉验证,我想我在我的系列中也做了类似的事情,因为每个数据对象现在也描述了一些先前的步骤,以便对步骤 n 的数值输出进行回归。
我的问题是,经过这种滞后窗口和统计转换后,k 折现在是否是线性回归或神经网络模型将此数据作为输入的可接受的验证方法?
谢谢,
乔丹
谢谢!
你比我更了解你的数据。
一般来说,不,如果你在未来进行训练并预测过去,那么测试是无效的。
嗨,Jason,
谢谢!一如既往的精彩解释。
我有一个关于通过跳过训练和测试之间的一些数据进行时间序列预测的问题。
因为例如今天我有兴趣预测 2 周(每天),但从 4 周后开始。(跳过接下来的 4 周)
为了交叉验证我的模型,我不能简单地这样创建我的折叠
折叠 1:训练第 1 周到第 10 周,预测第 11、12 周
折叠 2:训练第 1 周到第 11 周,预测第 12、13 周
依此类推……
这种分割无法给我模型性能的 ধারণা。所以我将我的折叠创建如下
折叠 1:训练第 1 周到第 10 周,跳过 11、12、13、14 周,预测第 15、16 周
折叠 2:训练第 1 周到第 11 周,跳过 12、13、14、15 周,预测第 16、17 周
依此类推……
这样交叉验证模型是否正确,或者您建议其他方法?
提前感谢
很好的问题。
您必须在您期望使用模型的条件下测试模型——无论情况如何。
清晰的答案。谢谢! 🙂
不客气。
“使用交叉验证进行时间序列数据、回归或分类是无效的。训练/测试数据必须以某种方式分割……”
在时间序列分类的情况下,我很难理解您的引述。我同意该引述可以应用于回归,但我看不出它如何应用于分类。我理解特征值取决于之前的观测值(时间顺序),但归根结底,分类不就是获取不同的特征值并将其分类/分割到桶中吗?因此,我们可以忽略数据的时间方面并随机分割我们的训练/测试集。
简单的二元例子来说明
特征1 目标变量
第1天:1 1
第2天:2 0
第3天:3 1
第4天:4 0
…
我们可以看到“target_variable”在偶数时为0,奇数时为1。特征数据按时间顺序排列,每个特征观测值都依赖于前一个观测值(+1)。但模型仍然应该能够识别这种模式并正确分类。所以我们是否需要为时间序列问题进行 TimeSeriesSplit 应该完全取决于我们试图解决的问题?谢谢。
如果您在未来的示例上进行训练,您的模型将是无效/乐观的,无论回归或分类。
我无法充分感谢您的精彩文章,但我为您祈祷一切顺利,上帝保佑您,布朗利博士。
谢谢!
嘿 Jason,感谢你的精彩帖子。
我想更好地理解前向验证和滑动窗口方法。您有将两者结合的资源吗?具体来说,您有关于多变量数据的示例吗?
谢谢,非常感谢您的工作!
是的,也许从这里开始
https://machinelearning.org.cn/multivariate-time-series-forecasting-lstms-keras/
嗨 Jason,您有关于前向验证方法优于其他时间序列验证方法的引用或参考文献吗?
所以,我在一些实验中使用了 LSTM,但很难解释,因为训练/验证和测试阶段(分割子集)之间存在明显的区别
抱歉,手头没有。任何关于时间序列的教科书都可以。
https://machinelearning.org.cn/books-on-time-series-forecasting-with-r/
你好 Jason。感谢你的文章。
我有一个问题,只是想知道我是否理解了何时使用滑动窗口和回溯测试。
回溯测试用于评估哪个模型最适合进行预测,而滑动窗口只是一种为最终预测准备数据的方法吗?
换句话说,对于一组数据,我首先使用不同的模型进行回溯测试,然后我将使用滑动窗口的最佳模型进行最终预测,对吗?
谢谢你。
差不多。
滑动窗口是我们为建模准备数据的方式,无论我们是测试还是使用模型。
回溯测试是我们评估模型的方式。
亲爱的 Jason,
非常感谢本教程,它对我的项目帮助很大。
我有一些关于多重训练分割和前向验证的问题。
首先,我使用了多重训练分割(在 python 中使用 TimeSeriesSplit,n_splits = 10),但我注意到前几次分割表现很差,我猜是因为早期分割中的训练数据量太小。这是否影响了模型性能的评估?
其次,前向验证是否也适用于具有直接方法的多步预测,其中我的输出将是 n_output >= 2(我正在应用 MLP,因此 n_output 是我的输出节点),其中我将对 n_output = 2 执行以下操作
训练:500,测试 2
训练:502,测试 2
训练:504,测试 2
....
非常感谢您的回复,我期待您的回复
此致
我建议通常使用前向验证。
嗨,Jason,
也许我有点迟钝,但我有点难以理解这一切是如何结合在一起的。无论它是前向验证,还是时间测试-训练分割,数据是从哪里来的?
假设我有一个时间序列,例如“abc def ghi jkl mno pqr s”,窗口大小为 3,并且进行 1 步预测,我将其分割如下
训练:“abcdefghi”
验证:“jklm”
测试:“nopqrs”
并在窗口“abc”上训练它以预测“d”,在“bcd”上预测“e”,……在“fgh”上预测“i”
对于验证,我是否使用“ghi”来预测“j”,……直到“jkl”来预测“m”?还是只使用“jkl”来单独预测“m”?也就是说,我是否使用训练数据来预测验证数据中的值?
同样,为了测试模型,我是从使用“klm”预测“n”开始并一直持续到序列结束(“pqr”预测“s”),还是从窗口“nop”预测“q”开始?
使用前向验证,您将只有训练集和测试集,没有验证集。
嗨,Jason,
我明白了,谢谢。但我如何确保模型不会过度拟合测试数据呢?
确保测试数据集足够大且具有代表性——这将使您确信没有过拟合。
嗨,Jason,
感谢您的所有博文,它们对像我这样机器学习的新手非常有帮助。
然而,作为一个新手,我很容易感到困惑,所以请忍受我可能问的愚蠢问题。
我一直在关注您的“使用 Keras 中的 LSTM 进行多变量时间序列预测”教程,并尝试将前向验证技术应用于该示例。因此,我将该示例中使用的训练-测试分割替换为本文中显示的前向循环,然后将模型的训练和评估移到该前向循环中。
结果是,我现在有数百个模型,每个模型都有自己的 RMSE。
我的问题是,我应该从前向验证中创建的所有模型中选择 RMSE 最佳的模型,还是应该以某种方式聚合这些模型。
此致,
哈里森
不客气。
是的,对于在相同的前向验证和数据上评估的每个模型,选择具有最佳技能和最低复杂度的模型。
嗨,Jason,
感谢您一如既往的精彩教程!
我们能否同时使用验证集来在过拟合点停止训练,以及前向验证?
如果可能,请告诉我如何操作。
不客气。
可能不行。听起来并不合适。
嗨,首先,内容很棒,谢谢。
关于迭代中的特征优化,如果我们在一次迭代中执行任何类型的优化,我们会将其保留到下一次迭代吗?
例如,我在第一次迭代中包含所有特征,如果我从结果中得知其中一些特征的预测价值很小,我会将它们保留到下一次迭代吗?
如果您有关于特征优化主题最佳实践的其他参考资料,可以分享吗?
提前感谢。
抱歉,我不明白。您能否详细说明一下?
嗨,Jason,
我的担忧与从一个分割迭代到下一个分割迭代的特征优化有关。
假设,在 Split N 的训练之后,我发现一个或多个特征的预测价值很小,我决定在测试阶段将它们从模型中移除。我是否在 Split n+1、n+2、……(排除特征只是一个例子,这种担忧可以推广到任何特征工程)的后续迭代中将其排除?
或者我应该从零开始训练每个分割迭代,所有特征都可用,并丢弃在先前分割中执行的任何其他特征优化?
谢谢
只是添加反映我理解的步骤。
获取所有相关数据
将数据分成多块
对第一块数据(第一个样本内)运行优化以找到最佳参数
将这些参数应用于第二块数据(第一个样本外)
对下一个样本内数据运行优化以找到最佳参数
将这些参数应用于下一个样本外数据
重复直到覆盖所有数据块
整理所有样本外数据的性能
我认为最好先选择一个要优化的指标,然后定义一个测试工具来评估模型,然后尝试一系列数据预处理/模型/配置在测试工具上以优化您的指标。
不,一个处理/模型/配置在您的测试工具上以一致的方式进行评估。
感谢您精彩的帖子,Jason!
您是否有关于如何进行前向测试的有用帖子/链接(例如,使用一步预测来预测下一天、下一周、下个月?)
谢谢你,继续努力!
Kevin
是的,前向验证可以做到这一点。
是的,我知道如何使用前向验证进行回溯测试(例如,使用 80% 的数据作为训练集,20% 作为测试集,对测试数据进行一步预测)。但是,我想知道您是否有示例展示如何对新数据(不匹配测试数据)进行预测?
谢谢!
Kevin
代码是一样的。在所有可用数据上拟合模型并调用 predict()。
也许这个例子会有帮助
https://machinelearning.org.cn/make-sample-forecasts-arima-python/
嗨,Jason,
您关于将时间序列构建为监督学习问题以及这篇关于回溯测试机器学习模型的文章对我来说非常有启发性。
我最近开始学习机器学习,目前正在研究使用天气(温度、风速)和其他相关污染物(NOx、CO…)作为预测因子来预测 PM2.5 值。这是一个多变量时间序列数据集,具有每小时的频率。
我想将此数据构建为监督学习数据集。基于滑动窗口方法,我计划为每个变量添加许多滞后变量。对于预测,我想进行每小时预测。因此,我正在考虑在每个小时步长重新训练模型以进行下一次预测,类似于您描述前向验证的方式。
我对您的问题是,您是否认为这种方法有任何缺陷?我之所以问,是因为您说我们需要选择滑动窗口或扩展窗口,而我似乎两者都在使用,这让我感到困惑。
例如,
1. 我计划最初在每小时数据上训练(例如)2017 年 1 月 1 日,上午 12 点 - 2018 年 12 月 31 日,晚上 11 点,
2. 然后预测 2017 年 1 月 1 日上午 12 点。
3. 并将每个后续小时数据点纳入训练集,用于模型再训练和下一步预测。
谢谢。
不,听起来是个好方法。原型化并测试它,并与其他您可以想到的方法进行比较。这将有所帮助
https://machinelearning.org.cn/how-to-develop-a-skilful-time-series-forecasting-model/
谢谢,这很有帮助。
另外,一个稍微相关的问题,您认为在应用前向验证时,如何合理地处理时间序列数据中缺失的块?我有一些缺失的补丁,目前正在用均值填充,但不确定这种方法有多好。
好问题,这里有一些建议
https://machinelearning.org.cn/faq/single-faq/how-do-i-handle-discontiguous-time-series-data
谢谢你。
一如既往的精彩文章。关于下游流程、概率阈值和参数搜索的问题
假设我已经在我的数据上执行了前向验证,现在我有了所有验证集的预测数据集。
假设我有一个下游流程,根据“真实概率”值决定是否采取某些行动。
假设我创建了一个程序来搜索最佳的“真实概率”阈值。
我是否需要将我的时间序列数据分成“训练”和“验证”集,以进行最佳的“真实概率”参数搜索?我已经在原始训练集上进行了前向验证。我是否还需要在前向流程中进行前向验证以找到最佳概率阈值?
嗯。很难,事情变得复杂了。
阈值寻找过程不得知道已知值或未来已知值。这是一个好的开始(要求)。
也许您可以保持模型不变,用新数据向前推进并使用它来调整阈值?
这只是初步想法。我认为您可能需要仔细考虑并甚至原型化一些想法。
Jason,多变量时间序列数据集没有滑动窗口有什么问题吗?例如,我的数据集是每小时以下的建筑用电量(目标变量)与天气数据和一周中的时间虚拟变量相结合。我所做的是,对于每个时间步长(15 分钟),拟合整个模型,除了最后一行,这是我用于预测 kW 的测试。显然,在离线过程中,我正在遍历全年的数据,在每个时间步长拟合一个模型,并预测一步。比较建模的 kW 与实际值,RMSE 并不是太差。但我不认为这是滑动窗口……
不确定您将如何训练或验证模型。
嗨 Jason,前向验证足以验证模型吗?例如,模型将预测大约半年的每小时数据(约 3000 个预测,每个预测都拟合了一个新模型),我正在比较实际值与预测值的 RMSE。非常感谢任何提示 🙂
是的。
我在我的书和博客中大多数关于深度学习用于时间序列的例子中都使用了前向验证。
是否也可以使用统计模型(OLS 多元回归)来验证机器学习模型?如果可以,过程是什么?例如,我是否会使用相同的变量通过回归模型预测和机器学习模型预测运行两个独立的前向验证……然后比较统计模型和机器学习模型之间的前向验证 RMSE?好奇您是否认为这会浪费时间!谢谢 Jason!
您可以训练一个替代模型并比较性能。但这不会验证/使另一个模型无效,只是提供一个参考点。
是的,这是一个很好的主意。
糟糕,我想我没有正确评论您的上一条消息,但我本来是想评论您的
是的。
我在我的书和博客中大多数关于深度学习用于时间序列的例子中都使用了前向验证。
嗨 Jason。为了提高模型拟合速度,我们能否加载从先前数据集获得的权重来训练下一个批次?因为我认为每次训练模型并忽略先前的权重并不是最优的。至少我们可以使用先前的权重作为下一个模型的初始权重。
是的。另请参阅此内容
https://machinelearning.org.cn/update-neural-network-models-with-more-data/
嗨,Jason,
感谢您在机器学习方面的所有工作,这真的很有帮助。
我有一个关于前向循环中预测的问题。
假设我们像您一样分割数据,例如 train=2816,test=1(前向循环中只有一个步骤)
当测试集只有 1 时,您如何进行预测?
换句话说,model.predict 函数中的输入数据应该是什么?
当然,我可以使用训练集中最后 100(或 n)个观测值作为输入来预测下一个时间步,但我们不应该在未见过的数据上测试模型吗?
前向验证假设我们正在进行一步预测。如果您愿意,可以进行多步预测——博客上有很多这方面的示例。
谢谢,但这不是我的意思。我想做一步预测,但我关心的是我们传递给预测函数的输入数据——它不应该与训练数据不同吗?
通常,模型会将最后 n 个时间步作为输入来预测 t。
这不一定是这样,您可以以任何您想要的方式设计预测问题!
非常感谢你。
不客气。
嗨,Jason,
我想为多变量时间序列的预测构建一个持久性模型,类型为多并行输入和多步输出。老实说,尽管我根据 series_to_supervised 函数组织得非常好的数据,但我一直未能构建这种风格的模型。
您能给我一个示例或告诉我如何构建此模型吗(除了数据组织,因为我已经根据情况准备好了)。
谢谢您的关注,我正在等待您的答复。
是的,博客上有很多例子,也许可以从这里开始
https://machinelearning.org.cn/start-here/#deep_learning_time_series
你好,如果我的训练和测试 csv 文件不同,那么如何使用测试文件来预测时间序列值?
在训练集上拟合您的模型,并在测试集上进行预测,然后将预测值与预期值进行比较。
你好,Jason!
感谢您提供了大量的教程和精彩的文章!
我使用您的一些教程作为基础,构建了我自己的 CNN LSTM 模型进行时间序列预测。我的模型用于预测第二天酒精消耗量的增加或减少(分类模型),或第二天酒精消耗量的绝对值。
在设计模型时,我当然已经接触过“滑动窗口”或“扩展窗口”这些术语,现在我应用一个 21 天的窗口,步长为 1,进行预测——据我理解,这与回溯测试无关。
然而,不知何故,整个事情对我来说听起来与回溯测试非常相似,或者我错了吗?我不太确定之后是否需要为回溯测试(在更大的框架中)生成另一个窗口,然后将其应用于整个模型。那么模型中使用的窗口是否会简单地用于回溯测试的更大窗口中?例如,模型中使用 21 天的窗口,回溯测试中使用 500 天的窗口?
在我的模型中,我还使用了 90% 到 10% 的训练-验证分割,然后我需要训练分割的大小信息来定义 cnn 模型中的 input_shape。如果使用回溯测试,这些信息是否会以某种方式省略,或者是否必须在每次回溯测试窗口调整期间反复调整?
在我迄今为止阅读的所有关于回溯测试的教程中,他们只是创建了一个非常简单的模型,然后在一个 for 循环中反复拟合。然而,我的模型由不同的部分组成,我不知何故缺乏如何将整个模型纳入回溯测试框架的知识……不幸的是,在线帮助相当有限。您知道有使用 CNN-LSTM 模型进行回溯测试的教程吗?那将对我非常有帮助!
无论如何,非常感谢您已经给予我的巨大帮助 🙂
不客气。
滑动窗口是一种回溯测试。当它用于每个滑动的新数据时,它被称为前向验证。
不确定这是否回答了您的问题。
感谢您的快速回复!
但是 CNN 或 LSTM 不总是以某种方式使用窗口来遍历数据吗?
例如,在您的博客文章 https://machinelearning.org.cn/how-to-develop-rnn-models-for-human-activity-recognition-time-series-classification/ 中,您结合了 LSTM 和 CNN 模型。您写道:“注意,在拟合 LSTM 时,通常不打乱序列数据。这里我们在训练期间打乱输入数据的窗口(默认)。在这个问题中,我们有兴趣利用 LSTM 学习和提取窗口中时间步特征的能力,而不是跨窗口。”。
这个窗口和回溯测试有什么关系吗?据我理解,这只是训练模型的一种方法,而不是评估模型的方法。
是的,其中每个批次甚至整个训练集都是有序的样本(窗口)列表。
是的,我们使用前向验证来评估这种类型的模型。
再次感谢您的超快回复……很抱歉我反应迟钝,我只是觉得很难理解。
那些“有序的样本列表”与回溯测试无关吗?
不,样本有序的事实对于问题的定义以及我们训练/测试/评估模型的方式至关重要。如果我们训练未来并预测过去,模型是无效的。
亲爱的 Jason,
非常感谢这篇深入的文章。我想知道您是否可以详细阐述在分类任务中对深度学习模型在受试者层面(LOSOCV)使用留一法交叉验证(LOOCV)。例如,使用LOSOCV训练CNN-LSTM模型,根据受试者的脑电图数据(或任何其他时间序列数据)将其分类为健康对照组或痴呆症患者。
谢谢你。
拉胡尔。
什么是“LOSOCV”?
嗨,Jason,
我一直在阅读您的内容,尝试学习如何使用Python编程机器学习。这很有帮助。
我不确定这是否巧合,但我发现与我的原始数据相比,使用步进验证时,存在向右的偏移(原始数据用于训练,偏移的是测试数据)。
如果我将其向左移动,结果看起来非常准确,但我不确定这是否是预期的。您能分享您的见解吗?是不是因为它是一个“步进”所以“偏移”了?
好问题,请看这个
https://machinelearning.org.cn/faq/single-faq/why-is-my-forecasted-time-series-right-behind-the-actual-time-series
你好,杰森,感谢您在许多主题上提供的巨大帮助,
为了比较多个预测模型,我使用步进交叉验证和扩展窗口对20个不同的数据集进行,并记录平均误差(MAE或RMSE),然后创建箱线图。这些数据集属于不同的设备,我用它们来优化超参数。在测试方面,我有点困惑。我还有另一组20个数据集。使用相同的超参数,以相同的方式(再次进行包括训练和验证的交叉验证)对这些辅助数据集组进行测试并再次生成误差度量,或者使用其他方式,这样做是否好?
此致
一旦您确认了超参数,您就再次训练您的模型,并使用您的测试集来评估它,以了解它对新数据的作用。您不需要再次进行交叉验证。但可以将您的测试集用作模型良好的确认。
嗨,Jason,
假设您必须对时间序列中的缺失值进行插值,您会在训练集和测试集中以相同的方式进行回测吗?通常,对于测试机器学习模型,不应使用测试集数据进行插补,但我不确定这在插值时间序列数据时如何适用?
时间序列插补可以是插值,也可以是“回填”或“前向填充”之类的复制。这些方法没有需要校准的参数,因此在训练和测试数据中应该同样适用。然而,将缺失值填充为平均值,需要非常小心平均值的含义,并且通常不是时间序列的好方法。
谢谢阿德里安的回复。您会检查插值/其他插补方法对测试集的准确性吗?例如,在您有实际数据的时间段进行插值,看看它是否能给出好的结果,否则您可能会在测试集中引入错误数据,这会给时间序列模型带来误导性的验证?
我相信您需要检查您的特定数据集。通常无法说它是否准确。这样的决定通常需要证明其合理性。
补充一下这篇文章,现在sklearn提供了时间序列分割功能,您可以在这里找到它
https://scikit-learn.cn/stable/modules/generated/sklearn.model_selection.TimeSeriesSplit.html
你好 Jason,
杰森,我读你的文章两年了,它们帮了我很多。
我还想知道是否有包含滑动窗口示例的代码示例,因为我几个月来一直在努力开始这项工作。
感谢任何帮助和建议,谢谢。
嗨,塞尔……我强烈推荐以下资源以更好地理解
https://machinelearning.org.cn/introduction-to-time-series-forecasting-with-python/
嗨,Jason,
我不确定。如果我们不能基于步进验证来调整模型。训练-测试分割足以调整超参数并测试模型吗?忽略通常在ANN模型中使用的验证分割。
非常感谢您的所有内容,帮助很大。
谢谢J.Llop的反馈!我不确定我是否理解您的问题。您能澄清一下吗,以便我能更好地帮助您?
抱歉,我没有看到您的回复,又在其他问题上问了一遍。
我的意思是,我正在通过步进验证(WFV)调整LSTM的超参数。所以我已经将数据集分成了训练数据和测试数据。
因为根据我的理解,进行WFV不需要进行训练-验证-测试分割。我跳过了在训练和测试时间序列之间创建验证集,所以我通过WFV获得的测试结果是我最终用于与其他模型比较的结果。
但这对我来说很奇怪,因为它让我觉得模型可能会过拟合,而没有验证集的存在。
所以,只需进行带有训练-测试分割的WFV,并在其间进行参数网格搜索就足够了,还是有必要
-进行训练-验证-测试分割,
-使用训练-验证集进行WFV来调整参数
-使用训练-验证集进行WFV来测试模型
提前感谢您!
嗨,J.LLOP……以下内容将更清楚地说明如何避免过拟合。
https://machinelearning.org.cn/early-stopping-to-avoid-overtraining-neural-network-models/
嗨,詹姆斯,我复习了,但应用到时间序列预测时我遗漏了一些东西。
如果我们使用步进验证。我们能只使用这种技术通过训练-测试分割来调整超参数吗?
或者是否有必要在训练-验证集之间进行步进验证来调整超参数。然后用训练(之前的训练+验证)-测试分割之间的步进验证来测试结果。
您能否总结一下调整时间序列预测时训练-验证-测试分割的过程?
我查阅了您的一篇文章,关于调整LSTM,但其中只有训练-测试分割。
是否可以假定我们有另一个测试分割用于在超参数调整完成后测试结果?
问题是,在我的模型中,我进行训练-测试分割和步进验证,并在此分割上调整超参数。所以我得到的最终结果(rmse…)也是基于这个分割的,我没有任何保留数据,所以我不知道我是否会过拟合,或者这是步进验证避免的问题,因为它不同于常规的k折交叉验证技术。
非常感谢您的帮助
嗨,J.LLOP……以下文章很好地解释了步进验证的好处。虽然它确实有帮助,如以下所述,您应该始终对未见过的数据进行验证,以确保不会发生过拟合。
“通过使用步进验证方法,我们实际上减少了过拟合问题的可能性,因为它从不使用用于拟合模型参数的测试数据。同时,这种方法允许通过尽可能多地使用数据来拟合和测试模型,从而充分利用数据。然而,尽管步进验证最适合统计模型;对于机器学习,改进的估计以计算成本为代价,因为我们创建了如此多的模型。在大型数据集的情况下,这可能是一个规模问题。”
(摘自 https://sarit-maitra.medium.com/take-time-series-a-level-up-with-walk-forward-validation-217c33114f68#:~:text=By%20using%20Walk%20Forward%20Validation,and%20to%20test%20the%20models。2022年1月20日)
我之前已经回复过您,但一个简单的问题是
我买了“深度学习时间序列预测 – 杰森·布朗利”这本书,并按照V章(多步预测)构建了一个网格搜索框架。
步进验证是否能确保结果不会过拟合,或者我们是否需要运行其他测试来验证这一点?
提前感谢
嗨,Jason,
我对某些事情不确定。如果我们想基于步进验证来调整(超参数,例如LSTM)模型。一个训练-测试分割是否足以同时调整超参数和测试模型?忽略通常在ANN模型(基于交叉验证)中使用的验证分割。
我的意思是,我是否可以使用训练-测试分割并进行步进验证来测试模型,同时选择最佳模型,从而跳过验证集本身。
非常感谢您的所有内容,帮助很大。
您的评论正在等待审核。
嗨,Jason,
感谢您的博客文章提供的所有见解。确实非常有用。
我正在准备用于LSTM时间序列预测的数据,如下所示
1. 创建滑动窗口,为每个样本获取Tx(此处为32)个输入数据点。然后查看未来的时间步以获取标签。这很标准。我将滑动窗口向前移动一个时间步,以获取下一组输入/输出数据。
2. 然后我将X和y洗牌并分割,以获得训练集、验证集和测试集。
因此,训练集、验证集和测试集是随机从整个数据集中获取的窗口化样本的集合。但我担心在这样做时,由于窗口的“重叠”,信息会从验证集和测试集泄漏回训练数据。
问)如果到目前为止您都理解我的意思,您能告诉我是否会发生这种情况吗?
我认为您的建议是:给定60:20:20的百分比分割,将前60%的时间数据作为训练数据,接下来的20%作为验证数据,最近20%作为测试数据,然后从这些分割中生成三组滑动窗口样本。
问)您会在训练前洗牌准备好的训练数据吗?
问)虽然这种方法消除了泄漏,但它是否对非平稳数据(如股票收盘价)敏感?
嗨,奈杰尔……时间序列数据不应更改或洗牌,以保持LSTM能够确定的自相关属性。
嗨 James,
谢谢你的回复。
澄清一下,我是在洗牌之前创建有序时间步和标签的序列。也就是说,我的LSTM输入是[m, Ty, n],其中
m – 样本数量
Ty – 时间步数量
n – 特征数量
Ty是在洗牌之前从时间序列中“窗口化”的连续测量值。是样本m被洗牌然后分割成训练、验证和测试集。
尽管如此,我是否仍然不应该洗牌数据,而是按照它们从时间序列数据中获取的“顺序”将样本输入LSTM?
嗨 James,
谢谢你的回复。
澄清一下,我是在洗牌之前创建有序时间步和标签的序列。也就是说,我的LSTM输入是[m, Ty, n],其中
m – 样本数量
Ty – 时间步数量
n – 特征数量
Ty是在洗牌之前从时间序列中“窗口化”的连续测量值。是样本m被洗牌然后分割成训练、验证和测试集。
尽管如此,我是否仍然不应该洗牌数据,而是按照它们从时间序列数据中获取的“顺序”将样本输入LSTM?
你好 James
假设我将实现一个循环来管理回测,每次只测试一个实例,并且训练数据在每个步骤(分割多个样本)中增长
模型的训练/拟合(Keras中的序列模型)怎么样,我们是否应该保持拟合而不重新编译新模型等等……
嗨,里米蒂……以下内容可能有助于更新模型。
https://machinelearning.org.cn/update-neural-network-models-with-more-data/
你好,我阅读这篇文章有点晚了,但谢谢你。我正在尝试使用步进分析在多个时间序列模型中进行选择。一个模型在训练数据集中明显胜出,另一个模型在未训练数据集中明显胜出。我如何确定哪个更好?我是否还应该考虑每个阶段之间的变化和/或从训练性能到未训练性能的退化程度?感谢您的想法!
嗨,史蒂夫……您选择在训练期间从未见过的数据上表现最好的模型。这就是“验证数据集”。
我有点困惑,您能帮我理解多次训练测试分割和步进验证之间的基本区别吗?
嗨,瓦佐……以下内容可能对您有帮助
https://machinelearning.org.cn/train-test-split-for-evaluating-machine-learning-algorithms/
在10次迭代的交叉验证中,我们可以说10折交叉验证。10次迭代的步进验证如何?我们也可以说10折步进验证吗?
嗨,杰森,非常感谢你的这篇文章。真的!
那么,让我看看我是否理解正确。
1)这是关于验证您的模型,以便在检查测试集(我应该只评估几次)之前了解它是否过拟合,对吗?所以,假设我验证并选择了我的模型,我想在测试集中进行样本外预测。如果我在滚动训练窗口中运行了几个模型,predict()命令应该如何工作?它应该选择最新的训练模型系数(为了简单起见,我们考虑线性回归)?
或者2)我是否应该在测试集中重新拟合一个新模型以使用更近的数据,然后进行提前一步的预测?(假设我已经在训练集中验证时选择了模型类型/配置)。
2.1)最初我认为测试集永远不应该被拟合,但更多地考虑实际的未知数据
我将不得不在现实世界中进行预测,我想使用最近的数据来获取我的模型
系数。
提前非常感谢,
伊莎多拉
嗨,Jason,
我有以下设置
分类任务预测0,1
特征:时间序列
我想回测交易策略,因此将使用扩展窗口交叉验证(您称之为步进交叉验证)。
但是我希望为每个模型调整超参数,因为实际上我需要在生产中这样做,所以回测应该反映这一点。
因此,您能告诉我这种方法是否正确
在初始窗口上训练数据,使用连续的数据窗口作为验证来调整超参数。
选择最佳参数。
在训练+验证上重新训练数据,然后
将另一个连续窗口作为测试。
移动1个数据点并重新执行。
获取测试数据集的平均性能。
比如说t_1到t_1000是初始窗口。在此基础上进行训练,并尝试不同的超参数,检查哪个在验证数据t_1001到t_1051上表现最好。然后选择最佳超参数,在训练+验证上重新训练模型,并在t_1052到t_1053上进行测试。
下一个问题是关于生产(即最终模型)。
一旦我得到了算法能力的估计,我需要获得最终模型。
我是否应该将所有数据分割成训练集+验证集,例如训练t_1到t_5000,验证t_5001到t_5500。
使用验证集调整超参数,从而建立最佳最终模型。
然后结合所有数据并使用找到的超参数拟合模型。
你好,感谢您所做的出色工作。我想知道在使用步进验证时可视化学习曲线是否是一个好主意。我的想法是绘制每次分割中获得的损失与连续分割次数或序列变量的对比图。这将解释模型在通过分割前进时损失如何表现。这对您来说有意义吗?这可以用作学习曲线的替代方案吗?
嗨,大卫……非常欢迎!您的想法非常有趣。请分享您实施该想法的结果。
嗨,詹姆斯,这个扩展窗口是在创建滞后特征并将数据转换为平稳数据之后应用的吗?如果确实如此,那么您认为我们应该如何执行转换?因为在每次迭代中,新的观察值将添加到训练集和测试集中,而应用转换的标准规则是将其应用于训练集并在测试集上拟合。您建议我如何处理这个问题?谢谢!
嗨,帕特尔……在对时间序列预测的机器学习模型进行回测时,使用扩展窗口方法,操作顺序至关重要。扩展窗口方法涉及逐渐增加训练集的大小,同时在每次迭代中保持测试集不变。以下是您如何逐步处理转换过程的步骤:
### 带转换的扩展窗口回测分步指南
#### 1. **初始设置和数据准备**
– **数据分割**:将时间序列数据分割成初始训练集和测试集。测试集在整个回测过程中保持不变,而训练集则扩展。
– **创建滞后特征**:在进行任何转换之前,从原始时间序列数据中创建滞后特征以捕获时间依赖性。
#### 2. **扩展窗口回测过程**
– **初始化参数**:设置初始训练窗口大小和扩展窗口的步长。
#### 3. **迭代过程**
– 对于每次迭代
1. **定义训练集和测试集**
– **训练集**:使用一个扩展窗口,该窗口以初始大小开始,并随着每次迭代按步长增加。
– **测试集**:保持测试集静态,通常是训练集之后的下一个观测值或一小批观测值。
2. **训练集上的转换**
– **平稳性转换**:应用转换以使训练数据平稳。常见的转换包括差分、对数转换或去趋势。这些转换应在训练数据上拟合。
– **缩放**:仅在训练数据上拟合缩放器(例如,StandardScaler、MinMaxScaler)。
3. **测试集上的转换**
– **平稳性转换**:将与训练集上拟合的相同转换应用于测试集。确保您使用从训练集导出的参数(例如,差分阶数、趋势系数)。
– **缩放**:使用在训练数据上拟合的缩放器转换测试数据。
4. **模型训练和预测**
– 在转换后的训练集上训练模型。
– 在转换后的测试集上进行预测。
5. **逆转换**(如果需要)
– 对预测进行缩放逆转换。
– 对平稳性进行逆转换,以使预测回到原始尺度。
#### 4. **性能评估**
– **计算指标**:使用适当的指标(例如,RMSE、MAE)在数据的原始尺度上评估模型性能。
– **存储结果**:存储每次迭代的性能指标以供后续分析。
#### 示例代码实现
以下是使用Python和scikit-learn的简化示例
python
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
# 示例数据
data = pd.read_csv('time_series_data.csv')
values = data['value'].values
# 参数
initial_train_size = 100
test_size = 10
step_size = 1
# 指标容器
rmse_scores = []
# 扩展窗口回测
for start in range(0, len(values) - initial_train_size - test_size, step_size)
train = values[start:start + initial_train_size]
test = values[start + initial_train_size:start + initial_train_size + test_size]
# 创建滞后特征
X_train = np.array([train[i - 1] for i in range(1, len(train))]).reshape(-1, 1)
y_train = train[1:]
X_test = np.array([test[i - 1] for i in range(1, len(test))]).reshape(-1, 1)
y_test = test[1:]
# 转换:缩放
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 模型训练
model = LinearRegression()
model.fit(X_train_scaled, y_train)
# 预测
predictions = model.predict(X_test_scaled)
# 评估
rmse = np.sqrt(mean_squared_error(y_test, predictions))
rmse_scores.append(rmse)
# 扩展训练窗口
initial_train_size += step_size
# 打印RMSE分数
print(f'RMSE Scores: {rmse_scores}')
### 关键点
1. **一致的转换**:确保应用于测试集的转换与应用于训练集的一致。
2. **在训练集上拟合参数**:始终在训练集上拟合转换参数(例如,缩放器、差分系数),并将其应用于测试集以避免数据泄漏。
3. **处理平稳性**:转换训练集和测试集以解决平稳性问题,确保测试集转换使用从训练集导出的参数。
这种方法允许您迭代地扩展训练集,适当地转换数据,并有效地评估模型的性能,同时遵守时间序列预测的原则。
嗨,詹姆斯,我真诚地感谢您的快速回复!
当您说“如果需要,应用逆转换”时,我感到困惑?从您所说的话中,我理解我们可能会或可能不会应用逆缩放或转换。然而,如果我们应用,比如说,Box-Cox 转换使数据呈正态分布,然后使用 StandardScaler 进行缩放使数据范围在 0-1 之间,那么我们不是应该先应用逆缩放,然后逆 Box-Cox 转换,然后再进行预测吗?
我的最终目标是从上一个观测月份(例如,如果上个月是2024年7月,那么预测24年8月到25年1月)的数据中预测未来6个月的数据。原始数据是按日存储的。根据最终目标,我能够将每日交易数据聚合到每月,这就是为什么我的观测计数减少了。我正在使用 PySpark(Databricks)中的随机森林回归器。
– 我仍然想知道我是否需要将年份或月份作为预测变量?
– 或者我不需要它,因为我将使用滞后特征作为输入?
– 我还想知道,如果我进行多步预测,我可能会丢失12个观测值(X的前6个和y的后6个,根据您的博客 https://machinelearning.org.cn/time-series-forecasting-supervised-learning/ )。数据量对随机森林回归器来说会是一个问题吗?
– 或者您能推荐更好的模型选项来处理这种数据量吗?
我将真诚地等待您的回复!谢谢詹姆斯!
嗨,詹姆斯,我好奇在给定的代码中,上升分数会在每次迭代中计算吗?我还添加了MAPE。我添加了MultiOutputRegressor(GradientBoostingRegressor())来处理3个月的预测。我研究了泛化误差,据说平均RMSE和MAPE是个好主意。但是当我平均训练和测试数据时,我发现模型在训练数据上过拟合。您认为我走在正确的轨道上吗?如果是,我该如何处理这个问题?以下是结果,显示了接下来3个月的独立RMSE、MAPE及其平均值。如果您需要更多信息,请告诉我。
第19次迭代 – 训练RMSE:[ 79.10635548 199.71090814 159.09861804],平均RMSE:145.9719605517029,测试MAPE:[0.00439754 0.01162348 0.00868421],平均MAPE:0.008235078949234488 第19次迭代 – 测试RMSE:[ 7423.70498965 33761.78813525 38862.97125315],平均RMSE:26682.82145934941,测试MAPE:[0.33376017 0.40927479 0.69712543],平均MAPE:0.4800534645140906
我还想知道,如果度量指标是在每次迭代中计算的,我如何相信存储的最佳模型(具有最小平均RMSE和MAPE)是预测未来3个月数据的完美拟合?
我正在等待回复。我很乐意听取任何人的建议!