自学内容网 自学内容网

Merlion笔记(三):多变量时间序列预测

1 多变量时间序列预测

1.1 加载数据集

多变量时间序列预测的工作方式类似于单变量时间序列预测。主要的区别在于必须指定目标单变量的索引进行预测。例如,对于一个包含5个变量的时间序列,可能希望预测第3个变量的值(通过指定 target_seq_index = 2 来表示)。

首先加载用于时间序列预测的多变量 SeattleTrail 数据集。

from merlion.utils import TimeSeries
from ts_datasets.forecast import SeattleTrail

time_series, metadata = SeattleTrail()[0]
train_data = TimeSeries.from_pd(time_series[metadata["trainval"]])
test_data = TimeSeries.from_pd(time_series[~metadata["trainval"]])

print(f"Time series is {train_data.dim}-dimensional")
Time series is 5-dimensional
time_series
BGT North of NE 70th TotalPed SouthPed NorthBike NorthBike South
timestamp
2014-01-01 00:00:0015.00.02.02.011.0
2014-01-01 01:00:009.01.00.01.07.0
2014-01-01 02:00:009.00.00.00.09.0
2014-01-01 03:00:0019.00.00.00.019.0
2014-01-01 04:00:0019.00.00.00.019.0
..................
2019-12-31 19:00:006.02.01.01.02.0
2019-12-31 20:00:002.00.00.00.02.0
2019-12-31 21:00:003.01.02.00.00.0
2019-12-31 22:00:001.00.00.00.01.0
2019-12-31 23:00:002.01.00.01.00.0

52584 rows × 5 columns

1.2 模型初始化与训练

在这里,将使用三个模型:

  1. DefaultForecaster(它会自动检测输入的时间序列是单变量还是多变量);

  2. ARIMA(一个经典的单变量算法)用于预测特定的单变量;

  3. ForecasterEnsemble,用于选择两者中表现较好的模型。

所有模型的训练都设置了最大允许的预测步长为100步。请注意,所有多变量预测模型都可以用于单变量时间序列;而通过适当指定 target_seq_index,单变量模型也可以用于多变量时间序列。此外,所有情况下的API都是相同的。这段代码运行约10分钟。

from merlion.evaluate.forecast import ForecastMetric
from merlion.models.factory import ModelFactory
from merlion.models.ensemble.combine import ModelSelector
from merlion.transform.resample import TemporalResample

# Time series is sampled hourly, so max_forecast_steps = 24 means we can predict up to 1 day in the future
target_seq_index = 2
max_forecast_steps = 24
kwargs = dict(target_seq_index=target_seq_index,
              max_forecast_steps=max_forecast_steps)

model1 = ModelFactory.create("DefaultForecaster", **kwargs)
model2 = ModelFactory.create("Arima", **kwargs)

# This ModelSelector combiner picks the best model based on sMAPE
model3 = ModelFactory.create("ForecasterEnsemble", models=[model1, model2], transform=TemporalResample(),
                             combiner=ModelSelector(metric=ForecastMetric.sMAPE))
for model in [model1, model2, model3]:
    print(f"Training {type(model).__name__}...")
    train_pred, train_stderr = model.train(train_data)

1.3 模型推断与定量评估

与单变量模型类似,我们可以调用 model.forecast() 来获取预测结果,并可能得到模型的标准误差。我们可以利用这些结果来评估模型的性能。请注意,ModelSelector能够成功选择两个模型中表现较好的一个。

from merlion.evaluate.forecast import ForecastMetric

for model in [model1, model2, model3]:
    forecast, stderr = model.forecast(
        test_data.time_stamps[:max_forecast_steps])
    rmse = ForecastMetric.RMSE.value(
        ground_truth=test_data, predict=forecast, target_seq_index=target_seq_index)
    smape = ForecastMetric.sMAPE.value(
        ground_truth=test_data, predict=forecast, target_seq_index=target_seq_index)
    print(f"{type(model).__name__}")
    print(f"RMSE:  {rmse:.4f}")
    print(f"sMAPE: {smape:.4f}")
    print()

