数据

这展示了仅包含 M4 数据集中 4 个序列的示例。如果你想在所有序列上自己运行,可以参考这本笔记本

import random
import tempfile

import lightgbm as lgb
import matplotlib.pyplot as plt
import numpy as np
import xgboost as xgb
from sklearn.linear_model import LinearRegression
from utilsforecast.feature_engineering import time_features
from utilsforecast.plotting import plot_series

from mlforecast.lag_transforms import ExpandingMean, ExponentiallyWeightedMean, RollingMean
from mlforecast.lgb_cv import LightGBMCV
from mlforecast.target_transforms import Differences, LocalStandardScaler
from mlforecast.utils import generate_daily_series
df = pd.read_parquet('https://datasets-nixtla.s3.amazonaws.com/m4-hourly.parquet')
ids = df['unique_id'].unique()
random.seed(0)
sample_ids = random.choices(ids, k=4)
sample_df = df[df['unique_id'].isin(sample_ids)]
sample_df
unique_iddsy
86796H196111.8
86797H196211.4
86798H196311.1
86799H196410.8
86800H196510.6
325235H413100499.0
325236H413100588.0
325237H413100647.0
325238H413100741.0
325239H413100834.0

我们现在将这些数据分为训练集和验证集。

horizon = 48
valid = sample_df.groupby('unique_id').tail(horizon)
train = sample_df.drop(valid.index)
train.shape, valid.shape
((3840, 3), (192, 3))

MLForecast

 MLForecast (models:Union[sklearn.base.BaseEstimator,List[sklearn.base.Bas
             eEstimator],Dict[str,sklearn.base.BaseEstimator]],
             freq:Union[int,str], lags:Optional[Iterable[int]]=None, lag_t
             ransforms:Optional[Dict[int,List[Union[Callable,Tuple[Callabl
             e,Any]]]]]=None,
             date_features:Optional[Iterable[Union[str,Callable]]]=None,
             num_threads:int=1, target_transforms:Optional[List[Union[mlfo
             recast.target_transforms.BaseTargetTransform,mlforecast.targe
             t_transforms._BaseGroupedArrayTargetTransform]]]=None,
             lag_transforms_namer:Optional[Callable]=None)

预测管道

类型默认值详情
模型联合类型将用于训练和计算预测的模型。
频率联合类型Pandas 偏移量、pandas 偏移量别名,例如 ‘D’、‘W-THU’,或表示序列频率的整数。
滞后项可选用作特征的目标变量的滞后项。
滞后变换可选目标滞后项与其变换的映射。
日期特征可选从日期计算得到的特征。可以是 pandas 日期属性或以日期作为输入的函数。
线程数int1计算特征时使用的线程数。
目标变换可选在计算特征之前应用于目标变量的变换,并在预测步骤之后恢复。
滞后变换命名器可选一个函数,接受一个变换(函数或类)、一个滞后项和额外参数,并生成一个名称。

MLForecast 对象封装了特征工程 + 模型训练 + 预测的功能。

fcst = MLForecast(
    models=lgb.LGBMRegressor(random_state=0, verbosity=-1),
    freq=1,
    lags=[24 * (i+1) for i in range(7)],
    lag_transforms={
        48: [ExponentiallyWeightedMean(alpha=0.3)],
    },
    num_threads=1,
    target_transforms=[Differences([24])],
)
fcst
MLForecast(models=[LGBMRegressor], freq=1, lag_features=['lag24', 'lag48', 'lag72', 'lag96', 'lag120', 'lag144', 'lag168', 'exponentially_weighted_mean_lag48_alpha0.3'], date_features=[], num_threads=1)

完成此设置后,我们可以计算特征并拟合模型。


