使用时间序列数据:拆分数据集并将模型投入生产

机器算法验证 机器学习 时间序列 预测 lstm
2022-03-24 08:40:17

我已经使用 ML 工作了一段时间,尤其是深度学习,但我之前没有使用过时间序列,现在我开始在一个需求预测项目中工作。我正在研究统计/自回归方法,并试图了解如何使用 CNN 和 LSTM 来解决问题。但是我很难在脑海中整理一些东西,主要是关于如何拆分数据集并将模型投入生产。所以,这是我的两个主要疑问:

时间序列嵌套交叉验证

我开始使用时间序列嵌套交叉验证。好吧,我知道这不是唯一的选择,但我认为调整我的模型超参数并保证它不会过度拟合非常合适。因为在生产中我必须预测接下来的 90 天,所以我的测试集总是 90 天。但这里有一个问题:对于统计/自回归模型(如 ARIMA),当我完成参数调整后,我应该怎么做?我应该使用具有最大训练集的模型投入生产吗?但我不会错过最近 90 天的数据吗?使用整个数据和相同的参数重新训练它是否安全,这样它就不会错过这些数据?

经过大量研究以了解如何将 LSTM 和其他机器学习模型用于时间序列,我了解到需要将训练数据集转换为具有滚动窗口的样本。我的意思是,我通过数据集传递一个窗口,其中 N 个元素作为输入,M 个元素作为输出,窗口一个接一个地移动。好的,但是,如何将训练数据集拆分为训练和验证(使用 ModelCheckpoint 和 EarlyStopping)?我看过一些使用这些生成样本的随机拆分的教程。但我觉得它会在训练集和验证集之间造成数据泄漏。另一个选项似乎是在滚动窗口过程之前以时间方式拆分(例如,拥有 90 天的验证集)。这对我来说听起来更好,因为不会泄露任何数据,但是,我将如何将其投入生产?如果我只是选择使用最大数据集训练的模型,它将从测试集中缺少 90 天加上从验证集中缺少 90 天。因此,它不会选择最近的趋势。而且我认为简单地用整个数据集和相同的超参数重新训练模型是不安全的,因为我没有办法提前停止训练过程。

我知道我需要不断地重新训练我的模型,因为世界在变化,它需要选择新的数据趋势。因此,在找到最佳超参数后,我希望模型能够在给定的时间表内(例如每周)自动使用它们进行训练。但我无法解决这些疑问。我是在使用 90 天前(使用统计模型)还是 180 天前(使用 ML} 的数据来训练一个模型来预测接下来的 90 天?

2个回答

对于标准统计方法(ARIMA、ETS、Holt-Winters 等...)

我不推荐任何形式的交叉验证(即使是时间序列交叉验证在实践中使用起来也有点棘手)。相反,使用简单的测试/训练拆分进行实验和初始概念证明等......

然后,当您开始生产时,根本不用担心训练/测试/评估拆分。正如您正确指出的那样,您不想丢失过去 90 天内存在的有价值的信息。相反,在生产中,您在整个数据集上训练多个模型,然后选择能够为您提供最低 AIC 或 BIC 的模型。

这种方法,然后尝试多个模型并选择具有最低信息标准的模型,可以被认为是直观地使用网格搜索/MSE/L2 正则化。

在大数据限制下,AIC相当于留了一个CV,BIC相当于K-fold CV(如果我没记错的话)。有关如何在不使用测试集的情况下训练模型的详细信息和一般讨论,请参阅统计学习要素的第 7 章。  

大多数生产级需求预测工具都使用这种方法,[包括我的团队使用的][1]。为了开发您自己的解决方案,如果您使用的是 R,那么 Forecast 和 Fable 包中的 auto.arima 和 ETS 函数将自动为您执行此 AIC/BIC 优化(您还可以根据需要手动调整一些搜索参数,增加)。

如果您使用的是 Python,那么 ARIMA 和 Statespace API 将为您适合的每个模型返回 AIC 和 BIC,但您必须自己进行网格搜索循环。有一些包可以执行类似于 auto.arima 的自动时间序列模型选择,但上次我检查(几个月前)它们还不成熟(绝对不是生产级)。