DefaultForecaster
RMSE:  12.4991
sMAPE: 173.7479

Arima
RMSE:  10.2208
sMAPE: 140.2772

ForecasterEnsemble
RMSE:  10.2208
sMAPE: 140.2772

我们还可以使用 ForecastEvaluator 来以模拟实时部署的方式评估模型。在这里,我们先在训练数据上训练初始模型,然后使用滑动窗口的方法获取模型在训练数据上的预测结果。滑动窗口为1天(horizon="1d" 表示我们希望模型在每个时间步预测未来1天的值,cadence="1d" 表示我们每天从模型中获取一次预测)。请注意,这里并不会重新训练模型(retrain_freq=None)。这段代码运行约10分钟。

from merlion.evaluate.forecast import ForecastEvaluator, ForecastEvaluatorConfig

for model in [model1, model2]:
    print(f"{type(model).__name__} Sliding Window Evaluation")
    evaluator = ForecastEvaluator(model=model, config=ForecastEvaluatorConfig(
        horizon="1d", cadence="1d", retrain_freq=None))
    train_result, test_pred = evaluator.get_predict(
        train_vals=train_data, test_vals=test_data)
    rmse = evaluator.evaluate(ground_truth=test_data,
                              predict=test_pred, metric=ForecastMetric.RMSE)
    smape = evaluator.evaluate(
        ground_truth=test_data, predict=test_pred, metric=ForecastMetric.sMAPE)
    print(f"RMSE:  {rmse:.4f}")
    print(f"sMAPE: {smape:.4f}")
    print()

DefaultForecaster Sliding Window Evaluation
RMSE:  19.3241
sMAPE: 164.4164

Arima Sliding Window Evaluation
RMSE:  13.1032
sMAPE: 112.2607

2 使用外生回归变量进行预测

外生回归变量(exogenous regressors)是指在预测目标变量时,可以使用的其他影响因素。这些变量可以是与目标变量相关的外部因素,通常可以提高模型的预测性能。在多变量时间序列预测中,可以将外生回归变量作为输入,帮助模型捕捉到更多的信息,从而改善预测结果。

考虑一个多变量时间序列 X ( 1 ) , … , X ( t ) X^{(1)},\ldots,X^{(t)} X(1),,X(t),其中每个 X ( i ) ∈ R d X^{(i)} \in \mathbb{R}^d X(i)Rd 是一个 d d d 维向量。在多变量预测中,我们的目标是预测第 k k k 个单变量的未来值 X k ( t + 1 ) , … , X k ( t + h ) X_k^{(t+1)},\ldots,X_k^{(t+h)} Xk(t+1),,Xk(t+h)

外生回归变量 Y ( i ) Y^{(i)} Y(i) 是一组我们事先已知值的附加变量。使用外生回归变量进行预测的任务是预测我们的目标单变量 X k ( t + 1 ) , … , X k ( t + h ) X_k^{(t+1)},\ldots,X_k^{(t+h)} Xk(t+1),,Xk(t+h),需要的数据为:

  • 时间序列 X ( 1 ) , … , X ( t ) X^{(1)},\ldots,X^{(t)} X(1),,X(t) 的过去值
  • 外生回归变量 Y ( 1 ) , … , Y ( t ) Y^{(1)},\ldots,Y^{(t)} Y(1),,Y(t) 的过去值
  • 外生回归变量 Y ( t + 1 ) , … , Y ( t + h ) Y^{(t+1)},\ldots,Y^{(t+h)} Y(t+1),,Y(t+h) 的未来值

例如,可以考虑预测某个商店特定商品的销售情况。内生变量 X ( i ) ∈ R 4 X^{(i)} \in \mathbb{R}^4 X(i)R4 可能包含销售数量(目标单变量)、外部温度、消费者价格指数和当前失业率。外生变量 Y ( i ) ∈ R 6 Y^{(i)} \in \mathbb{R}^6 Y(i)R6 是商店可以控制或已知的变量。它们可能包括某一天是否为假期,以及关于商店进行的各种降价促销的信息。