MLForecast.fit

 MLForecast.fit
                 (df:Union[pandas.core.frame.DataFrame,polars.dataframe.fr
                 ame.DataFrame], id_col:str='unique_id',
                 time_col:str='ds', target_col:str='y',
                 static_features:Optional[List[str]]=None,
                 dropna:bool=True, keep_last_n:Optional[int]=None,
                 max_horizon:Optional[int]=None, prediction_intervals:Opti
                 onal[mlforecast.utils.PredictionIntervals]=None,
                 fitted:bool=False, as_numpy:bool=False,
                 weight_col:Optional[str]=None)

应用特征工程并训练模型。

类型默认值详情
df联合类型长格式的序列数据。
id_colstrunique_id标识每个序列的列。
time_colstrds标识每个时间步的列,其值可以是时间戳或整数。
target_colstry包含目标变量的列。
静态特征可选静态特征的名称,预测时将重复使用。
如果 None,则会将所有列(id_col 和 time_col 除外)视为静态特征。
dropnaboolTrue删除由变换产生的缺失值行。
keep_last_n可选对于每个序列,仅保留这些数量的记录用于预测步骤。如果你的特征允许,可以节省时间和内存。
最大预测范围可选训练这么多个模型,每个模型将预测一个特定的预测范围。
预测区间可选用于校准预测区间(保形预测)的配置。
fittedboolFalse保存样本内预测。
as_numpyboolFalse将特征转换为 numpy 数组。
weight_col可选包含样本权重的列。
返回值MLForecast包含序列值和训练好的模型的预测对象。
fcst = MLForecast(
    models=lgb.LGBMRegressor(random_state=0, verbosity=-1),
    freq=1,
    lags=[24 * (i+1) for i in range(7)],
    lag_transforms={
        48: [ExponentiallyWeightedMean(alpha=0.3)],
    },
    num_threads=1,
    target_transforms=[Differences([24])],
)
train2 = train.copy()
train2['weight'] = np.random.default_rng(seed=0).random(train2.shape[0])
fcst.fit(train2, weight_col='weight', as_numpy=True).predict(5)
unique_iddsLGBMRegressor
0H19696116.079737
1H19696215.679737
2H19696315.279737
3H19696414.979737
4H19696514.679737
5H25696113.279737
6H25696212.679737
7H25696312.379737
8H25696412.079737
9H25696511.879737
10H38196156.939977
11H38196240.314608
12H38196333.859013
13H38196415.498139
14H38196525.722674
15H41396125.131194
16H41396219.177421
17H41396321.250829
18H41396418.743132
19H41396516.027263
fcst.cross_validation(train2, n_windows=2, h=5, weight_col='weight', as_numpy=True)
unique_iddscutoffyLGBMRegressor
0H19695195024.424.288850
1H19695295024.324.188850
2H19695395023.823.688850
3H19695495022.822.688850
4H19695595021.221.088850
5H25695195019.519.688850
6H25695295019.419.488850
7H25695395018.919.088850
8H25695495018.318.388850
9H25695595017.017.088850
10H381951950182.0208.327270
11H381952950222.0247.768326
12H381953950288.0277.965997
13H381954950264.0321.532857
14H381955950191.0206.316903
15H41395195077.060.972692
16H41395295091.054.936494
17H41395395076.073.949203
18H41395495068.067.087417
19H41395595068.075.896022
20H19695695519.319.287891
21H19695795518.218.187891
22H19695895517.517.487891
23H19695995516.916.887891
24H19696095516.516.487891
25H25695695515.515.687891
26H25695795514.714.787891
27H25695895514.114.287891
28H25695995513.613.787891
29H25696095513.213.387891
30H381956955130.0124.117828
31H381957955113.0119.180350
32H38195895594.0105.356552
33H381959955192.0127.095338
34H38196095587.0119.875754
35H41395695559.067.993133
36H41395795558.069.869815
37H41395895553.034.717960
38H41395995538.047.665581
39H41396095546.045.940137
fcst.fit(train, fitted=True);

MLForecast.save

 MLForecast.save (path:Union[str,pathlib.Path])

保存预测对象

类型详情
path联合类型存储工件的目录。
返回值

MLForecast.load

 MLForecast.load (path:Union[str,pathlib.Path])

