时间序列预测框架--Darts--快速开始(下)

协变量:用额外的数据

除了目标系列(我们有兴趣预测的系列),dart中的许多模型也在输入中接受协变量系列。协变量是我们不想预测的序列,但它可以为模型提供有用的额外信息。目标变量和协变量都可以是多变量或单变量。

dart中有两种协变量时间序列:

  • past_covariates:是在预测时间之前不一定已知的序列。例如,这些可以代表那些必须衡量而不为人知的东西。模型在进行预测时不使用past_covariates的未来值。
  • future_covariates:是在预测范围之前提前已知的序列。它可以表示日历信息、假期、天气预报等。接受future_协变量的模型在进行预测时将查看未来值(直到预测范围)。
    在这里插入图片描述
    每个协变量都可能是多变量。如果您有多个协变量序列(例如月和年值),您应该使用stack()或concatenate()它们来获得一个多变量序列。

你提供的协变量可能比需要的更长。dart会根据不同系列的时间索引,聪明地将它们以正确的方式进行分割,以预测目标。但是,如果协变量没有足够的时间跨度,您将收到一个错误。

现在,让我们为空气和牛奶系列构建一些包含月值和年值的外部协变量。在下面的单元格中,我们使用dartmouth .utils.timeseries_generation.datetime_attribute_timeseries()函数来生成包含月和年值的序列,并沿着“分量”轴连接这些序列,以便在每个目标序列中获得一个带有两个分量(月和年)的协变量序列。为了简单起见,我们直接将月和年的值缩放到(大致)0和1之间:

from darts import concatenate
from darts.utils.timeseries_generation import datetime_attribute_timeseries as dt_attr

air_covs = concatenate(
    [
        dt_attr(series_air.time_index, "month", dtype=np.float32) / 12,
        (dt_attr(series_air.time_index, "year", dtype=np.float32) - 1948) / 12,
    ],
    axis="component",
)

milk_covs = concatenate(
    [
        dt_attr(series_milk.time_index, "month", dtype=np.float32) / 12,
        (dt_attr(series_milk.time_index, "year", dtype=np.float32) - 1962) / 13,
    ],
    axis="component",
)

air_covs.plot()
plt.title(
    "one multivariate time series of 2 dimensions, containing covariates for the air series:"
);

在这里插入图片描述
并不是所有的模型都支持所有类型的协变量。NBEATSModel只支持past_covariates 。因此,即使我们的协变量表示日历信息,并且是提前知道的,我们将它们用作带有N-BEATS的past_covariates 。为了进行训练,我们所要做的就是将它们作为past_covariates赋给fit()函数,顺序与目标函数相同:

model = NBEATSModel(input_chunk_length=24, output_chunk_length=12, random_state=42)

model.fit(
    [train_air_scaled, train_milk_scaled],
    past_covariates=[air_covs, milk_covs],
    epochs=50,
    verbose=True,
);
[2022-06-21 16:05:10,026] INFO | darts.models.forecasting.torch_forecasting_model | Train dataset contains 194 samples.
[2022-06-21 16:05:10,026] INFO | darts.models.forecasting.torch_forecasting_model | Train dataset contains 194 samples.
2022-06-21 16:05:10 darts.models.forecasting.torch_forecasting_model INFO: Train dataset contains 194 samples.
[2022-06-21 16:05:10,085] INFO | darts.models.forecasting.torch_forecasting_model | Time series values are 32-bits; casting model to float32.
[2022-06-21 16:05:10,085] INFO | darts.models.forecasting.torch_forecasting_model | Time series values are 32-bits; casting model to float32.
2022-06-21 16:05:10 darts.models.forecasting.torch_forecasting_model INFO: Time series values are 32-bits; casting model to float32.
2022-06-21 16:05:10 pytorch_lightning.utilities.rank_zero INFO: GPU available: False, used: False
2022-06-21 16:05:10 pytorch_lightning.utilities.rank_zero INFO: TPU available: False, using: 0 TPU cores
2022-06-21 16:05:10 pytorch_lightning.utilities.rank_zero INFO: IPU available: False, using: 0 IPUs
2022-06-21 16:05:10 pytorch_lightning.utilities.rank_zero INFO: HPU available: False, using: 0 HPUs
2022-06-21 16:05:10 pytorch_lightning.callbacks.model_summary INFO:
  | Name          | Type             | Params
