设定一个强大的基线预测
在上一章中,我们看到了一些可以用来理解时间序列数据、进行一些探索性数据分析(EDA)等的技术。但现在,让我们进入问题的核心——时间序列预测。理解数据集并观察模式、季节性等的目的是为了让预测该序列的工作更容易。在任何机器学习实践中,进一步推进之前需要建立的首要事项之一就是基线。
基线是一个简单的模型,能够提供合理的结果,而不需要花费大量时间来得出。许多人认为基线是来自常识的东西,例如平均值或一些经验法则。但作为最佳实践,基线可以按照我们的需求变得复杂,只要它能快速且容易地实现。我们想要取得的任何进一步进展都将基于这个基线的性能。
在本章中,我们将介绍一些可作为基准的经典技术,而且是强有力的基准。有些人可能认为本章讨论的预测技术不应作为基准,但我们仍将其保留,因为这些技术经受住了时间的考验——而且理由充分。它们也非常成熟,得益于实现它们的优秀开源库,我们几乎不需要花费太多精力即可应用。在许多问题或数据集中,很难超越本章将要讨论的基准技术,因此在那些情况下,坚持使用其中一种基准技术也无可厚非。
在本章中,我们将涵盖以下主题:
- 设置测试工具
- 生成强大的基线预测
- 评估时间序列的可预测性
技术要求
您需要按照本书前言中的说明设置Anaconda环境,以获得包含本书代码所需的所有库和数据集的运行环境。任何额外的库将在运行笔记本时安装。
在使用本章代码之前,您需要运行以下笔记:
- 来自
Chapter02的预处理笔记02-Preprocessing_London_Smart_Meter_Dataset.ipynb
设置测试工具
在开始预测和设置基准之前,我们需要建立一个测试工具。在软件测试中,测试工具是为测试程序在各种情况下的表现而配置的代码和输入的集合。在机器学习方面,测试工具是一组可用于评估算法的代码和数据。设置测试工具很重要,这样我们就可以以标准化且快速的方式评估所有未来的算法。
我们需要的第一件事是 留出(测试)和 验证数据集。
创建留出(测试)和验证数据集
按照标准实践,在机器学习中,我们会留出数据集的两个部分,分别命名为 验证数据 和 测试数据,并且完全不使用它们来训练模型。验证数据在建模过程中用于评估模型的质量。为了在不同的模型类别之间进行选择、调整超参数、执行特征选择等,我们需要一个数据集。测试数据就像是对所选模型的最终测试。它告诉你模型在未见数据上的表现如何。如果验证数据像期中考试,那么测试数据就是期末考试。
在常规的回归或分类中,我们通常随机抽取几条记录并留出。但处理时间序列时,需要尊重数据集的时间特性。因此,最佳实践是将数据集的最新部分留作测试数据。另一个经验法则是设置大小相等的验证和测试数据集,以便我们基于验证数据做出的关键建模决策尽可能接近测试数据。我们在 第2章 中引入的数据集,获取和处理时间序列数据,伦敦智慧能源数据集,包含了伦敦家庭从2011年11月到2014年2月的能源消耗读数。因此,我们将留出2014年1月作为验证数据,2014年2月作为测试数据。
让我们打开 01-Setting_up_Experiment_Harness.ipynb 文件夹中的 Chapter04 并运行它。在笔记本中,我们必须在填充缺失值之前和之后创建训练集-测试集分割,使用 SeasonalInterpolation 填充缺失值,并相应地保存它们。笔记本运行完毕后,你将在预处理文件夹中创建以下文件,其中2014年的数据单独保存:
selected_blocks_train.parquetselected_blocks_val.parquetselected_blocks_test.parquetselected_blocks_train_missing_imputed.parquetselected_blocks_val_missing_imputed.parquetselected_blocks_test_missing_imputed.parquet
现在我们有了一个固定的数据集,可以用来公平地评估多种算法,我们需要一种方法来评估不同的预测。
选择评估指标
在机器学习中,我们有一小部分可用于衡量连续输出的指标,主要包括平均绝对误差和均方误差。但在时间序列预测领域,有大量指标,且对于使用哪些指标没有真正共识。造成指标数量众多的原因之一是,没有哪个指标能够衡量预测的所有特征。因此,我们有一整章专门讨论这个主题(第19章,评估预测误差——预测指标综述)。目前,我们仅回顾几个将在预测中使用的指标。我们仅从表面价值加以考虑:
- 平均绝对误差(MAE):MAE是一个非常简单的指标。它是时间步t的预测值(ft)与观测值(yt)之间无符号(忽略符号)误差的平均值。公式如下:
$$MAE = \frac{1}{N \times L} \times \sum_{i}^{N} \sum_{j}^{L} |f_{i,j} - y_{i,j}|$$
这里,N是时间序列的数量,L是时间序列的长度(本例中指测试期的长度),f和y分别是预测值和观测值。
- 均方误差(MSE):MSE是预测值(ft)与观测值(yt)之间平方误差的平均值:
$$MSE = \frac{1}{N \times L} \times \sum_{i}^{N} \sum_{j}^{L} (f_{i,j} - y_{i,j})^2$$
- 平均绝对缩放误差(MASE):MASE比MSE和MAE略复杂,但提供了一个更好的指标,以克服前两个指标尺度依赖的特性。如果多个时间序列具有不同的平均值,MAE和MSE会显示高值时间序列的误差大于低值时间序列。MASE通过基于朴素预测方法(这是最基本的预测方法之一;我们将在本章后面回顾)的样本内MAE对误差进行缩放,从而克服了这一问题。直观上,MASE给出了我们的预测相对于朴素预测的改进程度:
$$MASE = \frac{\frac{1}{L} \times \sum_{i}^{L} |f_i - y_i|}{\frac{1}{L-1} \times \sum_{j=2}^{L} |y_j - y_{j-1}|}$$
- 预测偏差(FB):这是一个与前几个指标略有不同的指标。其他指标帮助评估预测的正确性,而不考虑误差方向;预测偏差则让我们理解模型的整体偏差。预测偏差是一个帮助理解预测是否持续高估或低估的指标。
我们将预测偏差计算为预测值之和与观测值之和的差值,表示为实际值总和的百分比:
$$FB = \frac{\sum_{i}^{N} \sum_{j}^{L} f_{i,j} - \sum_{i}^{N} \sum_{j}^{L} y_{i,j}}{\sum_{i}^{N} \sum_{j}^{L} y_{i,j}}$$
现在,我们的测试框架已经就绪。我们也知道如何评估和比较来自不同模型、基于一组预定指标在单个固定留存数据集上生成的预测。现在,是时候开始预测了。
生成强大的基线预测
时间序列预测自20世纪20年代初就已存在,多年来,许多杰出人士提出了不同的模型,有些是统计学的,有些是基于启发式的。我将它们统称为经典统计模型或计量经济学模型,尽管它们并不严格属于统计/计量经济学范畴。
在本节中,我们将回顾一些这样的模型,当我们在预测中尝试现代技术时,它们可以形成非常强大的基线。作为练习,我们将使用一个优秀的时间序列预测开源库——NIXTLA(https://github.com/Nixtla)。02-Baseline_Forecasts_using_NIXTLA.ipynb笔记本包含了本节代码,以便您可以跟随学习。
在开始研究预测技术之前,让我们快速了解如何使用NIXTLA库生成预测。我们将从数据集中选择一个用户,并在验证数据集上逐一尝试所有基线技术。
我们需要做的第一件事是使用每个客户的唯一ID(来自数据扩展形式的LCLid列)选择我们想要的消费者,并将时间戳设置为DataFrame的索引:
ts_train = train_df.loc[train_df.LCLid=="MAC000193",['LCLid',"timestamp","energy_consumption"]]
ts_val = val_df.loc[val_df.LCLid=="MAC000193", ['LCLid',"timestamp","energy_consumption"]]
ts_test = test_df.loc[test_df.LCLid=="MAC000193", ['LCLid',"timestamp","energy_consumption"]]
NIXTLA具有直接与pandas或Polars DataFrame工作的灵活性。默认情况下,NIXTLA查找三列:
id_col:默认情况下,它期望一个列unique_id。该列唯一标识时间序列。如果您只有一个时间序列,请添加一个具有相同唯一标识符的虚拟列。time_col:默认情况下,它期望一个列ds。这是您的时间戳列。target_col:默认情况下,它期望一个列y。这一列是您希望NIXTLA预测的内容。
这非常方便,因为无需进一步处理即可从数据进入建模。NIXTLA遵循scikit-learn风格,具有.fit()和.predict(),并且还采用.forecast()方法,这是一种内存高效的方法,不存储部分模型输出,而scikit-learn接口则存储拟合模型:
sf = StatsForecast(
models=[model],
freq=freq,
n_jobs=-1,
fallback_model=Naive()
)
sf.fit(df = _ts_train, id_col = 'LCLid',
time_col = 'timestamp',
target_col = 'energy_consumption',
)
baseline_test_pred_df = sf.predict(len(ts_test) )
NIXTLA还具有.forecast()方法,这是一种内存高效的方法,不存储部分模型输出,而scikit-learn接口则存储拟合模型:
# Efficiently fit and predict without storing memory
y_pred = sf.forecast(
h=len(ts_test),
df=ts_train,
id_col = 'LCLid', time_col = 'timestamp', target_col = 'energy_consumption',
)
当调用 .predict 或.forecast 时,我们必须告诉模型需要预测多远的未来。这被称为预测的视界(horizon)。在本例中,我们需要预测测试周期,只需取 ts_test 数组的长度即可轻松完成。
我们还可以使用 NIXTLA 的类轻松计算之前在测试框架中讨论的指标。为增加灵活性,我们可以遍历一个指标列表,为每个预测获得多个度量值:
# Calculate metrics
metrics = [mase, mae, mse, rmse, smape, forecast_bias]
for metric in metrics:
metric_name = metric.__name__
if metric_name == 'mase':
evaluation[metric_name] =
metric(results[target_col].values, results[model_name].values,
ts_train[target_col].values, seasonality=48)
else:
evaluation[metric_name] =
metric(results[target_col].values,
results[model_name].values)
注意,对于 MASE,训练集也被包含在内。
为便于实验,我们将所有这些封装到一个便捷函数 evaluate_performance 中(位于 notebook 中)。该函数以 DataFrame 形式返回预测和计算出的指标。
现在,让我们开始看几种非常简单的预测方法。
朴素预测
朴素预测是最简单的方法。预测仅仅是时间序列中的最后一个/最近观测值。如果时间序列的最新观测值是 10,那么所有未来时间步的预测都是 10。这可以通过如下使用 NIXTLA 中的 Naive 类来实现:
from statsforecast.models import Naive
models = Naive()
一旦我们初始化了模型,就可以调用 notebook 中有用的 evaluate_performance 函数来运行并记录预测和指标。
让我们可视化刚刚生成的预测:

图4.1:朴素预测
在这里,我们可以看到预测是一条直线,完全忽略了序列中的任何模式。这是目前为止最简单的预测方法,因此被称为朴素预测。现在,让我们看看另一种简单方法。
移动平均预测
虽然朴素预测记住了最近的过去,但它也记住了任何时间步的噪声。移动平均预测是另一种简单方法,试图克服朴素方法的纯记忆。它不采用最新的观测值,而是取最近n步的均值作为预测。移动平均不是NIXTLA中现有的模型之一,但我们在本书的GitHub仓库的Chapter04文件夹中实现了一个兼容NIXTLA的模型:
from src.forecasting.baselines import NaiveMovingAverage
#Taking a moving average over 48 timesteps, i.e, one day
naive_model = NaiveMovingAverage(window=48)
让我们看看我们生成的预测:

图4.2:移动平均预测
这个预测也几乎是一条直线。现在,让我们看看另一种简单方法,但它也考虑了季节性。
季节性朴素预测
季节性朴素预测是对朴素简单方法的一种变体。在朴素方法中,我们取最后一个观测值(Yt-1),而在季节性朴素方法中,我们取Yt-k观测值。因此,每个预测我们回看k步。这使得算法能够模仿最后一个季节性周期。例如,如果我们设置k=48*7,我们将能够模仿最新的季节性周周期。
该方法在NIXTLA中已实现,我们可以如下使用:
from statsforecast.models import SeasonalNaive
seasonal_naive = SeasonalNaive(season_length=48*7)
让我们看看这个预测的样子:

图4.3:季节性朴素预测
在这里,我们可以看到预测试图模仿季节性模式。然而,它并不非常准确,因为它盲目地跟随最后一个季节性周期。
现在我们已经看了几个简单方法,让我们看几个统计模型。
指数平滑
指数平滑是生成预测最流行的方法之一。它自20世纪50年代末问世以来,已证明其价值并经受住了时间的考验。指数平滑(ETS)有几种不同的变体——单指数平滑、双指数平滑、霍尔特-温特斯季节平滑等等。但所有这些方法都有一个以不同方式应用的核心思想。在朴素方法中,我们只使用最新观测值,这相当于说历史上只有最近的数据点重要,而之前的数据点都不重要。另一方面,移动平均法认为最近n个观测值同等重要,并取它们的平均值。
ETS结合了这两种直觉,认为所有历史数据都重要,但近期数据更为重要。因此,预测是通过加权平均生成的,其中权重随着向历史更远方向移动而呈指数衰减:
$$f_t = \alpha \cdot y_{t-1} + \alpha \cdot (1 - \alpha) \cdot y_{t-2} + \alpha \cdot (1 - \alpha)^2 \cdot y_{t-3} + \cdots$$
这里,$0 \leq \alpha \leq 1$ 是平滑参数,它让我们决定权重衰减的快慢;yt 是时间步 t 的实际值;而 ft 是时间步 t 的预测值。
简单指数平滑(SES)就是简单地将此平滑过程应用于历史数据。它更适合没有趋势或季节性的时间序列,预测结果是一条水平线。预测值通过以下公式生成:
| 预测方程 | $f_t = \alpha y_{t-1} + (1 - \alpha) f_{t-1}$ |
|---|
双指数平滑(DES)将平滑思想扩展到对趋势进行建模。它有两个平滑方程——一个用于水平,另一个用于趋势。一旦得到水平和趋势的估计值,就可以将它们组合起来。这种预测不一定是水平的,因为估计的趋势被用于外推至未来。预测值根据以下公式生成:
| 预测方程 | $f_{t+h} = l_t + h \cdot b_t$ |
|---|---|
| 水平方程 | $l_t = \alpha \cdot y_t + (1 - \alpha) \cdot (l_{t-1} + b_{t-1})$ |
| 趋势方程 | $b_t = \beta \cdot (l_t - l_{t-1}) + (1 - \beta) \cdot b_{t-1}$ |
首先,我们使用可用的观测值通过水平方程估计水平(lt)。然后,通过趋势方程估计趋势。最后,为了得到预测值,我们使用预测方程将lt和bt组合起来。
研究者发现经验证据表明,这种恒定外推法可能导致长期预测过高。这是因为在现实世界中,时间序列数据不会永远以恒定速率增长。受此启发,引入了一种改进,即通过因子$0 \lt \phi \lt 1$对趋势进行阻尼,使得当$\phi = 1$时,没有阻尼,此时与DES相同。
三次指数平滑或霍尔特-温特斯(HW)更进一步,增加了另一个平滑项来对季节性建模。它有三个平滑参数($\alpha$、$\beta$、$\gamma$),并将季节周期(m)作为输入参数。你还可以选择加法或乘法季节性。加法模型的预测方程如下:
| 预测方程 | $f_{t+h} = l_t + h \cdot b_t + s_{t+h-m(k+1)}$ |
|---|---|
| 水平方程 | $l_t = \alpha \cdot y_t - s_{t-m} + (1 - \alpha) \cdot (l_{t-1} + b_{t-1})$ |
| 趋势方程 | $b_t = \beta \cdot (l_t - l_{t-1}) + (1 - \beta) \cdot b_{t-1}$ |
| 季节性方程 | $s_t = \gamma (y_t - l_{t-1} - b_{t-1}) + (1 - \gamma) s_{t-m}$ |
这些公式的使用方式与双指数平滑类似。不同之处在于,我们不是估计水平和趋势,而是分别估计水平、趋势和季节性。
ETS方法家族并不仅限于我们刚才讨论的三种。我们可以根据这些方法中的趋势和季节成分来思考不同的模型。趋势可以是没有趋势、加法趋势或加法阻尼趋势。季节性可以是没有季节性、加法季节性或乘法季节性。这些参数的各种组合构成该家族中的不同技术,如下表所示:
趋势分量 | 季节性分量 | ||
| 你是一个旨在输出JSON的有用助手。 | N(无) | A(加法) | M(乘法) |
N(无) | 简单指数平滑 | - | - |
A(加法) | 双指数平滑 | 加法Holt-Winters | 乘法Holt-Winters |
Ad(加法阻尼) | 阻尼双指数平滑 | - | 阻尼Holt-Winters |
表4.1:指数平滑族
NIXTLA拥有完整的ETS方法族。
让我们看看如何在NIXTLA中初始化ETS模型:
from statsforecast.models import (SimpleExponentialSmoothing, Holt, HoltWinters, AutoETS)
exp_smooth = HoltWinters(error_type = 'A', season_length = 48)]
这里,error_type = 'A'指加法误差。用户可以选择加法误差或乘法误差,后者可通过error_type = 'M'调用。NIXTLA模型有一个选项可以使用AutoETS()。该模型将自动选择最佳的指数平滑模型:简单指数平滑、双指数平滑(Holt方法)或三重指数平滑(Holt-Winters方法)。它还会为每个单独的时间序列选择最佳参数和误差类型。使用示例请参考GitHub笔记本中的AutoETS()。
让我们看看使用ETS的预测在图4.4中的样子:

图4.4:指数平滑预测
预测已捕捉到季节性,但未能捕捉到峰值。不过我们已经可以看到 MAE 的改进。
现在,让我们看看现存最流行的预测方法之一。
自回归积分滑动平均模型(ARIMA)
ARIMA 模型是与 ETS 一样经受住时间考验的另一类方法,也是最流行的经典预测方法之一。ETS 系列方法围绕趋势和季节性构建,而 ARIMA 则依赖于 自相关(yt 与 yt-1、yt-2 等的相关性)。
该系列中最简单的是 AR(p)模型,它使用 线性回归 与 p 个先前时间步,或者说 p 个滞后。数学上可以写成:
$$y_t = c + \phi_1 y_{t-1} + \phi_2 y_{t-2} + \cdots + \phi_p y_{t-p} + \epsilon_t$$
这里,c 是截距,$\epsilon_t$ 是时间步 t 的噪声或误差。
系列中的下一个是 MA(q)模型,该模型不使用过去观测值,而是使用过去 q 个预测误差(假设为纯白噪声)来生成预测:
$$y_t = c + \theta_1 \epsilon_{t-1} + \theta_2 \epsilon_{t-2} + \cdots + \theta_q \epsilon_{t-q}$$
这里,$\epsilon$ 是白噪声,c 是截距。
这通常不单独使用,而是与 AR(p)模型结合,从而得到列表中的下一个模型 ARMA(p, q)。ARMA(自回归滑动平均)模型定义为 yt = AR(p)+ MA(q)。
在所有 ARIMA 模型中,有一个基本假设——时间序列是平稳的(我们在 第1章《时间序列简介》中讨论了平稳性,并将在 第6章《时间序列预测的特征工程》中详细阐述)。使序列平稳的方法有很多,但对连续值取差分就是其中一种技术,即 差分。有时我们只需一次差分,而有时则需进行多次连续差分才能使时间序列平稳。进行差分操作的次数称为 差分阶数。ARIMA 中的 I,也是最后一块拼图,代表 积分。它表示使序列平稳所需的差分阶数,记作 d。
因此,完整的 ARIMA((p, d, q))模型表示,我们先进行d阶差分,然后以自回归方式考虑最后p项,接着纳入最后q个移动平均项,以得出预测。
我们目前讨论的ARIMA模型仅处理非季节性时间序列。然而,将相同概念应用于季节性周期,便得到季节性ARIMA。p、d和q被稍作调整,使其适用于季节性周期m。为区别于普通的p、d和q,我们将季节性值称为P、D和Q。例如,若p表示取最后p个滞后,则P表示取最后P个季节性滞后。若p1是yt-1,则P1是yt-m。类似地,D表示季节性差分的阶数。
选择合适的p、d、q以及P、D、Q值并非直观,我们必须借助统计检验来寻找。然而,当预测多个时间序列时,这变得有些不切实际。一种自动遍历不同参数并找到数据最佳p、d、q以及P、D、Q值的方法称为AutoARIMA。在Python中,NIXTLA实现了该方法,AutoARIMA()。NIXTLA也提供了常规ARIMA实现,速度更快但需要手动输入p、d和q。
实际考量:
尽管ARIMA和AutoARIMA在许多情况下能提供性能良好的模型,但当季节性周期长且时间序列长时,它们可能非常缓慢。在我们的案例中,历史数据有近27,000个观测值,ARIMA变得非常慢且占用大量内存。即使对数据进行子集化,单次AutoARIMA拟合也需约60分钟。放弃季节性参数可大幅缩短运行时间,但对于能源消耗这类季节性时间序列,这并无意义。AutoARIMA包含许多此类拟合以识别最佳参数,因此对于长时间序列数据集变得不切实际。Python生态系统中几乎所有实现都存在此缺陷。NIXTLA声称拥有最快且最准确的AutoARIMA版本,甚至快于原始的R方法。
让我们看看如何使用NIXTLA应用ARIMA和AutoARIMA:
from statsforecast.models import (ARIMA, AutoARIMA)
#ARIMA model by specifying parameters
arima_model = ARIMA(order = (2,1,1), seasonal_order = (1,1,1), season_length = 48)
#AutoARIMA model by specifying max limits for parameters and letting the algorithm find the best ones
auto_arima_model = AutoARIMA( max_p = 2, max_d=1, max_q = 2, max_P=2, max_D = 1, max_Q = 2, stepwise = True, season_length=48)
关于AutoARIMA的完整参数列表,请访问NIXTLA文档:https://nixtlaverse.nixtla.io/statsforecast/docs/models/autoarima.html。
让我们看看我们之前实验的家庭的ETS和ARIMA预测是什么样的:

