# 取消注释以下行以安装库
# %pip 安装 statsforecast
外生回归变量
在本笔记本中,我们将把外生回归变量纳入StatsForecast模型中。
本教程假设您对StatsForecast有基本的了解。有关最小示例,请访问快速入门
引言
外生回归变量是指可能影响时间序列值的变量。它们可能与正在预测的变量没有直接关系,但仍然可以对其产生影响。外生回归变量的例子包括天气数据、经济指标或促销销售。它们通常来自外部来源,通过将这些变量纳入预测模型,可以提高我们预测的准确性。
在本教程结束时,您将对如何将外生回归变量纳入StatsForecast的模型有一个良好的理解。此外,您还将看到如何评估它们的性能,并决定它们是否能够帮助改善预测。
大纲
- 安装库
- 加载和探索数据
- 拆分训练/测试集
- 添加外生回归变量
- 创建未来外生回归变量
- 训练模型
- 评估结果
安装库
我们假设您已经安装了StatsForecast。如果没有,请查看本指南以获取如何安装StatsForecast的说明。
import os
import pandas as pd
# 这样,预测方法的输出结果中就会包含一个id列。
# 而不是作为索引
'NIXTLA_ID_AS_COL'] = '1' os.environ[
加载和探索数据
在本例中,我们将使用来自 M5 Competition 数据集的单个时间序列。该序列代表了一家沃尔玛商店中某产品的每日销售情况。我们将在本笔记中使用的产品-商店组合的 unique_id = FOODS_3_586_CA_3
。选择这个时间序列是因为它不是间歇性的,并且具有对预测有用的外生回归变量。
我们将加载以下数据帧:
Y_ts
: (pandas DataFrame) 目标时间序列,包含列 [unique_id
,ds
,y
]。X_ts
: (pandas DataFrame) 外生时间序列,包含列 [unique_id
,ds
, 外生回归变量]。
= 'https://datasets-nixtla.s3.amazonaws.com'
base_url = [('unique_id', '=', 'FOODS_3_586_CA_3')]
filters = pd.read_parquet(f'{base_url}/m5_y.parquet', filters=filters)
Y_ts = pd.read_parquet(f'{base_url}/m5_x.parquet', filters=filters) X_ts
我们可以使用来自StatsForecast类的statsforecast.plot
方法来绘制这个产品-商店组合的销售情况。此方法有多个参数,在本笔记本中生成图表所需的参数在下面进行了说明。
df
:一个包含[unique_id
,ds
,y
]列的pandas数据框。forecasts_df
:一个包含[unique_id
,ds
]及模型的pandas数据框。engine
:str =matplotlib
。也可以是plotly
。plotly
生成交互式图表,而matplotlib
生成静态图表。
from statsforecast import StatsForecast
StatsForecast.plot(Y_ts)
M5竞赛包括几个外生回归变量。在这里,我们将使用以下两个。
sell_price
: 给定商店的产品价格。价格按周提供。snap_CA
: 一个二元变量,指示商店是否允许SNAP购买(如果允许则为1,否则为0)。SNAP代表补充营养援助计划,它为个人和家庭提供资金,以帮助他们购买食品产品。
= X_ts[['unique_id', 'ds', 'sell_price', 'snap_CA']]
X_ts X_ts.head()
unique_id | ds | sell_price | snap_CA | |
---|---|---|---|---|
0 | FOODS_3_586_CA_3 | 2011-01-29 | 1.48 | 0 |
1 | FOODS_3_586_CA_3 | 2011-01-30 | 1.48 | 0 |
2 | FOODS_3_586_CA_3 | 2011-01-31 | 1.48 | 0 |
3 | FOODS_3_586_CA_3 | 2011-02-01 | 1.48 | 1 |
4 | FOODS_3_586_CA_3 | 2011-02-02 | 1.48 | 1 |
在这里,unique_id
是一个类别,但对于外生回归变量,它需要是一个字符串。
'unique_id'] = X_ts.unique_id.astype(str) X_ts[
我们可以使用plotly
绘制外生回归变量。我们可以使用statsforecast.plot
,但那时必须将一个回归变量重命名为y
,并且在生成预测之前必须将名称改回原始名称。
=0) StatsForecast.plot(Y_ts, X_ts, max_insample_length
从这个图中,我们可以得出结论:价格已增加两倍,并且SNAP在规则的间隔发生。
切分训练/测试集
在M5竞赛中,参与者需要预测数据集中最后28天的销售额。我们将使用相同的预测范围,并相应地创建训练集和测试集。
# 提取训练集和测试集的日期
= Y_ts['ds'].unique()
dates = dates[:-28]
dtrain = dates[-28:]
dtest
= Y_ts.query('ds in @dtrain')
Y_train = Y_ts.query('ds in @dtest')
Y_test
= X_ts.query('ds in @dtrain')
X_train = X_ts.query('ds in @dtest') X_test
添加外部回归变量
外生回归变量需要放在目标变量 y
之后。
= Y_train.merge(X_ts, how = 'left', on = ['unique_id', 'ds'])
train train.head()
unique_id | ds | y | sell_price | snap_CA | |
---|---|---|---|---|---|
0 | FOODS_3_586_CA_3 | 2011-01-29 | 56.0 | 1.48 | 0 |
1 | FOODS_3_586_CA_3 | 2011-01-30 | 55.0 | 1.48 | 0 |
2 | FOODS_3_586_CA_3 | 2011-01-31 | 45.0 | 1.48 | 0 |
3 | FOODS_3_586_CA_3 | 2011-02-01 | 57.0 | 1.48 | 1 |
4 | FOODS_3_586_CA_3 | 2011-02-02 | 54.0 | 1.48 | 1 |
创建未来的外生回归变量
我们需要包含外生回归变量的未来值,以便能够生成预测。请注意,我们已经在X_test
中拥有这些信息。
X_test.head()
unique_id | ds | sell_price | snap_CA | |
---|---|---|---|---|
1941 | FOODS_3_586_CA_3 | 2016-05-23 | 1.68 | 0 |
1942 | FOODS_3_586_CA_3 | 2016-05-24 | 1.68 | 0 |
1943 | FOODS_3_586_CA_3 | 2016-05-25 | 1.68 | 0 |
1944 | FOODS_3_586_CA_3 | 2016-05-26 | 1.68 | 0 |
1945 | FOODS_3_586_CA_3 | 2016-05-27 | 1.68 | 0 |
如果外生回归变量的未来值不可用,则必须进行预测,或者需要从模型中消除这些回归变量。没有它们,就无法生成预测。
训练模型
为了生成预测,我们将使用 AutoARIMA,这是 StatsForecast 中可用的模型之一,允许外生回归变量。要使用此模型,我们首先需要从 statsforecast.models
导入它,然后我们需要实例化它。考虑到我们正在处理日数据,我们需要设置 season_length = 7
。
from statsforecast.models import AutoARIMA
# 创建一个包含模型及其实例化参数的列表
= [AutoARIMA(season_length=7)] models
接下来,我们需要实例化一个新的 StatsForecast 对象,其具有以下参数:
df
:包含训练数据的数据框。models
:在前一步中定义的模型列表。freq
:一个字符串,指示数据的频率。请参见 pandas 可用的频率。n_jobs
:一个整数,指示用于并行处理的作业数量。使用 -1 来选择所有核心。
= StatsForecast(
sf =models,
models='D',
freq=1,
n_jobs )
现在我们准备生成预测。为此,我们将使用 forecast
方法,接受以下参数。
h
:一个整数,代表预测的时间范围。在这种情况下,我们将预测接下来的28天。X_df
:一个 pandas 数据框,包含外生回归变量的未来值。level
:一个包含预测区间置信水平的浮点数列表。例如,level=[95]
表示该值范围应以95%的概率包含实际未来值。
= 28
horizon = [95]
level
= sf.forecast(df=train, h=horizon, X_df=X_test, level=level)
fcst fcst.head()
unique_id | ds | AutoARIMA | AutoARIMA-lo-95 | AutoARIMA-hi-95 | |
---|---|---|---|---|---|
0 | FOODS_3_586_CA_3 | 2016-05-23 | 72.956276 | 44.109070 | 101.803482 |
1 | FOODS_3_586_CA_3 | 2016-05-24 | 71.138611 | 40.761467 | 101.515747 |
2 | FOODS_3_586_CA_3 | 2016-05-25 | 68.140945 | 37.550083 | 98.731804 |
3 | FOODS_3_586_CA_3 | 2016-05-26 | 65.485588 | 34.841637 | 96.129539 |
4 | FOODS_3_586_CA_3 | 2016-05-27 | 64.961441 | 34.291973 | 95.630905 |
我们可以使用上述描述的 statsforecast.plot
方法绘制预测结果。
=28*2) StatsForecast.plot(Y_ts, fcst, max_insample_length
评估结果
我们将合并测试集和预测结果,以使用平均绝对误差 (MAE) 评估准确性。
= Y_test.merge(fcst, how='left', on=['unique_id', 'ds'])
res res.head()
unique_id | ds | y | AutoARIMA | AutoARIMA-lo-95 | AutoARIMA-hi-95 | |
---|---|---|---|---|---|---|
0 | FOODS_3_586_CA_3 | 2016-05-23 | 66.0 | 72.956276 | 44.109070 | 101.803482 |
1 | FOODS_3_586_CA_3 | 2016-05-24 | 62.0 | 71.138611 | 40.761467 | 101.515747 |
2 | FOODS_3_586_CA_3 | 2016-05-25 | 40.0 | 68.140945 | 37.550083 | 98.731804 |
3 | FOODS_3_586_CA_3 | 2016-05-26 | 72.0 | 65.485588 | 34.841637 | 96.129539 |
4 | FOODS_3_586_CA_3 | 2016-05-27 | 69.0 | 64.961441 | 34.291973 | 95.630905 |
= abs(res['y']-res['AutoARIMA']).mean()
mae print('The MAE with exogenous regressors is '+str(round(mae,2)))
The MAE with exogenous regressors is 11.42
为了检查外生回归变量是否有用,我们需要重新生成预测,这次不使用这些变量。为此,我们只需将不包含外生变量的数据框传递给 forecast
方法。请注意,数据仅包括 unique_id
、ds
和 y
。forecast
方法不再需要外生回归变量 X_df
的未来值。
# 单变量模型
= sf.forecast(df=train[['unique_id', 'ds', 'y']], h=28)
fcst_u
= Y_test.merge(fcst_u, how='left', on=['unique_id', 'ds'])
res_u = abs(res_u['y']-res_u['AutoARIMA']).mean() mae_u
print('The MAE without exogenous regressors is '+str(round(mae_u,2)))
The MAE without exogenous regressors is 12.18
因此,我们可以得出结论,使用 sell_price
和 snap_CA
作为外部回归变量有助于提高预测精度。
Give us a ⭐ on Github