季节性指数平滑模型
使用 SeasonalExponentialSmoothing Model
和 Statsforecast
的逐步指南。
目录
- 引言
- 季节性指数平滑
- 加载库和数据
- 使用 plot 方法探索数据
- 将数据拆分为训练集和测试集
- 使用 StatsForecast 实现 SeasonalExponentialSmoothing
- 交叉验证
- 模型评估
- 参考资料
引言
简单指数平滑(SES)是一种预测方法,它使用历史值的加权平均值来预测下一个值。权重分配给最近的值,而最旧的值权重较低。这是因为 SES 假设最近的值比旧的值与预测未来更相关。
SES 通过一个简单的公式实现
平滑因子控制分配给最近值的权重大小。 α 值越高意味着分配给新值的权重越大,而 α 值越低意味着分配给旧值的权重越大。
时间序列中的季节性是指时间序列在特定时间段内规律、重复的变化模式。
季节性在时间序列分析中可能是一个挑战,因为它会掩盖数据中潜在的趋势。
季节性是分析时间序列数据时需要考虑的重要因素。通过理解数据中的季节性模式,可以做出更准确的预测和更好的决策。
季节性指数平滑模型
指数平滑方法中最简单的方法自然称为简单指数平滑(SES)。这种方法适用于预测没有明显趋势或季节性模式的数据。
使用朴素方法,所有未来预测都等于序列的最后一个观测值,
对于 。因此,朴素方法假设最近的观测值是唯一重要的,所有之前的观测值对未来没有任何信息。这可以被视为加权平均,其中所有权重都赋予最后一个观测值。
使用平均方法,所有未来预测都等于观测数据的简单平均值,
对于 。因此,平均方法假设所有观测值都同等重要,并在生成预测时赋予它们同等权重。
我们通常想要介于这两个极端之间的方法。例如,给最近的观测值比遥远的观测值赋予更大的权重可能更合理。这正是简单指数平滑背后的概念。预测使用加权平均值计算,其中权重随着观测值来自更远的过去而呈指数下降——最旧的观测值关联的权重最小
其中 是平滑参数。时间 的一步提前预测是序列 中所有观测值的加权平均。权重下降的速度由参数 控制。
对于 0 到 1 之间的任何 ,随着时间回溯,分配给观测值的权重呈指数下降,因此得名“指数平滑”。如果 很小(即接近 0),则更多权重给予更遥远的过去的观测值。如果 很大(即接近 1),则更多权重给予最近的观测值。对于极端情况 ,,预测等于朴素预测。
如何知道季节性参数的值?
要确定季节性调整简单指数平滑(SES Seasonally Adjusted)模型中季节性参数 s 的值,可以使用不同的方法,具体取决于数据的性质和分析的目标。
以下是一些确定季节性参数 值的常用方法
-
可视化分析: 可以对时间序列数据进行可视化分析,以识别任何季节性模式。如果在数据中观察到明显的季节性模式,可以将季节性周期的长度用作 的值。
-
统计方法: 可以使用统计技术(例如自相关)来识别数据中的季节性模式。 的值可以是自相关函数中观察到显著峰值的周期数。
-
频率分析: 可以对数据进行频率分析以识别季节性模式。 的值可以是频谱中观察到显著峰值的周期数。参见
-
试错法: 您可以尝试不同的 值,并选择使模型与数据最佳拟合的值。
值得注意的是, 值b的选择会显著影响季节性调整 SES 模型预测的准确性
。因此,建议在选择最终 值之前,测试不同的 值并使用适当的评估指标评估模型性能。
如何验证简单指数平滑模型和季节性调整?
为了验证季节性调整简单指数平滑(SES Seasonally Adjusted)模型,可以使用不同的定理和评估指标,具体取决于分析的目标和数据的性质。
以下是一些用于验证季节性调整 SES 模型的常用定理
-
高斯-马尔可夫定理:此定理表明,如果满足某些条件,则最小二乘估计量是最佳线性无偏估计量。在季节性调整 SES 的情况下,模型参数使用最小二乘法进行估计,因此可以使用高斯-马尔可夫定理来评估模型拟合的质量。
-
单位根定理:此定理用于确定时间序列是否平稳。如果时间序列不平稳,则季节性调整 SES 模型不适用,因为它假设时间序列是平稳的。因此,使用单位根定理来评估时间序列的平稳性并确定季节性调整 SES 模型是否合适。
-
Ljung-Box 定理:此定理用于评估模型拟合的优度,并确定模型残差是否为白噪声。如果残差是白噪声,则模型与数据拟合良好,模型预测准确。Ljung-Box 定理用于检验模型残差是否独立且不相关。
除了这些定理外,还可以使用各种评估指标,例如均方根误差 (MSE)、平均绝对误差 (MAE) 和确定系数 (R²),来评估季节性调整 SES 模型的性能并将其与其他预测模型进行比较。
加载库和数据
提示
需要 Statsforecast。要安装,请参见说明。
接下来,我们导入绘图库并配置绘图样式。
读取数据
时间 | 广告 | |
---|---|---|
0 | 2017-09-13T00:00:00 | 80115 |
1 | 2017-09-13T01:00:00 | 79885 |
2 | 2017-09-13T02:00:00 | 89325 |
3 | 2017-09-13T03:00:00 | 101930 |
4 | 2017-09-13T04:00:00 | 121630 |
StatsForecast 的输入始终是具有三列的长格式数据框:unique_id、ds 和 y
-
unique_id
(字符串、整数或类别) 代表序列的标识符。 -
ds
(日期戳) 列应采用 Pandas 预期的格式,日期最好是 YYYY-MM-DD,时间戳最好是 YYYY-MM-DD HH:MM:SS。 -
y
(数值) 代表我们希望预测的度量值。
ds | y | unique_id | |
---|---|---|---|
0 | 2017-09-13T00:00:00 | 80115 | 1 |
1 | 2017-09-13T01:00:00 | 79885 | 1 |
2 | 2017-09-13T02:00:00 | 89325 | 1 |
3 | 2017-09-13T03:00:00 | 101930 | 1 |
4 | 2017-09-13T04:00:00 | 121630 | 1 |
我们可以看到我们的时间变量 (ds)
是对象格式,我们需要将其转换为日期格式
使用 plot 方法探索数据
使用 StatsForecast 类中的 plot 方法绘制一些序列。此方法会随机打印数据集中的一个序列,对于基本 EDA 非常有用。
增强迪基-福勒检验
增强迪基-福勒 (ADF) 检验是一种统计检验,用于确定时间序列数据中是否存在单位根。单位根可能导致时间序列分析中出现不可预测的结果。在单位根检验中形成零假设,以确定时间序列数据受趋势影响的程度。接受零假设意味着我们接受时间序列数据不平稳的证据。拒绝零假设或接受备择假设意味着我们接受时间序列数据由平稳过程生成的证据。此过程也称为平稳趋势。ADF 检验统计量的值为负。ADF 值越低,对零假设的拒绝越强。
增强迪基-福勒检验是用于检验给定时间序列是否平稳的常用统计检验。我们可以通过定义零假设和备择假设来实现此目的。
零假设:时间序列是非平稳的。它给出时间依赖的趋势。备择假设:时间序列是平稳的。换句话说,该序列不依赖于时间。
ADF 或 t 统计量 < 临界值:拒绝零假设,时间序列平稳。ADF 或 t 统计量 > 临界值:未能拒绝零假设,时间序列非平稳。
自相关图
自相关 (ACF) 和偏自相关 (PACF) 的重要特征如下
自相关 (ACF):1. 识别时间依赖模式:ACF 显示观测值与其滞后值在不同时间间隔的关联性。有助于识别时间序列中的时间依赖模式,例如趋势或季节性的存在。
-
指示序列的“记忆”:ACF 允许我们确定过去的观测值对未来观测值的影响程度。如果 ACF 在多个滞后处显示显著自相关,则表明序列具有长期记忆,并且过去的观测值与预测未来观测值相关。
-
有助于识别 MA(移动平均)模型:ACF 的形状可以揭示时间序列中存在移动平均分量。ACF 显示显著相关性的滞后可能表明 MA 模型的阶数。
偏自相关 (PACF):1. 识别直接依赖:与 ACF 不同,PACF 消除了中间滞后的间接影响,并测量观测值与其滞后值之间的直接关联性。它有助于识别观测值与其滞后值之间的直接依赖关系,而不受中间滞后影响。
-
有助于识别 AR(自回归)模型:PACF 的形状可以揭示时间序列中存在自回归分量。PACF 显示显著相关性的滞后可能表明 AR 模型的阶数。
-
与 ACF 结合使用:PACF 与 ACF 结合使用以确定 AR 或 MA 模型的阶数。通过分析 ACF 和 PACF,可以识别显著滞后并构建适合时间序列分析和预测的模型。
总而言之,ACF 和 PACF 是时间序列分析中的互补工具,它们提供时间依赖信息并帮助识别构建预测模型的适当组件。
时间序列分解
如何分解时间序列以及为什么?
在时间序列分析中预测新值时,了解过去数据非常重要。更正式地说,了解值随时间变化的模式非常重要。有很多原因可能导致我们的预测值偏离正确方向。基本上,时间序列由四个组件组成。这些组件的变化导致时间序列模式的变化。这些组件是
- 水平 (Level): 这是随时间平均的主要值。
- 趋势 (Trend): 趋势是导致时间序列中出现增加或减少模式的值。
- 季节性 (Seasonality): 这是时间序列中短时间发生的周期性事件,会导致时间序列中出现短期增加或减少的模式。
- 残差/噪声 (Residual/Noise): 这些是时间序列中的随机变化。
这些组件随时间组合在一起形成时间序列。大多数时间序列由水平和噪声/残差组成,趋势或季节性是可选值。
如果季节性和趋势是时间序列的一部分,那么将对预测值产生影响。因为预测时间序列的模式可能与之前的时间序列不同。
时间序列中组件的组合可以是两种类型:* 加性 * 乘性
加性时间序列
如果时间序列的组件相加构成时间序列。那么该时间序列称为加性时间序列。通过可视化,我们可以说如果时间序列的增加或减少模式在整个序列中相似,那么该时间序列就是加性的。任何加性时间序列的数学函数可以表示为:
乘性时间序列
如果时间序列的组件相乘在一起,那么该时间序列称为乘性时间序列。对于可视化,如果时间序列随时间呈指数增长或下降,则该时间序列可被视为乘性时间序列。乘性时间序列的数学函数可以表示为。
加性
乘性
将数据拆分为训练集和测试集
我们将数据分成集合
- 用于训练我们的
Seasonal Exponential Smoothing Model
的数据。 - 用于测试我们的模型的数据
对于测试数据,我们将使用最近 30 小时的数据来测试和评估我们模型的性能。
现在让我们绘制训练数据和测试数据。
使用 StatsForecast 实现 SeasonalExponentialSmoothing
加载库
实例化模型
导入并实例化模型。设置参数有时很棘手。Rob Hyndmann 大师的这篇关于季节性周期的文章对于确定 season_length
会很有帮助。
我们通过使用以下参数实例化新的 StatsForecast 对象来拟合模型
models: 模型列表。从 models 中选择您需要的模型并导入它们。
-
freq:
表示数据频率的字符串。(参见 pandas 可用的频率别名)。 -
n_jobs:
n_jobs: int,并行处理中使用的作业数,使用 -1 表示所有核心。 -
fallback_model:
如果模型失败则使用的模型。
任何设置都传入构造函数。然后调用其 fit 方法并传入历史数据框。
拟合模型
让我们看看我们的 Seasonal Exponential Smoothing Model
的结果。我们可以通过以下指令观察它
现在让我们可视化我们模型的拟合值。
正如我们所见,上面获得的结果是一个字典输出,要从字典中提取每个元素,我们将使用 .get()
函数提取元素,然后将其保存在 pd.DataFrame()
中。
拟合值 | ds | |
---|---|---|
0 | NaN | 2017-09-13 00:00:00 |
1 | NaN | 2017-09-13 01:00:00 |
2 | NaN | 2017-09-13 02:00:00 |
... | ... | ... |
183 | 145443.734375 | 2017-09-20 15:00:00 |
184 | 150638.000000 | 2017-09-20 16:00:00 |
185 | 155233.093750 | 2017-09-20 17:00:00 |
预测方法
如果您想在具有多个序列或模型的生产环境中提高速度,我们建议使用 StatsForecast.forecast
方法而不是 .fit
和 .predict
。
主要区别在于 .forecast
不存储拟合值,并且在分布式环境中具有高度可扩展性。
forecast 方法接受两个参数:预测接下来的 h
(horizon) 和 level
。
h (int):
表示未来 h 步的预测。在本例中,为未来 30 小时。
这里的 forecast 对象是一个新的数据框,它包含一列模型的名称和 y hat 值,以及不确定性区间列。根据您的计算机,此步骤大约需要 1 分钟。
unique_id | ds | 季节性指数平滑 | |
---|---|---|---|
0 | 1 | 2017-09-20 18:00:00 | 161567.593750 |
1 | 1 | 2017-09-20 19:00:00 | 163186.562500 |
2 | 1 | 2017-09-20 20:00:00 | 134410.937500 |
... | ... | ... | ... |
27 | 1 | 2017-09-21 21:00:00 | 106145.601562 |
28 | 1 | 2017-09-21 22:00:00 | 93383.164062 |
29 | 1 | 2017-09-21 23:00:00 | 79489.718750 |
unique_id | ds | y | 季节性指数平滑 | |
---|---|---|---|---|
0 | 1 | 2017-09-13 00:00:00 | 80115.0 | NaN |
1 | 1 | 2017-09-13 01:00:00 | 79885.0 | NaN |
2 | 1 | 2017-09-13 02:00:00 | 89325.0 | NaN |
3 | 1 | 2017-09-13 03:00:00 | 101930.0 | NaN |
4 | 1 | 2017-09-13 04:00:00 | 121630.0 | NaN |
带有置信区间的 predict 方法
使用 predict 方法生成预测。
predict 方法接受两个参数:预测接下来的 h
(for horizon) 和 level
。
h (int):
表示未来 h 步的预测。在本例中,为未来 30 小时。
这里的 forecast 对象是一个新的数据框,它包含一列模型的名称和 y hat 值,以及不确定性区间列。
此步骤应该不到 1 秒。
unique_id | ds | 季节性指数平滑 | |
---|---|---|---|
0 | 1 | 2017-09-20 18:00:00 | 161567.593750 |
1 | 1 | 2017-09-20 19:00:00 | 163186.562500 |
2 | 1 | 2017-09-20 20:00:00 | 134410.937500 |
... | ... | ... | ... |
27 | 1 | 2017-09-21 21:00:00 | 106145.601562 |
28 | 1 | 2017-09-21 22:00:00 | 93383.164062 |
29 | 1 | 2017-09-21 23:00:00 | 79489.718750 |
交叉验证
在前面的步骤中,我们使用了历史数据来预测未来。然而,为了评估其准确性,我们也希望知道模型在过去的表现如何。要评估模型在您的数据上的准确性和稳健性,请执行交叉验证。
对于时间序列数据,交叉验证是通过在历史数据上定义滑动窗口并预测其后的周期来完成的。这种形式的交叉验证使我们能够更好地估计模型在更广泛的时间实例上的预测能力,同时保持训练集中的数据连续,这是我们的模型所必需的。
下图描绘了这种交叉验证策略
执行时间序列交叉验证
时间序列模型的交叉验证被认为是最佳实践,但大多数实现速度很慢。statsforecast 库将交叉验证实现为分布式操作,从而减少执行过程的时间。如果您有大型数据集,您还可以使用 Ray、Dask 或 Spark 在分布式集群中执行交叉验证。
在这种情况下,我们希望评估每个模型在过去 5 个月(n_windows=5
)的性能,每隔一个月进行预测(step_size=12
)。根据您的计算机,此步骤大约需要 1 分钟。
StatsForecast 类中的 cross_validation 方法接受以下参数。
-
df:
训练数据框 -
h (int):
表示预测的未来 h 步。在本例中,为未来 30 小时。 -
step_size (int):
每个窗口之间的步长。换句话说:您希望多久运行一次预测过程。 -
n_windows(int):
用于交叉验证的窗口数。换句话说:您要评估过去多少个预测过程。
crossvalidation_df 对象是一个新的数据框,包含以下列
unique_id:
序列标识符。ds:
日期戳或时间索引cutoff:
n_windows 的最后一个日期戳或时间索引。y:
真实值"model":
模型名称和拟合值的列。
unique_id | ds | 截止日期 | y | 季节性指数平滑 | |
---|---|---|---|---|---|
0 | 1 | 2017-09-19 18:00:00 | 2017-09-19 17:00:00 | 161385.0 | 162297.953125 |
1 | 1 | 2017-09-19 19:00:00 | 2017-09-19 17:00:00 | 165010.0 | 155892.812500 |
2 | 1 | 2017-09-19 20:00:00 | 2017-09-19 17:00:00 | 134090.0 | 135694.703125 |
... | ... | ... | ... | ... | ... |
87 | 1 | 2017-09-21 21:00:00 | 2017-09-20 17:00:00 | 103080.0 | 106145.601562 |
88 | 1 | 2017-09-21 22:00:00 | 2017-09-20 17:00:00 | 95155.0 | 93383.164062 |
89 | 1 | 2017-09-21 23:00:00 | 2017-09-20 17:00:00 | 80285.0 | 79489.718750 |
模型评估
现在我们将使用预测结果评估我们的模型,我们将使用不同类型的指标 MAE、MAPE、MASE、RMSE、SMAPE 来评估准确性。
unique_id | 指标 | 季节性指数平滑 | |
---|---|---|---|
0 | 1 | mae | 5728.207812 |
1 | 1 | mape | 0.049386 |
2 | 1 | mase | 0.707731 |
3 | 1 | rmse | 7290.840738 |
4 | 1 | smape | 0.024009 |
致谢
我们要感谢 Naren Castellon 撰写此教程。
参考资料
- Changquan Huang • Alla Petukhina. Springer series (2022). Applied Time Series Analysis and Forecasting with Python.
- Ivan Svetunkov. 使用增强动态自适应模型 (ADAM) 进行预测和分析
- James D. Hamilton. Time Series Analysis Princeton University Press, Princeton, New Jersey, 1st Edition, 1994.
- Nixtla 参数.
- Pandas 可用频率.
- Rob J. Hyndman 和 George Athanasopoulos (2018). “Forecasting Principles and Practice (第 3 版)”.
- 季节性周期 - Rob J Hyndman.