autogluon.timeseries 1.3.2b20250703__tar.gz → 1.3.2b20250705__tar.gz
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-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/PKG-INFO +1 -1
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/setup.py +3 -3
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/abstract/abstract_timeseries_model.py +13 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/autogluon_tabular/mlforecast.py +127 -101
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/chronos/model.py +22 -8
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/local/abstract_local_model.py +1 -12
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/regressor.py +3 -2
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/version.py +1 -1
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon.timeseries.egg-info/PKG-INFO +1 -1
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon.timeseries.egg-info/requires.txt +7 -7
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/setup.cfg +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/configs/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/configs/presets_configs.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/dataset/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/dataset/ts_dataframe.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/evaluator.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/learner.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/metrics/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/metrics/abstract.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/metrics/point.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/metrics/quantile.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/metrics/utils.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/abstract/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/abstract/model_trial.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/abstract/tunable.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/autogluon_tabular/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/autogluon_tabular/transforms.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/autogluon_tabular/utils.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/chronos/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/chronos/pipeline/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/chronos/pipeline/base.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/chronos/pipeline/chronos.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/chronos/pipeline/chronos_bolt.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/chronos/pipeline/utils.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/ensemble/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/ensemble/abstract.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/ensemble/basic.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/ensemble/greedy.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/gluonts/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/gluonts/abstract.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/gluonts/dataset.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/gluonts/models.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/local/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/local/naive.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/local/npts.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/local/statsforecast.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/multi_window/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/multi_window/multi_window_model.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/models/presets.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/predictor.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/splitter.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/trainer.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/transforms/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/transforms/covariate_scaler.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/transforms/target_scaler.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/utils/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/utils/datetime/__init__.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/utils/datetime/base.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/utils/datetime/lags.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/utils/datetime/seasonality.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/utils/datetime/time_features.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/utils/features.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/utils/forecast.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon/timeseries/utils/warning_filters.py +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon.timeseries.egg-info/SOURCES.txt +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon.timeseries.egg-info/dependency_links.txt +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon.timeseries.egg-info/namespace_packages.txt +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon.timeseries.egg-info/top_level.txt +0 -0
- {autogluon.timeseries-1.3.2b20250703 → autogluon.timeseries-1.3.2b20250705}/src/autogluon.timeseries.egg-info/zip-safe +0 -0
@@ -33,9 +33,9 @@ install_requires = [
|
|
33
33
|
"gluonts>=0.15.0,<0.17",
|
34
34
|
"networkx", # version range defined in `core/_setup_utils.py`
|
35
35
|
"statsforecast>=1.7.0,<2.0.2",
|
36
|
-
"mlforecast
|
37
|
-
"utilsforecast>=0.2.3,<0.2.
|
38
|
-
"coreforecast>=0.0.12,<0.0.
|
36
|
+
"mlforecast>=0.14.0,<0.15.0", # cannot upgrade since v0.15.0 introduced a breaking change to DirectTabular
|
37
|
+
"utilsforecast>=0.2.3,<0.2.12", # to prevent breaking changes that propagate through mlforecast's dependency
|
38
|
+
"coreforecast>=0.0.12,<0.0.17", # to prevent breaking changes that propagate through mlforecast's dependency
|
39
39
|
"fugue>=0.9.0", # prevent dependency clash with omegaconf
|
40
40
|
"tqdm", # version range defined in `core/_setup_utils.py`
|
41
41
|
"orjson~=3.9", # use faster JSON implementation in GluonTS
|
@@ -546,6 +546,19 @@ class AbstractTimeSeriesModel(TimeSeriesModelBase, TimeSeriesTunable, ABC):
|
|
546
546
|
"as hyperparameters when initializing or use `hyperparameter_tune` instead."
|
547
547
|
)
|
548
548
|
|
549
|
+
def _log_unused_hyperparameters(self, extra_allowed_hyperparameters: list[str] | None = None) -> None:
|
550
|
+
"""Log a warning if unused hyperparameters were provided to the model."""
|
551
|
+
allowed_hyperparameters = self.allowed_hyperparameters
|
552
|
+
if extra_allowed_hyperparameters is not None:
|
553
|
+
allowed_hyperparameters = allowed_hyperparameters + extra_allowed_hyperparameters
|
554
|
+
|
555
|
+
unused_hyperparameters = [key for key in self.get_hyperparameters() if key not in allowed_hyperparameters]
|
556
|
+
if len(unused_hyperparameters) > 0:
|
557
|
+
logger.warning(
|
558
|
+
f"{self.name} ignores following hyperparameters: {unused_hyperparameters}. "
|
559
|
+
f"See the documentation for {self.name} for the list of supported hyperparameters."
|
560
|
+
)
|
561
|
+
|
549
562
|
def predict(
|
550
563
|
self,
|
551
564
|
data: TimeSeriesDataFrame,
|
@@ -1,17 +1,17 @@
|
|
1
|
+
import copy
|
1
2
|
import logging
|
2
3
|
import math
|
3
|
-
import os
|
4
4
|
import time
|
5
5
|
import warnings
|
6
|
-
from typing import Any, Callable, Collection, Dict, List, Optional, Tuple, Union
|
6
|
+
from typing import Any, Callable, Collection, Dict, List, Optional, Tuple, Type, Union
|
7
7
|
|
8
8
|
import numpy as np
|
9
9
|
import pandas as pd
|
10
10
|
from sklearn.base import BaseEstimator
|
11
|
-
from typing_extensions import Self
|
12
11
|
|
13
12
|
import autogluon.core as ag
|
14
|
-
from autogluon.
|
13
|
+
from autogluon.core.models import AbstractModel as AbstractTabularModel
|
14
|
+
from autogluon.tabular.registry import ag_model_registry
|
15
15
|
from autogluon.timeseries.dataset.ts_dataframe import ITEMID, TIMESTAMP, TimeSeriesDataFrame
|
16
16
|
from autogluon.timeseries.metrics.abstract import TimeSeriesScorer
|
17
17
|
from autogluon.timeseries.metrics.utils import in_sample_squared_seasonal_error
|
@@ -29,34 +29,27 @@ from .utils import MLF_ITEMID, MLF_TARGET, MLF_TIMESTAMP
|
|
29
29
|
logger = logging.getLogger(__name__)
|
30
30
|
|
31
31
|
|
32
|
-
class
|
33
|
-
"""
|
32
|
+
class TabularModel(BaseEstimator):
|
33
|
+
"""A scikit-learn compatible wrapper for arbitrary autogluon.tabular models"""
|
34
34
|
|
35
|
-
def __init__(
|
36
|
-
self
|
37
|
-
|
38
|
-
predictor_fit_kwargs: Optional[Dict[str, Any]] = None,
|
39
|
-
):
|
40
|
-
self.predictor_init_kwargs = predictor_init_kwargs if predictor_init_kwargs is not None else {}
|
41
|
-
self.predictor_fit_kwargs = predictor_fit_kwargs if predictor_fit_kwargs is not None else {}
|
42
|
-
|
43
|
-
def get_params(self, deep: bool = True) -> Dict[str, Any]:
|
44
|
-
return {
|
45
|
-
"predictor_init_kwargs": self.predictor_init_kwargs,
|
46
|
-
"predictor_fit_kwargs": self.predictor_fit_kwargs,
|
47
|
-
}
|
35
|
+
def __init__(self, model_class: Type[AbstractTabularModel], model_kwargs: Optional[dict] = None):
|
36
|
+
self.model_class = model_class
|
37
|
+
self.model_kwargs = {} if model_kwargs is None else model_kwargs
|
48
38
|
|
49
|
-
def fit(self,
|
50
|
-
|
51
|
-
|
52
|
-
self.predictor = TabularPredictor(**self.predictor_init_kwargs)
|
53
|
-
with warning_filter():
|
54
|
-
self.predictor.fit(df, **self.predictor_fit_kwargs)
|
39
|
+
def fit(self, *args, **kwargs):
|
40
|
+
self.model = self.model_class(**self.model_kwargs)
|
41
|
+
self.model.fit(*args, **kwargs)
|
55
42
|
return self
|
56
43
|
|
57
|
-
def predict(self,
|
58
|
-
|
59
|
-
|
44
|
+
def predict(self, *args, **kwargs):
|
45
|
+
return self.model.predict(*args, **kwargs)
|
46
|
+
|
47
|
+
def get_params(self, deep=True):
|
48
|
+
params = {"model_class": self.model_class, "model_kwargs": self.model_kwargs}
|
49
|
+
if deep:
|
50
|
+
return copy.deepcopy(params)
|
51
|
+
else:
|
52
|
+
return params
|
60
53
|
|
61
54
|
|
62
55
|
class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
@@ -101,28 +94,17 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
101
94
|
self.target_scaler = None
|
102
95
|
|
103
96
|
@property
|
104
|
-
def
|
105
|
-
return
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
save_path = super().save(path=path, verbose=verbose)
|
116
|
-
mean_estimator.predictor = tabular_predictor
|
117
|
-
return save_path
|
118
|
-
|
119
|
-
@classmethod
|
120
|
-
def load(cls, path: str, reset_paths: bool = True, load_oof: bool = False, verbose: bool = True) -> Self:
|
121
|
-
model = super().load(path=path, reset_paths=reset_paths, load_oof=load_oof, verbose=verbose)
|
122
|
-
assert "mean" in model._mlf.models_, "Loaded model doesn't have a trained TabularPredictor"
|
123
|
-
assert isinstance(model._mlf.models_["mean"], TabularEstimator)
|
124
|
-
model._mlf.models_["mean"].predictor = TabularPredictor.load(model.tabular_predictor_path)
|
125
|
-
return model
|
97
|
+
def allowed_hyperparameters(self) -> List[str]:
|
98
|
+
return super().allowed_hyperparameters + [
|
99
|
+
"lags",
|
100
|
+
"date_features",
|
101
|
+
"differences",
|
102
|
+
"model_name",
|
103
|
+
"model_hyperparameters",
|
104
|
+
"max_num_items",
|
105
|
+
"max_num_samples",
|
106
|
+
"lag_transforms",
|
107
|
+
]
|
126
108
|
|
127
109
|
def preprocess(
|
128
110
|
self,
|
@@ -143,17 +125,42 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
143
125
|
data[self.target] = data[self.target].fillna(value=self._train_target_median)
|
144
126
|
return data, known_covariates
|
145
127
|
|
146
|
-
def
|
147
|
-
|
128
|
+
def _process_deprecated_hyperparameters(self, model_params: Dict[str, Any]) -> Dict[str, Any]:
|
129
|
+
if "tabular_hyperparameters" in model_params:
|
130
|
+
logger.warning(
|
131
|
+
f"Hyperparameter 'tabular_hyperparameters' for {self.name} is deprecated and will be removed in v1.5. "
|
132
|
+
"Please use 'model_name' to specify the tabular model alias and 'model_hyperparameters' "
|
133
|
+
"to provide the tabular model hyperparameters."
|
134
|
+
)
|
135
|
+
tabular_hyperparameters = model_params.pop("tabular_hyperparameters")
|
136
|
+
if len(tabular_hyperparameters) == 1:
|
137
|
+
# We can automatically convert the hyperparameters if only one model is used
|
138
|
+
model_params["model_name"] = list(tabular_hyperparameters.keys())[0]
|
139
|
+
model_params["model_hyperparameters"] = tabular_hyperparameters[model_params["model_name"]]
|
140
|
+
else:
|
141
|
+
raise ValueError(
|
142
|
+
f"Provided 'tabular_hyperparameters' {tabular_hyperparameters} cannot be automatically converted "
|
143
|
+
f"to the new 'model_name' and 'model_hyperparameters' API for {self.name}."
|
144
|
+
)
|
145
|
+
if "tabular_fit_kwargs" in model_params:
|
146
|
+
logger.warning(
|
147
|
+
f"Hyperparameters 'tabular_fit_kwargs' for {self.name} is deprecated and is ignored by the model. "
|
148
|
+
"Please use 'model_name' to specify the tabular model alias and 'model_hyperparameters' "
|
149
|
+
"to provide the tabular model hyperparameters."
|
150
|
+
)
|
151
|
+
return model_params
|
148
152
|
|
149
153
|
def _get_default_hyperparameters(self) -> Dict[str, Any]:
|
150
154
|
return {
|
151
155
|
"max_num_items": 20_000,
|
152
156
|
"max_num_samples": 1_000_000,
|
153
|
-
"
|
154
|
-
"
|
157
|
+
"model_name": "GBM",
|
158
|
+
"model_hyperparameters": {},
|
155
159
|
}
|
156
160
|
|
161
|
+
def _create_tabular_model(self, model_name: str, model_hyperparameters: Dict[str, Any]) -> TabularModel:
|
162
|
+
raise NotImplementedError
|
163
|
+
|
157
164
|
def _get_mlforecast_init_args(
|
158
165
|
self, train_data: TimeSeriesDataFrame, model_params: Dict[str, Any]
|
159
166
|
) -> Dict[str, Any]:
|
@@ -206,6 +213,7 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
206
213
|
"lags": self._target_lags.tolist(),
|
207
214
|
"date_features": self._date_features,
|
208
215
|
"target_transforms": target_transforms,
|
216
|
+
"lag_transforms": model_params.get("lag_transforms"),
|
209
217
|
}
|
210
218
|
|
211
219
|
def _mask_df(self, df: pd.DataFrame) -> pd.DataFrame:
|
@@ -318,13 +326,14 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
318
326
|
from mlforecast import MLForecast
|
319
327
|
|
320
328
|
self._check_fit_params()
|
329
|
+
self._log_unused_hyperparameters()
|
321
330
|
fit_start_time = time.time()
|
322
331
|
self._train_target_median = train_data[self.target].median()
|
323
332
|
for col in self.covariate_metadata.known_covariates_real:
|
324
333
|
if not set(train_data[col].unique()) == set([0, 1]):
|
325
334
|
self._non_boolean_real_covariates.append(col)
|
326
|
-
# TabularEstimator is passed to MLForecast later to include tuning_data
|
327
335
|
model_params = self.get_hyperparameters()
|
336
|
+
model_params = self._process_deprecated_hyperparameters(model_params)
|
328
337
|
|
329
338
|
mlforecast_init_args = self._get_mlforecast_init_args(train_data, model_params)
|
330
339
|
assert self.freq is not None
|
@@ -337,35 +346,36 @@ class AbstractMLForecastModel(AbstractTimeSeriesModel):
|
|
337
346
|
max_num_samples=model_params["max_num_samples"],
|
338
347
|
)
|
339
348
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
"time_limit": (None if time_limit is None else time_limit - (time.time() - fit_start_time)),
|
350
|
-
"hyperparameters": model_params["tabular_hyperparameters"],
|
351
|
-
**model_params["tabular_fit_kwargs"],
|
352
|
-
},
|
349
|
+
tabular_model = self._create_tabular_model(
|
350
|
+
model_name=model_params["model_name"], model_hyperparameters=model_params["model_hyperparameters"]
|
351
|
+
)
|
352
|
+
tabular_model.fit(
|
353
|
+
X=train_df.drop(columns=[MLF_TARGET, MLF_ITEMID]),
|
354
|
+
y=train_df[MLF_TARGET],
|
355
|
+
X_val=val_df.drop(columns=[MLF_TARGET, MLF_ITEMID]),
|
356
|
+
y_val=val_df[MLF_TARGET],
|
357
|
+
time_limit=(None if time_limit is None else time_limit - (time.time() - fit_start_time)),
|
353
358
|
)
|
354
|
-
self._mlf.models = {"mean": estimator} # type: ignore
|
355
359
|
|
356
|
-
|
357
|
-
|
360
|
+
# We directly insert the trained model into models_ since calling _mlf.fit_models does not support X_val, y_val
|
361
|
+
self._mlf.models_ = {"mean": tabular_model}
|
358
362
|
|
359
363
|
self._save_residuals_std(val_df)
|
360
364
|
|
365
|
+
def get_tabular_model(self) -> AbstractTabularModel:
|
366
|
+
"""Get the unerlyin tabular regression model."""
|
367
|
+
assert "mean" in self._mlf.models_, "Call `fit` before calling `get_tabular_model`"
|
368
|
+
mean_estimator = self._mlf.models_["mean"]
|
369
|
+
assert isinstance(mean_estimator, TabularModel)
|
370
|
+
return mean_estimator.model
|
371
|
+
|
361
372
|
def _save_residuals_std(self, val_df: pd.DataFrame) -> None:
|
362
373
|
"""Compute standard deviation of residuals for each item using the validation set.
|
363
374
|
|
364
375
|
Saves per-item residuals to `self.residuals_std_per_item`.
|
365
376
|
"""
|
366
377
|
residuals_df = val_df[[MLF_ITEMID, MLF_TARGET]]
|
367
|
-
mean_estimator = self.
|
368
|
-
assert isinstance(mean_estimator, TabularEstimator)
|
378
|
+
mean_estimator = self.get_tabular_model()
|
369
379
|
|
370
380
|
residuals_df = residuals_df.assign(y_pred=mean_estimator.predict(val_df))
|
371
381
|
if self._scaler is not None:
|
@@ -484,15 +494,15 @@ class DirectTabularModel(AbstractMLForecastModel):
|
|
484
494
|
If None, will be determined automatically based on the frequency of the data.
|
485
495
|
differences : List[int], default = []
|
486
496
|
Differences to take of the target before computing the features. These are restored at the forecasting step.
|
487
|
-
If None, will be set to ``[seasonal_period]``, where seasonal_period is determined based on the data frequency.
|
488
497
|
Defaults to no differencing.
|
489
498
|
target_scaler : {"standard", "mean_abs", "min_max", "robust", None}, default = "mean_abs"
|
490
499
|
Scaling applied to each time series. Scaling is applied after differencing.
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
500
|
+
model_name : str, default = "GBM"
|
501
|
+
Name of the tabular regression model. See `autogluon.tabular.registry.ag_model_registry` or
|
502
|
+
`the documentation <https://auto.gluon.ai/stable/api/autogluon.tabular.models.html>`_ for the list of available
|
503
|
+
tabular models.
|
504
|
+
model_hyperparameters : Dict[str, Any], optional
|
505
|
+
Hyperparameters passed to the tabular regression model.
|
496
506
|
max_num_items : int or None, default = 20_000
|
497
507
|
If not None, the model will randomly select this many time series for training and validation.
|
498
508
|
max_num_samples : int or None, default = 1_000_000
|
@@ -511,6 +521,9 @@ class DirectTabularModel(AbstractMLForecastModel):
|
|
511
521
|
model_params.setdefault("target_scaler", "mean_abs")
|
512
522
|
if "differences" not in model_params or model_params["differences"] is None:
|
513
523
|
model_params["differences"] = []
|
524
|
+
if "lag_transforms" in model_params:
|
525
|
+
model_params.pop("lag_transforms")
|
526
|
+
logger.warning(f"{self.name} does not support the 'lag_transforms' hyperparameter.")
|
514
527
|
return model_params
|
515
528
|
|
516
529
|
def _mask_df(self, df: pd.DataFrame) -> pd.DataFrame:
|
@@ -566,8 +579,7 @@ class DirectTabularModel(AbstractMLForecastModel):
|
|
566
579
|
df = df.groupby(MLF_ITEMID, sort=False).tail(self.prediction_length)
|
567
580
|
df = df.replace(float("inf"), float("nan"))
|
568
581
|
|
569
|
-
mean_estimator = self.
|
570
|
-
assert isinstance(mean_estimator, TabularEstimator)
|
582
|
+
mean_estimator = self.get_tabular_model()
|
571
583
|
raw_predictions = mean_estimator.predict(df)
|
572
584
|
predictions = self._postprocess_predictions(raw_predictions, repeated_item_ids=df[MLF_ITEMID])
|
573
585
|
# Paste columns one by one to preserve dtypes
|
@@ -611,18 +623,23 @@ class DirectTabularModel(AbstractMLForecastModel):
|
|
611
623
|
column_order = ["mean"] + [col for col in predictions_df.columns if col != "mean"]
|
612
624
|
return predictions_df[column_order]
|
613
625
|
|
614
|
-
def
|
626
|
+
def _create_tabular_model(self, model_name: str, model_hyperparameters: Dict[str, Any]) -> TabularModel:
|
627
|
+
model_class = ag_model_registry.key_to_cls(model_name)
|
615
628
|
if self.is_quantile_model:
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
"eval_metric": "pinball_loss",
|
620
|
-
}
|
629
|
+
problem_type = ag.constants.QUANTILE
|
630
|
+
eval_metric = "pinball_loss"
|
631
|
+
model_hyperparameters["ag.quantile_levels"] = self.quantile_levels
|
621
632
|
else:
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
633
|
+
problem_type = ag.constants.REGRESSION
|
634
|
+
eval_metric = self.eval_metric.equivalent_tabular_regression_metric or "mean_absolute_error"
|
635
|
+
return TabularModel(
|
636
|
+
model_class=model_class,
|
637
|
+
model_kwargs={
|
638
|
+
"hyperparameters": model_hyperparameters,
|
639
|
+
"problem_type": problem_type,
|
640
|
+
"eval_metric": eval_metric,
|
641
|
+
},
|
642
|
+
)
|
626
643
|
|
627
644
|
|
628
645
|
class RecursiveTabularModel(AbstractMLForecastModel):
|
@@ -654,11 +671,15 @@ class RecursiveTabularModel(AbstractMLForecastModel):
|
|
654
671
|
If None, will be set to ``[seasonal_period]``, where seasonal_period is determined based on the data frequency.
|
655
672
|
target_scaler : {"standard", "mean_abs", "min_max", "robust", None}, default = "standard"
|
656
673
|
Scaling applied to each time series. Scaling is applied after differencing.
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
674
|
+
lag_transforms : Dict[int, List[Callable]], default = None
|
675
|
+
Dictionary mapping lag periods to transformation functions applied to lagged target values (e.g., rolling mean).
|
676
|
+
See `MLForecast documentation <https://nixtlaverse.nixtla.io/mlforecast/lag_transforms.html>`_ for more details.
|
677
|
+
model_name : str, default = "GBM"
|
678
|
+
Name of the tabular regression model. See `autogluon.tabular.registry.ag_model_registry` or
|
679
|
+
`the documentation <https://auto.gluon.ai/stable/api/autogluon.tabular.models.html>`_ for the list of available
|
680
|
+
tabular models.
|
681
|
+
model_hyperparameters : Dict[str, Any], optional
|
682
|
+
Hyperparameters passed to the tabular regression model.
|
662
683
|
max_num_items : int or None, default = 20_000
|
663
684
|
If not None, the model will randomly select this many time series for training and validation.
|
664
685
|
max_num_samples : int or None, default = 1_000_000
|
@@ -720,8 +741,13 @@ class RecursiveTabularModel(AbstractMLForecastModel):
|
|
720
741
|
predictions = pd.concat([predictions, forecast_for_short_series]) # type: ignore
|
721
742
|
return predictions.reindex(original_item_id_order, level=ITEMID)
|
722
743
|
|
723
|
-
def
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
744
|
+
def _create_tabular_model(self, model_name: str, model_hyperparameters: Dict[str, Any]) -> TabularModel:
|
745
|
+
model_class = ag_model_registry.key_to_cls(model_name)
|
746
|
+
return TabularModel(
|
747
|
+
model_class=model_class,
|
748
|
+
model_kwargs={
|
749
|
+
"hyperparameters": model_hyperparameters,
|
750
|
+
"problem_type": ag.constants.REGRESSION,
|
751
|
+
"eval_metric": self.eval_metric.equivalent_tabular_regression_metric or "mean_absolute_error",
|
752
|
+
},
|
753
|
+
)
|
@@ -135,14 +135,6 @@ class ChronosModel(AbstractTimeSeriesModel):
|
|
135
135
|
the model. Individual model implementations may have different context lengths specified in their configuration,
|
136
136
|
and may truncate the context further. For example, original Chronos models have a context length of 512, but
|
137
137
|
Chronos-Bolt models handle contexts up to 2048.
|
138
|
-
optimization_strategy : {None, "onnx", "openvino"}, default = None
|
139
|
-
[deprecated] Optimization strategy to use for inference on CPUs. If None, the model will use the default implementation.
|
140
|
-
If `onnx`, the model will be converted to ONNX and the inference will be performed using ONNX. If ``openvino``,
|
141
|
-
inference will be performed with the model compiled to OpenVINO. These optimizations are only available for
|
142
|
-
the original set of Chronos models, and not in Chronos-Bolt where they are not needed. You will need to
|
143
|
-
install the appropriate dependencies `optimum[onnxruntime]` or `optimum[openvino,nncf] optimum-intel[openvino,nncf]`
|
144
|
-
for optimizations to work. Note that support for optimization strategies is deprecated, and will be removed
|
145
|
-
in a future release. We recommend using Chronos-Bolt models for fast inference on the CPU.
|
146
138
|
torch_dtype : torch.dtype or {"auto", "bfloat16", "float32", "float64"}, default = "auto"
|
147
139
|
Torch data type for model weights, provided to ``from_pretrained`` method of Hugging Face AutoModels. If
|
148
140
|
original Chronos models are specified and the model size is ``small``, ``base``, or ``large``, the
|
@@ -351,6 +343,27 @@ class ChronosModel(AbstractTimeSeriesModel):
|
|
351
343
|
"fine_tune_shuffle_buffer_size": 10_000,
|
352
344
|
}
|
353
345
|
|
346
|
+
@property
|
347
|
+
def allowed_hyperparameters(self) -> list[str]:
|
348
|
+
return super().allowed_hyperparameters + [
|
349
|
+
"model_path",
|
350
|
+
"batch_size",
|
351
|
+
"num_samples",
|
352
|
+
"device",
|
353
|
+
"context_length",
|
354
|
+
"torch_dtype",
|
355
|
+
"data_loader_num_workers",
|
356
|
+
"fine_tune",
|
357
|
+
"fine_tune_lr",
|
358
|
+
"fine_tune_steps",
|
359
|
+
"fine_tune_batch_size",
|
360
|
+
"fine_tune_shuffle_buffer_size",
|
361
|
+
"eval_during_fine_tune",
|
362
|
+
"fine_tune_eval_max_items",
|
363
|
+
"fine_tune_trainer_kwargs",
|
364
|
+
"keep_transformers_logs",
|
365
|
+
]
|
366
|
+
|
354
367
|
def _get_fine_tune_trainer_kwargs(self, init_args, eval_during_fine_tune: bool):
|
355
368
|
output_dir = Path(self.path) / "transformers_logs"
|
356
369
|
fine_tune_trainer_kwargs = dict(
|
@@ -444,6 +457,7 @@ class ChronosModel(AbstractTimeSeriesModel):
|
|
444
457
|
transformers_logger.setLevel(logging.ERROR if verbosity <= 3 else logging.INFO)
|
445
458
|
|
446
459
|
self._check_fit_params()
|
460
|
+
self._log_unused_hyperparameters()
|
447
461
|
model_params = self.get_hyperparameters()
|
448
462
|
self._validate_and_assign_attributes(model_params)
|
449
463
|
do_fine_tune = model_params["fine_tune"]
|
@@ -109,23 +109,12 @@ class AbstractLocalModel(AbstractTimeSeriesModel):
|
|
109
109
|
if time_limit is not None and time_limit < self.init_time_in_seconds:
|
110
110
|
raise TimeLimitExceeded
|
111
111
|
|
112
|
-
unused_local_model_args = []
|
113
112
|
local_model_args = {}
|
114
|
-
# TODO: Move filtering logic to AbstractTimeSeriesModel
|
115
113
|
for key, value in self.get_hyperparameters().items():
|
116
114
|
if key in self.allowed_local_model_args:
|
117
115
|
local_model_args[key] = value
|
118
|
-
elif key in self.allowed_hyperparameters:
|
119
|
-
# Quietly ignore params in self.allowed_hyperparameters - they are used by AbstractTimeSeriesModel
|
120
|
-
pass
|
121
|
-
else:
|
122
|
-
unused_local_model_args.append(key)
|
123
116
|
|
124
|
-
|
125
|
-
logger.warning(
|
126
|
-
f"{self.name} ignores following hyperparameters: {unused_local_model_args}. "
|
127
|
-
f"See the docstring of {self.name} for the list of supported hyperparameters."
|
128
|
-
)
|
117
|
+
self._log_unused_hyperparameters(extra_allowed_hyperparameters=self.allowed_local_model_args)
|
129
118
|
|
130
119
|
if "seasonal_period" not in local_model_args or local_model_args["seasonal_period"] is None:
|
131
120
|
local_model_args["seasonal_period"] = get_seasonality(self.freq)
|
@@ -41,8 +41,9 @@ class GlobalCovariateRegressor(CovariateRegressor):
|
|
41
41
|
Parameters
|
42
42
|
----------
|
43
43
|
model_name : str
|
44
|
-
Name of the tabular regression model. See `autogluon.tabular.
|
45
|
-
list of available
|
44
|
+
Name of the tabular regression model. See `autogluon.tabular.registry.ag_model_registry` or
|
45
|
+
`the documentation <https://auto.gluon.ai/stable/api/autogluon.tabular.models.html>`_ for the list of available
|
46
|
+
tabular models.
|
46
47
|
model_hyperparameters : dict or None
|
47
48
|
Hyperparameters passed to the tabular regression model.
|
48
49
|
eval_metric : str
|
@@ -10,17 +10,17 @@ accelerate<2.0,>=0.34.0
|
|
10
10
|
gluonts<0.17,>=0.15.0
|
11
11
|
networkx<4,>=3.0
|
12
12
|
statsforecast<2.0.2,>=1.7.0
|
13
|
-
mlforecast<0.14
|
14
|
-
utilsforecast<0.2.
|
15
|
-
coreforecast<0.0.
|
13
|
+
mlforecast<0.15.0,>=0.14.0
|
14
|
+
utilsforecast<0.2.12,>=0.2.3
|
15
|
+
coreforecast<0.0.17,>=0.0.12
|
16
16
|
fugue>=0.9.0
|
17
17
|
tqdm<5,>=4.38
|
18
18
|
orjson~=3.9
|
19
19
|
tensorboard<3,>=2.9
|
20
|
-
autogluon.core[raytune]==1.3.
|
21
|
-
autogluon.common==1.3.
|
22
|
-
autogluon.features==1.3.
|
23
|
-
autogluon.tabular[catboost,lightgbm,xgboost]==1.3.
|
20
|
+
autogluon.core[raytune]==1.3.2b20250705
|
21
|
+
autogluon.common==1.3.2b20250705
|
22
|
+
autogluon.features==1.3.2b20250705
|
23
|
+
autogluon.tabular[catboost,lightgbm,xgboost]==1.3.2b20250705
|
24
24
|
|
25
25
|
[all]
|
26
26
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|