---------------------------------------------------
0 | criterion     | MSELoss          | 0
1 | train_metrics | MetricCollection | 0
2 | val_metrics   | MetricCollection | 0
3 | stacks        | ModuleList       | 6.6 M
---------------------------------------------------
6.6 M     Trainable params
1.7 K     Non-trainable params
6.6 M     Total params
26.314    Total estimated model params size (MB)

然后,为了产生预测,我们必须再次将协变量作为past_covariates提供给predict()函数。即使协变量时间序列也包含了截至预测视界的协变量的“未来”值,模型也不会消耗这些未来值,因为它使用它们作为过去的协变量(而不是未来的协变量)。

pred_air = model.predict(series=train_air_scaled, past_covariates=air_covs, n=36)
pred_milk = model.predict(series=train_milk_scaled, past_covariates=milk_covs, n=36)

# scale back:
pred_air, pred_milk = scaler.inverse_transform([pred_air, pred_milk])

plt.figure(figsize=(10, 6))
series_air.plot(label="actual (air)")
series_milk.plot(label="actual (milk)")
pred_air.plot(label="forecast (air)")
pred_milk.plot(label="forecast (milk)")

在这里插入图片描述
现在看来,该模型更好地捕捉了空气系列的趋势(这也有点扰乱了牛奶系列的预测)。

Encoder:Using covariates for free

使用与日历或时间轴相关的协变量(如我们上面的例子中的月和年)是如此频繁,以至于dart中的深度学习模型有一个内置的功能来使用这些协变量。

为了方便地将这些协变量集成到模型中,您可以简单地在模型创建时指定add_encoders参数。这个参数必须是一个字典,包含关于什么应该被编码为额外协变量的信息。下面是一个支持过去和未来协变量的模型的这样一个字典的示例:

encoders = {
    "cyclic": {"future": ["month"]},
    "datetime_attribute": {"future": ["hour", "dayofweek"]},
    "position": {"past": ["absolute"], "future": ["relative"]},
    "custom": {"past": [lambda idx: (idx.year - 1950) / 50]},
    "transformer": Scaler(),
}

在上面的字典中,指定了以下内容:

  • 月份应该作为未来的协变量,使用循环(sin/cos)编码。
  • 小时和星期应该被用作未来的协变量。
  • 绝对位置(序列中的时间步长)应该用作过去的协变量。
  • 相对位置(w.r.t预测时间)应作为未来的协变量。
  • 一个额外的年的自定义函数应该被用作过去的协变量
  • 所有上述协变量都应该使用Scaler进行缩放,该Scaler将在调用model fit()函数时进行匹配,然后用于转换协变量。

为了复制我们的例子,将月和年作为N-BEATS的过去协变量,我们可以使用以下一些编码器:

encoders = {"datetime_attribute": {"past": ["month", "year"]}, "transformer": Scaler()}

现在,带有这些协变量的N-BEATS模型的整个训练是这样的:

model = NBEATSModel(
    input_chunk_length=24,
    output_chunk_length=12,
    add_encoders=encoders,
    random_state=42,
)

model.fit([train_air_scaled, train_milk_scaled], epochs=50, verbose=True);
[2022-06-21 16:05:39,967] INFO | darts.models.forecasting.torch_forecasting_model | Train dataset contains 194 samples.
[2022-06-21 16:05:39,967] INFO | darts.models.forecasting.torch_forecasting_model | Train dataset contains 194 samples.
2022-06-21 16:05:39 darts.models.forecasting.torch_forecasting_model INFO: Train dataset contains 194 samples.
[2022-06-21 16:05:40,031] INFO | darts.models.forecasting.torch_forecasting_model | Time series values are 32-bits; casting model to float32.
[2022-06-21 16:05:40,031] INFO | darts.models.forecasting.torch_forecasting_model | Time series values are 32-bits; casting model to float32.
2022-06-21 16:05:40 darts.models.forecasting.torch_forecasting_model INFO: Time series values are 32-bits; casting model to float32.
2022-06-21 16:05:40 pytorch_lightning.utilities.rank_zero INFO: GPU available: False, used: False
2022-06-21 16:05:40 pytorch_lightning.utilities.rank_zero INFO: TPU available: False, using: 0 TPU cores
2022-06-21 16:05:40 pytorch_lightning.utilities.rank_zero INFO: IPU available: False, using: 0 IPUs
2022-06-21 16:05:40 pytorch_lightning.utilities.rank_zero INFO: HPU available: False, using: 0 HPUs
2022-06-21 16:05:40 pytorch_lightning.callbacks.model_summary INFO:
  | Name          | Type             | Params