为了更具体,让我们用一些真实数据来说明这一点。

# This is the same dataset used in the custom dataset tutorial
from ts_datasets.forecast import CustomDataset
csv = 'E:\Merlion\data\walmart\walmart_mini.csv'
dataset = CustomDataset(rootdir=csv, index_cols=["Store", "Dept"], test_frac=0.10)
ts, md = dataset[-1]
display(ts)
Weekly_SalesTemperatureFuel_PriceMarkDown1MarkDown2MarkDown3MarkDown4MarkDown5CPIUnemploymentIsHoliday
Date
2010-02-0539602.4740.192.572NaNNaNNaNNaNNaN210.7526058.324False
2010-02-1237984.4438.492.548NaNNaNNaNNaNNaN210.8979948.324True
2010-02-1938889.4339.692.514NaNNaNNaNNaNNaN210.9451608.324False
2010-02-2641137.7446.102.561NaNNaNNaNNaNNaN210.9759578.324False
2010-03-0539883.5047.172.625NaNNaNNaNNaNNaN211.0067548.324False
....................................
2012-09-2837104.6779.453.6667106.051.911.651549.103946.03222.6164336.565False
2012-10-0536361.2870.273.6176037.76NaN10.043027.373853.40222.8159306.170False
2012-10-1235332.3460.973.6012145.50NaN33.31586.8310421.01223.0154266.170False
2012-10-1935721.0968.083.5944461.89NaN1.141579.672642.29223.0598086.170False
2012-10-2634260.7669.793.5066152.59129.77200.00272.292924.15223.0783376.170False

143 rows × 11 columns

from merlion.utils import TimeSeries

# Get the 内生 variables X and split them into train & test
endog = ts[["Weekly_Sales", "Temperature", "CPI", "Unemployment"]]
train = TimeSeries.from_pd(endog[md.trainval])
test = TimeSeries.from_pd(endog[~md.trainval])

# Get the 外生 variables Y
exog = TimeSeries.from_pd(ts[["IsHoliday", "MarkDown1", "MarkDown2", "MarkDown3", "MarkDown4", "MarkDown5"]])

在这里,我们的任务是预测每周的销售额。我们希望我们的模型能够考虑可能影响消费者需求的变量(例如温度、消费者价格指数和失业率),因为对这些变量的了解可以提高销售预测的质量。这将是一个多变量预测问题,在这里进行讨论。

原则上,我们可以将降价促销和假期添加到多变量模型中。然而,作为零售商,我们事先知道哪些天是假期,并且我们自己控制降价促销。在许多情况下,通过提供这些变量的未来值以及过去值,我们可以获得更好的预测。此外,我们可能希望建模未来降价促销的变化如何影响未来销售。这就是为什么我们应该将这些变量建模为外生回归变量的原因。

所有 Merlion 预测器都支持一个 API,该 API 在训练和推理时都接受外生回归变量,尽管只有部分模型实际支持该功能。使用此功能非常简单,只需在 train()forecast() 中指定一个可选参数 exog_data。我们将在下面展示如何在流行的 Prophet 模型中使用该功能,并演示添加外生回归变量如何提高预测的质量。

from merlion.evaluate.forecast import ForecastMetric
from merlion.models.forecast.prophet import Prophet, ProphetConfig

# Train a model without exogenous data
model = Prophet(ProphetConfig(target_seq_index=0))
model.train(train)
pred, err = model.forecast(test.time_stamps)
smape = ForecastMetric.sMAPE.value(
    test, pred, target_seq_index=model.target_seq_index)
print(f"sMAPE (w/o exog) = {smape:.2f}")

