autogluon.timeseries 1.3.2b20250712__py3-none-any.whl → 1.4.1b20251116__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- autogluon/timeseries/configs/__init__.py +3 -2
- autogluon/timeseries/configs/hyperparameter_presets.py +62 -0
- autogluon/timeseries/configs/predictor_presets.py +84 -0
- autogluon/timeseries/dataset/ts_dataframe.py +98 -72
- autogluon/timeseries/learner.py +19 -18
- autogluon/timeseries/metrics/__init__.py +5 -5
- autogluon/timeseries/metrics/abstract.py +17 -17
- autogluon/timeseries/metrics/point.py +1 -1
- autogluon/timeseries/metrics/quantile.py +2 -2
- autogluon/timeseries/metrics/utils.py +4 -4
- autogluon/timeseries/models/__init__.py +4 -0
- autogluon/timeseries/models/abstract/abstract_timeseries_model.py +52 -75
- autogluon/timeseries/models/abstract/tunable.py +6 -6
- autogluon/timeseries/models/autogluon_tabular/mlforecast.py +72 -76
- autogluon/timeseries/models/autogluon_tabular/per_step.py +104 -46
- autogluon/timeseries/models/autogluon_tabular/transforms.py +9 -7
- autogluon/timeseries/models/chronos/model.py +115 -78
- autogluon/timeseries/models/chronos/{pipeline/utils.py → utils.py} +76 -44
- autogluon/timeseries/models/ensemble/__init__.py +29 -2
- autogluon/timeseries/models/ensemble/abstract.py +16 -52
- autogluon/timeseries/models/ensemble/array_based/__init__.py +3 -0
- autogluon/timeseries/models/ensemble/array_based/abstract.py +247 -0
- autogluon/timeseries/models/ensemble/array_based/models.py +50 -0
- autogluon/timeseries/models/ensemble/array_based/regressor/__init__.py +10 -0
- autogluon/timeseries/models/ensemble/array_based/regressor/abstract.py +87 -0
- autogluon/timeseries/models/ensemble/array_based/regressor/per_quantile_tabular.py +133 -0
- autogluon/timeseries/models/ensemble/array_based/regressor/tabular.py +141 -0
- autogluon/timeseries/models/ensemble/weighted/__init__.py +8 -0
- autogluon/timeseries/models/ensemble/weighted/abstract.py +41 -0
- autogluon/timeseries/models/ensemble/{basic.py → weighted/basic.py} +8 -18
- autogluon/timeseries/models/ensemble/{greedy.py → weighted/greedy.py} +13 -13
- autogluon/timeseries/models/gluonts/abstract.py +26 -26
- autogluon/timeseries/models/gluonts/dataset.py +4 -4
- autogluon/timeseries/models/gluonts/models.py +27 -12
- autogluon/timeseries/models/local/abstract_local_model.py +14 -14
- autogluon/timeseries/models/local/naive.py +4 -0
- autogluon/timeseries/models/local/npts.py +1 -0
- autogluon/timeseries/models/local/statsforecast.py +30 -14
- autogluon/timeseries/models/multi_window/multi_window_model.py +34 -23
- autogluon/timeseries/models/registry.py +65 -0
- autogluon/timeseries/models/toto/__init__.py +3 -0
- autogluon/timeseries/models/toto/_internal/__init__.py +9 -0
- autogluon/timeseries/models/toto/_internal/backbone/__init__.py +3 -0
- autogluon/timeseries/models/toto/_internal/backbone/attention.py +197 -0
- autogluon/timeseries/models/toto/_internal/backbone/backbone.py +262 -0
- autogluon/timeseries/models/toto/_internal/backbone/distribution.py +70 -0
- autogluon/timeseries/models/toto/_internal/backbone/kvcache.py +136 -0
- autogluon/timeseries/models/toto/_internal/backbone/rope.py +94 -0
- autogluon/timeseries/models/toto/_internal/backbone/scaler.py +306 -0
- autogluon/timeseries/models/toto/_internal/backbone/transformer.py +333 -0
- autogluon/timeseries/models/toto/_internal/dataset.py +165 -0
- autogluon/timeseries/models/toto/_internal/forecaster.py +423 -0
- autogluon/timeseries/models/toto/dataloader.py +108 -0
- autogluon/timeseries/models/toto/hf_pretrained_model.py +119 -0
- autogluon/timeseries/models/toto/model.py +236 -0
- autogluon/timeseries/predictor.py +94 -107
- autogluon/timeseries/regressor.py +31 -27
- autogluon/timeseries/splitter.py +7 -31
- autogluon/timeseries/trainer/__init__.py +3 -0
- autogluon/timeseries/trainer/ensemble_composer.py +250 -0
- autogluon/timeseries/trainer/model_set_builder.py +256 -0
- autogluon/timeseries/trainer/prediction_cache.py +149 -0
- autogluon/timeseries/{trainer.py → trainer/trainer.py} +182 -307
- autogluon/timeseries/trainer/utils.py +18 -0
- autogluon/timeseries/transforms/covariate_scaler.py +4 -4
- autogluon/timeseries/transforms/target_scaler.py +14 -14
- autogluon/timeseries/utils/datetime/lags.py +2 -2
- autogluon/timeseries/utils/datetime/time_features.py +2 -2
- autogluon/timeseries/utils/features.py +41 -37
- autogluon/timeseries/utils/forecast.py +5 -5
- autogluon/timeseries/utils/warning_filters.py +3 -1
- autogluon/timeseries/version.py +1 -1
- autogluon.timeseries-1.4.1b20251116-py3.9-nspkg.pth +1 -0
- {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info}/METADATA +32 -17
- autogluon_timeseries-1.4.1b20251116.dist-info/RECORD +96 -0
- {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info}/WHEEL +1 -1
- autogluon/timeseries/configs/presets_configs.py +0 -79
- autogluon/timeseries/evaluator.py +0 -6
- autogluon/timeseries/models/chronos/pipeline/__init__.py +0 -10
- autogluon/timeseries/models/chronos/pipeline/base.py +0 -160
- autogluon/timeseries/models/chronos/pipeline/chronos.py +0 -544
- autogluon/timeseries/models/chronos/pipeline/chronos_bolt.py +0 -530
- autogluon/timeseries/models/presets.py +0 -358
- autogluon.timeseries-1.3.2b20250712-py3.9-nspkg.pth +0 -1
- autogluon.timeseries-1.3.2b20250712.dist-info/RECORD +0 -71
- {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info/licenses}/LICENSE +0 -0
- {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info/licenses}/NOTICE +0 -0
- {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info}/namespace_packages.txt +0 -0
- {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info}/top_level.txt +0 -0
- {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info}/zip-safe +0 -0
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
import math
|
|
4
4
|
import time
|
|
5
5
|
import warnings
|
|
6
|
-
from typing import Any, Callable, Collection,
|
|
6
|
+
from typing import Any, Callable, Collection, Optional, Type, Union
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
import pandas as pd
|
|
@@ -13,7 +13,7 @@ import autogluon.core as ag
|
|
|
13
13
|
from autogluon.core.models import AbstractModel as AbstractTabularModel
|
|
14
14
|
from autogluon.features import AutoMLPipelineFeatureGenerator
|
|
15
15
|
from autogluon.tabular.registry import ag_model_registry
|
|
16
|
-
from autogluon.timeseries.dataset
|
|
16
|
+
from autogluon.timeseries.dataset import TimeSeriesDataFrame
|
|
17
17
|
from autogluon.timeseries.metrics.abstract import TimeSeriesScorer
|
|
18
18
|
from autogluon.timeseries.metrics.utils import in_sample_squared_seasonal_error
|
|
19
19
|
from autogluon.timeseries.models.abstract import AbstractTimeSeriesModel
|
|
@@ -36,7 +36,7 @@ class TabularModel(BaseEstimator):
|
|
|
36
36
|
def __init__(self, model_class: Type[AbstractTabularModel], model_kwargs: Optional[dict] = None):
|
|
37
37
|
self.model_class = model_class
|
|
38
38
|
self.model_kwargs = {} if model_kwargs is None else model_kwargs
|
|
39
|
-
self.feature_pipeline = AutoMLPipelineFeatureGenerator()
|
|
39
|
+
self.feature_pipeline = AutoMLPipelineFeatureGenerator(verbosity=0)
|
|
40
40
|
|
|
41
41
|
def fit(self, X: pd.DataFrame, y: pd.Series, X_val: pd.DataFrame, y_val: pd.Series, **kwargs):
|
|
42
42
|
self.model = self.model_class(**self.model_kwargs)
|
|
@@ -68,7 +68,7 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
|
68
68
|
path: Optional[str] = None,
|
|
69
69
|
name: Optional[str] = None,
|
|
70
70
|
eval_metric: Optional[Union[str, TimeSeriesScorer]] = None,
|
|
71
|
-
hyperparameters: Optional[
|
|
71
|
+
hyperparameters: Optional[dict[str, Any]] = None,
|
|
72
72
|
**kwargs,
|
|
73
73
|
):
|
|
74
74
|
super().__init__(
|
|
@@ -86,12 +86,12 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
|
86
86
|
self._sum_of_differences: int = 0 # number of time steps removed from each series by differencing
|
|
87
87
|
self._max_ts_length: Optional[int] = None
|
|
88
88
|
self._target_lags: np.ndarray
|
|
89
|
-
self._date_features:
|
|
89
|
+
self._date_features: list[Callable]
|
|
90
90
|
self._mlf: MLForecast
|
|
91
91
|
self._scaler: Optional[BaseTargetTransform] = None
|
|
92
92
|
self._residuals_std_per_item: pd.Series
|
|
93
93
|
self._train_target_median: Optional[float] = None
|
|
94
|
-
self._non_boolean_real_covariates:
|
|
94
|
+
self._non_boolean_real_covariates: list[str] = []
|
|
95
95
|
|
|
96
96
|
def _initialize_transforms_and_regressor(self):
|
|
97
97
|
super()._initialize_transforms_and_regressor()
|
|
@@ -99,7 +99,7 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
|
99
99
|
self.target_scaler = None
|
|
100
100
|
|
|
101
101
|
@property
|
|
102
|
-
def allowed_hyperparameters(self) ->
|
|
102
|
+
def allowed_hyperparameters(self) -> list[str]:
|
|
103
103
|
return super().allowed_hyperparameters + [
|
|
104
104
|
"lags",
|
|
105
105
|
"date_features",
|
|
@@ -117,10 +117,12 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
|
117
117
|
known_covariates: Optional[TimeSeriesDataFrame] = None,
|
|
118
118
|
is_train: bool = False,
|
|
119
119
|
**kwargs,
|
|
120
|
-
) ->
|
|
120
|
+
) -> tuple[TimeSeriesDataFrame, Optional[TimeSeriesDataFrame]]:
|
|
121
121
|
if is_train:
|
|
122
122
|
# All-NaN series are removed; partially-NaN series in train_data are handled inside _generate_train_val_dfs
|
|
123
|
-
all_nan_items = data.item_ids[
|
|
123
|
+
all_nan_items = data.item_ids[
|
|
124
|
+
data[self.target].isna().groupby(TimeSeriesDataFrame.ITEMID, sort=False).all()
|
|
125
|
+
]
|
|
124
126
|
if len(all_nan_items):
|
|
125
127
|
data = data.query("item_id not in @all_nan_items")
|
|
126
128
|
else:
|
|
@@ -130,32 +132,7 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
|
130
132
|
data[self.target] = data[self.target].fillna(value=self._train_target_median)
|
|
131
133
|
return data, known_covariates
|
|
132
134
|
|
|
133
|
-
def
|
|
134
|
-
if "tabular_hyperparameters" in model_params:
|
|
135
|
-
logger.warning(
|
|
136
|
-
f"Hyperparameter 'tabular_hyperparameters' for {self.name} is deprecated and will be removed in v1.5. "
|
|
137
|
-
"Please use 'model_name' to specify the tabular model alias and 'model_hyperparameters' "
|
|
138
|
-
"to provide the tabular model hyperparameters."
|
|
139
|
-
)
|
|
140
|
-
tabular_hyperparameters = model_params.pop("tabular_hyperparameters")
|
|
141
|
-
if len(tabular_hyperparameters) == 1:
|
|
142
|
-
# We can automatically convert the hyperparameters if only one model is used
|
|
143
|
-
model_params["model_name"] = list(tabular_hyperparameters.keys())[0]
|
|
144
|
-
model_params["model_hyperparameters"] = tabular_hyperparameters[model_params["model_name"]]
|
|
145
|
-
else:
|
|
146
|
-
raise ValueError(
|
|
147
|
-
f"Provided 'tabular_hyperparameters' {tabular_hyperparameters} cannot be automatically converted "
|
|
148
|
-
f"to the new 'model_name' and 'model_hyperparameters' API for {self.name}."
|
|
149
|
-
)
|
|
150
|
-
if "tabular_fit_kwargs" in model_params:
|
|
151
|
-
logger.warning(
|
|
152
|
-
f"Hyperparameters 'tabular_fit_kwargs' for {self.name} is deprecated and is ignored by the model. "
|
|
153
|
-
"Please use 'model_name' to specify the tabular model alias and 'model_hyperparameters' "
|
|
154
|
-
"to provide the tabular model hyperparameters."
|
|
155
|
-
)
|
|
156
|
-
return model_params
|
|
157
|
-
|
|
158
|
-
def _get_default_hyperparameters(self) -> Dict[str, Any]:
|
|
135
|
+
def _get_default_hyperparameters(self) -> dict[str, Any]:
|
|
159
136
|
return {
|
|
160
137
|
"max_num_items": 20_000,
|
|
161
138
|
"max_num_samples": 1_000_000,
|
|
@@ -163,12 +140,12 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
|
163
140
|
"model_hyperparameters": {},
|
|
164
141
|
}
|
|
165
142
|
|
|
166
|
-
def _create_tabular_model(self, model_name: str, model_hyperparameters:
|
|
143
|
+
def _create_tabular_model(self, model_name: str, model_hyperparameters: dict[str, Any]) -> TabularModel:
|
|
167
144
|
raise NotImplementedError
|
|
168
145
|
|
|
169
146
|
def _get_mlforecast_init_args(
|
|
170
|
-
self, train_data: TimeSeriesDataFrame, model_params:
|
|
171
|
-
) ->
|
|
147
|
+
self, train_data: TimeSeriesDataFrame, model_params: dict[str, Any]
|
|
148
|
+
) -> dict[str, Any]:
|
|
172
149
|
from mlforecast.target_transforms import Differences
|
|
173
150
|
|
|
174
151
|
from .transforms import MLForecastScaler
|
|
@@ -236,7 +213,7 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
|
236
213
|
|
|
237
214
|
def _generate_train_val_dfs(
|
|
238
215
|
self, data: TimeSeriesDataFrame, max_num_items: Optional[int] = None, max_num_samples: Optional[int] = None
|
|
239
|
-
) ->
|
|
216
|
+
) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
240
217
|
# Exclude items that are too short for chosen differences - otherwise exception will be raised
|
|
241
218
|
if self._sum_of_differences > 0:
|
|
242
219
|
ts_lengths = data.num_timesteps_per_item()
|
|
@@ -298,18 +275,28 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
|
298
275
|
"""
|
|
299
276
|
# TODO: Add support for past_covariates
|
|
300
277
|
selected_columns = self.covariate_metadata.known_covariates.copy()
|
|
301
|
-
column_name_mapping = {ITEMID: MLF_ITEMID, TIMESTAMP: MLF_TIMESTAMP}
|
|
278
|
+
column_name_mapping = {TimeSeriesDataFrame.ITEMID: MLF_ITEMID, TimeSeriesDataFrame.TIMESTAMP: MLF_TIMESTAMP}
|
|
302
279
|
if include_target:
|
|
303
280
|
selected_columns += [self.target]
|
|
304
281
|
column_name_mapping[self.target] = MLF_TARGET
|
|
305
282
|
|
|
306
283
|
df = pd.DataFrame(data)[selected_columns].reset_index()
|
|
307
284
|
if static_features is not None:
|
|
308
|
-
df = pd.merge(
|
|
285
|
+
df = pd.merge(
|
|
286
|
+
df, static_features, how="left", on=TimeSeriesDataFrame.ITEMID, suffixes=(None, "_static_feat")
|
|
287
|
+
)
|
|
309
288
|
|
|
310
289
|
for col in self._non_boolean_real_covariates:
|
|
311
290
|
# Normalize non-boolean features using mean_abs scaling
|
|
312
|
-
df[f"__scaled_{col}"] =
|
|
291
|
+
df[f"__scaled_{col}"] = (
|
|
292
|
+
df[col]
|
|
293
|
+
/ df[col]
|
|
294
|
+
.abs()
|
|
295
|
+
.groupby(df[TimeSeriesDataFrame.ITEMID])
|
|
296
|
+
.mean()
|
|
297
|
+
.reindex(df[TimeSeriesDataFrame.ITEMID])
|
|
298
|
+
.values
|
|
299
|
+
)
|
|
313
300
|
|
|
314
301
|
# Convert float64 to float32 to reduce memory usage
|
|
315
302
|
float64_cols = list(df.select_dtypes(include="float64"))
|
|
@@ -338,7 +325,6 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
|
338
325
|
if not set(train_data[col].unique()) == set([0, 1]):
|
|
339
326
|
self._non_boolean_real_covariates.append(col)
|
|
340
327
|
model_params = self.get_hyperparameters()
|
|
341
|
-
model_params = self._process_deprecated_hyperparameters(model_params)
|
|
342
328
|
|
|
343
329
|
mlforecast_init_args = self._get_mlforecast_init_args(train_data, model_params)
|
|
344
330
|
assert self.freq is not None
|
|
@@ -400,16 +386,16 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
|
400
386
|
self,
|
|
401
387
|
data: TimeSeriesDataFrame,
|
|
402
388
|
known_covariates: Optional[TimeSeriesDataFrame] = None,
|
|
403
|
-
) ->
|
|
389
|
+
) -> tuple[TimeSeriesDataFrame, Optional[TimeSeriesDataFrame], Optional[TimeSeriesDataFrame]]:
|
|
404
390
|
"""Remove series that are too short for chosen differencing from data and generate naive forecast for them.
|
|
405
391
|
|
|
406
392
|
Returns
|
|
407
393
|
-------
|
|
408
|
-
data_long
|
|
394
|
+
data_long
|
|
409
395
|
Data containing only time series that are long enough for the model to predict.
|
|
410
|
-
known_covariates_long
|
|
396
|
+
known_covariates_long
|
|
411
397
|
Future known covariates containing only time series that are long enough for the model to predict.
|
|
412
|
-
forecast_for_short_series
|
|
398
|
+
forecast_for_short_series
|
|
413
399
|
Seasonal naive forecast for short series, if there are any in the dataset.
|
|
414
400
|
"""
|
|
415
401
|
ts_lengths = data.num_timesteps_per_item()
|
|
@@ -468,12 +454,12 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
|
468
454
|
predictions[str(q)] = predictions["mean"] + norm.ppf(q) * std_per_timestep.to_numpy()
|
|
469
455
|
return predictions
|
|
470
456
|
|
|
471
|
-
def _more_tags(self) ->
|
|
457
|
+
def _more_tags(self) -> dict[str, Any]:
|
|
472
458
|
return {"allow_nan": True, "can_refit_full": True}
|
|
473
459
|
|
|
474
460
|
|
|
475
461
|
class DirectTabularModel(AbstractMLForecastModel):
|
|
476
|
-
"""Predict all future time series values simultaneously using
|
|
462
|
+
"""Predict all future time series values simultaneously using a regression model from AutoGluon-Tabular.
|
|
477
463
|
|
|
478
464
|
A single tabular model is used to forecast all future time series values using the following features:
|
|
479
465
|
|
|
@@ -493,35 +479,37 @@ class DirectTabularModel(AbstractMLForecastModel):
|
|
|
493
479
|
|
|
494
480
|
Other Parameters
|
|
495
481
|
----------------
|
|
496
|
-
lags :
|
|
482
|
+
lags : list[int], default = None
|
|
497
483
|
Lags of the target that will be used as features for predictions. If None, will be determined automatically
|
|
498
484
|
based on the frequency of the data.
|
|
499
|
-
date_features :
|
|
485
|
+
date_features : list[Union[str, Callable]], default = None
|
|
500
486
|
Features computed from the dates. Can be pandas date attributes or functions that will take the dates as input.
|
|
501
487
|
If None, will be determined automatically based on the frequency of the data.
|
|
502
|
-
differences :
|
|
488
|
+
differences : list[int], default = []
|
|
503
489
|
Differences to take of the target before computing the features. These are restored at the forecasting step.
|
|
504
490
|
Defaults to no differencing.
|
|
505
491
|
target_scaler : {"standard", "mean_abs", "min_max", "robust", None}, default = "mean_abs"
|
|
506
492
|
Scaling applied to each time series. Scaling is applied after differencing.
|
|
507
493
|
model_name : str, default = "GBM"
|
|
508
|
-
Name of the tabular regression model. See
|
|
494
|
+
Name of the tabular regression model. See ``autogluon.tabular.registry.ag_model_registry`` or
|
|
509
495
|
`the documentation <https://auto.gluon.ai/stable/api/autogluon.tabular.models.html>`_ for the list of available
|
|
510
496
|
tabular models.
|
|
511
|
-
model_hyperparameters :
|
|
497
|
+
model_hyperparameters : dict[str, Any], optional
|
|
512
498
|
Hyperparameters passed to the tabular regression model.
|
|
513
499
|
max_num_items : int or None, default = 20_000
|
|
514
500
|
If not None, the model will randomly select this many time series for training and validation.
|
|
515
501
|
max_num_samples : int or None, default = 1_000_000
|
|
516
|
-
If not None, training dataset passed to
|
|
517
|
-
end of each time series).
|
|
502
|
+
If not None, training dataset passed to the tabular regression model will contain at most this many rows
|
|
503
|
+
(starting from the end of each time series).
|
|
518
504
|
"""
|
|
519
505
|
|
|
506
|
+
ag_priority = 85
|
|
507
|
+
|
|
520
508
|
@property
|
|
521
509
|
def is_quantile_model(self) -> bool:
|
|
522
510
|
return self.eval_metric.needs_quantile
|
|
523
511
|
|
|
524
|
-
def get_hyperparameters(self) ->
|
|
512
|
+
def get_hyperparameters(self) -> dict[str, Any]:
|
|
525
513
|
model_params = super().get_hyperparameters()
|
|
526
514
|
# We don't set 'target_scaler' if user already provided 'scaler' to avoid overriding the user-provided value
|
|
527
515
|
if "scaler" not in model_params:
|
|
@@ -610,12 +598,14 @@ class DirectTabularModel(AbstractMLForecastModel):
|
|
|
610
598
|
predictions, repeated_item_ids=predictions[MLF_ITEMID], past_target=data[self.target]
|
|
611
599
|
)
|
|
612
600
|
predictions_tsdf: TimeSeriesDataFrame = TimeSeriesDataFrame(
|
|
613
|
-
predictions.rename(
|
|
601
|
+
predictions.rename(
|
|
602
|
+
columns={MLF_ITEMID: TimeSeriesDataFrame.ITEMID, MLF_TIMESTAMP: TimeSeriesDataFrame.TIMESTAMP}
|
|
603
|
+
)
|
|
614
604
|
)
|
|
615
605
|
|
|
616
606
|
if forecast_for_short_series is not None:
|
|
617
607
|
predictions_tsdf = pd.concat([predictions_tsdf, forecast_for_short_series]) # type: ignore
|
|
618
|
-
predictions_tsdf = predictions_tsdf.reindex(original_item_id_order, level=ITEMID)
|
|
608
|
+
predictions_tsdf = predictions_tsdf.reindex(original_item_id_order, level=TimeSeriesDataFrame.ITEMID)
|
|
619
609
|
|
|
620
610
|
return predictions_tsdf
|
|
621
611
|
|
|
@@ -632,7 +622,7 @@ class DirectTabularModel(AbstractMLForecastModel):
|
|
|
632
622
|
column_order = ["mean"] + [col for col in predictions_df.columns if col != "mean"]
|
|
633
623
|
return predictions_df[column_order]
|
|
634
624
|
|
|
635
|
-
def _create_tabular_model(self, model_name: str, model_hyperparameters:
|
|
625
|
+
def _create_tabular_model(self, model_name: str, model_hyperparameters: dict[str, Any]) -> TabularModel:
|
|
636
626
|
model_class = ag_model_registry.key_to_cls(model_name)
|
|
637
627
|
if self.is_quantile_model:
|
|
638
628
|
problem_type = ag.constants.QUANTILE
|
|
@@ -654,16 +644,16 @@ class DirectTabularModel(AbstractMLForecastModel):
|
|
|
654
644
|
|
|
655
645
|
|
|
656
646
|
class RecursiveTabularModel(AbstractMLForecastModel):
|
|
657
|
-
"""Predict future time series values one by one using
|
|
647
|
+
"""Predict future time series values one by one using a regression model from AutoGluon-Tabular.
|
|
658
648
|
|
|
659
|
-
A single
|
|
649
|
+
A single tabular regression model is used to forecast the future time series values using the following features:
|
|
660
650
|
|
|
661
651
|
- lag features (observed time series values) based on ``freq`` of the data
|
|
662
652
|
- time features (e.g., day of the week) based on the timestamp of the measurement
|
|
663
653
|
- known covariates (if available)
|
|
664
654
|
- static features of each item (if available)
|
|
665
655
|
|
|
666
|
-
|
|
656
|
+
The tabular model will always be trained with ``"regression"`` problem type, and dummy quantiles will be
|
|
667
657
|
obtained by assuming that the residuals follow zero-mean normal distribution.
|
|
668
658
|
|
|
669
659
|
Based on the `mlforecast <https://github.com/Nixtla/mlforecast>`_ library.
|
|
@@ -671,34 +661,36 @@ class RecursiveTabularModel(AbstractMLForecastModel):
|
|
|
671
661
|
|
|
672
662
|
Other Parameters
|
|
673
663
|
----------------
|
|
674
|
-
lags :
|
|
664
|
+
lags : list[int], default = None
|
|
675
665
|
Lags of the target that will be used as features for predictions. If None, will be determined automatically
|
|
676
666
|
based on the frequency of the data.
|
|
677
|
-
date_features :
|
|
667
|
+
date_features : list[Union[str, Callable]], default = None
|
|
678
668
|
Features computed from the dates. Can be pandas date attributes or functions that will take the dates as input.
|
|
679
669
|
If None, will be determined automatically based on the frequency of the data.
|
|
680
|
-
differences :
|
|
670
|
+
differences : list[int], default = None
|
|
681
671
|
Differences to take of the target before computing the features. These are restored at the forecasting step.
|
|
682
672
|
If None, will be set to ``[seasonal_period]``, where seasonal_period is determined based on the data frequency.
|
|
683
673
|
target_scaler : {"standard", "mean_abs", "min_max", "robust", None}, default = "standard"
|
|
684
674
|
Scaling applied to each time series. Scaling is applied after differencing.
|
|
685
|
-
lag_transforms :
|
|
675
|
+
lag_transforms : dict[int, list[Callable]], default = None
|
|
686
676
|
Dictionary mapping lag periods to transformation functions applied to lagged target values (e.g., rolling mean).
|
|
687
677
|
See `MLForecast documentation <https://nixtlaverse.nixtla.io/mlforecast/lag_transforms.html>`_ for more details.
|
|
688
678
|
model_name : str, default = "GBM"
|
|
689
|
-
Name of the tabular regression model. See
|
|
679
|
+
Name of the tabular regression model. See ``autogluon.tabular.registry.ag_model_registry`` or
|
|
690
680
|
`the documentation <https://auto.gluon.ai/stable/api/autogluon.tabular.models.html>`_ for the list of available
|
|
691
681
|
tabular models.
|
|
692
|
-
model_hyperparameters :
|
|
682
|
+
model_hyperparameters : dict[str, Any], optional
|
|
693
683
|
Hyperparameters passed to the tabular regression model.
|
|
694
684
|
max_num_items : int or None, default = 20_000
|
|
695
685
|
If not None, the model will randomly select this many time series for training and validation.
|
|
696
686
|
max_num_samples : int or None, default = 1_000_000
|
|
697
|
-
If not None, training dataset passed to
|
|
698
|
-
end of each time series).
|
|
687
|
+
If not None, training dataset passed to the tabular regression model will contain at most this many rows
|
|
688
|
+
(starting from the end of each time series).
|
|
699
689
|
"""
|
|
700
690
|
|
|
701
|
-
|
|
691
|
+
ag_priority = 90
|
|
692
|
+
|
|
693
|
+
def get_hyperparameters(self) -> dict[str, Any]:
|
|
702
694
|
model_params = super().get_hyperparameters()
|
|
703
695
|
# We don't set 'target_scaler' if user already provided 'scaler' to avoid overriding the user-provided value
|
|
704
696
|
if "scaler" not in model_params:
|
|
@@ -741,18 +733,22 @@ class RecursiveTabularModel(AbstractMLForecastModel):
|
|
|
741
733
|
X_df=X_df,
|
|
742
734
|
)
|
|
743
735
|
assert isinstance(raw_predictions, pd.DataFrame)
|
|
744
|
-
raw_predictions = raw_predictions.rename(
|
|
736
|
+
raw_predictions = raw_predictions.rename(
|
|
737
|
+
columns={MLF_ITEMID: TimeSeriesDataFrame.ITEMID, MLF_TIMESTAMP: TimeSeriesDataFrame.TIMESTAMP}
|
|
738
|
+
)
|
|
745
739
|
|
|
746
740
|
predictions: TimeSeriesDataFrame = TimeSeriesDataFrame(
|
|
747
741
|
self._add_gaussian_quantiles(
|
|
748
|
-
raw_predictions,
|
|
742
|
+
raw_predictions,
|
|
743
|
+
repeated_item_ids=raw_predictions[TimeSeriesDataFrame.ITEMID],
|
|
744
|
+
past_target=data[self.target],
|
|
749
745
|
)
|
|
750
746
|
)
|
|
751
747
|
if forecast_for_short_series is not None:
|
|
752
748
|
predictions = pd.concat([predictions, forecast_for_short_series]) # type: ignore
|
|
753
|
-
return predictions.reindex(original_item_id_order, level=ITEMID)
|
|
749
|
+
return predictions.reindex(original_item_id_order, level=TimeSeriesDataFrame.ITEMID)
|
|
754
750
|
|
|
755
|
-
def _create_tabular_model(self, model_name: str, model_hyperparameters:
|
|
751
|
+
def _create_tabular_model(self, model_name: str, model_hyperparameters: dict[str, Any]) -> TabularModel:
|
|
756
752
|
model_class = ag_model_registry.key_to_cls(model_name)
|
|
757
753
|
return TabularModel(
|
|
758
754
|
model_class=model_class,
|