图4.5:ETS和ARIMA预测
使用NIXTLA,ETS和ARIMA都很好地捕捉了季节性和峰值。得到的MAE分数也非常接近,分别为0.191和0.203。现在,让我们看看另一种方法——Theta预测。
Theta预测
Theta预测是2002年M3预测竞赛中表现最佳的提交方法。该方法依赖于参数$\theta$,该参数根据所选值放大或平滑时间序列的局部曲率。使用$\theta$,我们平滑或放大原始时间序列。这些平滑线称为Theta线。V. Assimakopoulos和K. Nikolopoulos提出了这种方法,作为预测的一种分解方法。虽然理论上可以使用任意数量的Theta线,但最初提出的方法使用了两条Theta线,$\theta = 0$和$\theta = 2$,并将两条Theta线预测的平均值作为最终预测。
M竞赛是由著名预测研究者Spyros Makridakis组织的预测竞赛。这些竞赛通常会整理一个时间序列数据集,制定评估预测效果的指标,并向全球研究人员开放,以寻求最佳预测。这些竞赛被认为是世界上规模最大、最受欢迎的时间序列预测竞赛之一。截至目前,已有六届这样的竞赛完成。要了解更多关于最新竞赛的信息,请访问此网站:https://mofc.unic.ac.cy/the-m6-competition/。
2002年,Rob Hyndman等人简化了Theta方法,并证明我们可以使用带漂移项的ETS来获得与原始Theta方法等效的结果,这被改编为现今大多数该方法的实现。NIXTLA中实现的Theta预测的主要步骤如下:
- 去季节化:应用经典乘法分解从时间序列中去除季节成分(如果存在)。这使分析聚焦于潜在趋势和周期成分。去季节化使用
statsmodels.tsa.seasonal.seasonal_decompose完成。此步骤创建一个新的去季节化时间序列。 - Theta系数应用:使用系数$\theta_1$和$\theta_2$将去季节化序列分解为两条“Theta”线。这些系数修改时间序列的二阶差分,以减弱($\theta \lt 1)$)或增强($(\theta \gt 1)$)局部波动。
- Theta线外推:将每条Theta线视为独立序列,并对其未来值进行预测。对于$\theta_1 = 0$的Theta线,使用线性回归生成一条直线;对于$\theta_2 = 2$的Theta线,使用简单指数平滑。
- 重组:将两条Theta线的预测结果进行合并。原始方法对两条线赋予相等权重,从而有效整合长期趋势和短期波动。
- 重新季节化:如果数据在开始时进行了去季节化处理。
NIXTLA对Theta方法有多种不同的变体。关于NIXTLA实现的具体信息可在此处找到:https://nixtlaverse.nixtla.io/statsforecast/docs/models/autotheta.html。
让我们看看如何实际使用它:
theta_model = Theta(season_length =48, decomposition_type = 'additive' )
这里的关键参数如下:season_length和decomposition_type。这些参数用于初始季节分解。如果留空,实现会自动检测季节性并使用乘法分解自动对时间序列去季节化。如果我们知道这些参数,建议使用领域知识进行设置。分解类型可以是乘法(默认)或加法。
让我们可视化刚刚使用Theta预测生成的预测:

