autogluon.timeseries 1.2.1b20250422__py3-none-any.whl → 1.2.1b20250423__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/dataset/ts_dataframe.py +1 -1
- autogluon/timeseries/learner.py +0 -4
- autogluon/timeseries/metrics/__init__.py +1 -30
- autogluon/timeseries/metrics/abstract.py +0 -10
- autogluon/timeseries/metrics/point.py +41 -131
- autogluon/timeseries/metrics/quantile.py +15 -36
- autogluon/timeseries/models/abstract/__init__.py +2 -2
- autogluon/timeseries/models/abstract/abstract_timeseries_model.py +178 -129
- autogluon/timeseries/models/chronos/model.py +3 -2
- autogluon/timeseries/models/ensemble/__init__.py +3 -2
- autogluon/timeseries/models/ensemble/abstract.py +139 -0
- autogluon/timeseries/models/ensemble/basic.py +88 -0
- autogluon/timeseries/models/ensemble/{greedy_ensemble.py → greedy.py} +67 -61
- autogluon/timeseries/models/presets.py +0 -4
- autogluon/timeseries/predictor.py +1 -12
- autogluon/timeseries/trainer.py +35 -27
- autogluon/timeseries/version.py +1 -1
- {autogluon.timeseries-1.2.1b20250422.dist-info → autogluon.timeseries-1.2.1b20250423.dist-info}/METADATA +4 -4
- {autogluon.timeseries-1.2.1b20250422.dist-info → autogluon.timeseries-1.2.1b20250423.dist-info}/RECORD +26 -25
- autogluon/timeseries/models/ensemble/abstract_timeseries_ensemble.py +0 -86
- /autogluon.timeseries-1.2.1b20250422-py3.9-nspkg.pth → /autogluon.timeseries-1.2.1b20250423-py3.9-nspkg.pth +0 -0
- {autogluon.timeseries-1.2.1b20250422.dist-info → autogluon.timeseries-1.2.1b20250423.dist-info}/LICENSE +0 -0
- {autogluon.timeseries-1.2.1b20250422.dist-info → autogluon.timeseries-1.2.1b20250423.dist-info}/NOTICE +0 -0
- {autogluon.timeseries-1.2.1b20250422.dist-info → autogluon.timeseries-1.2.1b20250423.dist-info}/WHEEL +0 -0
- {autogluon.timeseries-1.2.1b20250422.dist-info → autogluon.timeseries-1.2.1b20250423.dist-info}/namespace_packages.txt +0 -0
- {autogluon.timeseries-1.2.1b20250422.dist-info → autogluon.timeseries-1.2.1b20250423.dist-info}/top_level.txt +0 -0
- {autogluon.timeseries-1.2.1b20250422.dist-info → autogluon.timeseries-1.2.1b20250423.dist-info}/zip-safe +0 -0
@@ -9,9 +9,10 @@ import autogluon.core as ag
|
|
9
9
|
from autogluon.core.models.greedy_ensemble.ensemble_selection import EnsembleSelection
|
10
10
|
from autogluon.timeseries import TimeSeriesDataFrame
|
11
11
|
from autogluon.timeseries.metrics import TimeSeriesScorer
|
12
|
-
from autogluon.timeseries.models.ensemble import AbstractTimeSeriesEnsembleModel
|
13
12
|
from autogluon.timeseries.utils.datetime import get_seasonality
|
14
13
|
|
14
|
+
from .abstract import AbstractWeightedTimeSeriesEnsembleModel
|
15
|
+
|
15
16
|
logger = logging.getLogger(__name__)
|
16
17
|
|
17
18
|
|
@@ -24,16 +25,15 @@ class TimeSeriesEnsembleSelection(EnsembleSelection):
|
|
24
25
|
sorted_initialization: bool = False,
|
25
26
|
bagging: bool = False,
|
26
27
|
tie_breaker: str = "random",
|
27
|
-
random_state: np.random.RandomState = None,
|
28
|
+
random_state: Optional[np.random.RandomState] = None,
|
28
29
|
prediction_length: int = 1,
|
29
30
|
target: str = "target",
|
30
|
-
eval_metric_seasonal_period:
|
31
|
-
horizon_weight: Optional[np.ndarray] = None,
|
31
|
+
eval_metric_seasonal_period: int = 1,
|
32
32
|
**kwargs,
|
33
33
|
):
|
34
34
|
super().__init__(
|
35
35
|
ensemble_size=ensemble_size,
|
36
|
-
metric=metric,
|
36
|
+
metric=metric, # type: ignore
|
37
37
|
problem_type=problem_type,
|
38
38
|
sorted_initialization=sorted_initialization,
|
39
39
|
bagging=bagging,
|
@@ -44,14 +44,33 @@ class TimeSeriesEnsembleSelection(EnsembleSelection):
|
|
44
44
|
self.prediction_length = prediction_length
|
45
45
|
self.target = target
|
46
46
|
self.eval_metric_seasonal_period = eval_metric_seasonal_period
|
47
|
-
self.
|
47
|
+
self.metric: TimeSeriesScorer
|
48
48
|
|
49
|
-
|
49
|
+
self.dummy_pred_per_window = []
|
50
|
+
self.scorer_per_window = []
|
51
|
+
|
52
|
+
self.dummy_pred_per_window: Optional[List[TimeSeriesDataFrame]]
|
53
|
+
self.scorer_per_window: Optional[List[TimeSeriesScorer]]
|
54
|
+
self.data_future_per_window: Optional[List[TimeSeriesDataFrame]]
|
55
|
+
|
56
|
+
def fit( # type: ignore
|
50
57
|
self,
|
51
|
-
predictions: List[List[TimeSeriesDataFrame]],
|
58
|
+
predictions: List[List[TimeSeriesDataFrame]],
|
52
59
|
labels: List[TimeSeriesDataFrame],
|
53
|
-
time_limit: Optional[
|
54
|
-
|
60
|
+
time_limit: Optional[float] = None,
|
61
|
+
):
|
62
|
+
return super().fit(
|
63
|
+
predictions=predictions, # type: ignore
|
64
|
+
labels=labels, # type: ignore
|
65
|
+
time_limit=time_limit,
|
66
|
+
)
|
67
|
+
|
68
|
+
def _fit( # type: ignore
|
69
|
+
self,
|
70
|
+
predictions: List[List[TimeSeriesDataFrame]],
|
71
|
+
labels: List[TimeSeriesDataFrame],
|
72
|
+
time_limit: Optional[float] = None,
|
73
|
+
sample_weight: Optional[List[float]] = None,
|
55
74
|
):
|
56
75
|
# Stack predictions for each model into a 3d tensor of shape [num_val_windows, num_rows, num_cols]
|
57
76
|
stacked_predictions = [np.stack(preds) for preds in predictions]
|
@@ -77,26 +96,33 @@ class TimeSeriesEnsembleSelection(EnsembleSelection):
|
|
77
96
|
|
78
97
|
super()._fit(
|
79
98
|
predictions=stacked_predictions,
|
80
|
-
labels=data_future,
|
99
|
+
labels=data_future, # type: ignore
|
81
100
|
time_limit=time_limit,
|
82
101
|
)
|
83
102
|
self.dummy_pred_per_window = None
|
84
103
|
self.evaluator_per_window = None
|
85
104
|
self.data_future_per_window = None
|
86
105
|
|
87
|
-
def _calculate_regret(
|
106
|
+
def _calculate_regret( # type: ignore
|
107
|
+
self,
|
108
|
+
y_true,
|
109
|
+
y_pred_proba,
|
110
|
+
metric: TimeSeriesScorer,
|
111
|
+
sample_weight=None,
|
112
|
+
):
|
88
113
|
# Compute average score across all validation windows
|
89
114
|
total_score = 0.0
|
115
|
+
|
116
|
+
assert self.data_future_per_window is not None
|
117
|
+
assert self.dummy_pred_per_window is not None
|
118
|
+
assert self.scorer_per_window is not None
|
119
|
+
|
90
120
|
for window_idx, data_future in enumerate(self.data_future_per_window):
|
91
121
|
dummy_pred = self.dummy_pred_per_window[window_idx]
|
92
122
|
dummy_pred[list(dummy_pred.columns)] = y_pred_proba[window_idx]
|
93
123
|
# We use scorer.compute_metric instead of scorer.score to avoid repeated calls to scorer.save_past_metrics
|
94
124
|
metric_value = self.scorer_per_window[window_idx].compute_metric(
|
95
|
-
data_future,
|
96
|
-
dummy_pred,
|
97
|
-
target=self.target,
|
98
|
-
prediction_length=self.prediction_length,
|
99
|
-
horizon_weight=self.horizon_weight,
|
125
|
+
data_future, dummy_pred, target=self.target
|
100
126
|
)
|
101
127
|
total_score += metric.sign * metric_value
|
102
128
|
avg_score = total_score / len(self.data_future_per_window)
|
@@ -104,32 +130,46 @@ class TimeSeriesEnsembleSelection(EnsembleSelection):
|
|
104
130
|
return -avg_score
|
105
131
|
|
106
132
|
|
107
|
-
class
|
108
|
-
"""Constructs a weighted ensemble using the greedy Ensemble Selection algorithm
|
133
|
+
class GreedyEnsemble(AbstractWeightedTimeSeriesEnsembleModel):
|
134
|
+
"""Constructs a weighted ensemble using the greedy Ensemble Selection algorithm by
|
135
|
+
Caruana et al. [Car2004]
|
136
|
+
|
137
|
+
Other Parameters
|
138
|
+
----------------
|
139
|
+
ensemble_size: int, default = 100
|
140
|
+
Number of models (with replacement) to include in the ensemble.
|
141
|
+
|
142
|
+
References
|
143
|
+
----------
|
144
|
+
.. [Car2024] Caruana, Rich, et al. "Ensemble selection from libraries of models."
|
145
|
+
Proceedings of the twenty-first international conference on Machine learning. 2004.
|
146
|
+
"""
|
109
147
|
|
110
|
-
def __init__(self, name: Optional[str] = None,
|
148
|
+
def __init__(self, name: Optional[str] = None, **kwargs):
|
111
149
|
if name is None:
|
150
|
+
# FIXME: the name here is kept for backward compatibility. it will be called
|
151
|
+
# GreedyEnsemble in v1.4 once ensemble choices are exposed
|
112
152
|
name = "WeightedEnsemble"
|
113
153
|
super().__init__(name=name, **kwargs)
|
114
|
-
self.ensemble_size = ensemble_size
|
115
|
-
self.model_to_weight: Dict[str, float] = {}
|
116
154
|
|
117
|
-
def
|
155
|
+
def _get_default_hyperparameters(self) -> Dict:
|
156
|
+
return {"ensemble_size": 100}
|
157
|
+
|
158
|
+
def _fit(
|
118
159
|
self,
|
119
160
|
predictions_per_window: Dict[str, List[TimeSeriesDataFrame]],
|
120
161
|
data_per_window: List[TimeSeriesDataFrame],
|
121
|
-
|
122
|
-
|
162
|
+
model_scores: Optional[Dict[str, float]] = None,
|
163
|
+
time_limit: Optional[float] = None,
|
123
164
|
):
|
124
165
|
if self.eval_metric_seasonal_period is None:
|
125
166
|
self.eval_metric_seasonal_period = get_seasonality(self.freq)
|
126
167
|
ensemble_selection = TimeSeriesEnsembleSelection(
|
127
|
-
ensemble_size=self.ensemble_size,
|
168
|
+
ensemble_size=self.get_hyperparameters()["ensemble_size"],
|
128
169
|
metric=self.eval_metric,
|
129
170
|
prediction_length=self.prediction_length,
|
130
171
|
target=self.target,
|
131
172
|
eval_metric_seasonal_period=self.eval_metric_seasonal_period,
|
132
|
-
horizon_weight=self.horizon_weight,
|
133
173
|
)
|
134
174
|
ensemble_selection.fit(
|
135
175
|
predictions=list(predictions_per_window.values()),
|
@@ -143,37 +183,3 @@ class TimeSeriesGreedyEnsemble(AbstractTimeSeriesEnsembleModel):
|
|
143
183
|
|
144
184
|
weights_for_printing = {model: round(weight, 2) for model, weight in self.model_to_weight.items()}
|
145
185
|
logger.info(f"\tEnsemble weights: {pprint.pformat(weights_for_printing, width=200)}")
|
146
|
-
|
147
|
-
@property
|
148
|
-
def model_names(self) -> List[str]:
|
149
|
-
return list(self.model_to_weight.keys())
|
150
|
-
|
151
|
-
@property
|
152
|
-
def model_weights(self) -> np.ndarray:
|
153
|
-
return np.array(list(self.model_to_weight.values()), dtype=np.float64)
|
154
|
-
|
155
|
-
def predict(self, data: Dict[str, Optional[TimeSeriesDataFrame]], **kwargs) -> TimeSeriesDataFrame:
|
156
|
-
if not set(self.model_names).issubset(set(data.keys())):
|
157
|
-
raise ValueError(
|
158
|
-
f"Set of models given for prediction in {self.name} differ from those provided during initialization."
|
159
|
-
)
|
160
|
-
for model_name, model_pred in data.items():
|
161
|
-
if model_pred is None:
|
162
|
-
raise RuntimeError(f"{self.name} cannot predict because base model {model_name} failed.")
|
163
|
-
|
164
|
-
# Make sure that all predictions have same shape
|
165
|
-
assert len(set(pred.shape for pred in data.values())) == 1
|
166
|
-
|
167
|
-
return sum(data[model_name] * weight for model_name, weight in self.model_to_weight.items())
|
168
|
-
|
169
|
-
def get_info(self) -> dict:
|
170
|
-
info = super().get_info()
|
171
|
-
info["model_weights"] = self.model_to_weight
|
172
|
-
return info
|
173
|
-
|
174
|
-
def remap_base_models(self, model_refit_map: Dict[str, str]) -> None:
|
175
|
-
updated_weights = {}
|
176
|
-
for model, weight in self.model_to_weight.items():
|
177
|
-
model_full_name = model_refit_map.get(model, model)
|
178
|
-
updated_weights[model_full_name] = weight
|
179
|
-
self.model_to_weight = updated_weights
|
@@ -4,8 +4,6 @@ import re
|
|
4
4
|
from collections import defaultdict
|
5
5
|
from typing import Any, Dict, List, Optional, Type, Union
|
6
6
|
|
7
|
-
import numpy as np
|
8
|
-
|
9
7
|
from autogluon.common import space
|
10
8
|
from autogluon.core import constants
|
11
9
|
from autogluon.timeseries.metrics import TimeSeriesScorer
|
@@ -186,7 +184,6 @@ def get_preset_models(
|
|
186
184
|
path: str,
|
187
185
|
eval_metric: Union[str, TimeSeriesScorer],
|
188
186
|
eval_metric_seasonal_period: Optional[int],
|
189
|
-
horizon_weight: Optional[np.ndarray],
|
190
187
|
hyperparameters: Union[str, Dict, None],
|
191
188
|
hyperparameter_tune: bool,
|
192
189
|
covariate_metadata: CovariateMetadata,
|
@@ -265,7 +262,6 @@ def get_preset_models(
|
|
265
262
|
eval_metric=eval_metric,
|
266
263
|
eval_metric_seasonal_period=eval_metric_seasonal_period,
|
267
264
|
covariate_metadata=covariate_metadata,
|
268
|
-
horizon_weight=horizon_weight,
|
269
265
|
hyperparameters=model_hps,
|
270
266
|
**kwargs,
|
271
267
|
)
|
@@ -24,7 +24,7 @@ from autogluon.timeseries import __version__ as current_ag_version
|
|
24
24
|
from autogluon.timeseries.configs import TIMESERIES_PRESETS_CONFIGS
|
25
25
|
from autogluon.timeseries.dataset.ts_dataframe import ITEMID, TimeSeriesDataFrame
|
26
26
|
from autogluon.timeseries.learner import TimeSeriesLearner
|
27
|
-
from autogluon.timeseries.metrics import TimeSeriesScorer, check_get_evaluation_metric
|
27
|
+
from autogluon.timeseries.metrics import TimeSeriesScorer, check_get_evaluation_metric
|
28
28
|
from autogluon.timeseries.splitter import ExpandingWindowSplitter
|
29
29
|
from autogluon.timeseries.trainer import TimeSeriesTrainer
|
30
30
|
from autogluon.timeseries.utils.forecast import make_future_data_frame
|
@@ -93,14 +93,6 @@ class TimeSeriesPredictor:
|
|
93
93
|
eval_metric_seasonal_period : int, optional
|
94
94
|
Seasonal period used to compute some evaluation metrics such as mean absolute scaled error (MASE). Defaults to
|
95
95
|
``None``, in which case the seasonal period is computed based on the data frequency.
|
96
|
-
horizon_weight : List[float], optional
|
97
|
-
Weight assigned to each time step in the forecast horizon when computing the `eval_metric`. If provided, this
|
98
|
-
must be a list with `prediction_length` non-negative values, where at least some values are greater than zero.
|
99
|
-
AutoGluon will automatically normalize the weights so that they sum up to `prediction_length`. By default, all
|
100
|
-
time steps in the forecast horizon have the same weight, which is equivalent to setting `horizon_weight = [1] * prediction_length`.
|
101
|
-
|
102
|
-
This parameter only affects model selection and ensemble construction; it has no effect on the loss function of
|
103
|
-
the individual forecasting models.
|
104
96
|
known_covariates_names: List[str], optional
|
105
97
|
Names of the covariates that are known in advance for all time steps in the forecast horizon. These are also
|
106
98
|
known as dynamic features, exogenous variables, additional regressors or related time series. Examples of such
|
@@ -152,7 +144,6 @@ class TimeSeriesPredictor:
|
|
152
144
|
freq: Optional[str] = None,
|
153
145
|
eval_metric: Union[str, TimeSeriesScorer, None] = None,
|
154
146
|
eval_metric_seasonal_period: Optional[int] = None,
|
155
|
-
horizon_weight: list[float] | None = None,
|
156
147
|
path: Optional[Union[str, Path]] = None,
|
157
148
|
verbosity: int = 2,
|
158
149
|
log_to_file: bool = True,
|
@@ -198,7 +189,6 @@ class TimeSeriesPredictor:
|
|
198
189
|
self.freq = std_freq
|
199
190
|
self.eval_metric = check_get_evaluation_metric(eval_metric)
|
200
191
|
self.eval_metric_seasonal_period = eval_metric_seasonal_period
|
201
|
-
self.horizon_weight = check_get_horizon_weight(horizon_weight, prediction_length=self.prediction_length)
|
202
192
|
if quantile_levels is None:
|
203
193
|
quantile_levels = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
|
204
194
|
self.quantile_levels = sorted(quantile_levels)
|
@@ -206,7 +196,6 @@ class TimeSeriesPredictor:
|
|
206
196
|
path_context=self.path,
|
207
197
|
eval_metric=eval_metric,
|
208
198
|
eval_metric_seasonal_period=eval_metric_seasonal_period,
|
209
|
-
horizon_weight=self.horizon_weight,
|
210
199
|
target=self.target,
|
211
200
|
known_covariates_names=self.known_covariates_names,
|
212
201
|
prediction_length=self.prediction_length,
|
autogluon/timeseries/trainer.py
CHANGED
@@ -19,8 +19,8 @@ from autogluon.core.utils.loaders import load_pkl
|
|
19
19
|
from autogluon.core.utils.savers import save_pkl
|
20
20
|
from autogluon.timeseries import TimeSeriesDataFrame
|
21
21
|
from autogluon.timeseries.metrics import TimeSeriesScorer, check_get_evaluation_metric
|
22
|
-
from autogluon.timeseries.models.abstract import AbstractTimeSeriesModel
|
23
|
-
from autogluon.timeseries.models.ensemble import AbstractTimeSeriesEnsembleModel,
|
22
|
+
from autogluon.timeseries.models.abstract import AbstractTimeSeriesModel, TimeSeriesModelBase
|
23
|
+
from autogluon.timeseries.models.ensemble import AbstractTimeSeriesEnsembleModel, GreedyEnsemble
|
24
24
|
from autogluon.timeseries.models.multi_window import MultiWindowBacktestingModel
|
25
25
|
from autogluon.timeseries.models.presets import contains_searchspace, get_preset_models
|
26
26
|
from autogluon.timeseries.splitter import AbstractWindowSplitter, ExpandingWindowSplitter
|
@@ -34,7 +34,7 @@ from autogluon.timeseries.utils.warning_filters import disable_tqdm, warning_fil
|
|
34
34
|
logger = logging.getLogger("autogluon.timeseries.trainer")
|
35
35
|
|
36
36
|
|
37
|
-
class TimeSeriesTrainer(AbstractTrainer[
|
37
|
+
class TimeSeriesTrainer(AbstractTrainer[TimeSeriesModelBase]):
|
38
38
|
_cached_predictions_filename = "cached_predictions.pkl"
|
39
39
|
|
40
40
|
max_rel_importance_score: float = 1e5
|
@@ -47,7 +47,6 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
47
47
|
prediction_length: int = 1,
|
48
48
|
eval_metric: Union[str, TimeSeriesScorer, None] = None,
|
49
49
|
eval_metric_seasonal_period: Optional[int] = None,
|
50
|
-
horizon_weight: Optional[np.ndarray] = None,
|
51
50
|
save_data: bool = True,
|
52
51
|
skip_model_selection: bool = False,
|
53
52
|
enable_ensemble: bool = True,
|
@@ -74,12 +73,12 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
74
73
|
# Ensemble cannot be fit if val_scores are not computed
|
75
74
|
self.enable_ensemble = enable_ensemble and not skip_model_selection
|
76
75
|
if ensemble_model_type is None:
|
77
|
-
ensemble_model_type =
|
76
|
+
ensemble_model_type = GreedyEnsemble
|
78
77
|
else:
|
79
78
|
logger.warning(
|
80
79
|
"Using a custom `ensemble_model_type` is experimental functionality that may break in future versions."
|
81
80
|
)
|
82
|
-
self.ensemble_model_type = ensemble_model_type
|
81
|
+
self.ensemble_model_type: Type[AbstractTimeSeriesEnsembleModel] = ensemble_model_type
|
83
82
|
|
84
83
|
self.verbosity = verbosity
|
85
84
|
|
@@ -89,7 +88,6 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
89
88
|
|
90
89
|
self.eval_metric: TimeSeriesScorer = check_get_evaluation_metric(eval_metric)
|
91
90
|
self.eval_metric_seasonal_period = eval_metric_seasonal_period
|
92
|
-
self.horizon_weight = horizon_weight
|
93
91
|
if val_splitter is None:
|
94
92
|
val_splitter = ExpandingWindowSplitter(prediction_length=self.prediction_length)
|
95
93
|
assert isinstance(val_splitter, AbstractWindowSplitter), "val_splitter must be of type AbstractWindowSplitter"
|
@@ -147,7 +145,7 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
147
145
|
|
148
146
|
def _add_model(
|
149
147
|
self,
|
150
|
-
model:
|
148
|
+
model: TimeSeriesModelBase,
|
151
149
|
base_models: Optional[List[str]] = None,
|
152
150
|
):
|
153
151
|
"""Add a model to the model graph of the trainer. If the model is an ensemble, also add
|
@@ -155,7 +153,7 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
155
153
|
|
156
154
|
Parameters
|
157
155
|
----------
|
158
|
-
model :
|
156
|
+
model : TimeSeriesModelBase
|
159
157
|
The model to be added to the model graph.
|
160
158
|
base_models : List[str], optional, default None
|
161
159
|
If the model is an ensemble, the list of base model names that are included in the ensemble.
|
@@ -444,6 +442,8 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
444
442
|
num_base_models = len(models)
|
445
443
|
model_names_trained = []
|
446
444
|
for i, model in enumerate(models):
|
445
|
+
assert isinstance(model, AbstractTimeSeriesModel)
|
446
|
+
|
447
447
|
if time_limit is None:
|
448
448
|
time_left = None
|
449
449
|
time_left_for_model = None
|
@@ -560,20 +560,24 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
560
560
|
return ensemble_name
|
561
561
|
|
562
562
|
def fit_ensemble(
|
563
|
-
self,
|
563
|
+
self,
|
564
|
+
data_per_window: List[TimeSeriesDataFrame],
|
565
|
+
model_names: List[str],
|
566
|
+
time_limit: Optional[float] = None,
|
564
567
|
) -> str:
|
565
568
|
logger.info("Fitting simple weighted ensemble.")
|
566
569
|
|
567
|
-
|
570
|
+
predictions_per_window: Dict[str, List[TimeSeriesDataFrame]] = {}
|
571
|
+
base_model_scores = self.get_models_attribute_dict(attribute="val_score", models=self.get_model_names(0))
|
572
|
+
|
568
573
|
for model_name in model_names:
|
569
|
-
|
574
|
+
predictions_per_window[model_name] = self._get_model_oof_predictions(model_name=model_name)
|
570
575
|
|
571
576
|
time_start = time.time()
|
572
577
|
ensemble = self.ensemble_model_type(
|
573
578
|
name=self._get_ensemble_model_name(),
|
574
579
|
eval_metric=self.eval_metric,
|
575
580
|
eval_metric_seasonal_period=self.eval_metric_seasonal_period,
|
576
|
-
horizon_weight=self.horizon_weight,
|
577
581
|
target=self.target,
|
578
582
|
prediction_length=self.prediction_length,
|
579
583
|
path=self.path,
|
@@ -582,7 +586,12 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
582
586
|
covariate_metadata=self.covariate_metadata,
|
583
587
|
)
|
584
588
|
with warning_filter():
|
585
|
-
ensemble.
|
589
|
+
ensemble.fit(
|
590
|
+
predictions_per_window=predictions_per_window,
|
591
|
+
data_per_window=data_per_window,
|
592
|
+
model_scores=base_model_scores,
|
593
|
+
time_limit=time_limit,
|
594
|
+
)
|
586
595
|
ensemble.fit_time = time.time() - time_start
|
587
596
|
|
588
597
|
predict_time = 0
|
@@ -592,7 +601,7 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
592
601
|
|
593
602
|
score_per_fold = []
|
594
603
|
for window_idx, data in enumerate(data_per_window):
|
595
|
-
predictions = ensemble.predict({n:
|
604
|
+
predictions = ensemble.predict({n: predictions_per_window[n][window_idx] for n in ensemble.model_names})
|
596
605
|
score_per_fold.append(self._score_with_predictions(data, predictions))
|
597
606
|
ensemble.val_score = float(np.mean(score_per_fold, dtype=np.float64))
|
598
607
|
|
@@ -737,7 +746,7 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
737
746
|
return unpersisted_models
|
738
747
|
|
739
748
|
def _get_model_for_prediction(
|
740
|
-
self, model: Optional[Union[str,
|
749
|
+
self, model: Optional[Union[str, TimeSeriesModelBase]] = None, verbose: bool = True
|
741
750
|
) -> str:
|
742
751
|
"""Given an optional identifier or model object, return the name of the model with which to predict.
|
743
752
|
|
@@ -754,7 +763,7 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
754
763
|
)
|
755
764
|
return self.model_best
|
756
765
|
else:
|
757
|
-
if isinstance(model,
|
766
|
+
if isinstance(model, TimeSeriesModelBase):
|
758
767
|
return model.name
|
759
768
|
else:
|
760
769
|
if model not in self.get_model_names():
|
@@ -765,7 +774,7 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
765
774
|
self,
|
766
775
|
data: TimeSeriesDataFrame,
|
767
776
|
known_covariates: Optional[TimeSeriesDataFrame] = None,
|
768
|
-
model: Optional[Union[str,
|
777
|
+
model: Optional[Union[str, TimeSeriesModelBase]] = None,
|
769
778
|
use_cache: bool = True,
|
770
779
|
random_seed: Optional[int] = None,
|
771
780
|
) -> TimeSeriesDataFrame:
|
@@ -796,13 +805,12 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
796
805
|
prediction_length=self.prediction_length,
|
797
806
|
target=self.target,
|
798
807
|
seasonal_period=self.eval_metric_seasonal_period,
|
799
|
-
horizon_weight=self.horizon_weight,
|
800
808
|
)
|
801
809
|
|
802
810
|
def score(
|
803
811
|
self,
|
804
812
|
data: TimeSeriesDataFrame,
|
805
|
-
model: Optional[Union[str,
|
813
|
+
model: Optional[Union[str, TimeSeriesModelBase]] = None,
|
806
814
|
metric: Union[str, TimeSeriesScorer, None] = None,
|
807
815
|
use_cache: bool = True,
|
808
816
|
) -> float:
|
@@ -813,7 +821,7 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
813
821
|
def evaluate(
|
814
822
|
self,
|
815
823
|
data: TimeSeriesDataFrame,
|
816
|
-
model: Optional[Union[str,
|
824
|
+
model: Optional[Union[str, TimeSeriesModelBase]] = None,
|
817
825
|
metrics: Optional[Union[str, TimeSeriesScorer, List[Union[str, TimeSeriesScorer]]]] = None,
|
818
826
|
use_cache: bool = True,
|
819
827
|
) -> Dict[str, float]:
|
@@ -835,7 +843,7 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
835
843
|
self,
|
836
844
|
data: TimeSeriesDataFrame,
|
837
845
|
features: List[str],
|
838
|
-
model: Optional[Union[str,
|
846
|
+
model: Optional[Union[str, TimeSeriesModelBase]] = None,
|
839
847
|
metric: Optional[Union[str, TimeSeriesScorer]] = None,
|
840
848
|
time_limit: Optional[float] = None,
|
841
849
|
method: Literal["naive", "permutation"] = "permutation",
|
@@ -938,7 +946,7 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
938
946
|
|
939
947
|
return importance_df
|
940
948
|
|
941
|
-
def _model_uses_feature(self, model: Union[str,
|
949
|
+
def _model_uses_feature(self, model: Union[str, TimeSeriesModelBase], feature: str) -> bool:
|
942
950
|
"""Check if the given model uses the given feature."""
|
943
951
|
models_with_ancestors = set(self.get_minimum_model_set(model))
|
944
952
|
|
@@ -980,7 +988,7 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
980
988
|
|
981
989
|
def _predict_model(
|
982
990
|
self,
|
983
|
-
model: Union[str,
|
991
|
+
model: Union[str, TimeSeriesModelBase],
|
984
992
|
data: TimeSeriesDataFrame,
|
985
993
|
model_pred_dict: Dict[str, Optional[TimeSeriesDataFrame]],
|
986
994
|
known_covariates: Optional[TimeSeriesDataFrame] = None,
|
@@ -996,7 +1004,7 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
996
1004
|
|
997
1005
|
def _get_inputs_to_model(
|
998
1006
|
self,
|
999
|
-
model: Union[str,
|
1007
|
+
model: Union[str, TimeSeriesModelBase],
|
1000
1008
|
data: TimeSeriesDataFrame,
|
1001
1009
|
model_pred_dict: Dict[str, Optional[TimeSeriesDataFrame]],
|
1002
1010
|
) -> Union[TimeSeriesDataFrame, Dict[str, Optional[TimeSeriesDataFrame]]]:
|
@@ -1188,6 +1196,7 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
1188
1196
|
model_name = model.name
|
1189
1197
|
if model._get_tags()["can_refit_full"]:
|
1190
1198
|
model_full = model.convert_to_refit_full_template()
|
1199
|
+
assert isinstance(model_full, AbstractTimeSeriesModel)
|
1191
1200
|
logger.info(f"Fitting model: {model_full.name}")
|
1192
1201
|
models_trained = self._train_and_save(
|
1193
1202
|
train_data=refit_full_data,
|
@@ -1253,12 +1262,11 @@ class TimeSeriesTrainer(AbstractTrainer[AbstractTimeSeriesModel]):
|
|
1253
1262
|
freq: Optional[str] = None,
|
1254
1263
|
excluded_model_types: Optional[List[str]] = None,
|
1255
1264
|
hyperparameter_tune: bool = False,
|
1256
|
-
) -> List[
|
1265
|
+
) -> List[TimeSeriesModelBase]:
|
1257
1266
|
return get_preset_models(
|
1258
1267
|
path=self.path,
|
1259
1268
|
eval_metric=self.eval_metric,
|
1260
1269
|
eval_metric_seasonal_period=self.eval_metric_seasonal_period,
|
1261
|
-
horizon_weight=self.horizon_weight,
|
1262
1270
|
prediction_length=self.prediction_length,
|
1263
1271
|
freq=freq,
|
1264
1272
|
hyperparameters=hyperparameters,
|
autogluon/timeseries/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: autogluon.timeseries
|
3
|
-
Version: 1.2.
|
3
|
+
Version: 1.2.1b20250423
|
4
4
|
Summary: Fast and Accurate ML in 3 Lines of Code
|
5
5
|
Home-page: https://github.com/autogluon/autogluon
|
6
6
|
Author: AutoGluon Community
|
@@ -55,9 +55,9 @@ Requires-Dist: fugue>=0.9.0
|
|
55
55
|
Requires-Dist: tqdm<5,>=4.38
|
56
56
|
Requires-Dist: orjson~=3.9
|
57
57
|
Requires-Dist: tensorboard<3,>=2.9
|
58
|
-
Requires-Dist: autogluon.core[raytune]==1.2.
|
59
|
-
Requires-Dist: autogluon.common==1.2.
|
60
|
-
Requires-Dist: autogluon.tabular[catboost,lightgbm,xgboost]==1.2.
|
58
|
+
Requires-Dist: autogluon.core[raytune]==1.2.1b20250423
|
59
|
+
Requires-Dist: autogluon.common==1.2.1b20250423
|
60
|
+
Requires-Dist: autogluon.tabular[catboost,lightgbm,xgboost]==1.2.1b20250423
|
61
61
|
Provides-Extra: all
|
62
62
|
Provides-Extra: chronos-onnx
|
63
63
|
Requires-Dist: optimum[onnxruntime]<1.23,>=1.17; extra == "chronos-onnx"
|
@@ -1,25 +1,25 @@
|
|
1
|
-
autogluon.timeseries-1.2.
|
1
|
+
autogluon.timeseries-1.2.1b20250423-py3.9-nspkg.pth,sha256=cQGwpuGPqg1GXscIwt-7PmME1OnSpD-7ixkikJ31WAY,554
|
2
2
|
autogluon/timeseries/__init__.py,sha256=_CrLLc1fkjen7UzWoO0Os8WZoHOgvZbHKy46I8v_4k4,304
|
3
3
|
autogluon/timeseries/evaluator.py,sha256=l642tYfTHsl8WVIq_vV6qhgAFVFr9UuZD7gLra3A_Kc,250
|
4
|
-
autogluon/timeseries/learner.py,sha256=
|
5
|
-
autogluon/timeseries/predictor.py,sha256=
|
4
|
+
autogluon/timeseries/learner.py,sha256=7dqSHKCIX2osjv9cmWWLwaGvdrPvla0HTnsR75bdenY,14112
|
5
|
+
autogluon/timeseries/predictor.py,sha256=eklp1Qils6f4vIex8KhLD6nVsUQwZ6Jt9UKkTsSyErM,85739
|
6
6
|
autogluon/timeseries/regressor.py,sha256=xw5VPrXS-NQ_Ts4ppDjoNV0TdqUYjW4VINUtb_BZdiI,11868
|
7
7
|
autogluon/timeseries/splitter.py,sha256=yzPca9p2bWV-_VJAptUyyzQsxu-uixAdpMoGQtDzMD4,3205
|
8
|
-
autogluon/timeseries/trainer.py,sha256
|
9
|
-
autogluon/timeseries/version.py,sha256=
|
8
|
+
autogluon/timeseries/trainer.py,sha256=-8UBCe_uzwOoMk8wHgVEEhN7mN2biumUzGrf5YY6n4w,58131
|
9
|
+
autogluon/timeseries/version.py,sha256=5cHaVBGEbXKlEyQMJ8g3TzPJ5O8xRFYaKM8gVl6YgvE,91
|
10
10
|
autogluon/timeseries/configs/__init__.py,sha256=BTtHIPCYeGjqgOcvqb8qPD4VNX-ICKOg6wnkew1cPOE,98
|
11
11
|
autogluon/timeseries/configs/presets_configs.py,sha256=cLat8ecLlWrI-SC5KLBDCX2SbVXaucemy2pjxJAtSY0,2543
|
12
12
|
autogluon/timeseries/dataset/__init__.py,sha256=UvnhAN5tjgxXTHoZMQDy64YMDj4Xxa68yY7NP4vAw0o,81
|
13
|
-
autogluon/timeseries/dataset/ts_dataframe.py,sha256=
|
14
|
-
autogluon/timeseries/metrics/__init__.py,sha256=
|
15
|
-
autogluon/timeseries/metrics/abstract.py,sha256=
|
16
|
-
autogluon/timeseries/metrics/point.py,sha256=
|
17
|
-
autogluon/timeseries/metrics/quantile.py,sha256=
|
13
|
+
autogluon/timeseries/dataset/ts_dataframe.py,sha256=uX639T0zD6DDmsO4PbCY_X2gI_4M95Gf4oYCy4etGhk,47169
|
14
|
+
autogluon/timeseries/metrics/__init__.py,sha256=dJCrZ2cHwqhqNctwQjwG-FHgGUmzIFT-D0z72f4RAVM,2104
|
15
|
+
autogluon/timeseries/metrics/abstract.py,sha256=CHUZB6xt9oF9yijSOjgGtjLuKo2X0mT6dQDuwg4ZzpU,8192
|
16
|
+
autogluon/timeseries/metrics/point.py,sha256=2nlieQcPBCI9hXMT3v0Oe802ykZDuzvEtDpunzt0IVA,15785
|
17
|
+
autogluon/timeseries/metrics/quantile.py,sha256=wvFeDMvRf1mFurhvVr_7g13Kg-hKIRoW4y9t2no_e7A,3969
|
18
18
|
autogluon/timeseries/metrics/utils.py,sha256=HuDe1BNe8yJU4f_DKM913nNrUueoRaw6zhxm1-S20s0,910
|
19
19
|
autogluon/timeseries/models/__init__.py,sha256=MYD9JJ-wUDE5B6jW6E6LU2eXQ6vflfQBvqQJkdzJa3A,1189
|
20
|
-
autogluon/timeseries/models/presets.py,sha256=
|
21
|
-
autogluon/timeseries/models/abstract/__init__.py,sha256=
|
22
|
-
autogluon/timeseries/models/abstract/abstract_timeseries_model.py,sha256=
|
20
|
+
autogluon/timeseries/models/presets.py,sha256=BdSTW91-flgqhVNuZIvqEf7wUj1iB6BPger4tJaoAZQ,12322
|
21
|
+
autogluon/timeseries/models/abstract/__init__.py,sha256=Htfkjjc3vo92RvyM8rIlQ0PLWt3jcrCKZES07UvCMV0,146
|
22
|
+
autogluon/timeseries/models/abstract/abstract_timeseries_model.py,sha256=ZaMkFUgr3YTxGAjm3k3xZCp0bIbgelTzZ2kwWqQ1IQ4,32978
|
23
23
|
autogluon/timeseries/models/abstract/model_trial.py,sha256=ENPg_7nsdxIvaNM0o0UShZ3x8jFlRmwRc5m0fGPC0TM,3720
|
24
24
|
autogluon/timeseries/models/abstract/tunable.py,sha256=SFl4vjkb6BfFFaRPVdftnnLYlIyCThutLHxiiAlV6tY,7168
|
25
25
|
autogluon/timeseries/models/autogluon_tabular/__init__.py,sha256=r9i6jWcyeLHYClkcMSKRVsfrkBUMxpDrTATNTBc_qgQ,136
|
@@ -27,15 +27,16 @@ autogluon/timeseries/models/autogluon_tabular/mlforecast.py,sha256=QaQcImTXJpzl-
|
|
27
27
|
autogluon/timeseries/models/autogluon_tabular/transforms.py,sha256=CVvNun8DKH7UQGyXU-iO2xmvBIHRQElw72gIrZ7QjkU,2504
|
28
28
|
autogluon/timeseries/models/autogluon_tabular/utils.py,sha256=Fn3Vu_Q0PCtEUbtNgLp1xIblg7dOdpFlF3W5kLHgruI,63
|
29
29
|
autogluon/timeseries/models/chronos/__init__.py,sha256=wT77HzTtmQxW3sw2k0mA5Ot6PSHivX-Uvn5fjM05EU4,60
|
30
|
-
autogluon/timeseries/models/chronos/model.py,sha256=
|
30
|
+
autogluon/timeseries/models/chronos/model.py,sha256=dYc3nZE6BqpunwI2IyuOm1LGW1RJJEzxYCB5ZW0585E,31649
|
31
31
|
autogluon/timeseries/models/chronos/pipeline/__init__.py,sha256=N-YZH9BGBoi99r5cznJe1zEEjwjIg7cOYIHZkKuJq44,247
|
32
32
|
autogluon/timeseries/models/chronos/pipeline/base.py,sha256=14OAKHmio6LmO4mVom2mPGB0CvIrOjMGJzb-MVSAq-s,5596
|
33
33
|
autogluon/timeseries/models/chronos/pipeline/chronos.py,sha256=uFJLsSb2WQiSrmDZ0g2mO-lhTFUlq7vplGRBXZ9_VBk,22591
|
34
34
|
autogluon/timeseries/models/chronos/pipeline/chronos_bolt.py,sha256=kNIDesojKB3rbEK9jM8st4k7ZeaT6tz1znf4PsRDv2Q,20066
|
35
35
|
autogluon/timeseries/models/chronos/pipeline/utils.py,sha256=dtDX5Pyu95bGv7qmqgfUc1iYowWPY84dnGN0uyqyHyQ,13131
|
36
|
-
autogluon/timeseries/models/ensemble/__init__.py,sha256=
|
37
|
-
autogluon/timeseries/models/ensemble/
|
38
|
-
autogluon/timeseries/models/ensemble/
|
36
|
+
autogluon/timeseries/models/ensemble/__init__.py,sha256=_BivnZaOWJiIvu93IQy0mrLdCZKT2NHHSqkf31hwF2s,158
|
37
|
+
autogluon/timeseries/models/ensemble/abstract.py,sha256=ie-BKD4JIkQQoKqtf6sYI5Aix7dSgywFsSdeGPxoElk,5821
|
38
|
+
autogluon/timeseries/models/ensemble/basic.py,sha256=BRPWg_Wgfb87iInFSoTRE75BRHaovRR5HFRvzxET_wU,3423
|
39
|
+
autogluon/timeseries/models/ensemble/greedy.py,sha256=2MVLTPvJ9Khuqri1gwQlo0RmKFeWK4qFkEcLH1Dh41E,7362
|
39
40
|
autogluon/timeseries/models/gluonts/__init__.py,sha256=asC1PTj4j9xMbilvk1IT1julnpeoKbv5ZNuAR6-DFgA,361
|
40
41
|
autogluon/timeseries/models/gluonts/abstract_gluonts.py,sha256=35T8rty6sPGiaSFNpiVNmeseo1_qpn664UcWo92W5eI,32906
|
41
42
|
autogluon/timeseries/models/gluonts/torch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -59,11 +60,11 @@ autogluon/timeseries/utils/datetime/base.py,sha256=3NdsH3NDq4cVAOSoy3XpaNixyNlbj
|
|
59
60
|
autogluon/timeseries/utils/datetime/lags.py,sha256=gQDk5_zmsY5DUWDUpSaCKYkQ9nHKKY-LsywJQRAoYSk,5988
|
60
61
|
autogluon/timeseries/utils/datetime/seasonality.py,sha256=YK_2k8hvYIMW-sJPnjGWRtCnvIOthwA2hATB3nwVoD4,834
|
61
62
|
autogluon/timeseries/utils/datetime/time_features.py,sha256=MjLi3zQ00uWWJtXH9oGX2GJkTbvjdSiuabSa4kcVuxE,2672
|
62
|
-
autogluon.timeseries-1.2.
|
63
|
-
autogluon.timeseries-1.2.
|
64
|
-
autogluon.timeseries-1.2.
|
65
|
-
autogluon.timeseries-1.2.
|
66
|
-
autogluon.timeseries-1.2.
|
67
|
-
autogluon.timeseries-1.2.
|
68
|
-
autogluon.timeseries-1.2.
|
69
|
-
autogluon.timeseries-1.2.
|
63
|
+
autogluon.timeseries-1.2.1b20250423.dist-info/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
|
64
|
+
autogluon.timeseries-1.2.1b20250423.dist-info/METADATA,sha256=vs0Qvp4NFtgEq_tw4OkGPvAwv8EPGJWseJ7StCv_cU4,12687
|
65
|
+
autogluon.timeseries-1.2.1b20250423.dist-info/NOTICE,sha256=7nPQuj8Kp-uXsU0S5so3-2dNU5EctS5hDXvvzzehd7E,114
|
66
|
+
autogluon.timeseries-1.2.1b20250423.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
67
|
+
autogluon.timeseries-1.2.1b20250423.dist-info/namespace_packages.txt,sha256=giERA4R78OkJf2ijn5slgjURlhRPzfLr7waIcGkzYAo,10
|
68
|
+
autogluon.timeseries-1.2.1b20250423.dist-info/top_level.txt,sha256=giERA4R78OkJf2ijn5slgjURlhRPzfLr7waIcGkzYAo,10
|
69
|
+
autogluon.timeseries-1.2.1b20250423.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
70
|
+
autogluon.timeseries-1.2.1b20250423.dist-info/RECORD,,
|