对于基于 LSTM 的预测,其原理会有所不同。

对于实验和概念验证,再次使用简单的训练/测试拆分(特别是如果您要与 ARIMA、ETS 等其他模型进行比较时)——基本上就是您在第二个选项中描述的内容。

然后引入你的整个数据集,包括你最初留给验证的 90 天,并将一些超参数搜索方案应用到你的 LSTM 与完整的数据集。贝叶斯优化是目前最流行的超参数调整方法之一。

找到最佳超参数后,将模型部署到生产环境,并开始对其性能进行评分。

这是 LSTM 和统计模型之间的一个重要区别:

通常,每次有新数据出现时都会重新训练统计模型(对于我工作过的各个团队,我们每周或有时每晚重新训练模型 - 在生产中我们总是使用不同风格的指数平滑模型)。

您不必对 LSTM 执行此操作,而只需每 3~6 个月重新训练一次,或者您可以在性能监控表明错误超过某个阈值时自动重新触发重新训练过程。

但是-这是一个非常重要的但是!!!!- 你可以这样做只是因为你的 LSTM 已经同时接受了数百或数千个产品/时间序列的训练,即它是一个全局模型。这就是为什么不那么频繁地重新训练 LSTM 是“安全的”,它已经看到了很多以前的时间序列示例,它可以在新产品中挑选趋势和变化,而无需适应本地时间序列的特定动态。

请注意,正因为如此,您必须包含额外的产品特征(产品类别、价格、品牌等),以便 LSTM 了解不同产品之间的相似性。只有在大量不同产品上进行训练时,LSTM 才能在需求预测中表现得比统计方法更好。如果你为每个单独的时间序列产品训练一个单独的 LSTM,那么你几乎肯定会过度拟合,并且统计方法可以保证更好地工作(并且由于上述 IC 技巧更容易调整)。 

回顾一下:

在这两种情况下,在进行初始训练/验证拆分后,对整个数据集进行重新训练,包括 90 天的验证集。 

  • 对于统计方法,使用简单的时间序列训练/测试拆分进行一些初始验证和概念证明,但不要为超参数调整使用 CV。相反,在生产中训练多个模型,并使用 AIC 或 BIC 作为自动模型选择的指标。此外,尽可能频繁地执行此培训和选择(即每次获得新的需求数据时)。
  • 对于 LSTM,在尽可能多的时间序列和产品上训练一个全局模型,并使用额外的产品功能,以便 LSTM 可以学习产品之间的相似性。这使得每隔几个月而不是每天或每周重新训练模型是安全的。如果你不能做到这一点(因为你没有额外的功能,或者你只有有限数量的产品等......),根本不要理会 LSTM,而是坚持使用统计方法。 
  • 最后,看看分层预测,这是另一种在多个相关产品的需求预测中非常流行的方法。 

只需根据您更新小时预测的频率选择预测范围。假设您有 200 个观测值并计划每 7 个周期重新预测一次。现在取 193 个最近的值并预测 194-200 期间的观察结果。现在取 186 个观测值并预测 187-193 的观测值。现在取 186 个历史值并预测 187-193 。通过这种方式,您的所有历史记录都用于获取模型和参数,以预测来自 K 个原点(测试点)的下 7 个值。

现在,在未来改造的每个点上,使用所有已知数据来预测接下来的 7 个值。

重要的是要注意,可以在每个测试点指定模型或允许经验识别ala https://autobox.com/pdfs/ARIMA%20FLOW%20CHART.pdf,以便提供对预期不足的测量/充分性。

通过这种方式,您的模型是动态的,并根据所有历史数据进行识别。

现在我的建议是,在每个模型构建阶段,您都明确测试参数的恒定性和误差方差的恒定性,以便产生有用的模型并响应模型动态(变化)。通过这种方式,您可以有效地丢弃不再相关的数据,因为事情可能已经发生变化,因此需要将旧数据放在一边(参数恒定性)或至少通过方差稳定权重 (GLS) 进行修改。