加载预测对象

类型详情
path联合类型包含已保存工件的目录。
返回值MLForecast

MLForecast.update

 MLForecast.update
                    (df:Union[pandas.core.frame.DataFrame,polars.dataframe
                    .frame.DataFrame])

更新存储序列的值。

类型详情
df联合类型包含新观测值的 Dataframe。
返回值

MLForecast.make_future_dataframe

 MLForecast.make_future_dataframe (h:int)

创建一个包含所有 id 和预测范围内的未来时间的 dataframe。

类型详情
hint要预测的周期数。
返回值联合类型包含预期 id 和未来时间的 DataFrame
expected_future = fcst.make_future_dataframe(h=1)
expected_future
unique_idds
0H196961
1H256961
2H381961
3H413961

MLForecast.get_missing_future

 MLForecast.get_missing_future (h:int, X_df:~DFType)

获取 X_df 中缺失的 id 和时间组合。

类型详情
hint要预测的周期数。
X_dfDFType包含未来外部特征的 Dataframe。应包含 id 列和时间列。
返回值DFType包含在 X_df 中缺失的预期 id 和未来时间的 DataFrame
missing_future = fcst.get_missing_future(h=1, X_df=expected_future.head(2))
pd.testing.assert_frame_equal(
    missing_future,
    expected_future.tail(2).reset_index(drop=True)
)

MLForecast.forecast_fitted_values

 MLForecast.forecast_fitted_values
                                    (level:Optional[List[Union[int,float]]
                                    ]=None)

访问样本内预测。

类型默认值详情
level可选预测区间置信水平,介于 0 到 100 之间。
返回值联合类型包含训练集预测的 Dataframe
fcst.forecast_fitted_values()
unique_iddsyLGBMRegressor
0H19619312.712.671271
1H19619412.312.271271
2H19619511.911.871271
3H19619611.711.671271
4H19619711.411.471271
3067H41395659.068.280574
3068H41395758.070.427570
3069H41395853.044.767965
3070H41395938.048.691257
3071H41396046.046.652238
fcst.forecast_fitted_values(level=[90])
unique_iddsyLGBMRegressorLGBMRegressor-lo-90LGBMRegressor-hi-90
0H19619312.712.67127112.54063412.801909
1H19619412.312.27127112.14063412.401909
2H19619511.911.87127111.74063412.001909
3H19619611.711.67127111.54063411.801909
4H19619711.411.47127111.34063411.601909
3067H41395659.068.28057458.84664077.714509
3068H41395758.070.42757060.99363679.861504
3069H41395853.044.76796535.33403154.201899
3070H41395938.048.69125739.25732358.125191
3071H41396046.046.65223837.21830456.086172

一旦运行完成,我们就可以计算预测结果了。


MLForecast.predict

 MLForecast.predict (h:int,
                     before_predict_callback:Optional[Callable]=None,
                     after_predict_callback:Optional[Callable]=None,
                     new_df:Optional[~DFType]=None,
                     level:Optional[List[Union[int,float]]]=None,
                     X_df:Optional[~DFType]=None,
                     ids:Optional[List[str]]=None)

计算未来 h 步的预测。

类型默认值详情
hint要预测的周期数。
before_predict_callback可选在计算预测之前应用于特征的函数。
此函数将接受传递给模型进行预测的输入 dataframe,并应返回具有相同结构的 dataframe。
序列标识符位于索引中。
after_predict_callback可选在更新目标变量之前应用于预测结果的函数。
此函数将接受一个包含预测结果的 pandas Series,并应返回另一个具有相同结构的 Series。
序列标识符位于索引中。
new_df可选用于生成预测的新观测值的序列数据。
这个 dataframe 应该与用于拟合模型的 dataframe 具有相同的结构,包括任何特征和时间序列数据。
如果 new_df 不为 None,该方法将为新观测值生成预测。
level可选预测区间置信水平,介于 0 到 100 之间。
X_df可选包含未来外部特征的 Dataframe。应包含 id 列和时间列。
ids可选包含训练期间看到的 id 子集的列表,将为这些 id 计算预测。
返回值DFType每个序列和时间步的预测,每个模型有一列。
predictions = fcst.predict(horizon)

