import warnings
'ignore')
warnings.simplefilter(
import logging
'statsforecast').setLevel(logging.ERROR) logging.getLogger(
概率预测
在这个例子中,我们将实现预测区间
本教程假设对StatsForecast有基本的了解。有关最小示例,请访问快速开始
引言
当我们生成预测时,通常会产生一个称为点预测的单一值。然而,这个值并不能告诉我们与预测相关的不确定性。为了衡量这种不确定性,我们需要预测区间。
预测区间是一组值,它表示预测在给定概率下可能取的范围。因此,95%的预测区间应该包含一个范围,这个范围以95%的概率包含实际未来值。概率预测旨在生成完整的预测分布。相反,点预测通常返回该分布的平均值或中位数。然而,在现实场景中,预测不仅最可能的未来结果,还应包括许多替代结果。
StatsForecast有很多模型可以生成点预测。它还提供可以生成相同点预测及其预测区间的概率模型。这些模型是随机数据生成过程,可以产生完整的预测分布。在本教程结束时,您将对StatsForecast中可用的概率模型有一个良好的理解,并能够使用它们生成点预测和预测区间。此外,您还将学习如何生成包含历史数据、点预测和预测区间的图表。
尽管这两个术语经常被混淆,但预测区间与置信区间并不相同。
在实际中,大多数预测区间过于狭窄,因为模型未考虑所有不确定性来源。关于这一点的讨论可以在 这里 找到。
大纲:
- 安装库
- 加载和探索数据
- 训练模型
- 绘制预测区间
安装库
我们假设您已经安装了StatsForecast。如果没有,请查看本指南了解如何安装StatsForecast的说明。
使用pip install statsforecast
安装必要的包
%%capture
-U pip install statsforecast
加载和探索数据
在这个例子中,我们将使用来自M4竞赛的每小时数据集。我们首先需要从一个URL下载数据,然后将其加载为pandas
数据框。请注意,我们将分别加载训练数据和测试数据。我们还将把测试数据的y
列重命名为y_test
。
import pandas as pd
= pd.read_csv('https://auto-arima-results.s3.amazonaws.com/M4-Hourly.csv')
train = pd.read_csv('https://auto-arima-results.s3.amazonaws.com/M4-Hourly-test.csv').rename(columns={'y': 'y_test'}) 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个系列以减少总计算时间。
= 8
n_series = train['unique_id'].unique()[:n_series] # 选择数据集中的前n_series个序列
uids = train.query('unique_id in @uids')
train = test.query('unique_id in @uids') test
我们可以使用来自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
= False) StatsForecast.plot(train, test, plot_random
/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 =24),
AutoETS(season_length
HistoricAverage(),
Naive(),
RandomWalkWithDrift(), =24)
SeasonalNaive(season_length ]
要实例化一个新的 StatsForecast 对象,我们需要以下参数:
df
:包含训练数据的数据框。models
:在前一步中定义的模型列表。freq
:一个字符串,指示数据的频率。请参见 pandas 可用的频率。n_jobs
:一个整数,用于指示并行处理时使用的作业数。使用 -1 选择所有核心。
= StatsForecast(
sf =train,
df=models,
models='H',
freq=-1
n_jobs )
现在我们准备生成点预测和预测区间。为此,我们将使用 forecast
方法,该方法需要两个参数:
h
:一个整数,表示预测的时间范围。在这种情况下,我们将预测接下来的48小时。level
:一个浮点数列表,表示预测区间的置信水平。例如,level=[95]
表示值的范围应该以95%的概率包含实际的未来值。
= [80, 90, 95, 99] # 预测区间的置信水平
levels
= sf.forecast(h=48, level=levels)
forecasts = forecasts.reset_index()
forecasts 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.merge(forecasts, how='left', on=['unique_id', 'ds']) test
绘制预测区间
为了绘制点和预测区间,我们将再次使用 statsforecast.plot
方法。请注意,现在我们还需要指定我们想要绘制的模型和水平。
自动ETS
= 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) sf.plot(train, test, plot_random
从这些图中,我们可以得出结论,每个预测周围的不确定性取决于所使用的模型。对于相同的时间序列,一个模型可能预测出比其他模型更广泛的可能未来值范围。
参考文献
Rob J. Hyndman 和 George Athanasopoulos (2018). “预测原则与实践,统计预测的视角”。
Give us a ⭐ on Github