import warnings
warnings.simplefilter('ignore')
import logging
logging.getLogger('statsforecast').setLevel(logging.ERROR)概率预测
在这个例子中,我们将实现预测区间
本教程假设对StatsForecast有基本的了解。有关最小示例,请访问快速开始
引言
当我们生成预测时,通常会产生一个称为点预测的单一值。然而,这个值并不能告诉我们与预测相关的不确定性。为了衡量这种不确定性,我们需要预测区间。
预测区间是一组值,它表示预测在给定概率下可能取的范围。因此,95%的预测区间应该包含一个范围,这个范围以95%的概率包含实际未来值。概率预测旨在生成完整的预测分布。相反,点预测通常返回该分布的平均值或中位数。然而,在现实场景中,预测不仅最可能的未来结果,还应包括许多替代结果。
StatsForecast有很多模型可以生成点预测。它还提供可以生成相同点预测及其预测区间的概率模型。这些模型是随机数据生成过程,可以产生完整的预测分布。在本教程结束时,您将对StatsForecast中可用的概率模型有一个良好的理解,并能够使用它们生成点预测和预测区间。此外,您还将学习如何生成包含历史数据、点预测和预测区间的图表。
尽管这两个术语经常被混淆,但预测区间与置信区间并不相同。
在实际中,大多数预测区间过于狭窄,因为模型未考虑所有不确定性来源。关于这一点的讨论可以在 这里 找到。
大纲:
- 安装库
- 加载和探索数据
- 训练模型
- 绘制预测区间
安装库
我们假设您已经安装了StatsForecast。如果没有,请查看本指南了解如何安装StatsForecast的说明。
使用pip install statsforecast安装必要的包
%%capture
pip install statsforecast -U加载和探索数据
在这个例子中,我们将使用来自M4竞赛的每小时数据集。我们首先需要从一个URL下载数据,然后将其加载为pandas数据框。请注意,我们将分别加载训练数据和测试数据。我们还将把测试数据的y列重命名为y_test。
import pandas as pd
train = pd.read_csv('https://auto-arima-results.s3.amazonaws.com/M4-Hourly.csv')
test = pd.read_csv('https://auto-arima-results.s3.amazonaws.com/M4-Hourly-test.csv').rename(columns={'y': 'y_test'})train.head()| unique_id | ds | y | |
|---|---|---|---|
| 0 | H1 | 1 | 605.0 |
| 1 | H1 | 2 | 586.0 |
| 2 | H1 | 3 | 586.0 |
| 3 | H1 | 4 | 559.0 |
| 4 | H1 | 5 | 511.0 |
test.head()| unique_id | ds | y_test | |
|---|---|---|---|
| 0 | H1 | 701 | 619.0 |
| 1 | H1 | 702 | 565.0 |
| 2 | H1 | 703 | 532.0 |
| 3 | H1 | 704 | 495.0 |
| 4 | H1 | 705 | 481.0 |
由于本笔记的目的是生成预测区间,我们将仅使用数据集中的前8个系列以减少总计算时间。
n_series = 8
uids = train['unique_id'].unique()[:n_series] # 选择数据集中的前n_series个序列
train = train.query('unique_id in @uids')
test = test.query('unique_id in @uids')我们可以使用来自StatsForecast类的statsforecast.plot方法绘制这些系列。该方法有多个参数,生成本笔记本中图形所需的参数如下所述。
df:一个包含[unique_id, ds, y]列的pandas数据框。forecasts_df:一个包含[unique_id, ds]和模型的pandas数据框。plot_random:bool =True。随机绘制时间序列。models:List[str]。一个我们想要绘制的模型列表。level:List[float]。一个我们想要绘制的预测区间列表。engine:str =plotly。也可以是matplotlib。plotly生成交互式图形,而matplotlib生成静态图形。
from statsforecast import StatsForecast
StatsForecast.plot(train, test, plot_random = False)/Users/fedex/projects/statsforecast/statsforecast/core.py:21: TqdmExperimentalWarning: Using `tqdm.autonotebook.tqdm` in notebook mode. Use `tqdm.tqdm` instead to force console mode (e.g. in jupyter console)
from tqdm.autonotebook import tqdm
训练模型
StatsForecast 可以高效地在不同的时间序列上训练多个 模型。大多数模型可以生成概率预测,这意味着它们可以同时产生点预测和预测区间。
在这个例子中,我们将使用 AutoETS 以及以下基准模型:
要使用这些模型,我们首先需要从 statsforecast.models 中导入它们,然后实例化这些模型。由于我们正在处理每小时的数据,因此在需要该参数的模型中,我们需要设置 seasonal_length=24。
from statsforecast.models import (
AutoETS,
HistoricAverage,
Naive,
RandomWalkWithDrift,
SeasonalNaive
)
# 创建一个模型及其实例化参数的列表
models = [
AutoETS(season_length=24),
HistoricAverage(),
Naive(),
RandomWalkWithDrift(),
SeasonalNaive(season_length=24)
]要实例化一个新的 StatsForecast 对象,我们需要以下参数:
df:包含训练数据的数据框。models:在前一步中定义的模型列表。freq:一个字符串,指示数据的频率。请参见 pandas 可用的频率。n_jobs:一个整数,用于指示并行处理时使用的作业数。使用 -1 选择所有核心。
sf = StatsForecast(
df=train,
models=models,
freq='H',
n_jobs=-1
) 现在我们准备生成点预测和预测区间。为此,我们将使用 forecast 方法,该方法需要两个参数:
h:一个整数,表示预测的时间范围。在这种情况下,我们将预测接下来的48小时。level:一个浮点数列表,表示预测区间的置信水平。例如,level=[95]表示值的范围应该以95%的概率包含实际的未来值。
levels = [80, 90, 95, 99] # 预测区间的置信水平
forecasts = sf.forecast(h=48, level=levels)
forecasts = forecasts.reset_index()
forecasts.head()| unique_id | ds | AutoETS | AutoETS-lo-99 | AutoETS-lo-95 | AutoETS-lo-90 | AutoETS-lo-80 | AutoETS-hi-80 | AutoETS-hi-90 | AutoETS-hi-95 | ... | RWD-hi-99 | SeasonalNaive | SeasonalNaive-lo-80 | SeasonalNaive-lo-90 | SeasonalNaive-lo-95 | SeasonalNaive-lo-99 | SeasonalNaive-hi-80 | SeasonalNaive-hi-90 | SeasonalNaive-hi-95 | SeasonalNaive-hi-99 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | H1 | 701 | 631.889587 | 533.371826 | 556.926819 | 568.978882 | 582.874084 | 680.905090 | 694.800354 | 706.852356 | ... | 789.416626 | 691.0 | 582.823792 | 552.157349 | 525.558777 | 473.573395 | 799.176208 | 829.842651 | 856.441223 | 908.426575 |
| 1 | H1 | 702 | 559.750854 | 460.738586 | 484.411835 | 496.524353 | 510.489288 | 609.012329 | 622.977295 | 635.089844 | ... | 833.254150 | 618.0 | 509.823822 | 479.157379 | 452.558807 | 400.573395 | 726.176208 | 756.842651 | 783.441223 | 835.426575 |
| 2 | H1 | 703 | 519.235474 | 419.731232 | 443.522095 | 455.694794 | 469.729156 | 568.741821 | 582.776123 | 594.948853 | ... | 866.990601 | 563.0 | 454.823822 | 424.157379 | 397.558807 | 345.573395 | 671.176208 | 701.842651 | 728.441223 | 780.426575 |
| 3 | H1 | 704 | 486.973358 | 386.979523 | 410.887451 | 423.120056 | 437.223480 | 536.723267 | 550.826660 | 563.059265 | ... | 895.510132 | 529.0 | 420.823822 | 390.157379 | 363.558807 | 311.573395 | 637.176208 | 667.842651 | 694.441223 | 746.426575 |
| 4 | H1 | 705 | 464.697357 | 364.216339 | 388.240753 | 400.532959 | 414.705078 | 514.689636 | 528.861755 | 541.153992 | ... | 920.702881 | 504.0 | 395.823822 | 365.157379 | 338.558807 | 286.573395 | 612.176208 | 642.842651 | 669.441223 | 721.426575 |
5 rows × 47 columns
我们现在将预测结果及其预测区间与测试集进行合并。这将使我们能够生成每个概率模型的图表。
test = test.merge(forecasts, how='left', on=['unique_id', 'ds'])绘制预测区间
为了绘制点和预测区间,我们将再次使用 statsforecast.plot 方法。请注意,现在我们还需要指定我们想要绘制的模型和水平。
自动ETS
sf.plot(train, test, plot_random = False, models=['AutoETS'], level=levels)历史平均值
sf.plot(train, test, plot_random = False, models=['HistoricAverage'], level=levels)天真的
sf.plot(train, test, plot_random = False, models=['Naive'], level=levels)带漂移的随机游走
sf.plot(train, test, plot_random = False, models=['RWD'], level=levels)季节性简单预测
sf.plot(train, test, plot_random = False, models=['SeasonalNaive'], level=levels)从这些图中,我们可以得出结论,每个预测周围的不确定性取决于所使用的模型。对于相同的时间序列,一个模型可能预测出比其他模型更广泛的可能未来值范围。
参考文献
Rob J. Hyndman 和 George Athanasopoulos (2018). “预测原则与实践,统计预测的视角”。
Give us a ⭐ on Github