我们可以查看一些结果。

results = valid.merge(predictions, on=['unique_id', 'ds'])
fig = plot_series(forecasts_df=results)

预测区间

使用 MLForecast,你可以使用保形预测生成预测区间。要配置保形预测,你需要将 PredictionIntervals 类的一个实例传递给 fit 方法的 prediction_intervals 参数。该类接受三个参数:n_windowshmethod

  • n_windows 表示用于校准区间的交叉验证窗口数
  • h 是预测范围
  • method 可以是 conformal_distributionconformal_errorconformal_distribution(默认)根据交叉验证误差创建预测路径,并使用这些路径计算分位数,而 conformal_error 计算误差分位数以生成预测区间。该策略将针对每个预测步长调整区间,导致每个步长的宽度不同。请注意,必须至少使用 2 个交叉验证窗口。
fcst.fit(
    train,
    prediction_intervals=PredictionIntervals(n_windows=3, h=48)
);

之后,你只需使用 level 参数将所需的置信水平包含到 predict 方法中即可。水平必须介于 0 到 100 之间。

predictions_w_intervals = fcst.predict(48, level=[50, 80, 95])
predictions_w_intervals.head()
unique_iddsLGBMRegressorLGBMRegressor-lo-95LGBMRegressor-lo-80LGBMRegressor-lo-50LGBMRegressor-hi-50LGBMRegressor-hi-80LGBMRegressor-hi-95
0H19696116.07127115.95804215.97127116.00509116.13745216.17127116.184501
1H19696215.67127115.55363215.55363215.57863215.76391115.78891115.788911
2H19696315.27127115.15363215.15363215.16245215.38009115.38891115.388911
3H19696414.97127114.85804214.87127114.90509115.03745215.07127115.084501
4H19696514.67127114.55363214.55363214.56245214.78009114.78891114.788911

让我们探索生成的区间。

results = valid.merge(predictions_w_intervals, on=['unique_id', 'ds'])
fig = plot_series(forecasts_df=results, level=[50, 80, 95])

如果你想减少计算时间并为整个预测范围生成相同宽度的区间,只需将 h=1 传递给 PredictionIntervals 类即可。这种策略的缺点是,在某些情况下,绝对残差的方差可能很小(甚至为零),因此区间可能会太窄。

fcst.fit(
    train,  
    prediction_intervals=PredictionIntervals(n_windows=3, h=1)
);
predictions_w_intervals_ws_1 = fcst.predict(48, level=[80, 90, 95])

让我们探索生成的区间。

results = valid.merge(predictions_w_intervals_ws_1, on=['unique_id', 'ds'])
fig = plot_series(forecasts_df=results, level=[90])

使用预训练模型进行预测

MLForecast 允许你使用预训练模型为新数据集生成预测。只需在调用 predict 方法时,将包含新观测值的 pandas dataframe 作为 new_df 参数的值即可。该 dataframe 应与用于拟合模型的 dataframe 具有相同的结构,包括任何特征和时间序列数据。然后,该函数将使用预训练模型为新观测值生成预测。这使得你可以轻松地将预训练模型应用于新数据集并生成预测,而无需重新训练模型。

ercot_df = pd.read_csv('https://datasets-nixtla.s3.amazonaws.com/ERCOT-clean.csv')
# we have to convert the ds column to integers
# since MLForecast was trained with that structure
ercot_df['ds'] = np.arange(1, len(ercot_df) + 1)
# use the `new_df` argument to pass the ercot dataset 
ercot_fcsts = fcst.predict(horizon, new_df=ercot_df)
fig = plot_series(ercot_df, ercot_fcsts, max_insample_length=48 * 2)

如果你想查看将用于训练模型的数据,可以调用 Forecast.preprocess


