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.
Files changed (90) hide show
  1. autogluon/timeseries/configs/__init__.py +3 -2
  2. autogluon/timeseries/configs/hyperparameter_presets.py +62 -0
  3. autogluon/timeseries/configs/predictor_presets.py +84 -0
  4. autogluon/timeseries/dataset/ts_dataframe.py +98 -72
  5. autogluon/timeseries/learner.py +19 -18
  6. autogluon/timeseries/metrics/__init__.py +5 -5
  7. autogluon/timeseries/metrics/abstract.py +17 -17
  8. autogluon/timeseries/metrics/point.py +1 -1
  9. autogluon/timeseries/metrics/quantile.py +2 -2
  10. autogluon/timeseries/metrics/utils.py +4 -4
  11. autogluon/timeseries/models/__init__.py +4 -0
  12. autogluon/timeseries/models/abstract/abstract_timeseries_model.py +52 -75
  13. autogluon/timeseries/models/abstract/tunable.py +6 -6
  14. autogluon/timeseries/models/autogluon_tabular/mlforecast.py +72 -76
  15. autogluon/timeseries/models/autogluon_tabular/per_step.py +104 -46
  16. autogluon/timeseries/models/autogluon_tabular/transforms.py +9 -7
  17. autogluon/timeseries/models/chronos/model.py +115 -78
  18. autogluon/timeseries/models/chronos/{pipeline/utils.py → utils.py} +76 -44
  19. autogluon/timeseries/models/ensemble/__init__.py +29 -2
  20. autogluon/timeseries/models/ensemble/abstract.py +16 -52
  21. autogluon/timeseries/models/ensemble/array_based/__init__.py +3 -0
  22. autogluon/timeseries/models/ensemble/array_based/abstract.py +247 -0
  23. autogluon/timeseries/models/ensemble/array_based/models.py +50 -0
  24. autogluon/timeseries/models/ensemble/array_based/regressor/__init__.py +10 -0
  25. autogluon/timeseries/models/ensemble/array_based/regressor/abstract.py +87 -0
  26. autogluon/timeseries/models/ensemble/array_based/regressor/per_quantile_tabular.py +133 -0
  27. autogluon/timeseries/models/ensemble/array_based/regressor/tabular.py +141 -0
  28. autogluon/timeseries/models/ensemble/weighted/__init__.py +8 -0
  29. autogluon/timeseries/models/ensemble/weighted/abstract.py +41 -0
  30. autogluon/timeseries/models/ensemble/{basic.py → weighted/basic.py} +8 -18
  31. autogluon/timeseries/models/ensemble/{greedy.py → weighted/greedy.py} +13 -13
  32. autogluon/timeseries/models/gluonts/abstract.py +26 -26
  33. autogluon/timeseries/models/gluonts/dataset.py +4 -4
  34. autogluon/timeseries/models/gluonts/models.py +27 -12
  35. autogluon/timeseries/models/local/abstract_local_model.py +14 -14
  36. autogluon/timeseries/models/local/naive.py +4 -0
  37. autogluon/timeseries/models/local/npts.py +1 -0
  38. autogluon/timeseries/models/local/statsforecast.py +30 -14
  39. autogluon/timeseries/models/multi_window/multi_window_model.py +34 -23
  40. autogluon/timeseries/models/registry.py +65 -0
  41. autogluon/timeseries/models/toto/__init__.py +3 -0
  42. autogluon/timeseries/models/toto/_internal/__init__.py +9 -0
  43. autogluon/timeseries/models/toto/_internal/backbone/__init__.py +3 -0
  44. autogluon/timeseries/models/toto/_internal/backbone/attention.py +197 -0
  45. autogluon/timeseries/models/toto/_internal/backbone/backbone.py +262 -0
  46. autogluon/timeseries/models/toto/_internal/backbone/distribution.py +70 -0
  47. autogluon/timeseries/models/toto/_internal/backbone/kvcache.py +136 -0
  48. autogluon/timeseries/models/toto/_internal/backbone/rope.py +94 -0
  49. autogluon/timeseries/models/toto/_internal/backbone/scaler.py +306 -0
  50. autogluon/timeseries/models/toto/_internal/backbone/transformer.py +333 -0
  51. autogluon/timeseries/models/toto/_internal/dataset.py +165 -0
  52. autogluon/timeseries/models/toto/_internal/forecaster.py +423 -0
  53. autogluon/timeseries/models/toto/dataloader.py +108 -0
  54. autogluon/timeseries/models/toto/hf_pretrained_model.py +119 -0
  55. autogluon/timeseries/models/toto/model.py +236 -0
  56. autogluon/timeseries/predictor.py +94 -107
  57. autogluon/timeseries/regressor.py +31 -27
  58. autogluon/timeseries/splitter.py +7 -31
  59. autogluon/timeseries/trainer/__init__.py +3 -0
  60. autogluon/timeseries/trainer/ensemble_composer.py +250 -0
  61. autogluon/timeseries/trainer/model_set_builder.py +256 -0
  62. autogluon/timeseries/trainer/prediction_cache.py +149 -0
  63. autogluon/timeseries/{trainer.py → trainer/trainer.py} +182 -307
  64. autogluon/timeseries/trainer/utils.py +18 -0
  65. autogluon/timeseries/transforms/covariate_scaler.py +4 -4
  66. autogluon/timeseries/transforms/target_scaler.py +14 -14
  67. autogluon/timeseries/utils/datetime/lags.py +2 -2
  68. autogluon/timeseries/utils/datetime/time_features.py +2 -2
  69. autogluon/timeseries/utils/features.py +41 -37
  70. autogluon/timeseries/utils/forecast.py +5 -5
  71. autogluon/timeseries/utils/warning_filters.py +3 -1
  72. autogluon/timeseries/version.py +1 -1
  73. autogluon.timeseries-1.4.1b20251116-py3.9-nspkg.pth +1 -0
  74. {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info}/METADATA +32 -17
  75. autogluon_timeseries-1.4.1b20251116.dist-info/RECORD +96 -0
  76. {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info}/WHEEL +1 -1
  77. autogluon/timeseries/configs/presets_configs.py +0 -79
  78. autogluon/timeseries/evaluator.py +0 -6
  79. autogluon/timeseries/models/chronos/pipeline/__init__.py +0 -10
  80. autogluon/timeseries/models/chronos/pipeline/base.py +0 -160
  81. autogluon/timeseries/models/chronos/pipeline/chronos.py +0 -544
  82. autogluon/timeseries/models/chronos/pipeline/chronos_bolt.py +0 -530
  83. autogluon/timeseries/models/presets.py +0 -358
  84. autogluon.timeseries-1.3.2b20250712-py3.9-nspkg.pth +0 -1
  85. autogluon.timeseries-1.3.2b20250712.dist-info/RECORD +0 -71
  86. {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info/licenses}/LICENSE +0 -0
  87. {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info/licenses}/NOTICE +0 -0
  88. {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info}/namespace_packages.txt +0 -0
  89. {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info}/top_level.txt +0 -0
  90. {autogluon.timeseries-1.3.2b20250712.dist-info → autogluon_timeseries-1.4.1b20251116.dist-info}/zip-safe +0 -0
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from pprint import pformat
4
- from typing import Any, Dict, Optional, Sequence, Type, Union
4
+ from typing import Any, Optional, Sequence, Type, Union
5
5
 