---------------------------------------------------
0 | criterion     | MSELoss          | 0
1 | train_metrics | MetricCollection | 0
2 | val_metrics   | MetricCollection | 0
3 | stacks        | ModuleList       | 6.6 M
---------------------------------------------------
6.6 M     Trainable params
1.7 K     Non-trainable params
6.6 M     Total params
26.314    Total estimated model params size (MB)

并获得一些航空旅客系列的预测:

pred_air = model.predict(series=train_air_scaled, n=36)

# scale back:
pred_air = scaler.inverse_transform(pred_air)

plt.figure(figsize=(10, 6))
series_air.plot(label="actual (air)")
pred_air.plot(label="forecast (air)")

在这里插入图片描述

回归预测模型

回归模型是围绕sklearning兼容回归模型的预测模型。内部回归模型用于预测目标序列的未来值,作为目标、过去和未来协变量的某些滞后的函数。在这种情况下,时间序列被制成表格,以便以正确的方式构建训练数据集。

默认情况下,RegressionModel将进行线性回归。通过指定模型参数,可以很容易地使用任何需要的sklearn兼容的回归模型,但为了方便起见,dart还提供了一些现成的模型:

  • RandomForest包围了sklearn.ensemble.RandomForestRegressor
  • lighttgbmmodel包裹lightbm
  • 线性回归模型包围了sklearn.linear_model.LinearRegression(接受相同的kwargs)。

例如,这是拟合Bayesian ridge regression 到我们的两个系列问题的样子:

from darts.models import RegressionModel
from sklearn.linear_model import BayesianRidge

model = RegressionModel(lags=72, lags_future_covariates=[-6, 0], model=BayesianRidge())

model.fit(
    [train_air_scaled, train_milk_scaled], future_covariates=[air_covs, milk_covs]
);

以上发生了几件事:

  • lag =72告诉回归模型查看目标过去的72个lag。
  • 此外,lags_future_covariates=[- 6,0]意味着该模型还将查看我们提供的future_covariates的滞后。在这里,我们列举了我们希望模型考虑到的精确滞后;" - 6th “和” 0th "有滞后。“第0”滞后指的是“当前”滞后(即预测的时间步长);显然,了解这种滞后需要提前了解数据(因此我们使用future_covariates)。类似地,-6意味着我们还会在预测时间步长之前6个月查看协变量的值(这也要求我们提前知道协变量如果我们提前6步预测的话)
  • model=BayesianRidge()提供了实际的内部回归模型

现在让我们来做一些预测:

pred_air, pred_milk = model.predict(
    series=[train_air_scaled, train_milk_scaled],
    future_covariates=[air_covs, milk_covs],
    n=36,
)

# scale back:
pred_air, pred_milk = scaler.inverse_transform([pred_air, pred_milk])

plt.figure(figsize=(10, 6))
series_air.plot(label="actual (air)")
series_milk.plot(label="actual (milk)")
pred_air.plot(label="forecast (air)")
pred_milk.plot(label="forecast (milk)")

在这里插入图片描述
请注意我们是如何同时获得上述两个时间序列的预测的。类似地,我们也可以获得一系列序列的一些指标:

mape([series_air, series_milk], [pred_air, pred_milk])
[3.41736301779747, 5.282935127615929]
mape([series_air, series_milk], [pred_air, pred_milk], inter_reduction=np.mean)
4.350149072706699

顺便说一下:与Scaler等转换器类似,通过指定n_jobs=N,当在多个系列对上执行时,计算指标可以在N个处理器上并行化。

似乎这个模型在空中交通系列中表现很好,当我们在这个系列中进行回测时,它的表现如何?

bayes_ridge_model = RegressionModel(
    lags=72, lags_future_covariates=[0], model=BayesianRidge()
)