MLForecast.preprocess

 MLForecast.preprocess (df:~DFType, id_col:str='unique_id',
                        time_col:str='ds', target_col:str='y',
                        static_features:Optional[List[str]]=None,
                        dropna:bool=True, keep_last_n:Optional[int]=None,
                        max_horizon:Optional[int]=None,
                        return_X_y:bool=False, as_numpy:bool=False,
                        weight_col:Optional[str]=None)

将特征添加到 data

类型默认值详情
dfDFType长格式的序列数据。
id_colstrunique_id标识每个序列的列。
time_colstrds标识每个时间步的列,其值可以是时间戳或整数。
target_colstry包含目标变量的列。
静态特征可选静态特征的名称,预测时将重复使用。
dropnaboolTrue删除由变换产生的缺失值行。
keep_last_n可选对于每个序列,仅保留这些数量的记录用于预测步骤。如果你的特征允许,可以节省时间和内存。
最大预测范围可选训练这么多个模型,每个模型将预测一个特定的预测范围。
return_X_yboolFalse返回包含特征和目标的元组。如果为 False,将返回一个 dataframe。
as_numpyboolFalse将特征转换为 numpy 数组。仅当 return_X_y=True 时有效。
weight_col可选包含样本权重的列。
返回值联合类型df 加上添加的特征和目标变量。
prep_df = fcst.preprocess(train)
prep_df
unique_iddsylag24lag48lag72lag96lag120lag144lag168exponentially_weighted_mean_lag48_alpha0.3
86988H1961930.10.00.00.00.30.10.10.30.002810
86989H1961940.1-0.10.10.00.30.10.10.30.031967
86990H1961950.1-0.10.10.00.30.10.20.10.052377
86991H1961960.10.00.00.00.30.20.10.20.036664
86992H1961970.00.00.00.10.20.20.10.20.025665
325187H4139560.010.01.06.0-53.044.0-21.021.07.963225
325188H4139579.010.010.0-7.0-46.027.0-19.024.08.574257
325189H41395816.08.05.0-9.0-36.032.0-13.08.07.501980
325190H413959-3.017.0-7.02.0-31.022.05.0-2.03.151386
325191H41396015.011.0-6.0-5.0-17.022.0-18.010.00.405970

如果我们这样做,那么必须调用 Forecast.fit_models,因为这仅存储了序列信息。


MLForecast.fit_models

 MLForecast.fit_models (X:Union[pandas.core.frame.DataFrame,polars.datafra
                        me.frame.DataFrame,numpy.ndarray],
                        y:numpy.ndarray)

手动训练模型。如果你事先调用了 MLForecast.preprocess,请使用此方法。

类型详情
X联合类型特征。
yndarray目标。
返回值MLForecast包含训练好的模型的预测对象。
X, y = prep_df.drop(columns=['unique_id', 'ds', 'y']), prep_df['y']
fcst.fit_models(X, y)
MLForecast(models=[LGBMRegressor], freq=1, lag_features=['lag24', 'lag48', 'lag72', 'lag96', 'lag120', 'lag144', 'lag168', 'exponentially_weighted_mean_lag48_alpha0.3'], date_features=[], num_threads=1)
predictions2 = fcst.predict(horizon)
pd.testing.assert_frame_equal(predictions, predictions2)

MLForecast.cross_validation

 MLForecast.cross_validation (df:~DFType, n_windows:int, h:int,
                              id_col:str='unique_id', time_col:str='ds',
                              target_col:str='y',
                              step_size:Optional[int]=None,
                              static_features:Optional[List[str]]=None,
                              dropna:bool=True,
                              keep_last_n:Optional[int]=None,
                              refit:Union[bool,int]=True,
                              max_horizon:Optional[int]=None, before_predi
                              ct_callback:Optional[Callable]=None, after_p
                              redict_callback:Optional[Callable]=None, pre
                              diction_intervals:Optional[mlforecast.utils.
                              PredictionIntervals]=None,
                              level:Optional[List[Union[int,float]]]=None,
                              input_size:Optional[int]=None,
                              fitted:bool=False, as_numpy:bool=False,
                              weight_col:Optional[str]=None)