# Train a model with exogenous data
exog_model = Prophet(ProphetConfig(target_seq_index=0))
exog_model.train(train, exog_data=exog)
exog_pred, exog_err = exog_model.forecast(test.time_stamps, exog_data=exog)
exog_smape = ForecastMetric.sMAPE.value(
    test, exog_pred, target_seq_index=exog_model.target_seq_index)
print(f"sMAPE (w/ exog)  = {exog_smape:.2f}")
sMAPE (w/o exog) = 3.97
sMAPE (w/ exog)  = 3.17

在我们结束本教程之前,我们注意到外生变量包含大量缺失数据:

display(exog.to_pd())

IsHolidayMarkDown1MarkDown2MarkDown3MarkDown4MarkDown5
time
2010-02-050.0NaNNaNNaNNaNNaN
2010-02-121.0NaNNaNNaNNaNNaN
2010-02-190.0NaNNaNNaNNaNNaN
2010-02-260.0NaNNaNNaNNaNNaN
2010-03-050.0NaNNaNNaNNaNNaN
.....................
2012-09-280.07106.051.911.651549.103946.03
2012-10-050.06037.76NaN10.043027.373853.40
2012-10-120.02145.50NaN33.31586.8310421.01
2012-10-190.04461.89NaN1.141579.672642.29
2012-10-260.06152.59129.77200.00272.292924.15

143 rows × 6 columns

Merlion 模型会对外生变量应用可选的 exog_transform,然后将外生变量重采样到与内生变量相同的时间戳。这个重采样是通过 exog_missing_value_policyexog_aggregation_policy 实现的,这些策略可以在接受外生回归变量的任何模型的配置中指定。我们可以通过检查配置来查看这些参数的默认值:

print(f"Default exog_transform:            {type(exog_model.config.exog_transform).__name__}")
print(f"Default exog_missing_value_policy: {exog_model.config.exog_missing_value_policy}")
print(f"Default exog_aggregation_policy:   {exog_model.config.exog_aggregation_policy}")
Default exog_transform:            MeanVarNormalize
Default exog_missing_value_policy: MissingValuePolicy.ZFill
Default exog_aggregation_policy:   AggregationPolicy.Mean

以下是每个参数的含义及其功能:

  1. exog_transform: MeanVarNormalize
  • 含义MeanVarNormalize 是一种数据预处理方法,用于对外生变量进行均值和方差归一化。具体而言,它会将每个外生变量的均值调整为 0,并将方差调整为 1。
  • 功能:这种变换可以帮助模型更好地学习数据,因为它消除了不同变量之间的量纲差异,使得所有变量在相同的尺度上进行比较和处理。
  1. exog_missing_value_policy: MissingValuePolicy.ZFill
  • 含义MissingValuePolicy.ZFill 指的是在处理缺失值时采用的策略。ZFill 意味着用零填充缺失值。
  • 功能:通过用零替换缺失的数据点,模型可以继续处理数据,而不会因为缺失值而导致错误或数据不完整。这种策略在某些情况下是合理的,尤其是当缺失值不影响数据的整体趋势时。
  1. exog_aggregation_policy: AggregationPolicy.Mean
  • 含义AggregationPolicy.Mean 指的是在对外生变量进行重采样时所采用的聚合策略。Mean 表示对多个时间点的数据取平均值。
  • 功能:在重采样过程中,如果在某个时间点存在多个外生变量值,使用均值聚合可以生成该时间点的代表值,从而保持数据的一致性和连续性。这有助于避免由于单一极端值而对模型预测造成的影响。

总结

  • exog_transform 用于标准化外生变量。
  • exog_missing_value_policy 指定缺失值的填充策略。
  • exog_aggregation_policy 决定重采样时如何处理多个值。

这些策略的组合可以提高模型对外生变量的处理能力,从而改善整体预测的质量。

因此,在这种情况下,我们首先对外生数据应用均值方差归一化。然后,我们通过用零填充缺失值(ZFill)来进行缺失值填充,并通过对任何相关窗口取均值来对外生数据进行下采样。


原文地址:https://blog.csdn.net/m0_56676945/article/details/142958564

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!