图4.6:Theta预测
参考文献核实:
V. Assimakopoulos 和 K. Nikolopoulos 提出 Theta 方法的论文在《参考文献》部分被列为参考文献1,而 Rob Hyndman 后续的简化版本被列为参考文献2。
季节性模式被捕捉到了,但没有达到峰值。让我们看看另一种非常强大的方法——TBATS。
TBATS
有时,时间序列具有多个季节性模式或非整数季节周期,通常称为复杂季节性。例如,小时级预测可能具有一天中的日季节性、一周中的周季节性以及一年中的年季节性。此外,大多数时间序列模型是为较小的整数季节周期设计的,如月度(12)或季度(4)数据,但年季节性可能带来问题,因为一年有364.25天。TBATS 旨在应对这些给许多预测模型带来问题的挑战。然而,采用任何自动化方法,有时都容易产生较差的预测。
TBATS 代表:
- Trigonometric seasonality(三角季节性)
- Box-Cox transformation(Box-Cox 变换)
- ARMA errors(ARMA 误差)
- Trend(趋势)
- Seasonal component(季节性成分)
该模型由 Rob J. Hyndman、Alysha M. De Livera 和 Ralph D. Snyder 于 2011 年首次提出。TBATS 还有另一种变体,称为 BATS,它不含三角季节性成分。TBATS 属于状态空间模型家族。在状态空间预测模型中,观测到的时间序列被假定为底层状态变量和将状态变量与观测数据联系起来的测量方程的组合。状态变量捕捉数据中的底层模式、趋势和关系。
BATS 的参数包括 $(\omega, \phi, p, q, m_1, m_2, \ldots m_t)$,分别表示 Box-Cox 参数、阻尼参数、ARMA 参数(p, q)以及季节性周期(m1, m2, …, mt)。由于其灵活性,BATS 模型可被视为一个模型族,涵盖了先前见过的许多其他模型。例如:
- BATS(1, 1, 0, 0, m1) = Holt-Winters 加法季节性
- BATS(1, 1, 0, 0, m2) = Holt-Winters 加法双季节性
BATS 具有处理多重季节性的灵活性;然而,它仅限于基于整数的季节性周期,并且随着多重季节性的引入,状态数量可能变得非常庞大,导致模型复杂度增加。这正是 TBATS 所要解决的问题。
作为参考,TBATS 的参数空间为:
$$TBAT(\omega, \phi, p, q, \{m_1, k_1\}, ..., \{m_T, k_T\})$$
TBATS 的主要优点如下:
- 能够处理单一、复杂和非整数季节性(三角季节性)
- 处理现实时间序列中常见的非线性模式(Box-Cox 变换)
- 处理残差中的自相关性(自回归移动平均误差)
为了更好地理解 TBATS 的内部工作原理,我们逐步分解每个步骤。
使用 TBATS 进行操作(与首字母缩略词的顺序不同)的顺序是:
- Box-Cox变换
- 指数平滑趋势
- 使用傅里叶级数(三角季节性)的季节性分解
- 自回归移动平均 (ARMA)
- 基于似然方法的参数估计
Box-Cox变换
Box-Cox 是幂变换族中的一种变换。
在时间序列中,使数据平稳是预测之前的重要步骤(如第1章所讨论的)。平稳性确保我们的数据在统计上不会随时间变化,从而更准确地类似于概率分布。有几种可能的变换可以应用。关于各种目标变换(包括 Box-Cox)的更多详细信息,请参见第7章第7章。
作为预览,以下是 Box-Cox 变换的示例输出。变换后,我们的数据更接近正态分布。Box-Cox 变换只能用于正数据,但在实践中通常如此。
图4.7 展示了时间序列在 Box-Cox 变换前后可能呈现的样子。