backtest = bayes_ridge_model.historical_forecasts(
    series_air, future_covariates=air_covs, start=0.6, forecast_horizon=3, verbose=True
)

print("MAPE = %.2f" % (mape(backtest, series_air)))
series_air.plot()
backtest.plot()

Our best model so far!

概率预测

有些模型可以产生概率预测。这是所有深度学习模型(如RNNModel, NBEATSModel等),以及ARIMA和ExponentialSmoothing的情况。完整的列表可以在dart README页面上找到。

对于ARIMA和ExponentialSmoothing,可以简单地为predict()函数指定num_samples参数。然后返回的TimeSeries将由num_samples Monte Carlo样本组成,这些样本描述时间序列值的分布。依赖蒙特卡洛样本(与显式置信区间相比)的优势在于,它们可以用来描述分量上的任何参数或非参数联合分布,并计算任意分位数。

model_es = ExponentialSmoothing()
model_es.fit(train)
probabilistic_forecast = model_es.predict(len(val), num_samples=500)

series.plot(label="actual")
probabilistic_forecast.plot(label="probabilistic forecast")
plt.legend()
plt.show()

在这里插入图片描述

用神经网络

对于神经网络,我们必须给模型一个Likelihood对象。可能性指定模型将试图拟合哪个分布,以及分布参数的潜在先验值。完整的可能性列表可以在文档中找到。

利用可能性很容易。例如,下面是如何训练NBEATSModel来拟合拉普拉斯似然:

from darts.models import TCNModel
from darts.utils.likelihood_models import LaplaceLikelihood

model = TCNModel(
    input_chunk_length=24,
    output_chunk_length=12,
    random_state=42,
    likelihood=LaplaceLikelihood(),
)

model.fit(train_air_scaled, epochs=400, verbose=True);
[2022-06-21 16:06:11,849] INFO | darts.models.forecasting.torch_forecasting_model | Train dataset contains 73 samples.
[2022-06-21 16:06:11,849] INFO | darts.models.forecasting.torch_forecasting_model | Train dataset contains 73 samples.
2022-06-21 16:06:11 darts.models.forecasting.torch_forecasting_model INFO: Train dataset contains 73 samples.
[2022-06-21 16:06:11,853] INFO | darts.models.forecasting.tcn_model | Number of layers chosen: 3
[2022-06-21 16:06:11,853] INFO | darts.models.forecasting.tcn_model | Number of layers chosen: 3
2022-06-21 16:06:11 darts.models.forecasting.tcn_model INFO: Number of layers chosen: 3
[2022-06-21 16:06:11,856] INFO | darts.models.forecasting.torch_forecasting_model | Time series values are 32-bits; casting model to float32.
[2022-06-21 16:06:11,856] INFO | darts.models.forecasting.torch_forecasting_model | Time series values are 32-bits; casting model to float32.
2022-06-21 16:06:11 darts.models.forecasting.torch_forecasting_model INFO: Time series values are 32-bits; casting model to float32.
2022-06-21 16:06:11 pytorch_lightning.utilities.rank_zero INFO: GPU available: False, used: False
2022-06-21 16:06:11 pytorch_lightning.utilities.rank_zero INFO: TPU available: False, using: 0 TPU cores
2022-06-21 16:06:11 pytorch_lightning.utilities.rank_zero INFO: IPU available: False, using: 0 IPUs
2022-06-21 16:06:11 pytorch_lightning.utilities.rank_zero INFO: HPU available: False, using: 0 HPUs
2022-06-21 16:06:11 pytorch_lightning.callbacks.model_summary INFO:
  | Name          | Type              | Params
----------------------------------------------------
0 | criterion     | MSELoss           | 0
1 | train_metrics | MetricCollection  | 0
2 | val_metrics   | MetricCollection  | 0
3 | dropout       | MonteCarloDropout | 0
4 | res_blocks    | ModuleList        | 166
----------------------------------------------------
166       Trainable params
0         Non-trainable params
166       Total params
0.001     Total estimated model params size (MB)

然后为了得到概率预测,我们同样只需要指定一些num_samples >> 1:

pred = model.predict(n=36, num_samples=500)

# scale back:
pred = scaler.inverse_transform(pred)

