评估预测——验证策略
在最后几章中,我们探讨了时间序列预测中一些相关但鲜少讨论的方面。上一章我们学习了不同的预测指标,现在继续探讨最后一块拼图——验证策略。这是评估预测的另一个不可或缺的部分。
在本章中,我们尝试回答这个问题:如何选择验证策略来从时间序列预测的角度评估模型? 我们将研究不同的策略及其优缺点,以便在本章结束时,您能为自己的时间序列问题做出明智的决策,设置合适的验证策略。
本章涵盖以下主要主题:
- 模型验证
- 留出策略
- 交叉验证策略
- 选择验证策略
- 多时间序列数据集的验证策略
技术要求
你需要按照本书前言中的说明设置Anaconda环境,以获得包含本书代码所需的所有包和数据集的可用环境。
模型验证
在第19章《评估预测误差——预测指标综述》中,我们学习了可用于衡量预测质量的不同预测指标。其主要用途之一是衡量我们的预测在测试数据(新的未见数据)上的表现,但这发生在训练模型、调整和反复修改直到满意之后。我们如何知道正在训练或调整的模型是否足够好?
模型验证是使用数据评估训练模型以判断模型好坏的过程。我们使用在第19章《评估预测误差——预测指标综述》中学到的指标来计算预测的优良性。但还有一个问题我们未回答:我们使用数据的哪一部分进行评估?在标准的机器学习设置(分类或回归)中,我们随机抽取一部分训练数据作为验证数据,所有建模决策都基于这些数据。该领域的最佳实践是使用交叉验证。交叉验证是一种重采样过程,我们在多个迭代中抽取训练数据集的不同部分进行训练和测试。除了重复评估外,交叉验证还能最有效地利用数据。
然而,在时间序列预测领域,并不存在关于最佳实践的共识。这主要是由于时间序列的时间性质以及我们可以采用的各种方式的多样性。不同的时间序列可能有不同的历史长度,我们可能选择不同的建模方式,或者有不同的预测期,等等。由于数据中的时间依赖性,标准的 i.i.d. 假设不成立;因此像交叉验证这样的技术有其自身的复杂性。当随机选择时,验证数据集和训练数据集可能并不独立,这将导致错误估计过于乐观且具有误导性。
验证主要有两种范式:
- 样本内验证:顾名思义,模型在与训练数据相同或训练数据的子集上进行评估。
- 样本外验证:在该范式下,用于评估模型的数据与用于训练模型的数据没有交集。
样本内验证有助于你理解模型对现有数据的拟合程度。这在统计时代非常流行,当时模型精心设计,主要用于推断而非预测。在这种情况下,样本内误差展示了指定模型对数据的拟合程度,以及我们从该模型得出的推断的有效性。但在预测范式下(如大多数机器学习),样本内误差并不是衡量模型优良性的正确指标。复杂模型可以轻松拟合训练数据、记住它,并在新的未见数据上表现不佳。因此,当今的预测模型评估几乎只使用样本外验证。由于本书仅关注预测(这是一个预测任务),我们将只使用样本外评估。
如前所述,为预测问题决定验证策略并不像标准机器学习那样简单。这里主要有两个学派:
- 基于留出法的策略,这类策略尊重问题的时间完整性
- 基于交叉验证的策略,这类策略以无时间顺序或非常松散的顺序采样验证拆分
我们来讨论每类中的主要策略。需要记住的是,本书中讨论的所有验证策略并非详尽无遗,它们只是一些常用的方法。在随后的解释中,验证期的长度为Lv,训练期的长度为Lt。
现在,我们来看第一种思路。
留出策略
留出策略包含三个方面,它们可以混合搭配以产生该策略的多种变体。例如,我们可能采用固定分割的采样策略、训练数据的滚动窗口以及每次迭代重新校准模型。这三个方面如下:
- 采样策略:采样策略是从训练数据中采样验证拆分的方式。
- 窗口策略:窗口策略决定如何从训练数据中采样训练拆分的窗口。
- 校准策略:校准策略决定是否重新校准模型。
也就是说,为时间序列问题设计留出验证策略包括对这三个方面做出决策。
采样策略是在训练数据中选取一个或多个原点的方法。这些原点是确定验证拆分起点和训练拆分终点的时间点。验证拆分的具体长度由参数Lv控制,该参数是为验证选择的预测期。训练拆分的长度取决于窗口策略。
窗口策略
有两种方式可以划定训练集的窗口——扩展窗口和滚动窗口。图20.1展示了这两种设置的区别:

图20.1:扩展(左)与滚动(右)窗口策略
在扩展窗口策略下,训练集随起点向前移动而扩展。换句话说,在扩展窗口策略下,我们选择起点之前所有可用的数据作为训练集。这实际上使得每次起点向前移动时,训练长度都会增加。
在滚动窗口策略下,我们保持训练集的长度恒定(Lt)。因此,当我们将起点向前移动三个时间步时,训练集就会从时间序列的起始处丢弃三个时间步。
尽管扩展窗口和滚动窗口的概念可能让你联想到特征工程中使用的窗口或深度学习模型中用作上下文的窗口,但这里的窗口是不同的。本章讨论的窗口是我们选择用于训练模型的训练数据窗口。例如,机器学习模型的特征可能只延伸到前5天,但我们可以使用过去5年的数据作为训练集。
这两种窗口策略各有优缺点。让我们用几个要点来总结:
- 扩展窗口适用于短时间序列,因为它能为模型提供更多的数据。
- 滚动窗口会从训练中移除最旧的数据。如果时间序列是非平稳的,且行为随时间推移必然会发生变化,那么使用滚动窗口将有利于保持模型的最新性。
- 当我们使用扩展窗口策略进行重复评估(如交叉验证)时,训练所用时间序列长度的增加可能会对历史较长的窗口引入一些偏差。滚动窗口策略通过保持序列长度相同来消除这种偏差。
现在,让我们看看验证策略的另一个方面。
校准策略
校准策略仅适用于我们使用不同原点进行多次评估的情况。有两种方法可以使用不同原点进行评估——重新校准每个原点或更新每个原点(术语来自Tashman,参考文献1)。
在重新校准策略下,模型针对每个原点用新的训练集重新训练。这个重新训练的模型用于评估验证集。对于更新策略,我们不重新训练模型,而是使用已训练的模型来评估新的验证集。
让我们总结一下选择策略时需要考虑的几个关键点:
- 黄金标准是重新校准每个新原点,但很多时候这并不可行。在计量经济学/经典统计模型中,常规做法是重新校准每个原点。这之所以可行,是因为这些模型计算量相对较小,且当时的数据集也很小。因此,可以在很短的时间内重新拟合模型。如今,数据集规模变大,模型也变得更大。每次移动原点时重新训练深度学习模型可能并不容易。
因此,如果你使用的是训练时间较长的现代复杂模型,更新策略可能更合适。
- 对于运行速度快的经典模型,我们可以探索重新校准策略。然而,如果你预测的时间序列非常动态,行为变化非常频繁,那么重新校准策略可能是更好的选择。
现在,让我们进入验证策略的第三部分。
采样策略
在留出策略中,我们在时间序列上采样一个点(原点),最好靠近末尾,使得原点之后的时间序列部分比之前的部分短。从这个原点,我们可以使用扩展或滚动窗口策略来生成训练和验证集。模型在训练集上训练,并在保留的验证集上测试。这个策略简称为留出策略。校准策略固定为重新校准,因为我们只测试和评估模型一次。
简单的留出策略有一个缺点——由于单一的评估范式,我们在保留数据上计算的预测度量可能不够稳健。我们依赖于数据的一个单一划分来计算模型的预测性能。对于非平稳序列,这可能是一个问题,因为我们可能选择一个捕捉了所选划分特殊性的模型。
我们可以通过重复多次留出评估来克服这个问题。我们可以根据业务领域知识手动定制不同的原点,例如考虑季节性或其他因素,或者我们可以随机采样原点。如果重复n次,就会有n个验证集,它们可能相互重叠,也可能不重叠。这些重复试验的性能指标可以用均值、最大值和最小值等函数聚合。这称为重复留出(Rep-Holdout)策略。
实现注意事项:
简单的留出策略非常容易实现,因为我们决定验证集的大小,并将时间序列末尾相应数量的数据保留用于验证。Rep-Holdout策略涉及随机采样多个窗口或使用预定义窗口作为验证集。我们可以利用scikit-learn中的PredefinedSplit类来实现这一点。
图20.2展示了使用扩展窗口方法的两种留出策略:

图20.2: 留出策略(a)和Rep-Holdout策略(b)
Rep-Holdout策略还有更多变体。普通的Rep-Holdout策略评估多个验证数据集,通常是手工设计的,并且验证数据集可以有重叠。Rep-Holdout策略的一个变体要求多个验证集之间没有重叠,这是一个更流行的选择。我们称之为Repeated Holdout (No Overlap) (Rep-Holdout-O)。这具有交叉验证的一些特性,并试图更系统地使用数据。图20.3 (a)展示了这个策略:

图20.3: Rep-Holdout策略的变体
Rep-Holdout-O策略在scikit-learn中很容易实现,使用TimeSeriesSplit类用于单时间序列数据集。
笔记本提示:
相关的笔记本展示了如何实现不同的验证策略,可以在Chapter20文件夹中找到,名称为01-Validation_Strategies.ipynb。
来自sklearn.model_selection的TimeSeriesSplit类实现了Rep-Holdout验证策略,并且支持扩展或滚动窗口变体。主要参数是n_splits。这决定了你想从数据中划分多少个分割,验证集大小根据以下公式自动决定:
$$round \left( \frac{n\_samples}{n_{splits} + 1} \right)$$
在默认配置下,这实现了一个扩展窗口的重复留出-无重叠策略。但有一个max_train_size参数。如果我们设置这个参数,它将以滚动窗口的方式使用一个max_train_size大小的窗口。
重复留出策略的另一种变体在训练集和验证集之间引入了一个长度为Lg的间隔。这是为了增加训练集和验证集之间的独立性,从而通过该过程获得更好的误差估计。我们称这种策略为带间隔的重复留出(无重叠)(Rep-Holdout-O(G))。该策略如图20.3(b)所示。
我们也可以使用TimeSeriesSplit类来实现这一点。我们只需要使用一个名为gap的参数。默认情况下,间隔设置为0。但如果更改为非零数字,它将在训练结束和验证开始之间插入相应的时间步间隔。
在进入下一组策略之前,让我们总结并讨论一下关于留出策略的一些关键点:
- 留出策略尊重问题的时间完整性,长期以来一直是评估预测模型的首选方法。然而,它们确实存在对可用数据利用效率低下的弱点。对于短时间序列,留出或重复留出可能没有足够的训练数据来训练模型。
- 简单的留出依赖于单次评估,误差估计不稳健。即使在平稳序列中,这个过程也不能保证良好的误差估计。在非平稳时间序列(如季节性时间序列)中,这个问题更加严重。但重复留出及其变体解决了这个问题。
现在,让我们看看另一个主要思想流派。
交叉验证策略
交叉验证是评估标准回归和分类方法时最重要的工具之一。这有两个原因:
- 简单的留出方法没有使用所有可用数据,而在数据稀缺的情况下,交叉验证充分利用了可用数据。
- 理论上,我们观察到的时间序列是随机过程的一次实现,因此获取的数据误差度量也是一个随机变量。因此,必须多次采样误差估计以了解随机变量的分布。直观上,我们可以将此视为从单个数据切片得出的误差度量的“缺乏可靠性”。
标准机器学习中最常用的策略称为k折交叉验证。在该策略下,我们随机打乱训练数据并将其分成k个相等的部分。然后,整个模型训练和计算误差的过程重复k次,使得每次保留的一个子集恰好被用作一次测试集。当我们使用特定子集作为测试数据时,我们使用所有其他子集作为训练数据。在获得k个不同的误差估计后,我们用求平均等函数进行聚合。这个平均值通常比单个误差度量更稳健。
然而,有效性过程有一个核心假设:i.i.d样本。这是时间序列问题中无效的假设,因为根据定义,时间序列中的不同样本通过自相关相互依赖。
有人认为,当我们使用时间延迟嵌入将时间序列转换为回归问题时,就可以在时间序列问题上开始使用k折交叉验证。尽管存在明显的理论问题,Bergmeir等人(参考文献2)通过实验表明,k折交叉验证并非一个糟糕的选择,但前提是时间序列必须是平稳的。我们将在下一节更详细地讨论这一点,届时将探讨这些策略的优缺点。
然而,针对序列数据,已有对k折策略的改进。
Snijders等人(参考文献4)提出了一种改进,我们称之为分块交叉验证(Bl-CV)策略。它类似于标准的k折策略,但在将数据集划分为k个长度为Lv的子集之前,我们不会随机打乱数据集。因此,这种划分策略会产生k个连续的观测块。然后,像标准的k折策略一样,我们对每个k块进行训练和测试,并聚合这些多次评估的误差度量,从而部分满足问题的时序完整性。
换句话说,时序完整性在每个块内部得以保持,但在块之间则不然。图20.4 (a)展示了这一策略:

图20.4: Bl-CV策略
要实现Bl-CV策略,我们可以使用scikit-learn中的Kfold类。如前所述,scikit-learn中交叉验证类的主要参数是n_splits。这里,n_splits也定义了它选择的等大小折数。还有另一个参数shuffle,默认设置为True。如果我们确保数据按时间排序,然后使用Kfold类并设置shuffle=False,它将模拟Bl-CV策略。随附的笔记本展示了这一用法。我强烈建议你查看笔记本以更好地理解如何实现。
在前一节中,我们讨论了在训练集和验证集之间引入间隔以增加它们的独立性。Bl-CV的另一个变体是使用这些间隔的版本,我们称之为带间隔的分块交叉验证(Bl-CV(G))。我们可以在图20.4 (b)中看到其效果。
不幸的是,scikit-learn中的Kfold实现不支持此变体,但扩展Kfold实现以包含间隔是简单的。随附的笔记本有其实现。它有一个额外的参数gap,允许我们设置训练集和验证集之间的间隔。
我们看到了许多不同的验证策略;现在,让我们尝试列出几点,以帮助你为问题选择合适的策略。
选择验证策略
选择正确的验证策略是机器学习工作流中最重要但最容易被忽视的任务之一。一个好的验证设置将在建模过程的所有不同步骤中发挥重要作用,例如特征工程、特征选择、模型选择和超参数调优。尽管在制定验证策略时没有硬性规定,但我们可以遵循一些指导原则。其中一些来自经验(既有我的也有他人的),另一些来自已发表为研究论文的实证和理论研究:
- 设计中的一个指导原则是,我们尽量让验证策略尽可能复制模型的实际使用情况。例如,如果模型将用于预测接下来的24个时间步,那么我们将验证集的分割长度设置为24个时间步。当然,这并非如此简单,因为在设计验证策略时,还必须考虑其他实际约束,例如足够的数据、时间和计算机的可用性。
- 尊重时间序列问题的时间顺序的重复保持(Rep-Holdout)策略是首选选项,特别是在有足够数据可用的情况下。
- 对于纯自回归形式的平稳时间序列,也可以使用常规的
Kfold,并且 Bergmeir 等人(参考文献2)通过实验表明,它们比保持(holdout)策略表现更好。但在交叉验证策略中,Bl-CV 是更好的选择。也可以使用Cerqueira 等人(参考文献3)在其针对平稳时间序列的实证研究中证实了这些发现。 - 如果时间序列是非平稳的,那么 Cerqueira 等人 通过实验表明,保持策略(尤其是重复保持(Rep-Holdout)策略)是最佳选择。
- 如果时间序列较短,在使时间序列平稳后使用 Bl-CV 对于自回归形式(如时间延迟嵌入)是一个好策略。然而,对于使用某种历史记忆进行预测的模型,例如指数平滑或深度学习模型(如 RNN),交叉验证策略可能不安全。
- 如果除了自回归部分之外还有外生变量,使用交叉验证策略可能不安全。最好坚持使用基于保持(holdout)的策略。
- 对于强季节性时间序列,使用模拟预测时段的验证期是有益的。例如,如果我们要预测10月、11月和12月,那么检查模型在去年10月、11月和12月上的表现是有益的。
到目前为止,我们一直在讨论单时间序列的验证策略。但在全局模型的背景下,我们也需要考虑这些情况下的验证策略。
多时间序列数据集的验证策略
到目前为止我们看到的所有策略都完全适用于多时间序列数据集,例如本书中使用的伦敦智能电表数据集。我们在上一节讨论的见解也适用。这些策略的实现可能稍微棘手,因为所讨论的 scikit-learn 类适用于单个时间序列。这些实现假设我们有一个按时间顺序排序的单个时间序列。如果有多个时间序列,分割将变得杂乱无章。
对于多时间序列数据集,我们可以采用几种选择:
- 我们可以遍历不同的时间序列,并使用我们讨论过的方法进行训练-验证集划分,然后将所有时间序列的结果集拼接起来。但这样做效率并不高。
- 我们可以编写代码并设计验证策略,使用日期时间或时间索引(例如我们在第15章全局深度学习预测模型的策略中看到的PyTorch forecasting中的索引)。我在本章的延伸阅读部分提供了一个来自Konrad Banachewicz的优秀notebook的链接,其中他使用了一个自定义的
GroupSplit类,该类将时间索引作为分组。这是在包含多个时间序列的数据集上使用重复留出策略的一种方法。
对于包含多个时间序列的数据集,我们需要牢记以下几点:
- 不要对不同的时间序列使用不同的时间窗口。这是因为不同时间窗口会有不同的误差,这会使我们跟踪的聚合误差指标产生偏差。
- 如果不同时间序列的长度不同,则要统一所有序列的验证期长度。训练长度可以不同,但验证窗口应相同,以便每个时间序列对聚合误差指标的贡献相等。
- 很容易被复杂的验证方案冲昏头脑,但始终要记住因选择特定技术而产生的技术债务。
至此,我们结束了一个简短但重要的章节。
小结
我们结束了时间序列预测领域的旅程。在最近几章中,我们讨论了一些预测的机制,例如如何进行多步预测以及如何评估预测结果。本章的主题是用于评估预测结果和预测模型的不同验证策略。
我们首先阐明了为什么模型验证是一项重要任务。然后,我们探讨了几种不同的验证策略,例如留出策略,并讨论了时间序列交叉验证这一有争议的话题。我们花了一些时间总结并列出了一些选择验证策略的指南。最后,我们讨论了这些验证策略如何适用于包含多个时间序列的数据集,并介绍了如何针对此类场景进行调整。
至此,我们走到了本书的终点。恭喜你坚持读完了全书,希望你已经从本书中获得了足够的技能来应对下一个时间序列问题。我强烈建议你开始将书中所学的技能付诸实践,因为正如理查德·费曼所说,“不经实践,便无真知。”
参考文献
以下是本章所使用的参考文献:
- Tashman, Len. (2000). 预测准确性的样本外检验:分析与回顾. International Journal of Forecasting. 16. 437–450. 10.1016/S0169-2070(00)00065-0: https://www.researchgate.net/publication/223319987_Out-of-sample_tests_of_forecasting_accuracy_An_analysis_and_review.
- Bergmeir, Christoph and Benítez, José M. (2012). 关于交叉验证在时间序列预测评估中的应用. In Information Sciences, Volume 191, 2012, Pages 192–213: https://www.sciencedirect.com/science/article/abs/pii/S0020025511006773.
- Cerqueira, V., Torgo, L., and Mozetič, I. (2020). 评估时间序列预测模型:关于性能估计方法的实证研究. Mach Learn 109, 1997–2028 (2020):https://doi.org/10.1007/s10994-020-05910-7.
- Snijders, T.A.B. (1988). 关于时间序列预测评估的交叉验证. In: Dijkstra, T.K. (eds) 模型不确定性及其统计影响. Lecture Notes in Economics and Mathematical Systems, vol 307. Springer, Berlin, Heidelberg. https://doi.org/10.1007/978-3-642-61564-1_4.
延伸阅读
- TS-10:时间序列的验证方法 由 Konrad Banachewicz 编写: : https://www.kaggle.com/code/konradb/ts-10-validation-methods-for-time-series
留下评论!
感谢您从Packt出版社购买本书——希望您喜欢!您的反馈非常宝贵,有助于我们改进和成长。请花一点时间在亚马逊上写个评论;只需一分钟,但对像您这样的读者来说意义重大。
扫描下方二维码即可免费获得一本您选择的电子书。