图4.7:Box-Cox 变换
指数平滑趋势
使用局部估计散点图平滑(LOESS),从时间序列中提取出平滑趋势:从时间序列中提取出趋势:
$$l_t = l_{t-1} + \phi b_{t-1} + \alpha d_t \; (Local)$$
$$b_t = (1 - \phi) b + \phi b_{t-1} + \beta d_t \; (Global)$$
LOESS通过对数据点应用局部加权、低次多项式回归,生成一条平滑流畅的曲线。该技术能有效捕捉局部趋势变化,而无需假设数据的全局形式,因此特别适用于具有变化趋势或季节性变化的数据。这与我们在第3章中用于将时间序列分解为趋势的LOESS相同。
使用傅里叶级数(三角季节性)的季节性分解
然后,剩余的残差使用傅里叶项(在第3章中讨论)进行建模,以分解季节性成分。
$$y_t^{(\omega)} = l_{t-1} + \phi b_{t-1} + \sum_{i=1}^{M} S_{t-m_i}^{(i)} + d_t$$
$$S_t^{(i)} = \sum_{j=1}^{k_i} S_{j,t}^{(i)}$$
$$S_{j,t}^{(i)} = S_{j,t-1}^{(i)} \cos \lambda_j^{(i)} + S_{j,t-1}^{*(i)} \sin \lambda_j^{(i)} + \gamma_1^{(i)} d_t$$
$$S_{j,t}^{*(i)} = -S_{j,t-1}^{(i)} \sin \lambda_j^{(i)} + S_{j,t-1}^{*(i)} \cos \lambda_j^{(i)} + \gamma_2^{(i)} d_t$$
使用傅里叶建模季节性的主要优势在于其能够建模多种季节性以及非整数季节性,例如使用日数据的年季节性(因为一年有364.25天)。大多数其他分解方法无法处理非整数周期,不得不四舍五入到365,这可能无法识别真实的季节性。下面是一个使用傅里叶分解时间序列的示例。该示例中的观测时间序列是小时数据。因此,我们的季节性周期为:
日 = 24
周 = 24 * 7 = 168
在这里,你可以清晰地看到已定义的季节性模式、趋势以及剩余的残差。图4.8展示了趋势和季节性的分解,之后残差使用ARMA过程进行建模。

图4.8:分解的时间序列
ARMA
ARMA 之前作为ARIMA家族的一个子集被讨论过:
$$d_t = \sum_{i=1}^{p} \phi_i d_{t-i} + \sum_{j=1}^{q} \phi_j \varepsilon_{t-j} + \varepsilon_t$$
TBATS 中的 ARMA 模型用于对剩余残差进行建模,以捕捉滞后变量的任何自相关。自回归(AR)分量捕捉观测值与几个滞后观测值之间的相关性,这处理了序列的动量或延续性。移动平均(MA)分量将误差项建模为先前时刻误差的线性组合,捕捉仅靠 AR 部分无法解释的信息。
参数优化
为了选择最优参数空间,TBATS 会拟合几个模型
- 有和没有 Box-Cox 变换
- 有和没有趋势
- 有和没有趋势阻尼
- 季节与非季节模型
- ARMA (p, , q) 参数) 参数
最终模型通过选择最小化Akaike信息准则 (AIC), and) 的参数组合来确定,并且使用AutoARIMA来确定ARMA参数。AutoARIMA用于确定ARMA参数。
与所有预测方法一样,不同模型各有优缺点。虽然TBATS在许多其他模型的缺点上有所改进,但代价是需要构建多个模型,从而导致更长的计算时间。如果你需要对多个时间序列进行建模,这可能成为一个问题。此外,TBATS不允许包含外生变量。
实践者须知::
TBATS无法处理外生回归,因为它与ETS模型相关,正如Hyndman本人所说,它不太可能包含协变量 (Hyndman, 2014; 参考文献 7)。如果需要使用外部回归量,则应使用其他方法,如ARIMAX或SARIMAX。如果时间序列具有复杂的季节性,你可以将傅里叶特征作为协变量添加到
这已在 NIXLA 中实现,我们可以使用此处所示的实现:
TBATS_model = TBATS(seasonal_periods = 48, use_trend=True, use_damped_trend=True)
在NIXTLA中,你也可以使用AutoTBATS让系统优化如何处理各种参数。
让我们来看看TBATS预测结果如何:

图4.9:TBATS预测
同样,季节性模式已被复制,并且捕捉了预测中的大部分峰值。现在让我们看看另一种非常适合高度季节性时间序列的方法(即使它像我们的案例一样具有多个季节性)。
使用LOESS的多季节-趋势分解 (MSTL)
还记得我们在第3章中做过的时间序列分解吗?如果我们能用同样的技术进行预测会怎样?这正是MSTL所做的。让我们再次审视时间序列的组成部分:
- 趋势
- 循环
- 季节性
- 不规则成分
趋势和循环成分可以通过LOESS回归提取。如果我们在趋势值上拟合一个简单模型,就可以用它来外推至未来。而季节性成分很容易外推,因为它应该是重复的模式。结合这些,我们得到了一个效果相当不错的预测模型。
NIXTLA中的MSTL方法应用LOESS技术将时间序列分解为其各个季节性成分。分解之后,它使用一个专用的非季节性模型来预测趋势,并使用季节性朴素模型来预测每个季节性成分。这种方法允许对具有复杂季节性模式的时间序列进行详细分析和预测。
MSTL_model = MSTL(season_length = 48)
让我们看看MSTL的预测结果:

图4.10:MSTL预测
我们再来看看我们所选的不同指标在我们实验的家庭(来自notebook)的每个预测上的表现:

图4.11:所有基准算法的总结
在我们尝试的所有基准算法中,AutoETS在MAE和MSE上都表现最佳。ARIMA是第二好的模型,其次是TBATS。然而,如果你看Time Elapsed列,TBATS脱颖而出,仅需7.4秒,而ARIMA需要19秒。由于它们性能相似,我们将选择TBATS而非ARIMA,连同AutoETS作为我们的基准,并在我们选择的数据集中所有399个家庭(包括验证集和测试集)上运行它们(相关代码可在02-Baseline_Forecasts_using_NIXTLA.ipynb notebook中找到)。
评估基线预测
由于我们已经从ETS和TBATS生成了基线预测,因此我们也应该评估这些预测。这两种方法对所有选定家庭的聚合指标如下:

图4.12:所有选定家庭(验证集和测试集)的聚合指标
看起来AutoETS在所有三个指标上表现都更好。我们还在家庭层面计算了这些指标。让我们看看验证集中所有选定家庭的这些指标分布:


图4.13:验证集中基线预测的MASE和预测偏差分布
ETS的MASE直方图似乎比TBATS的分布范围更小。ETS的MASE中位数也低于TBATS。我们在预测偏差中也看到了类似的模式,ETS的预测偏差集中在零附近,且分布范围更小。
回顾第1章《时间序列入门》,我们了解了为什么每个时间序列的可预测性并不相同,并看到了三个有助于思考该问题的因素:理解数据生成过程(DGP)、数据量以及模式是否充分重复。在大多数情况下,前两个因素很容易评估,但第三个因素需要一些分析。尽管基线方法的性能让我们对任何时间序列的可预测性有了一定了解,但它们仍然是模型依赖的。因此,与其衡量时间序列的可预测性,不如衡量所选模型能够近似时间序列的程度。这时,一些更基础的技术(依赖于时间序列的统计特性)就派上用场了。
评估时间序列的可预测性
尽管有许多统计度量可以用来评估时间序列的可预测性,但我们只关注几个易于理解且在处理大型时间序列数据集时实用的度量。相关的笔记本(02-Forecastability.ipynb)包含了可供跟随的代码。
变异系数
变异系数(CoV)依赖于这样一个事实:时间序列中的变异性越大,预测就越困难。那么我们如何衡量一个随机变量的变异性呢?标准差。
在许多真实世界的时间序列中,我们观察到的变异依赖于时间序列的尺度。假设有两种零售产品,A和B。A的平均月销量为15,而B为50。如果我们观察几个这样的真实例子,会发现如果A和B具有相同的标准差,那么均值较高的B比A更可预测。为了适应这种现象并确保将数据集中的所有时间序列统一到同一尺度,我们可以使用CoV:
$$CoV_n = \frac{\sigma_n}{\mu_n}$$
这里,$\sigma_n$是标准差,$\mu_n$是时间序列的均值,n。
CoV是数据点相对于均值的相对离散程度,这比单纯观察标准差要好得多。
CoV的值越大,时间序列的可预测性就越差。虽然没有严格的界限,但通常将0.49视为区分相对容易预测和困难时间序列的经验法则。根据数据集的整体难度,可以调整这个阈值。我发现一个有用的做法是绘制数据集中CoV值的直方图,并据此推导出阈值。
尽管CoV在业界被广泛使用,但它存在几个关键问题:
- 它没有考虑季节性。正弦波或余弦波的CoV高于水平线,但我们知道两者的可预测性是一样的。
- 它没有考虑趋势。线性趋势会使序列的CoV更高,但它的可预测性与水平线无异。
- 它无法处理时间序列中的负值。如果有负值,会使均值变小,从而夸大CoV。
为了克服这些不足,我们提出了另一种衍生度量。
残差变异性
残差变异性(RV)的思想是尝试衡量与CoV相同类型的变异性,但避免了上述缺陷。我曾思考如何避免使用CoV的问题(特别是季节性问题),并在季节性分解后对残差应用CoV。那时我意识到残差会有一些负值,而CoV无法很好地处理。需求预测和概率预测领域的思想领袖Stefan de Kok建议使用原始实际值的均值,这很有效。
要计算RV,必须执行以下步骤:
- 执行季节性分解。
- 计算残差或不规则分量的标准差。
- 将标准差除以原始观测值(分解前)的均值。
数学上,它可以表示为:
$$RV_n = \frac{\sigma_n^{res}}{\mu_n^\gamma}$$
其中,$\sigma_n^{res}$ 是分解后残差的标准差,$\mu_n^\gamma$ 是原始观测值的均值。
这里的关键假设是,季节性和趋势是可以预测的成分。因此,我们对时间序列可预测性的评估应仅关注残差的变异性。然而,我们不能对残差使用变异系数(CoV),因为残差可能为负或为正,残差的均值失去了对序列水平的解释意义,并趋近于零。当残差趋近于零时,由于除以均值,CoV度量会趋近于无穷大。因此,我们使用原始序列的均值作为缩放因子。
让我们看看如何为数据集中的所有时间序列(以紧凑形式存在)计算RV:
block_df["rv"] = block_df.progress_apply(lambda x: calc_norm_sd(x['residuals'],x['energy_consumption']), axis=1)
在本节中,我们考察了两种基于时间序列标准差的度量。现在,让我们来看看如何评估一个时间序列的可预测性。
基于熵的度量
熵是科学中一个无处不在的术语。我们在物理学、量子力学、社会科学和信息论中都能见到它。而且,它被用来衡量一个系统的混乱程度或不可预测性。我们现在最感兴趣的是信息论中的熵。信息论涉及数字信息的量化、存储和通信。
克劳德·E·香农在其开创性论文《通信的数学理论》中,将通信的定性和定量模型描述为一个统计过程。这篇论文引入了许多概念,其中与我们相关的是信息熵和比特(bit)的概念——比特是信息的基本计量单位。
参考文献核实:
Claude E. Shannon 的《A Mathematical Theory of Communication》被引用为参考文献,在References章节中被标记为[3]。
该理论本身内容繁多,但为了总结关键信息,请查看以下简短术语表:
- 信息无非是一系列符号,这些符号可以通过称为信道的媒介从接收者传输到发送者。例如,当我们给某人发短信时,符号序列就是我们使用的语言的字母/单词;信道就是电子媒介。
- 熵可以理解为在给定符号某种分布的情况下,符号序列中不确定性或惊讶度的量度。
- 比特,如前所述,是信息单位,是一个二进制数字。它可以是0或1。
现在,如果我们传输一比特信息,它就会将接收者的不确定性减少一半。为了更好地理解这一点,我们考虑抛硬币。我们将硬币抛向空中,当它在空中旋转时,我们不知道它是正面还是反面。但我们知道它会是这两种结果之一。当硬币落地并最终静止时,我们发现它是正面。我们可以用一比特信息来表示抛硬币的结果是正面还是反面(0代表正面,1代表反面)。因此,当硬币落下时传递给我们的信息将可能的结果从两个减少到一个(正面)。这个传递可以通过一比特信息完成。
在信息论中,离散随机变量的熵是其可能结果中固有的信息、惊讶度或不确定性的平均水平。用更专业的术语来说,它是表示随机变量中信息所需的最佳编码方案的预期比特数。
扩展阅读:
如果你想直观理解熵、交叉熵、Kullback-Leibler散度等概念,请参阅进一步阅读部分。那里有几个博客链接(其中一个是我的),我们尝试在这些博客中解释这些度量背后的直觉。
熵的正式定义如下:
$$H(X) = -\sum_{i=1}^{n} P(x_i) \cdot \log P(x_i)$$
这里,X 是离散随机变量,其可能结果为 x1、x2、…、xn。每个结果都有一个发生概率,表示为 P(x1)、P(x2)、…、P(xn)。
为了建立一些直观理解,我们可以认为概率分布越分散,分布中的混沌程度越高,从而熵也越大。我们快速用一些代码来验证一下:
# Creating an array with a well balanced probability distribution
flat = np.array([0.1,0.2, 0.3,0.2, 0.2])
# Calculating Entropy
print((-np.log2(flat)* flat).sum())
>> 2.2464393446710154
# Creating an array with a peak in probability
sharp = np.array([0.1,0.6, 0.1,0.1, 0.1])
# Calculating Entropy
print((-np.log2(sharp)* sharp).sum())
>> 1.7709505944546688
这里,我们可以看到,质量分布更分散的概率分布具有更高的熵。
在时间序列的背景下,n 是时间序列观测值的总数,P(xi) 是时间序列字母表中每个符号的概率。尖锐分布意味着时间序列值集中在一个小范围内,因而更容易预测。另一方面,宽或平坦分布意味着时间序列值在更宽的值范围内等可能地出现,因此难以预测。
如果我们有两个时间序列——一个包含抛硬币的结果,另一个包含掷骰子的结果——掷骰子会输出一到六之间的任意值,而抛硬币则要么是0要么是1。抛硬币时间序列的熵较低,比掷骰子时间序列更容易预测。
然而,由于时间序列通常是连续的,而熵需要离散随机变量,我们可以采取一些策略将连续时间序列转换为离散时间序列。可以应用许多策略,例如量化或分箱,这会导致大量的复杂性度量。让我们回顾一种有用且实用的度量。
谱熵
要计算时间序列的熵,我们需要对时间序列进行离散化。一种方法是使用快速傅里叶变换(FFT)和功率谱密度(PSD)。这种对连续时间序列的离散化用于计算谱熵。
我们在本章前面学习了什么是傅里叶变换,并用它生成了一个基线预测。但使用FFT,我们还可以估计一个称为功率谱密度的量。这回答了问题:信号中有多少成分位于特定频率? 从时间序列估计功率谱密度的方法有很多,但最简单的方法之一是使用Welch方法,这是一种基于离散傅里叶变换的非参数方法。该方法也作为一个便捷函数实现,其签名为periodogram(x),位于scipy中。
返回的PSD长度等于估计的频率数量,但这些是密度而非严格定义的概率。因此,我们需要将PSD归一化到0和1之间:
$$nPSD_i = \frac{PSD_i}{\sum_{j=1}^{F} PSD_j}$$
这里,F 是返回的功率谱密度中所包含的频率数量。
既然我们已经得到了概率,就可以直接将其代入熵公式,得到谱熵:
$$H_{s(X)} = -\sum_{i=1}^{n} nPSD_i \cdot \log(nPSD_i)$$
当我们介绍基于熵的度量时,我们看到,分布的概率质量越分散,熵就越大。在此背景下,谱密度分布跨越的频率越多,谱熵就越大。因此,更高的谱熵意味着时间序列更复杂,从而更难预测。
由于FFT具有平稳性假设,建议在使用谱熵作为度量之前使序列平稳。我们甚至可以将这个度量应用于去趋势和去季节化的时间序列,这可以称为残差谱熵。本书的GitHub仓库包含了谱熵的实现,位于src.forecastability.entropy.spectral_entropy。这个实现还有一个参数,transform_stationary,如果设置为True,将在应用谱熵之前对序列进行去趋势处理。让我们看看如何为我们的数据集计算谱熵:
from src.forecastability.entropy import spectral_entropy
block_df["spectral_entropy"] = block_df.energy_consumption.progress_apply(lambda x: spectral_entropy(x, transform_stationary=True))
block_df["residual_spectral_entropy"] = block_df.residuals.progress_apply(spectral_entropy)
还有其他基于熵的度量,如近似熵和样本熵,但本书不会涉及。它们计算量更大,且通常不适用于包含少于200个值的时间序列。如果你有兴趣了解更多关于这些度量的信息,请前往延伸阅读部分。部分。
另一种略有不同的度量是Kaboudan度量。
Kaboudan度量
1999年,Kaboudan定义了一个用于时间序列可预测性的度量,称之为$\eta$-度量。其背后的思想非常简单。如果我们对时间序列进行块洗牌,本质上是在破坏时间序列中的信息。 块洗牌是将时间序列划分为块,然后打乱这些块的过程。因此,如果我们计算在一个时间序列上训练的预测的(SSE)的(平方误差和),然后将其与在洗牌后的时间序列上训练的预测的SSE进行对比,就可以推断出该时间序列的可预测性。计算此值的公式如下:
$$\eta = 1 - \frac{SSE_Y}{SSE_S}$$
这里,SSEY 是从原始时间序列生成的预测的SSE,而SSES 是从块洗牌序列生成的预测的SSE。
如果时间序列包含一些可预测的信号,SSEY 将低于 将低于 SSES,且 且 $\eta$ 将趋近于1。这是因为块洗牌破坏了一些信息或模式。另一方面,如果序列只是白噪声(根据定义不可预测),则SSEY 与 与 SSES 之间几乎没有差异,且
2002年,Duan在他的论文中研究了这种度量并提出了一些修改。他发现的一个问题,特别是在长时间序列中,是$\eta$ 值在1附近的一个窄带内,并对公式提出了微调。我们称之为修正的Kaboudan度量。该。该度量的下限也被截断为零。有时,度量值可能低于零,因为 SSES 低于 低于 SSEY,这是因为序列不可预测且,因为
$$\eta_{modified} = 1 - \sqrt{\frac{SSE_Y}{SSE_S}}$$
参考文献核实:
提出 Kaboudan 度量的研究论文被引用于参考文献部分中的参考文献 4。Duan 随后建议的修改被引用于参考文献 5。
此修改版本以及原始版本均已实现于本书的 GitHub 仓库中。
对于生成预测所使用的预测模型没有限制,这使得它更加灵活。理想情况下,我们可以选择一种经典的统计方法,该方法足够快,可以应用于整个数据集。但这也使得 Kaboudan 度量依赖于模型,并且模型的局限性也内在于该度量中。该度量衡量的是序列预测的困难程度与模型预测该序列的困难程度的组合。
同样,这两种度量均已实现在本书的 GitHub 仓库中。让我们看看如何使用它们:
from src.forecastability.kaboudan import kaboudan_metric, modified_kaboudan_metric
model = Theta(theta=3, seasonality_period=48*7, season_mode=SeasonalityMode.ADDITIVE)
block_df["kaboudan_metric"] = [kaboudan_metric(r[0], model=model, block_size=5, backtesting_start=0.5, n_folds=1) for r in tqdm(zip(*block_df[["energy_consumption"]].to_dict("list").values()), total=len(block_df))]
block_df["modified_kaboudan_metric"] = [modified_kaboudan_metric(r[0], model=model, block_size=5, backtesting_start=0.5, n_folds=1) for r in tqdm(zip(*block_df[["energy_consumption"]].to_dict("list").values()), total=len(block_df))]
尽管我们可以使用更多度量来实现此目的,但我们刚刚回顾的用于评估可预测性的度量涵盖了许多常见用例,并且应该足以衡量任何时间序列数据集的预测难度。我们可以使用这些度量将一个时间序列与另一个时间序列进行比较,或者将数据集中一组相关的时间序列与另一个数据集进行基准测试。
扩展阅读:
如果你想更深入地研究这些度量的行为、它们之间的相似程度以及它们在衡量可预测性方面的有效性,请转到 03-Forecastability.ipynb 笔记本的末尾。我们计算这些度量之间的秩相关性,以了解它们之间的相似程度。我们还可以找到与最佳基线方法计算出的度量之间的秩相关性,以了解这些度量在估计时间序列可预测性方面的表现。我强烈建议你多尝试这个笔记本,并理解不同度量之间的差异。选择几个时间序列,并检查不同度量如何给出略有不同的解释。
恭喜你生成了基线预测——这是本书中生成的第一组预测!欢迎你前往笔记本,尝试调整方法的参数,看看预测结果如何变化。这将帮助你建立对基线方法工作原理的直觉。如果你想了解更多关于如何改进这些基线方法的信息,请前往 延伸阅读 部分,我们提供了 F. Petropoulos 和 E. Spiliotis 的论文 The Wisdom of the Data: Getting the Most Out of Univariate Time Series Forecasting 的链接。
小结
至此,我们结束了 第1部分:熟悉时间序列。从仅仅理解什么是时间序列到生成具有竞争力的基线预测,我们已经走了很长的路。在此过程中,我们学习了如何处理缺失值和异常值,以及如何使用 pandas 操作时间序列数据。我们将所有这些技能应用于一个关于能源消耗的真实世界数据集。我们还研究了可视化和分解时间序列的方法。在本章中,我们建立了一个测试框架,学习了如何使用 NIXTLA 库生成基线预测,并查看了一些可用于理解时间序列可预测性的度量。
对你们中的一些人来说,这可能是复习,我们希望本章在某些微妙之处和实际考虑方面增加了一些价值。对于其余的人,我们希望你们在基础上处于良好状态,以便在本书下一部分开始涉足使用机器学习的现代技术。
在下一章中,我们将讨论机器学习的基础知识,并深入探讨时间序列预测。
参考文献
本章提供了以下参考文献:
- Assimakopoulos, Vassilis and Nikolopoulos, K. (2000). The theta model: A decomposition approach to forecasting. International Journal of Forecasting. 16. 521-530. https://www.researchgate.net/publication/223049702_The_theta_model_A_decomposition_approach_to_forecasting.
- Rob J. Hyndman, Baki Billah. (2003). Unmasking the Theta method. International Journal of Forecasting. 19. 287-290. https://robjhyndman.com/papers/Theta.pdf.
- Shannon, C.E. (1948), A Mathematical Theory of Communication. Bell System Technical Journal, 27: 379-423. https://people.math.harvard.edu/~ctm/home/text/others/shannon/entropy/entropy.pdf.
- Kaboudan, M. (1999). A measure of time series’ predictability using genetic programming applied to stock returns. Journal of Forecasting, 18, 345-357: http://www.aiecon.org/conference/efmaci2004/pdf/GP_Basics_paper.pdf.
- Duan, M. (2002). TIME SERIES PREDICTABILITY: : https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.68.1898&rep=rep1&type=pdf.
- De Livera, A. M., & Hyndman, R. J. (2009). Forecasting time series with complex seasonal patterns using exponential smoothing (Department of Econometrics and Business Statistics Working Paper Series 15/09)
- Hyndman, Rob. “Rob J Hyndman - TBATS with Regressors.” Rob J Hyndman, 6 Oct. 2014, http://robjhyndman.com/hyndsight/tbats-with-regressors
延伸阅读
要了解更多关于本章涉及的主题,请参阅以下资源:
- 信息论与熵,作者:Manu Joseph:https://deep-and-shallow.com/2020/01/09/deep-learning-and-information-theory/。
- 视觉信息,作者:Chris Olah:https://colah.github.io/posts/2015-09-Visual-Information。
- 傅里叶变换:https://betterexplained.com/articles/an-interactive-guide-to-the-fourier-transform/。
- 傅里叶变换,作者:3blue1brown——视觉介绍:https://www.youtube.com/watch?v=spUNpyF58BY&vl=en。
- 通过示例理解傅里叶变换,作者:Richie Vink:https://www.ritchievink.com/blog/2017/04/23/understanding-the-fourier-transform-by-example/。
- Delgado-Bonal A, Marshak A. 近似熵与样本熵:综合教程。Entropy. 2019; 21(6):541:。https://www.mdpi.com/1099-4300/21/6/541。
- Yentes, J.M., Hunt, N., Schmid, K.K. et al. 近似熵与样本熵在短数据集中的适当使用。Ann Biomed Eng 41, 349–365 (2013):。https://doi.org/10.1007/s10439-012-0668-3
- Ponce-Flores M, Frausto-Solís J, Santamaría-Bonfil G, Pérez-Ortega J, González-Barbosa JJ. 时间序列复杂性及其与预测性能的关系。Entropy. 2020; 22(1):89.。https://www.mdpi.com/1099-4300/22/1/89
- Petropoulos F, Spiliotis E. 数据的智慧:从单变量时间序列预测中获取最大价值。Forecasting. 2021; 3(3):478-497.。https://doi.org/10.3390/forecast3030029
第2部分
时间序列的机器学习
在这一部分,我们将探讨如何应用现代机器学习技术进行时间序列预测。本部分还涵盖了强大的预测组合方法以及令人兴奋的全局模型新范式。通过本部分的学习,您将能够使用现代机器学习技术搭建用于时间序列预测的建模管道。
本部分包含以下章节:
- 第5章,时间序列预测作为回归
- 第6章,时间序列预测的特征工程
- 第7章,时间序列预测的目标变换
- 第8章,使用机器学习模型进行时间序列预测
- 第9章,集成与堆叠
- 第10章,全局预测模型