执行时间序列交叉验证。创建 n_windows 个分割,每个窗口包含 h 个测试周期,然后训练模型,计算预测并合并实际值。

类型默认值详情
dfDFType长格式的序列数据。
n_windowsint要评估的窗口数。
hint预测范围。
id_colstrunique_id标识每个序列的列。
time_colstrds标识每个时间步的列,其值可以是时间戳或整数。
target_colstry包含目标变量的列。
step_size可选每个交叉验证窗口之间的步长。如果为 None,则等于 h
静态特征可选静态特征的名称,预测时将重复使用。
dropnaboolTrue删除由变换产生的缺失值行。
keep_last_n可选对于每个序列,仅保留这些数量的记录用于预测步骤。如果你的特征允许,可以节省时间和内存。
refit联合类型True对每个交叉验证窗口重新训练模型。
如果为 False,模型在开始时训练,然后用于预测每个窗口。
如果是正整数,模型将每隔 refit 个窗口重新训练。
最大预测范围可选
before_predict_callback可选在计算预测之前应用于特征的函数。
此函数将接受传递给模型进行预测的输入 dataframe,并应返回具有相同结构的 dataframe。
序列标识符位于索引中。
after_predict_callback可选在更新目标变量之前应用于预测结果的函数。
此函数将接受一个包含预测结果的 pandas Series,并应返回另一个具有相同结构的 Series。
序列标识符位于索引中。
预测区间可选用于校准预测区间(保形预测)的配置。
level可选预测区间置信水平,介于 0 到 100 之间。
input_size可选每个窗口中每个序列的最大训练样本数。如果为 None,将使用扩展窗口。
fittedboolFalse存储样本内预测。
as_numpyboolFalse将特征转换为 numpy 数组。
weight_col可选包含样本权重的列。
返回值DFType每个窗口的预测,包含序列 id、时间戳、上次训练日期、目标值以及每个模型的预测。

如果我们想知道特定模型和特征集下的预测效果如何,可以进行交叉验证。交叉验证的作用是将我们的数据分成两部分,第一部分用于训练,第二部分用于验证。由于数据具有时间依赖性,我们通常将数据的最后 x 个观测值作为验证集。

此过程在 MLForecast.cross_validation 中实现,它接收我们的数据并执行上述过程 n_windows 次,其中每个窗口包含 h 个验证样本。例如,如果我们有 100 个样本并想进行 2 次回测,每次大小为 14,则分割如下:

  1. 训练集:1 到 72。验证集:73 到 86。
  2. 训练集:1 到 86。验证集:87 到 100。

你可以使用 step_size 参数控制每个交叉验证窗口之间的距离。例如,如果我们有 100 个样本并想进行 2 次大小为 14 的回测,并在每个折叠中向前移动一步(step_size=1),则分割如下:

  1. 训练集:1 到 85。验证集:86 到 99。
  2. 训练集:1 到 86。验证集:87 到 100。

你还可以通过设置 refit=False 来执行交叉验证,而无需对每个窗口重新训练模型。这使得你可以使用多个窗口大小评估模型的性能,而无需每次都重新训练它们。

fcst = MLForecast(
    models=lgb.LGBMRegressor(random_state=0, verbosity=-1),
    freq=1,
    lags=[24 * (i+1) for i in range(7)],
    lag_transforms={
        1: [RollingMean(window_size=24)],
        24: [RollingMean(window_size=24)],
        48: [ExponentiallyWeightedMean(alpha=0.3)],
    },
    num_threads=1,
    target_transforms=[Differences([24])],
)
cv_results = fcst.cross_validation(
    train,
    n_windows=2,
    h=horizon,
    step_size=horizon,
    fitted=True,
)
cv_results
unique_iddscutoffyLGBMRegressor
0H19686586415.515.373393
1H19686686415.114.973393
2H19686786414.814.673393
3H19686886414.414.373393
4H19686986414.214.073393
379H41395691259.064.284167
380H41395791258.064.830429
381H41395891253.040.726851
382H41395991238.042.739657
383H41396091246.052.802769