6
6
  import numpy as np
7
7
 
@@ -28,7 +28,7 @@ __all__ = [
28
28
 
29
29
  DEFAULT_METRIC_NAME = "WQL"
30
30
 
31
- AVAILABLE_METRICS: Dict[str, Type[TimeSeriesScorer]] = {
31
+ AVAILABLE_METRICS: dict[str, Type[TimeSeriesScorer]] = {
32
32
  "MASE": MASE,
33
33
  "MAPE": MAPE,
34
34
  "SMAPE": SMAPE,
@@ -48,7 +48,7 @@ DEPRECATED_METRICS = {
48
48
  }
49
49
 
50
50
  # Experimental metrics that are not yet user facing
51
- EXPERIMENTAL_METRICS: Dict[str, Type[TimeSeriesScorer]] = {
51
+ EXPERIMENTAL_METRICS: dict[str, Type[TimeSeriesScorer]] = {
52
52
  "WCD": WCD,
53
53
  }
54
54
 
@@ -63,7 +63,7 @@ def check_get_evaluation_metric(
63
63
 
64
64
  Returns
65
65
  -------
66
- scorer :
66
+ scorer
67
67
  A `TimeSeriesScorer` object based on the provided `eval_metric`.
68
68
 
69
69
  `scorer.prediction_length` is always set to the `prediction_length` provided to this method.
@@ -75,7 +75,7 @@ def check_get_evaluation_metric(
75
75
  value of `horizon_weight` is kept.
76
76
  """
77
77
  scorer: TimeSeriesScorer
78
- metric_kwargs: Dict[str, Any] = dict(
78
+ metric_kwargs: dict[str, Any] = dict(
79
79
  prediction_length=prediction_length, seasonal_period=seasonal_period, horizon_weight=horizon_weight
80
80
  )
81
81
  if isinstance(eval_metric, TimeSeriesScorer):
@@ -1,8 +1,7 @@
1
1
  import warnings
2
- from typing import Optional, Sequence, Tuple, Union, overload
2
+ from typing import Optional, Sequence, Union, overload
3
3
 
4
4
  import numpy as np
5
- import numpy.typing as npt
6
5
  import pandas as pd
7
6
 
8
7
  from autogluon.timeseries import TimeSeriesDataFrame
@@ -20,14 +19,14 @@ class TimeSeriesScorer:
20
19
  Parameters
21
20
  ----------
22
21
  prediction_length : int, default = 1
23
- The length of the forecast horizon. The predictions provided to the `TimeSeriesScorer` are expected to contain
22
+ The length of the forecast horizon. The predictions provided to the ``TimeSeriesScorer`` are expected to contain
24
23
  a forecast for this many time steps for each time series.
25
24
  seasonal_period : int or None, default = None
26
25
  Seasonal period used to compute some evaluation metrics such as mean absolute scaled error (MASE). Defaults to
27
- `None`, in which case the seasonal period is computed based on the data frequency.
26
+ ``None``, in which case the seasonal period is computed based on the data frequency.
28
27
  horizon_weight : Sequence[float], np.ndarray or None, default = None
29
28
  Weight assigned to each time step in the forecast horizon when computing the metric. If provided, the
30
- `horizon_weight` will be stored as a numpy array of shape `[1, prediction_length]`.
29
+ ``horizon_weight`` will be stored as a numpy array of shape ``[1, prediction_length]``.
31
30
 
32
31
  Attributes
33
32
  ----------
@@ -44,8 +43,9 @@ class TimeSeriesScorer:
44
43
  Whether the given metric uses the quantile predictions. Some models will modify the training procedure if they
45
44
  are trained to optimize a quantile metric.
46
45
  equivalent_tabular_regression_metric : str
47
- Name of an equivalent metric used by AutoGluon-Tabular with ``problem_type="regression"``. Used by models that
48
- train a TabularPredictor under the hood. This attribute should only be specified by point forecast metrics.
46
+ Name of an equivalent metric used by AutoGluon-Tabular with ``problem_type="regression"``. Used by forecasting
47
+ models that train tabular regression models under the hood. This attribute should only be specified by point
48
+ forecast metrics.
49
49
  """
50
50
 
51
51
  greater_is_better_internal: bool = False
@@ -199,14 +199,14 @@ class TimeSeriesScorer:
199
199
  @staticmethod
200
200
  def _get_point_forecast_score_inputs(
201
201
  data_future: TimeSeriesDataFrame, predictions: TimeSeriesDataFrame, target: str = "target"
202
- ) -> Tuple[pd.Series, pd.Series]:
202
+ ) -> tuple[pd.Series, pd.Series]:
203
203
  """Get inputs necessary to compute point forecast metrics.
204
204
 
205
205
  Returns
206
206
  -------
207
- y_true : pd.Series, shape [num_items * prediction_length]
207
+ y_true
208
208
  Target time series values during the forecast horizon.
209
- y_pred : pd.Series, shape [num_items * prediction_length]
209
+ y_pred
210
210
  Predicted time series values during the forecast horizon.
211
211
  """
212
212
  y_true = data_future[target]
@@ -216,16 +216,16 @@ class TimeSeriesScorer:
216
216
  @staticmethod
217
217
  def _get_quantile_forecast_score_inputs(
218
218
  data_future: TimeSeriesDataFrame, predictions: TimeSeriesDataFrame, target: str = "target"
219
- ) -> Tuple[pd.Series, pd.DataFrame, np.ndarray]:
219
+ ) -> tuple[pd.Series, pd.DataFrame, np.ndarray]:
220
220
  """Get inputs necessary to compute quantile forecast metrics.
221
221
 
222
222
  Returns
223
223
  -------
224
- y_true : pd.Series, shape [num_items * prediction_length]
224
+ y_true
225
225
  Target time series values during the forecast horizon.
226
- q_pred : pd.DataFrame, shape [num_items * prediction_length, num_quantiles]
226
+ q_pred
227
227
  Quantile forecast for each predicted quantile level. Column order corresponds to ``quantile_levels``.
228
- quantile_levels : np.ndarray, shape [num_quantiles]
228
+ quantile_levels
229
229
  Quantile levels for which the forecasts are generated (as floats).
230
230
  """
231
231
  quantile_columns = [col for col in predictions.columns if col != "mean"]
@@ -241,18 +241,18 @@ class TimeSeriesScorer:
241
241
  @staticmethod
242
242
  def check_get_horizon_weight(
243
243
  horizon_weight: Union[Sequence[float], np.ndarray], prediction_length: int
244
- ) -> npt.NDArray[np.float64]: ...
244
+ ) -> np.ndarray: ...
245
245
 
246
246
  @staticmethod
247
247
  def check_get_horizon_weight(
248
248
  horizon_weight: Union[Sequence[float], np.ndarray, None], prediction_length: int
249
- ) -> Optional[npt.NDArray[np.float64]]:
249
+ ) -> Optional[np.ndarray]:
250
250
  """Convert horizon_weight to a non-negative numpy array that sums up to prediction_length.
251
251
  Raises an exception if horizon_weight has an invalid shape or contains invalid values.
252
252
 
253
253
  Returns
254
254
  -------
255
- horizon_weight:
255
+ horizon_weight
256
256
  None if the input is None, otherwise a numpy array of shape [1, prediction_length].
257
257
  """
258
258
  if horizon_weight is None:
@@ -143,7 +143,7 @@ class WAPE(TimeSeriesScorer):
143
143
  - not sensitive to outliers
144
144
  - prefers models that accurately estimate the median
145
145
 
146
- If `self.horizon_weight` is provided, both the errors and the target time series in the denominator will be re-weighted.
146
+ If ``self.horizon_weight`` is provided, both the errors and the target time series in the denominator will be re-weighted.
147
147
 
148
148
  References
149
149
  ----------
@@ -3,7 +3,7 @@ from typing import Optional, Sequence
3
3
  import numpy as np
4
4
  import pandas as pd
5
5
 
6
- from autogluon.timeseries.dataset.ts_dataframe import TimeSeriesDataFrame
6
+ from autogluon.timeseries.dataset import TimeSeriesDataFrame
7
7
 
8
8
  from .abstract import TimeSeriesScorer
9
9
  from .utils import in_sample_abs_seasonal_error
@@ -25,7 +25,7 @@ class WQL(TimeSeriesScorer):
25
25
  - scale-dependent (time series with large absolute value contribute more to the loss)
26
26
  - equivalent to WAPE if ``quantile_levels = [0.5]``
27
27
 
28
- If `horizon_weight` is provided, both the errors and the target time series in the denominator will be re-weighted.
28
+ If ``horizon_weight`` is provided, both the errors and the target time series in the denominator will be re-weighted.
29
29
 
30
30
  References
31
31
  ----------
@@ -1,18 +1,18 @@
1
1
  import pandas as pd
2
2
 
3
- from autogluon.timeseries.dataset.ts_dataframe import ITEMID
3
+ from autogluon.timeseries.dataset import TimeSeriesDataFrame
4
4
 
5
5
 
6
6
  def _get_seasonal_diffs(*, y_past: pd.Series, seasonal_period: int = 1) -> pd.Series:
7
- return y_past.groupby(level=ITEMID, sort=False).diff(seasonal_period).abs()
7
+ return y_past.groupby(level=TimeSeriesDataFrame.ITEMID, sort=False).diff(seasonal_period).abs()
8
8
 
9
9
 
10
10
  def in_sample_abs_seasonal_error(*, y_past: pd.Series, seasonal_period: int = 1) -> pd.Series:
11
11
  """Compute seasonal naive forecast error (predict value from seasonal_period steps ago) for each time series."""
12
12
  seasonal_diffs = _get_seasonal_diffs(y_past=y_past, seasonal_period=seasonal_period)
13
- return seasonal_diffs.groupby(level=ITEMID, sort=False).mean().fillna(1.0)
13
+ return seasonal_diffs.groupby(level=TimeSeriesDataFrame.ITEMID, sort=False).mean().fillna(1.0)
14
14
 
15
15
 
16
16
  def in_sample_squared_seasonal_error(*, y_past: pd.Series, seasonal_period: int = 1) -> pd.Series:
17
17
  seasonal_diffs = _get_seasonal_diffs(y_past=y_past, seasonal_period=seasonal_period)
18
- return seasonal_diffs.pow(2.0).groupby(level=ITEMID, sort=False).mean().fillna(1.0)
18
+ return seasonal_diffs.pow(2.0).groupby(level=TimeSeriesDataFrame.ITEMID, sort=False).mean().fillna(1.0)
@@ -27,6 +27,8 @@ from .local import (
27
27
  ThetaModel,
28
28
  ZeroModel,
29
29
  )
30
+ from .registry import ModelRegistry
31
+ from .toto import TotoModel
30
32
 
31
33
  __all__ = [
32
34
  "ADIDAModel",
@@ -43,6 +45,7 @@ __all__ = [
43
45
  "ETSModel",
44
46
  "IMAPAModel",
45
47
  "ChronosModel",
48
+ "ModelRegistry",
46
49
  "NPTSModel",
47
50
  "NaiveModel",
48
51
  "PatchTSTModel",
@@ -54,6 +57,7 @@ __all__ = [
54
57
  "TemporalFusionTransformerModel",
55
58
  "ThetaModel",
56
59
  "TiDEModel",
60
+ "TotoModel",
57
61
  "WaveNetModel",
58
62
  "ZeroModel",
59
63
  ]
@@ -1,12 +1,10 @@
1
- from __future__ import annotations
2
-
3
1
  import copy
4
2
  import logging
5
3
  import os
6
4
  import re
7
5
  import time
8
6
  from abc import ABC, abstractmethod
9
- from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
7
+ from typing import Any, Optional, Sequence, Union
10
8
 
11
9
  import pandas as pd
12
10
  from typing_extensions import Self
@@ -21,6 +19,7 @@ from autogluon.core.models import ModelBase
21
19
  from autogluon.core.utils.exceptions import TimeLimitExceeded
22
20
  from autogluon.timeseries.dataset import TimeSeriesDataFrame
23
21
  from autogluon.timeseries.metrics import TimeSeriesScorer, check_get_evaluation_metric
22
+ from autogluon.timeseries.models.registry import ModelRegistry
24
23
  from autogluon.timeseries.regressor import CovariateRegressor, get_covariate_regressor
25
24
  from autogluon.timeseries.transforms import CovariateScaler, TargetScaler, get_covariate_scaler, get_target_scaler
26
25
  from autogluon.timeseries.utils.features import CovariateMetadata
@@ -37,27 +36,27 @@ class TimeSeriesModelBase(ModelBase, ABC):
37
36
 
38
37
  Parameters
39
38
  ----------
40
- path : str, default = None
39
+ path
41
40
  Directory location to store all outputs.
42
41
  If None, a new unique time-stamped directory is chosen.
43
- freq: str
42
+ freq
44
43
  Frequency string (cf. gluonts frequency strings) describing the frequency
45
44
  of the time series data. For example, "h" for hourly or "D" for daily data.
46
- prediction_length: int
45
+ prediction_length
47
46
  Length of the prediction horizon, i.e., the number of time steps the model
48
47
  is fit to forecast.
49
- name : str, default = None
48
+ name
50
49
  Name of the subdirectory inside path where model will be saved.
51
50
  The final model directory will be os.path.join(path, name)
52
51
  If None, defaults to the model's class name: self.__class__.__name__
53
- covariate_metadata: CovariateMetadata
52
+ covariate_metadata
54
53
  A mapping of different covariate types known to autogluon.timeseries to column names
55
54
  in the data set.
56
- eval_metric : Union[str, TimeSeriesScorer], default = "WQL"
55
+ eval_metric
57
56
  Metric by which predictions will be ultimately evaluated on future test data. This only impacts
58
57
  ``model.score()``, as eval_metric is not used during training. Available metrics can be found in
59
58
  ``autogluon.timeseries.metrics``.
60
- hyperparameters : dict, default = None
59
+ hyperparameters
61
60
  Hyperparameters that will be used by the model (can be search spaces instead of fixed values).
62
61
  If None, model defaults are used. This is identical to passing an empty dictionary.
63
62
  """
@@ -78,7 +77,7 @@ class TimeSeriesModelBase(ModelBase, ABC):
78
77
  self,
79
78
  path: Optional[str] = None,
80
79
  name: Optional[str] = None,
81
- hyperparameters: Optional[Dict[str, Any]] = None,
80
+ hyperparameters: Optional[dict[str, Any]] = None,
82
81
  freq: Optional[str] = None,
83
82
  prediction_length: int = 1,
84
83
  covariate_metadata: Optional[CovariateMetadata] = None,
@@ -118,7 +117,7 @@ class TimeSeriesModelBase(ModelBase, ABC):
118
117
  else:
119
118
  self.must_drop_median = False
120
119
 
121
- self._oof_predictions: Optional[List[TimeSeriesDataFrame]] = None
120
+ self._oof_predictions: Optional[list[TimeSeriesDataFrame]] = None
122
121
 
123
122
  # user provided hyperparameters and extra arguments that are used during model training
124
123
  self._hyperparameters, self._extra_ag_args = self._check_and_split_hyperparameters(hyperparameters)
@@ -146,22 +145,21 @@ class TimeSeriesModelBase(ModelBase, ABC):
146
145
 
147
146
  @classmethod
148
147
  def _check_and_split_hyperparameters(
149
- cls, hyperparameters: Optional[Dict[str, Any]] = None
150
- ) -> Tuple[Dict[str, Any], Dict[str, Any]]:
151
- """
152
- Given the user-specified hyperparameters, split into `hyperparameters` and `extra_ag_args`, intended
148
+ cls, hyperparameters: Optional[dict[str, Any]] = None
149
+ ) -> tuple[dict[str, Any], dict[str, Any]]:
150
+ """Given the user-specified hyperparameters, split into `hyperparameters` and `extra_ag_args`, intended
153
151
  to be used during model initialization.
154
152
 
155
153
  Parameters
156
154
  ----------
157
- hyperparameters : Optional[Dict[str, Any]], default = None
155
+ hyperparameters
158
156
  The model hyperparameters dictionary provided to the model constructor.
159
157
 
160
158
  Returns
161
159
  -------
162
- hyperparameters: Dict[str, Any]
160
+ hyperparameters
163
161
  Native model hyperparameters that are passed into the "inner model" AutoGluon wraps
164
- extra_ag_args: Dict[str, Any]
162
+ extra_ag_args
165
163
  Special auxiliary parameters that modify the model training process used by AutoGluon
166
164
  """
167
165
  hyperparameters = copy.deepcopy(hyperparameters) if hyperparameters is not None else dict()
@@ -213,7 +211,7 @@ class TimeSeriesModelBase(ModelBase, ABC):
213
211
  return model
214
212
 
215
213
  @classmethod
216
- def load_oof_predictions(cls, path: str, verbose: bool = True) -> List[TimeSeriesDataFrame]:
214
+ def load_oof_predictions(cls, path: str, verbose: bool = True) -> list[TimeSeriesDataFrame]:
217
215
  """Load the cached OOF predictions from disk."""
218
216
  return load_pkl.load(path=os.path.join(path, "utils", cls._oof_filename), verbose=verbose)
219
217
 
@@ -283,7 +281,7 @@ class TimeSeriesModelBase(ModelBase, ABC):
283
281
  return False
284
282
 
285
283
  @staticmethod
286
- def _get_system_resources() -> Dict[str, Any]:
284
+ def _get_system_resources() -> dict[str, Any]:
287
285
  resource_manager = get_resource_manager()
288
286
  system_num_cpus = resource_manager.get_cpu_count()
289
287
  system_num_gpus = resource_manager.get_gpu_count()
@@ -305,7 +303,8 @@ class TimeSeriesModelBase(ModelBase, ABC):
305
303
  def _more_tags(self) -> dict:
306
304
  """Encode model properties using tags, similar to sklearn & autogluon.tabular.
307
305
 
308
- For more details, see `autogluon.core.models.abstract.AbstractModel._get_tags()` and https://scikit-learn.org/stable/_sources/developers/develop.rst.txt.
306
+ For more details, see `autogluon.core.models.abstract.AbstractModel._get_tags()` and
307
+ https://scikit-learn.org/stable/_sources/developers/develop.rst.txt.
309
308
 
310
309
  List of currently supported tags:
311
310
  - allow_nan: Can the model handle data with missing values represented by np.nan?
@@ -360,6 +359,10 @@ class TimeSeriesModelBase(ModelBase, ABC):
360
359
  """After calling this function, returned model should be able to be fit without `val_data`."""
361
360
  params = copy.deepcopy(self.get_params())
362
361
 
362
+ # Remove 0.5 from quantile_levels so that the cloned model sets its must_drop_median correctly
363
+ if self.must_drop_median:
364
+ params["quantile_levels"].remove(0.5)
365
+
363
366
  if "hyperparameters" not in params:
364
367
  params["hyperparameters"] = dict()
365
368
 
@@ -372,16 +375,18 @@ class TimeSeriesModelBase(ModelBase, ABC):
372
375
  return template
373
376
 
374
377
 
375
- class AbstractTimeSeriesModel(TimeSeriesModelBase, TimeSeriesTunable, ABC):
378
+ class AbstractTimeSeriesModel(TimeSeriesModelBase, TimeSeriesTunable, metaclass=ModelRegistry):
376
379
  """Abstract base class for all time series models that take historical data as input and
377
380
  make predictions for the forecast horizon.
378
381
  """
379
382
 
383
+ ag_priority: int = 0
384
+
380
385
  def __init__(
381
386
  self,
382
387
  path: Optional[str] = None,
383
388
  name: Optional[str] = None,
384
- hyperparameters: Optional[Dict[str, Any]] = None,
389
+ hyperparameters: Optional[dict[str, Any]] = None,
385
390
  freq: Optional[str] = None,
386
391
  prediction_length: int = 1,
387
392
  covariate_metadata: Optional[CovariateMetadata] = None,
@@ -421,9 +426,9 @@ class AbstractTimeSeriesModel(TimeSeriesModelBase, TimeSeriesTunable, ABC):
421
426
  )
422
427
 
423
428
  @property
424
- def allowed_hyperparameters(self) -> List[str]:
429
+ def allowed_hyperparameters(self) -> list[str]:
425
430
  """List of hyperparameters allowed by the model."""
426
- return ["target_scaler", "covariate_regressor"]
431
+ return ["target_scaler", "covariate_regressor", "covariate_scaler"]
427
432
 
428
433
  def fit(
429
434
  self,
@@ -438,32 +443,32 @@ class AbstractTimeSeriesModel(TimeSeriesModelBase, TimeSeriesTunable, ABC):
438
443
  Models should not override the `fit` method, but instead override the `_fit` method which
439
444
  has the same arguments.
440
445
 
441
- Other Parameters
442
- ----------------
443
- train_data : TimeSeriesDataFrame
446
+ Parameters
447
+ ----------
448
+ train_data
444
449
  The training data provided in the library's `autogluon.timeseries.dataset.TimeSeriesDataFrame`
445
450
  format.
446
- val_data : TimeSeriesDataFrame, optional
451
+ val_data
447
452
  The validation data set in the same format as training data.
448
- time_limit : float, default = None
453
+ time_limit
449
454
  Time limit in seconds to adhere to when fitting model.
450
455
  Ideally, model should early stop during fit to avoid going over the time limit if specified.
451
- num_cpus : int, default = 'auto'
456
+ num_cpus
452
457
  How many CPUs to use during fit.
453
458
  This is counted in virtual cores, not in physical cores.
454
459
  If 'auto', model decides.
455
- num_gpus : int, default = 'auto'
460
+ num_gpus
456
461
  How many GPUs to use during fit.
457
462
  If 'auto', model decides.
458
- verbosity : int, default = 2
463
+ verbosity
459
464
  Verbosity levels range from 0 to 4 and control how much information is printed.
460
465
  Higher levels correspond to more detailed print statements (you can set verbosity = 0 to suppress warnings).
461
- **kwargs :
466
+ **kwargs
462
467
  Any additional fit arguments a model supports.
463
468
 
464
469
  Returns
465
470
  -------
466
- model: AbstractTimeSeriesModel
471
+ model
467
472
  The fitted model object
468
473
  """
469
474
  start_time = time.monotonic()
@@ -546,7 +551,7 @@ class AbstractTimeSeriesModel(TimeSeriesModelBase, TimeSeriesTunable, ABC):
546
551
  "as hyperparameters when initializing or use `hyperparameter_tune` instead."
547
552
  )
548
553
 
549
- def _log_unused_hyperparameters(self, extra_allowed_hyperparameters: list[str] | None = None) -> None:
554
+ def _log_unused_hyperparameters(self, extra_allowed_hyperparameters: Optional[list[str]] = None) -> None:
550
555
  """Log a warning if unused hyperparameters were provided to the model."""
551
556
  allowed_hyperparameters = self.allowed_hyperparameters
552
557
  if extra_allowed_hyperparameters is not None:
@@ -574,15 +579,15 @@ class AbstractTimeSeriesModel(TimeSeriesModelBase, TimeSeriesTunable, ABC):
574
579
 
575
580
  Parameters
576
581
  ----------
577
- data: Union[TimeSeriesDataFrame, Dict[str, Optional[TimeSeriesDataFrame]]]
582
+ data
578
583
  The dataset where each time series is the "context" for predictions. For ensemble models that depend on
579
584
  the predictions of other models, this method may accept a dictionary of previous models' predictions.
580
- known_covariates : Optional[TimeSeriesDataFrame]
585
+ known_covariates
581
586
  A TimeSeriesDataFrame containing the values of the known covariates during the forecast horizon.
582
587
 
583
588
  Returns
584
589
  -------
585
- predictions: TimeSeriesDataFrame
590
+ predictions
586
591
  pandas dataframes with a timestamp index, where each input item from the input
587
592
  data is given as a separate forecast item in the dictionary, keyed by the `item_id`s
588
593
  of input items.
@@ -604,11 +609,13 @@ class AbstractTimeSeriesModel(TimeSeriesModelBase, TimeSeriesTunable, ABC):
604
609
  predictions = self._predict(data=data, known_covariates=known_covariates, **kwargs)
605
610
  self.covariate_regressor = covariate_regressor
606
611
 
607
- column_order = pd.Index(["mean"] + [str(q) for q in self.quantile_levels])
612
+ # Ensure that 'mean' is the leading column. Trailing columns might not match quantile_levels if self is
613
+ # a MultiWindowBacktestingModel and base_model.must_drop_median=True
614
+ column_order = pd.Index(["mean"] + [col for col in predictions.columns if col != "mean"])
608
615
  if not predictions.columns.equals(column_order):
609
616
  predictions = predictions.reindex(columns=column_order)
610
617
 
611
- # "0.5" might be missing from the quantiles if self is a wrapper (MultiWindowBacktestingModel or ensemble)
618
+ # "0.5" might be missing from the quantiles if self is a MultiWindowBacktestingModel
612
619
  if "0.5" in predictions.columns:
613
620
  if self.eval_metric.optimized_by_median:
614
621
  predictions["mean"] = predictions["0.5"]
@@ -631,36 +638,6 @@ class AbstractTimeSeriesModel(TimeSeriesModelBase, TimeSeriesTunable, ABC):
631
638
  predictions = self.target_scaler.inverse_transform(predictions)
632
639
  return predictions
633
640
 
634
- def convert_to_refit_full_via_copy(self) -> Self:
635
- # save the model as a new model on disk
636
- previous_name = self.name
637
- self.rename(self.name + REFIT_FULL_SUFFIX)
638
- refit_model_path = self.path
639
- self.save(path=self.path, verbose=False)
640
-
641
- self.rename(previous_name)
642
-
643
- refit_model = self.load(path=refit_model_path, verbose=False)
644
- refit_model.val_score = None
645
- refit_model.predict_time = None
646
-
647
- return refit_model
648
-
649
- def convert_to_refit_full_template(self):
650
- """After calling this function, returned model should be able to be fit without `val_data`."""
651
- params = copy.deepcopy(self.get_params())
652
-
653
- if "hyperparameters" not in params:
654
- params["hyperparameters"] = dict()
655
-
656
- if AG_ARGS_FIT not in params["hyperparameters"]:
657
- params["hyperparameters"][AG_ARGS_FIT] = dict()
658
-
659
- params["name"] = params["name"] + REFIT_FULL_SUFFIX
660
- template = self.__class__(**params)
661
-
662
- return template
663
-
664
641
  def get_forecast_horizon_index(self, data: TimeSeriesDataFrame) -> pd.MultiIndex:
665
642
  """For each item in the dataframe, get timestamps for the next `prediction_length` time steps into the future."""
666
643
  return pd.MultiIndex.from_frame(
@@ -726,12 +703,12 @@ class AbstractTimeSeriesModel(TimeSeriesModelBase, TimeSeriesTunable, ABC):
726
703
 
727
704
  Parameters
728
705
  ----------
729
- data: TimeSeriesDataFrame
706
+ data
730
707
  Dataset used for scoring.
731
708
 
732
709
  Returns
733
710
  -------
734
- score: float
711
+ score
735
712
  The computed forecast evaluation score on the last `self.prediction_length`
736
713
  time steps of each time series.
737
714
  """
@@ -766,6 +743,6 @@ class AbstractTimeSeriesModel(TimeSeriesModelBase, TimeSeriesTunable, ABC):
766
743
  known_covariates: Optional[TimeSeriesDataFrame] = None,
767
744
  is_train: bool = False,
768
745
  **kwargs,
769
- ) -> Tuple[TimeSeriesDataFrame, Optional[TimeSeriesDataFrame]]:
746
+ ) -> tuple[TimeSeriesDataFrame, Optional[TimeSeriesDataFrame]]:
770
747
  """Method that implements model-specific preprocessing logic."""
771
748
  return data, known_covariates
@@ -5,7 +5,7 @@ import os
5
5
  import time
6
6
  from abc import ABC, abstractmethod
7
7
  from contextlib import nullcontext
8
- from typing import Any, Dict, Optional, Tuple, Union
8
+ from typing import Any, Optional, Union
9
9
 
10
10
  from typing_extensions import Self
11
11
 
@@ -43,7 +43,7 @@ class TimeSeriesTunable(Tunable, ABC):
43
43
  refit_every_n_windows: Optional[int] = 1,
44
44
  hyperparameter_tune_kwargs: Union[str, dict] = "auto",
45
45
  time_limit: Optional[float] = None,
46
- ) -> Tuple[Dict[str, Any], Any]:
46
+ ) -> tuple[dict[str, Any], Any]:
47
47
  hpo_executor = self._get_default_hpo_executor()
48
48
  hpo_executor.initialize(
49
49
  hyperparameter_tune_kwargs, default_num_trials=default_num_trials, time_limit=time_limit
@@ -144,14 +144,14 @@ class TimeSeriesTunable(Tunable, ABC):
144
144
  """
145
145
  return None
146
146
 
147
- def get_minimum_resources(self, is_gpu_available: bool = False) -> Dict[str, Union[int, float]]:
147
+ def get_minimum_resources(self, is_gpu_available: bool = False) -> dict[str, Union[int, float]]:
148
148
  return {
149
149
  "num_cpus": 1,
150
150
  }
151
151
 
152
152
  def _save_with_data(
153
153
  self, train_data: TimeSeriesDataFrame, val_data: Optional[TimeSeriesDataFrame]
154
- ) -> Tuple[str, str]:
154
+ ) -> tuple[str, str]:
155
155
  self.path = os.path.abspath(self.path)
156
156
  self.path_root = self.path.rsplit(self.name, 1)[0]
157
157
 
@@ -173,7 +173,7 @@ class TimeSeriesTunable(Tunable, ABC):
173
173
  pass
174
174
 
175
175
  @abstractmethod
176
- def _get_search_space(self) -> Dict[str, Any]:
176
+ def _get_search_space(self) -> dict[str, Any]:
177
177
  pass
178
178
 
179
179
  @abstractmethod
@@ -185,5 +185,5 @@ class TimeSeriesTunable(Tunable, ABC):
185
185
 
186
186
  @staticmethod
187
187
  @abstractmethod
188
- def _get_system_resources() -> Dict[str, Any]:
188
+ def _get_system_resources() -> dict[str, Any]:
189
189
  pass