series_air.plot()
pred.plot()

在这里插入图片描述
此外,我们还可以通过指定prior_b=.1,例如指定我们有一些先验的信念,即分布的规模大约(在转换的域中),同时仍然捕获分布的一些时间依赖性。

Behind the scenes this will regularize the training loss with a Kullback-Leibler divergence term.

model = TCNModel(
    input_chunk_length=24,
    output_chunk_length=12,
    random_state=42,
    likelihood=LaplaceLikelihood(prior_b=0.1),
)

model.fit(train_air_scaled, epochs=400, verbose=True);
2022-06-21 16:06:26,627] INFO | darts.models.forecasting.torch_forecasting_model | Train dataset contains 73 samples.
[2022-06-21 16:06:26,627] INFO | darts.models.forecasting.torch_forecasting_model | Train dataset contains 73 samples.
2022-06-21 16:06:26 darts.models.forecasting.torch_forecasting_model INFO: Train dataset contains 73 samples.
[2022-06-21 16:06:26,632] INFO | darts.models.forecasting.tcn_model | Number of layers chosen: 3
[2022-06-21 16:06:26,632] INFO | darts.models.forecasting.tcn_model | Number of layers chosen: 3
2022-06-21 16:06:26 darts.models.forecasting.tcn_model INFO: Number of layers chosen: 3
[2022-06-21 16:06:26,636] INFO | darts.models.forecasting.torch_forecasting_model | Time series values are 32-bits; casting model to float32.
[2022-06-21 16:06:26,636] INFO | darts.models.forecasting.torch_forecasting_model | Time series values are 32-bits; casting model to float32.
2022-06-21 16:06:26 darts.models.forecasting.torch_forecasting_model INFO: Time series values are 32-bits; casting model to float32.
2022-06-21 16:06:26 pytorch_lightning.utilities.rank_zero INFO: GPU available: False, used: False
2022-06-21 16:06:26 pytorch_lightning.utilities.rank_zero INFO: TPU available: False, using: 0 TPU cores
2022-06-21 16:06:26 pytorch_lightning.utilities.rank_zero INFO: IPU available: False, using: 0 IPUs
2022-06-21 16:06:26 pytorch_lightning.utilities.rank_zero INFO: HPU available: False, using: 0 HPUs
2022-06-21 16:06:26 pytorch_lightning.callbacks.model_summary INFO:
  | Name          | Type              | Params
----------------------------------------------------
0 | criterion     | MSELoss           | 0
1 | train_metrics | MetricCollection  | 0
2 | val_metrics   | MetricCollection  | 0
3 | dropout       | MonteCarloDropout | 0
4 | res_blocks    | ModuleList        | 166
----------------------------------------------------
166       Trainable params
0         Non-trainable params
166       Total params
0.001     Total estimated model params size (MB)
pred = model.predict(n=36, num_samples=500)

# scale back:
pred = scaler.inverse_transform(pred)

series_air.plot()
pred.plot()

在这里插入图片描述
默认情况下,TimeSeries.plot()显示(如果TimeSeries是多变量的)边际分布的中位数以及第5和第95个百分位数。这是可以控制的:

pred.plot(low_quantile=0.01, high_quantile=0.99, label="1-99th percentiles")
pred.plot(low_quantile=0.2, high_quantile=0.8, label="20-80th percentiles")

在这里插入图片描述

分布的类型

可能性必须与你的时间序列值的范围相一致。例如,泊松似然可以用于离散的正值,指数似然可以用于真实的正值,贝塔似然可以用于真实的值【0,1】。

还可以使用QuantileRegression来应用分位数损失,并直接匹配一些所需的分位数。

评估概率预测

我们如何评估概率预测的质量?默认情况下,大多数指标函数(如mape())将继续工作,但只查看预测的中位数。也可以使用-风险度量(或分位数损失),它将每个预测的分位数的错误量化:

from darts.metrics import rho_risk

print("MAPE of median forecast: %.2f" % mape(series_air, pred))
for rho in [0.05, 0.1, 0.5, 0.9, 0.95]:
    rr = rho_risk(series_air, pred, rho=rho)
    print("rho-risk at quantile %.2f: %.2f" % (rho, rr))