由于我们将 fitted 设置为 True,我们也可以通过 cross_validation_fitted_values 方法访问训练集的预测结果。

fcst.cross_validation_fitted_values()
unique_iddsfoldyLGBMRegressor
0H196193012.712.673393
1H196194012.312.273393
2H196195011.911.873393
3H196196011.711.673393
4H196197011.411.473393
5563H413908149.050.620196
5564H413909139.035.972331
5565H413910129.029.359678
5566H413911124.025.784563
5567H413912120.023.168413

我们还可以通过将配置传递给 prediction_intervals 以及通过 levels 传递宽度值来计算预测区间。

cv_results_intervals = fcst.cross_validation(
    train,
    n_windows=2,
    h=horizon,
    step_size=horizon,
    prediction_intervals=PredictionIntervals(h=horizon),
    level=[80, 90]
)
cv_results_intervals
unique_iddscutoffyLGBMRegressorLGBMRegressor-lo-90LGBMRegressor-lo-80LGBMRegressor-hi-80LGBMRegressor-hi-90
0H19686586415.515.37339315.31137915.31652815.43025815.435407
1H19686686415.114.97339314.94055614.94055615.00623015.006230
2H19686786414.814.67339314.60623014.60623014.74055614.740556
3H19686886414.414.37339314.30623014.30623014.44055614.440556
4H19686986414.214.07339314.00623014.00623014.14055614.140556
379H41395691259.064.28416729.89009934.37154594.19678898.678234
380H41395791258.064.83042956.87457257.82768971.83316972.786285
381H41395891253.040.72685135.29619535.84620645.60749546.157506
382H41395991238.042.73965735.29215335.80764049.67167450.187161
383H41396091246.052.80276942.46559743.89567061.70986963.139941

refit 参数允许我们控制是否要在每个窗口中重新训练模型。它可以是

  • 一个布尔值:True 将在每个窗口中重新训练,False 仅在第一个窗口中训练。
  • 一个正整数:模型将在第一个窗口中训练,然后每隔 refit 个窗口训练一次。
fcst = MLForecast(
    models=LinearRegression(),
    freq=1,
    lags=[1, 24],
)
for refit, expected_models in zip([True, False, 2], [4, 1, 2]):
    fcst.cross_validation(
        train,
        n_windows=4,
        h=horizon,
        refit=refit,
    )
    test_eq(len(fcst.cv_models_), expected_models)
fig = plot_series(forecasts_df=cv_results.drop(columns='cutoff'))

fig = plot_series(forecasts_df=cv_results_intervals.drop(columns='cutoff'), level=[90])


MLForecast.from_cv

 MLForecast.from_cv (cv:mlforecast.lgb_cv.LightGBMCV)

一旦找到一组适用于你的问题的特征和参数,就可以使用 MLForecast.from_cv 从中构建一个预测对象,该方法接受训练好的 LightGBMCV 对象,并构建一个将使用相同特征和参数的 MLForecast 对象。然后,你就可以像往常一样调用 fit 和 predict。

cv = LightGBMCV(
    freq=1,
    lags=[24 * (i+1) for i in range(7)],
    lag_transforms={
        48: [ExponentiallyWeightedMean(alpha=0.3)],
    },
    num_threads=1,
    target_transforms=[Differences([24])]
)
hist = cv.fit(
    train,
    n_windows=2,
    h=horizon,
    params={'verbosity': -1},
)
[10] mape: 0.118569
[20] mape: 0.111506
[30] mape: 0.107314
[40] mape: 0.106089
[50] mape: 0.106630
Early stopping at round 50
Using best iteration: 40
fcst = MLForecast.from_cv(cv)
assert cv.best_iteration_ == fcst.models['LGBMRegressor'].n_estimators