MAPE of median forecast: 11.75
rho-risk at quantile 0.05: 0.14
rho-risk at quantile 0.10: 0.15
rho-risk at quantile 0.50: 0.11
rho-risk at quantile 0.90: 0.03
rho-risk at quantile 0.95: 0.02

使用分位数损失

我们是否可以通过直接匹配这些分位数来做得更好?我们可以只使用QuantileRegression可能性:

from darts.utils.likelihood_models import QuantileRegression

model = TCNModel(
    input_chunk_length=24,
    output_chunk_length=12,
    random_state=42,
    likelihood=QuantileRegression([0.05, 0.1, 0.5, 0.9, 0.95]),
)

model.fit(train_air_scaled, epochs=400, verbose=True);
[2022-06-21 16:06:42,853] INFO | darts.models.forecasting.torch_forecasting_model | Train dataset contains 73 samples.
[2022-06-21 16:06:42,853] INFO | darts.models.forecasting.torch_forecasting_model | Train dataset contains 73 samples.
2022-06-21 16:06:42 darts.models.forecasting.torch_forecasting_model INFO: Train dataset contains 73 samples.
[2022-06-21 16:06:42,858] INFO | darts.models.forecasting.tcn_model | Number of layers chosen: 3
[2022-06-21 16:06:42,858] INFO | darts.models.forecasting.tcn_model | Number of layers chosen: 3
2022-06-21 16:06:42 darts.models.forecasting.tcn_model INFO: Number of layers chosen: 3
[2022-06-21 16:06:42,862] INFO | darts.models.forecasting.torch_forecasting_model | Time series values are 32-bits; casting model to float32.
[2022-06-21 16:06:42,862] INFO | darts.models.forecasting.torch_forecasting_model | Time series values are 32-bits; casting model to float32.
2022-06-21 16:06:42 darts.models.forecasting.torch_forecasting_model INFO: Time series values are 32-bits; casting model to float32.
2022-06-21 16:06:42 pytorch_lightning.utilities.rank_zero INFO: GPU available: False, used: False
2022-06-21 16:06:42 pytorch_lightning.utilities.rank_zero INFO: TPU available: False, using: 0 TPU cores
2022-06-21 16:06:42 pytorch_lightning.utilities.rank_zero INFO: IPU available: False, using: 0 IPUs
2022-06-21 16:06:42 pytorch_lightning.utilities.rank_zero INFO: HPU available: False, using: 0 HPUs
2022-06-21 16:06:42 pytorch_lightning.callbacks.model_summary INFO:
  | Name          | Type              | Params
----------------------------------------------------
0 | criterion     | MSELoss           | 0
1 | train_metrics | MetricCollection  | 0
2 | val_metrics   | MetricCollection  | 0
3 | dropout       | MonteCarloDropout | 0
4 | res_blocks    | ModuleList        | 208
----------------------------------------------------
208       Trainable params
0         Non-trainable params
208       Total params
0.001     Total estimated model params size (MB)
pred = model.predict(n=36, num_samples=500)

# scale back:
pred = scaler.inverse_transform(pred)

series_air.plot()
pred.plot()

print("MAPE of median forecast: %.2f" % mape(series_air, pred))
for rho in [0.05, 0.1, 0.5, 0.9, 0.95]:
    rr = rho_risk(series_air, pred, rho=rho)
    print("rho-risk at quantile %.2f: %.2f" % (rho, rr))
MAPE of median forecast: 4.97
rho-risk at quantile 0.05: 0.00
rho-risk at quantile 0.10: 0.00
rho-risk at quantile 0.50: 0.03
rho-risk at quantile 0.90: 0.01
rho-risk at quantile 0.95: 0.01

在这里插入图片描述

集成模型

集成是指将几个模型产生的预测结果结合起来,以获得一个最终的、有望更好的预测结果。

例如,在我们上面的一个不那么幼稚的模型示例中,我们手动地将幼稚的季节模型与幼稚的漂移模型结合起来。在这里,我们将展示模型预测如何自动结合,使用天真集成模型,或使用回归集成模型学习。

Naive 集成

朴素的集合只是把几个模型的预测平均起来。dart提供了一个NaiveEnsembleModel,它允许在操作一个预测模型(例如,它允许更容易的回测)的同时做到这一点:

from darts.models import NaiveEnsembleModel

models = [NaiveDrift(), NaiveSeasonal(12)]

ensemble_model = NaiveEnsembleModel(models=models)

backtest = ensemble_model.historical_forecasts(
    series_air, start=0.6, forecast_horizon=3, verbose=True
)

print("MAPE = %.2f" % (mape(backtest, series_air)))
series_air.plot()
backtest.plot()
MAPE = 11.88

在这里插入图片描述

可学习的集成

正如在这种情况下所预期的那样,天真的集合并没有给出很好的结果(尽管在某些情况下它可以!)

如果我们把集合看作一个有监督的回归问题,我们有时可以做得更好:给定一组预测(特征),找到一个结合它们的模型,以便将目标上的误差最小化。这就是回归集成模型所做的。它接受三个参数:

  • forecasting_models is a list of forecasting models whose predictions we want to ensemble.
  • Regression_train_n_points是用于拟合“集合回归”模型(即结合预测的内部模型)的时间步数。
  • regression_model是sklearn兼容的回归模型或Darts回归模型,可选用于集成回归。如果没有指定,则使用线性回归。使用sklearn模型是一种简单的开箱即用的方法,但是使用RegressionModel允许将个别预测的任意滞后作为回归模型的输入。

一旦这些元素就位,回归集成模型就可以像常规预测模型一样使用:

from darts.models import RegressionEnsembleModel

models = [NaiveDrift(), NaiveSeasonal(12)]

ensemble_model = RegressionEnsembleModel(
    forecasting_models=models, regression_train_n_points=12
)

backtest = ensemble_model.historical_forecasts(
    series_air, start=0.6, forecast_horizon=3, verbose=True
)

print("MAPE = %.2f" % (mape(backtest, series_air)))
series_air.plot()
backtest.plot()
MAPE = 4.85

在这里插入图片描述
我们还可以检查在线性组合中用于衡量两个内部模型的系数:

ensemble_model.regression_model.model.coef_
array([0.09948264, 1.0118142 ])

Filtering models

除了能够预测序列未来值的预测模型之外,dart还包含一些有用的过滤模型,可以对“样本”序列的值分布进行建模。

Fitting 卡尔曼滤波

卡尔曼滤波器实现了卡尔曼滤波器。它的实现依赖于nfoursid,因此可以提供一个包含转移矩阵、过程噪声协方差、观测噪声协方差等的nfoursid.kalman. kalman对象。

也可以通过调用fit()来使用N4SID系统识别算法“训练”卡尔曼滤波器来进行系统识别:

from darts.models import KalmanFilter

kf = KalmanFilter(dim_x=3)
kf.fit(train_air_scaled)
filtered_series = kf.filter(train_air_scaled, num_samples=100)

train_air_scaled.plot()
filtered_series.plot()

在这里插入图片描述

用高斯过程推断缺失值

dart还包含一个GaussianProcessFilter,可用于序列的概率建模:

from darts.models import GaussianProcessFilter
from sklearn.gaussian_process.kernels import RBF

# create a series with holes:
values = train_air_scaled.values()
values[20:22] = np.nan
values[28:32] = np.nan
values[55:59] = np.nan
values[72:80] = np.nan
series_holes = TimeSeries.from_times_and_values(train_air_scaled.time_index, values)
series_holes.plot()

kernel = RBF()

gpf = GaussianProcessFilter(kernel=kernel, alpha=0.1, normalize_y=True)
filtered_series = gpf.filter(series_holes, num_samples=100)

filtered_series.plot()

A Word of Caution

那么,N-BEATS、指数平滑、或者以牛奶产量为训练对象的贝叶斯脊回归是预测未来航空乘客数量的最佳方法吗?嗯,在这一点上,实际上很难说哪一个是最好的。我们的时间序列很小,我们的验证集更小。在这种情况下,很容易将整个预测操作过度拟合到如此小的验证集上。如果可用模型的数量及其自由度很高(例如深度学习模型),或者我们在一个测试集中使用许多模型(如本笔记本中所做的),这尤其正确。作为数据科学家,我们有责任了解我们的模型在多大程度上是可信的。所以,在做出任何预测之前,一定要对结果持保留态度,尤其是在小数据集上,并应用科学方法:)建模愉快

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值