autogluon.timeseries 1.4.1b20250820__py3-none-any.whl → 1.4.1b20250902__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 (52) 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 +9 -9
  5. autogluon/timeseries/learner.py +14 -14
  6. autogluon/timeseries/metrics/__init__.py +5 -5
  7. autogluon/timeseries/metrics/abstract.py +11 -12
  8. autogluon/timeseries/models/__init__.py +2 -0
  9. autogluon/timeseries/models/abstract/abstract_timeseries_model.py +39 -41
  10. autogluon/timeseries/models/abstract/tunable.py +6 -6
  11. autogluon/timeseries/models/autogluon_tabular/mlforecast.py +30 -30
  12. autogluon/timeseries/models/autogluon_tabular/per_step.py +12 -12
  13. autogluon/timeseries/models/chronos/model.py +10 -10
  14. autogluon/timeseries/models/chronos/pipeline/base.py +8 -8
  15. autogluon/timeseries/models/chronos/pipeline/chronos.py +12 -12
  16. autogluon/timeseries/models/chronos/pipeline/chronos_bolt.py +12 -12
  17. autogluon/timeseries/models/chronos/pipeline/utils.py +12 -12
  18. autogluon/timeseries/models/ensemble/abstract.py +19 -19
  19. autogluon/timeseries/models/ensemble/basic.py +8 -8
  20. autogluon/timeseries/models/ensemble/greedy.py +13 -13
  21. autogluon/timeseries/models/gluonts/abstract.py +24 -24
  22. autogluon/timeseries/models/gluonts/dataset.py +2 -2
  23. autogluon/timeseries/models/gluonts/models.py +7 -7
  24. autogluon/timeseries/models/local/abstract_local_model.py +12 -12
  25. autogluon/timeseries/models/local/statsforecast.py +11 -11
  26. autogluon/timeseries/models/multi_window/multi_window_model.py +33 -22
  27. autogluon/timeseries/models/registry.py +3 -3
  28. autogluon/timeseries/predictor.py +37 -37
  29. autogluon/timeseries/regressor.py +13 -13
  30. autogluon/timeseries/splitter.py +6 -6
  31. autogluon/timeseries/trainer/__init__.py +3 -0
  32. autogluon/timeseries/trainer/model_set_builder.py +256 -0
  33. autogluon/timeseries/trainer/prediction_cache.py +149 -0
  34. autogluon/timeseries/{trainer.py → trainer/trainer.py} +72 -128
  35. autogluon/timeseries/transforms/covariate_scaler.py +3 -3
  36. autogluon/timeseries/transforms/target_scaler.py +7 -7
  37. autogluon/timeseries/utils/datetime/lags.py +2 -2
  38. autogluon/timeseries/utils/datetime/time_features.py +2 -2
  39. autogluon/timeseries/utils/features.py +32 -32
  40. autogluon/timeseries/version.py +1 -1
  41. {autogluon.timeseries-1.4.1b20250820.dist-info → autogluon.timeseries-1.4.1b20250902.dist-info}/METADATA +5 -5
  42. autogluon.timeseries-1.4.1b20250902.dist-info/RECORD +75 -0
  43. autogluon/timeseries/configs/presets_configs.py +0 -79
  44. autogluon/timeseries/models/presets.py +0 -280
  45. autogluon.timeseries-1.4.1b20250820.dist-info/RECORD +0 -72
  46. /autogluon.timeseries-1.4.1b20250820-py3.9-nspkg.pth → /autogluon.timeseries-1.4.1b20250902-py3.9-nspkg.pth +0 -0
  47. {autogluon.timeseries-1.4.1b20250820.dist-info → autogluon.timeseries-1.4.1b20250902.dist-info}/LICENSE +0 -0
  48. {autogluon.timeseries-1.4.1b20250820.dist-info → autogluon.timeseries-1.4.1b20250902.dist-info}/NOTICE +0 -0
  49. {autogluon.timeseries-1.4.1b20250820.dist-info → autogluon.timeseries-1.4.1b20250902.dist-info}/WHEEL +0 -0
  50. {autogluon.timeseries-1.4.1b20250820.dist-info → autogluon.timeseries-1.4.1b20250902.dist-info}/namespace_packages.txt +0 -0
  51. {autogluon.timeseries-1.4.1b20250820.dist-info → autogluon.timeseries-1.4.1b20250902.dist-info}/top_level.txt +0 -0
  52. {autogluon.timeseries-1.4.1b20250820.dist-info → autogluon.timeseries-1.4.1b20250902.dist-info}/zip-safe +0 -0
@@ -3,7 +3,7 @@ import os
3
3
  import shutil
4
4
  from datetime import timedelta
5
5
  from pathlib import Path
6
- from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Type, Union, cast, overload
6
+ from typing import TYPE_CHECKING, Any, Callable, Optional, Type, Union, cast, overload
7
7
 
8
8
  import gluonts
9
9
  import gluonts.core.settings
@@ -42,20 +42,20 @@ class AbstractGluonTSModel(AbstractTimeSeriesModel):
42
42
 
43
43
  Parameters
44
44
  ----------
45
- path: str
45
+ path
46
46
  directory to store model artifacts.
47
- freq: str
47
+ freq
48
48
  string representation (compatible with GluonTS frequency strings) for the data provided.
49
49
  For example, "1D" for daily data, "1H" for hourly data, etc.
50
- prediction_length: int
50
+ prediction_length
51
51
  Number of time steps ahead (length of the forecast horizon) the model will be optimized
52
52
  to predict. At inference time, this will be the number of time steps the model will
53
53
  predict.
54
- name: str
54
+ name
55
55
  Name of the model. Also, name of subdirectory inside path where model will be saved.
56
- eval_metric: str
56
+ eval_metric
57
57
  objective function the model intends to optimize, will use WQL by default.
58
- hyperparameters:
58
+ hyperparameters
59
59
  various hyperparameters that will be used by model (can be search spaces instead of
60
60
  fixed values). See *Other Parameters* in each inheriting model's documentation for
61
61
  possible values.
@@ -77,7 +77,7 @@ class AbstractGluonTSModel(AbstractTimeSeriesModel):
77
77
  path: Optional[str] = None,
78
78
  name: Optional[str] = None,
79
79
  eval_metric: Optional[str] = None,
80
- hyperparameters: Optional[Dict[str, Any]] = None,
80
+ hyperparameters: Optional[dict[str, Any]] = None,
81
81
  **kwargs, # noqa
82
82
  ):
83
83
  super().__init__(
@@ -100,9 +100,9 @@ class AbstractGluonTSModel(AbstractTimeSeriesModel):
100
100
  self.num_feat_dynamic_real = 0
101
101
  self.num_past_feat_dynamic_cat = 0
102
102
  self.num_past_feat_dynamic_real = 0
103
- self.feat_static_cat_cardinality: List[int] = []
104
- self.feat_dynamic_cat_cardinality: List[int] = []
105
- self.past_feat_dynamic_cat_cardinality: List[int] = []
103
+ self.feat_static_cat_cardinality: list[int] = []
104
+ self.feat_dynamic_cat_cardinality: list[int] = []
105
+ self.past_feat_dynamic_cat_cardinality: list[int] = []
106
106
  self.negative_data = True
107
107
 
108
108
  def save(self, path: Optional[str] = None, verbose: bool = True) -> str:
@@ -234,7 +234,7 @@ class AbstractGluonTSModel(AbstractTimeSeriesModel):
234
234
 
235
235
  return self._get_default_hyperparameters() | init_args
236
236
 
237
- def _get_estimator_init_args(self) -> Dict[str, Any]:
237
+ def _get_estimator_init_args(self) -> dict[str, Any]:
238
238
  """Get GluonTS specific constructor arguments for estimator objects, an alias to `self.get_hyperparameters`
239
239
  for better readability."""
240
240
  return self.get_hyperparameters()
@@ -277,8 +277,8 @@ class AbstractGluonTSModel(AbstractTimeSeriesModel):
277
277
 
278
278
  return torch.cuda.is_available()
279
279
 
280
- def get_minimum_resources(self, is_gpu_available: bool = False) -> Dict[str, Union[int, float]]:
281
- minimum_resources: Dict[str, Union[int, float]] = {"num_cpus": 1}
280
+ def get_minimum_resources(self, is_gpu_available: bool = False) -> dict[str, Union[int, float]]:
281
+ minimum_resources: dict[str, Union[int, float]] = {"num_cpus": 1}
282
282
  # if GPU is available, we train with 1 GPU per trial
283
283
  if is_gpu_available:
284
284
  minimum_resources["num_gpus"] = 1
@@ -440,7 +440,7 @@ class AbstractGluonTSModel(AbstractTimeSeriesModel):
440
440
  self,
441
441
  time_limit: Optional[float],
442
442
  early_stopping_patience: Optional[int] = None,
443
- ) -> List[Callable]:
443
+ ) -> list[Callable]:
444
444
  """Retrieve a list of callback objects for the GluonTS trainer"""
445
445
  from lightning.pytorch.callbacks import EarlyStopping, Timer
446
446
 
@@ -473,7 +473,7 @@ class AbstractGluonTSModel(AbstractTimeSeriesModel):
473
473
  data: TimeSeriesDataFrame,
474
474
  known_covariates: Optional[TimeSeriesDataFrame] = None,
475
475
  num_samples: Optional[int] = None,
476
- ) -> List[Forecast]:
476
+ ) -> list[Forecast]:
477
477
  assert self.gts_predictor is not None, "GluonTS models must be fit before predicting."
478
478
  gts_data = self._to_gluonts_dataset(data, known_covariates=known_covariates)
479
479
  return list(
@@ -483,7 +483,7 @@ class AbstractGluonTSModel(AbstractTimeSeriesModel):
483
483
  )
484
484
  )
485
485
 
486
- def _stack_quantile_forecasts(self, forecasts: List[QuantileForecast], item_ids: pd.Index) -> pd.DataFrame:
486
+ def _stack_quantile_forecasts(self, forecasts: list[QuantileForecast], item_ids: pd.Index) -> pd.DataFrame:
487
487
  # GluonTS always saves item_id as a string
488
488
  item_id_to_forecast = {str(f.item_id): f for f in forecasts}
489
489
  result_dfs = []
@@ -496,7 +496,7 @@ class AbstractGluonTSModel(AbstractTimeSeriesModel):
496
496
  columns_order = ["mean"] + [str(q) for q in self.quantile_levels]
497
497
  return forecast_df[columns_order]
498
498
 
499
- def _stack_sample_forecasts(self, forecasts: List[SampleForecast], item_ids: pd.Index) -> pd.DataFrame:
499
+ def _stack_sample_forecasts(self, forecasts: list[SampleForecast], item_ids: pd.Index) -> pd.DataFrame:
500
500
  item_id_to_forecast = {str(f.item_id): f for f in forecasts}
501
501
  samples_per_item = []
502
502
  for item_id in item_ids:
@@ -509,7 +509,7 @@ class AbstractGluonTSModel(AbstractTimeSeriesModel):
509
509
  return pd.DataFrame(forecast_array, columns=["mean"] + [str(q) for q in self.quantile_levels])
510
510
 
511
511
  def _stack_distribution_forecasts(
512
- self, forecasts: List["DistributionForecast"], item_ids: pd.Index
512
+ self, forecasts: list["DistributionForecast"], item_ids: pd.Index
513
513
  ) -> pd.DataFrame:
514
514
  import torch
515
515
  from gluonts.torch.distributions import AffineTransformed
@@ -523,7 +523,7 @@ class AbstractGluonTSModel(AbstractTimeSeriesModel):
523
523
  "Expected forecast.distribution to be an instance of AffineTransformed"
524
524
  )
525
525
 
526
- def stack_distributions(distributions: List[Distribution]) -> Distribution:
526
+ def stack_distributions(distributions: list[Distribution]) -> Distribution:
527
527
  """Stack multiple torch.Distribution objects into a single distribution"""
528
528
  last_dist: Distribution = distributions[-1]
529
529
 
@@ -561,18 +561,18 @@ class AbstractGluonTSModel(AbstractTimeSeriesModel):
561
561
 
562
562
  def _gluonts_forecasts_to_data_frame(
563
563
  self,
564
- forecasts: List[Forecast],
564
+ forecasts: list[Forecast],
565
565
  forecast_index: pd.MultiIndex,
566
566
  ) -> TimeSeriesDataFrame:
567
567
  from gluonts.torch.model.forecast import DistributionForecast
568
568
 
569
569
  item_ids = forecast_index.unique(level=ITEMID)
570
570
  if isinstance(forecasts[0], SampleForecast):
571
- forecast_df = self._stack_sample_forecasts(cast(List[SampleForecast], forecasts), item_ids)
571
+ forecast_df = self._stack_sample_forecasts(cast(list[SampleForecast], forecasts), item_ids)
572
572
  elif isinstance(forecasts[0], QuantileForecast):
573
- forecast_df = self._stack_quantile_forecasts(cast(List[QuantileForecast], forecasts), item_ids)
573
+ forecast_df = self._stack_quantile_forecasts(cast(list[QuantileForecast], forecasts), item_ids)
574
574
  elif isinstance(forecasts[0], DistributionForecast):
575
- forecast_df = self._stack_distribution_forecasts(cast(List[DistributionForecast], forecasts), item_ids)
575
+ forecast_df = self._stack_distribution_forecasts(cast(list[DistributionForecast], forecasts), item_ids)
576
576
  else:
577
577
  raise ValueError(f"Unrecognized forecast type {type(forecasts[0])}")
578
578
 
@@ -1,4 +1,4 @@
1
- from typing import Any, Dict, Iterator, Optional, Type
1
+ from typing import Any, Iterator, Optional, Type
2
2
 
3
3
  import numpy as np
4
4
  import pandas as pd
@@ -76,7 +76,7 @@ class SimpleGluonTSDataset(GluonTSDataset):
76
76
  def __len__(self):
77
77
  return len(self.indptr) - 1 # noqa
78
78
 
79
- def __iter__(self) -> Iterator[Dict[str, Any]]:
79
+ def __iter__(self) -> Iterator[dict[str, Any]]:
80
80
  for j in range(len(self.indptr) - 1):
81
81
  start_idx = self.indptr[j]
82
82
  end_idx = self.indptr[j + 1]
@@ -3,7 +3,7 @@ Module including wrappers for PyTorch implementations of models in GluonTS
3
3
  """
4
4
 
5
5
  import logging
6
- from typing import Any, Dict, Type
6
+ from typing import Any, Type
7
7
 
8
8
  from gluonts.model.estimator import Estimator as GluonTSEstimator
9
9
 
@@ -91,7 +91,7 @@ class DeepARModel(AbstractGluonTSModel):
91
91
 
92
92
  return DeepAREstimator
93
93
 
94
- def _get_estimator_init_args(self) -> Dict[str, Any]:
94
+ def _get_estimator_init_args(self) -> dict[str, Any]:
95
95
  init_kwargs = super()._get_estimator_init_args()
96
96
  init_kwargs["num_feat_static_cat"] = self.num_feat_static_cat
97
97
  init_kwargs["num_feat_static_real"] = self.num_feat_static_real
@@ -113,7 +113,7 @@ class SimpleFeedForwardModel(AbstractGluonTSModel):
113
113
  ----------------
114
114
  context_length : int, default = max(10, 2 * prediction_length)
115
115
  Number of time units that condition the predictions
116
- hidden_dimensions: List[int], default = [20, 20]
116
+ hidden_dimensions: list[int], default = [20, 20]
117
117
  Size of hidden layers in the feedforward network
118
118
  distr_output : gluonts.torch.distributions.Output, default = StudentTOutput()
119
119
  Distribution output object that defines how the model output is converted to a forecast, and how the loss is computed.
@@ -221,7 +221,7 @@ class TemporalFusionTransformerModel(AbstractGluonTSModel):
221
221
  "context_length": min(512, max(64, 2 * self.prediction_length)),
222
222
  }
223
223
 
224
- def _get_estimator_init_args(self) -> Dict[str, Any]:
224
+ def _get_estimator_init_args(self) -> dict[str, Any]:
225
225
  init_kwargs = super()._get_estimator_init_args()
226
226
  if self.num_feat_dynamic_real > 0:
227
227
  init_kwargs["dynamic_dims"] = [self.num_feat_dynamic_real]
@@ -361,7 +361,7 @@ class PatchTSTModel(AbstractGluonTSModel):
361
361
  def _get_default_hyperparameters(self):
362
362
  return super()._get_default_hyperparameters() | {"context_length": 96, "patch_len": 16}
363
363
 
364
- def _get_estimator_init_args(self) -> Dict[str, Any]:
364
+ def _get_estimator_init_args(self) -> dict[str, Any]:
365
365
  init_kwargs = super()._get_estimator_init_args()
366
366
  init_kwargs["num_feat_dynamic_real"] = self.num_feat_dynamic_real
367
367
  return init_kwargs
@@ -438,7 +438,7 @@ class WaveNetModel(AbstractGluonTSModel):
438
438
 
439
439
  return WaveNetEstimator
440
440
 
441
- def _get_estimator_init_args(self) -> Dict[str, Any]:
441
+ def _get_estimator_init_args(self) -> dict[str, Any]:
442
442
  init_kwargs = super()._get_estimator_init_args()
443
443
  init_kwargs["num_feat_static_cat"] = self.num_feat_static_cat
444
444
  init_kwargs["num_feat_static_real"] = self.num_feat_static_real
@@ -547,7 +547,7 @@ class TiDEModel(AbstractGluonTSModel):
547
547
  "batch_size": 256,
548
548
  }
549
549
 
550
- def _get_estimator_init_args(self) -> Dict[str, Any]:
550
+ def _get_estimator_init_args(self) -> dict[str, Any]:
551
551
  init_kwargs = super()._get_estimator_init_args()
552
552
  init_kwargs["num_feat_static_cat"] = self.num_feat_static_cat
553
553
  init_kwargs["num_feat_static_real"] = self.num_feat_static_real
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  import time
3
3
  from multiprocessing import TimeoutError
4
- from typing import Any, Callable, Dict, List, Optional, Tuple, Union
4
+ from typing import Any, Callable, Optional, Union
5
5
 
6
6
  import numpy as np
7
7
  import pandas as pd
@@ -29,17 +29,17 @@ class AbstractLocalModel(AbstractTimeSeriesModel):
29
29
 
30
30
  Attributes
31
31
  ----------
32
- allowed_local_model_args : List[str]
32
+ allowed_local_model_args
33
33
  Argument that can be passed to the underlying local model.
34
- default_max_ts_length : Optional[int]
34
+ default_max_ts_length
35
35
  If not None, only the last ``max_ts_length`` time steps of each time series will be used to train the model.
36
36
  This significantly speeds up fitting and usually leads to no change in accuracy.
37
- init_time_in_seconds : int
37
+ init_time_in_seconds
38
38
  Time that it takes to initialize the model in seconds (e.g., because of JIT compilation by Numba).
39
39
  If time_limit is below this number, model won't be trained.
40
40
  """
41
41
 
42
- allowed_local_model_args: List[str] = []
42
+ allowed_local_model_args: list[str] = []
43
43
  default_max_ts_length: Optional[int] = 2500
44
44
  default_max_time_limit_ratio = 1.0
45
45
  init_time_in_seconds: int = 0
@@ -51,7 +51,7 @@ class AbstractLocalModel(AbstractTimeSeriesModel):
51
51
  path: Optional[str] = None,
52
52
  name: Optional[str] = None,
53
53
  eval_metric: Union[str, TimeSeriesScorer, None] = None,
54
- hyperparameters: Optional[Dict[str, Any]] = None,
54
+ hyperparameters: Optional[dict[str, Any]] = None,
55
55
  **kwargs, # noqa
56
56
  ):
57
57
  super().__init__(
@@ -64,12 +64,12 @@ class AbstractLocalModel(AbstractTimeSeriesModel):
64
64
  **kwargs,
65
65
  )
66
66
 
67
- self._local_model_args: Dict[str, Any]
67
+ self._local_model_args: dict[str, Any]
68
68
  self._seasonal_period: int
69
69
  self._dummy_forecast: pd.DataFrame
70
70
 
71
71
  @property
72
- def allowed_hyperparameters(self) -> List[str]:
72
+ def allowed_hyperparameters(self) -> list[str]:
73
73
  return (
74
74
  super().allowed_hyperparameters
75
75
  + ["use_fallback_model", "max_ts_length", "n_jobs"]
@@ -82,7 +82,7 @@ class AbstractLocalModel(AbstractTimeSeriesModel):
82
82
  known_covariates: Optional[TimeSeriesDataFrame] = None,
83
83
  is_train: bool = False,
84
84
  **kwargs,
85
- ) -> Tuple[TimeSeriesDataFrame, Optional[TimeSeriesDataFrame]]:
85
+ ) -> tuple[TimeSeriesDataFrame, Optional[TimeSeriesDataFrame]]:
86
86
  if not self._get_tags()["allow_nan"]:
87
87
  data = data.fill_missing_values()
88
88
  return data, known_covariates
@@ -134,7 +134,7 @@ class AbstractLocalModel(AbstractTimeSeriesModel):
134
134
  stats_repeated = np.tile(stats_marginal.values, [self.prediction_length, 1])
135
135
  return pd.DataFrame(stats_repeated, columns=stats_marginal.index)
136
136
 
137
- def _update_local_model_args(self, local_model_args: Dict[str, Any]) -> Dict[str, Any]:
137
+ def _update_local_model_args(self, local_model_args: dict[str, Any]) -> dict[str, Any]:
138
138
  return local_model_args
139
139
 
140
140
  def _predict(self, data: TimeSeriesDataFrame, **kwargs) -> TimeSeriesDataFrame:
@@ -185,7 +185,7 @@ class AbstractLocalModel(AbstractTimeSeriesModel):
185
185
  time_series: pd.Series,
186
186
  use_fallback_model: bool,
187
187
  end_time: Optional[float] = None,
188
- ) -> Tuple[pd.DataFrame, bool]:
188
+ ) -> tuple[pd.DataFrame, bool]:
189
189
  if end_time is not None and time.time() >= end_time:
190
190
  raise TimeLimitExceeded
191
191
 
@@ -222,7 +222,7 @@ class AbstractLocalModel(AbstractTimeSeriesModel):
222
222
 
223
223
 
224
224
  def seasonal_naive_forecast(
225
- target: np.ndarray, prediction_length: int, quantile_levels: List[float], seasonal_period: int
225
+ target: np.ndarray, prediction_length: int, quantile_levels: list[float], seasonal_period: int
226
226
  ) -> pd.DataFrame:
227
227
  """Generate seasonal naive forecast, predicting the last observed value from the same period."""
228
228
 
@@ -1,5 +1,5 @@
1
1
  import logging
2
- from typing import Any, Dict, Optional, Type
2
+ from typing import Any, Optional, Type
3
3
 
4
4
  import numpy as np
5
5
  import pandas as pd
@@ -14,7 +14,7 @@ class AbstractStatsForecastModel(AbstractLocalModel):
14
14
 
15
15
  init_time_in_seconds = 15 # numba compilation for the first run
16
16
 
17
- def _update_local_model_args(self, local_model_args: Dict[str, Any]) -> Dict[str, Any]:
17
+ def _update_local_model_args(self, local_model_args: dict[str, Any]) -> dict[str, Any]:
18
18
  seasonal_period = local_model_args.pop("seasonal_period")
19
19
  local_model_args["season_length"] = seasonal_period
20
20
  return local_model_args
@@ -22,7 +22,7 @@ class AbstractStatsForecastModel(AbstractLocalModel):
22
22
  def _get_model_type(self, variant: Optional[str] = None) -> Type:
23
23
  raise NotImplementedError
24
24
 
25
- def _get_local_model(self, local_model_args: Dict):
25
+ def _get_local_model(self, local_model_args: dict):
26
26
  local_model_args = local_model_args.copy()
27
27
  variant = local_model_args.pop("variant", None)
28
28
  model_type = self._get_model_type(variant)
@@ -31,7 +31,7 @@ class AbstractStatsForecastModel(AbstractLocalModel):
31
31
  def _get_point_forecast(
32
32
  self,
33
33
  time_series: pd.Series,
34
- local_model_args: Dict,
34
+ local_model_args: dict,
35
35
  ) -> np.ndarray:
36
36
  return self._get_local_model(local_model_args).forecast(
37
37
  h=self.prediction_length, y=time_series.values.ravel()
@@ -176,9 +176,9 @@ class ARIMAModel(AbstractProbabilisticStatsForecastModel):
176
176
 
177
177
  Other Parameters
178
178
  ----------------
179
- order: Tuple[int, int, int], default = (1, 1, 1)
179
+ order: tuple[int, int, int], default = (1, 1, 1)
180
180
  The (p, d, q) order of the model for the number of AR parameters, differences, and MA parameters to use.
181
- seasonal_order: Tuple[int, int, int], default = (0, 0, 0)
181
+ seasonal_order: tuple[int, int, int], default = (0, 0, 0)
182
182
  The (P, D, Q) parameters of the seasonal ARIMA model. Setting to (0, 0, 0) disables seasonality.
183
183
  include_mean : bool, default = True
184
184
  Should the ARIMA model include a mean term?
@@ -194,7 +194,7 @@ class ARIMAModel(AbstractProbabilisticStatsForecastModel):
194
194
  method : {"CSS-ML", "CSS", "ML"}, default = "CSS-ML"
195
195
  Fitting method: CSS (conditional sum of squares), ML (maximum likelihood), CSS-ML (initialize with CSS, then
196
196
  optimize with ML).
197
- fixed : Dict[str, float], optional
197
+ fixed : dict[str, float], optional
198
198
  Dictionary containing fixed coefficients for the ARIMA model.
199
199
  seasonal_period : int or None, default = None
200
200
  Number of time steps in a complete seasonal cycle for seasonal models. For example, 7 for daily data with a
@@ -449,7 +449,7 @@ class AbstractConformalizedStatsForecastModel(AbstractStatsForecastModel):
449
449
  def _get_nonconformity_scores(
450
450
  self,
451
451
  time_series: pd.Series,
452
- local_model_args: Dict,
452
+ local_model_args: dict,
453
453
  ) -> np.ndarray:
454
454
  h = self.prediction_length
455
455
  y = time_series.values.ravel()
@@ -556,7 +556,7 @@ class AutoCESModel(AbstractProbabilisticStatsForecastModel):
556
556
  local_model_args.setdefault("model", "Z")
557
557
  return local_model_args
558
558
 
559
- def _get_point_forecast(self, time_series: pd.Series, local_model_args: Dict):
559
+ def _get_point_forecast(self, time_series: pd.Series, local_model_args: dict):
560
560
  # Disable seasonality if time series too short for chosen season_length or season_length == 1,
561
561
  # otherwise model will crash
562
562
  if len(time_series) < 5:
@@ -568,7 +568,7 @@ class AutoCESModel(AbstractProbabilisticStatsForecastModel):
568
568
 
569
569
 
570
570
  class AbstractStatsForecastIntermittentDemandModel(AbstractConformalizedStatsForecastModel):
571
- def _update_local_model_args(self, local_model_args: Dict[str, Any]) -> Dict[str, Any]:
571
+ def _update_local_model_args(self, local_model_args: dict[str, Any]) -> dict[str, Any]:
572
572
  _ = local_model_args.pop("seasonal_period")
573
573
  return local_model_args
574
574
 
@@ -733,6 +733,6 @@ class ZeroModel(AbstractStatsForecastIntermittentDemandModel):
733
733
  def _get_point_forecast(
734
734
  self,
735
735
  time_series: pd.Series,
736
- local_model_args: Dict,
736
+ local_model_args: dict,
737
737
  ):
738
738
  return np.zeros(self.prediction_length)
@@ -4,9 +4,10 @@ import logging
4
4
  import math
5
5
  import os
6
6
  import time
7
- from typing import Any, Dict, Optional, Type, Union
7
+ from typing import Any, Optional, Type, Union
8
8
 
9
9
  import numpy as np
10
+ from typing_extensions import Self
10
11
 
11
12
  import autogluon.core as ag
12
13
  from autogluon.timeseries.dataset.ts_dataframe import TimeSeriesDataFrame
@@ -25,10 +26,10 @@ class MultiWindowBacktestingModel(AbstractTimeSeriesModel):
25
26
 
26
27
  Parameters
27
28
  ----------
28
- model_base : Union[AbstractTimeSeriesModel, Type[AbstractTimeSeriesModel]]
29
+ model_base
29
30
  The base model to repeatedly train. If a AbstractTimeSeriesModel class, then also provide model_base_kwargs
30
31
  which will be used to initialize the model via model_base(**model_base_kwargs).
31
- model_base_kwargs : Optional[Dict[str, any]], default = None
32
+ model_base_kwargs
32
33
  kwargs used to initialize model_base if model_base is a class.
33
34
  """
34
35
 
@@ -38,7 +39,7 @@ class MultiWindowBacktestingModel(AbstractTimeSeriesModel):
38
39
  def __init__(
39
40
  self,
40
41
  model_base: Union[AbstractTimeSeriesModel, Type[AbstractTimeSeriesModel]],
41
- model_base_kwargs: Optional[Dict[str, Any]] = None,
42
+ model_base_kwargs: Optional[dict[str, Any]] = None,
42
43
  **kwargs,
43
44
  ):
44
45
  if inspect.isclass(model_base) and issubclass(model_base, AbstractTimeSeriesModel):
@@ -73,10 +74,6 @@ class MultiWindowBacktestingModel(AbstractTimeSeriesModel):
73
74
  def supports_past_covariates(self) -> bool:
74
75
  return self.model_base.supports_past_covariates
75
76
 
76
- @property
77
- def supports_cat_covariates(self) -> bool:
78
- return self.model_base.supports_cat_covariates
79
-
80
77
  def _get_model_base(self):
81
78
  return self.model_base
82
79
 
@@ -86,15 +83,18 @@ class MultiWindowBacktestingModel(AbstractTimeSeriesModel):
86
83
  def _is_gpu_available(self) -> bool:
87
84
  return self._get_model_base()._is_gpu_available()
88
85
 
89
- def get_minimum_resources(self, is_gpu_available: bool = False) -> bool:
86
+ def get_minimum_resources(self, is_gpu_available: bool = False) -> dict[str, Union[int, float]]:
90
87
  return self._get_model_base().get_minimum_resources(is_gpu_available)
91
88
 
92
89
  def _fit(
93
90
  self,
94
91
  train_data: TimeSeriesDataFrame,
95
92
  val_data: Optional[TimeSeriesDataFrame] = None,
96
- time_limit: Optional[int] = None,
97
- val_splitter: AbstractWindowSplitter = None,
93
+ time_limit: Optional[float] = None,
94
+ num_cpus: Optional[int] = None,
95
+ num_gpus: Optional[int] = None,
96
+ verbosity: int = 2,
97
+ val_splitter: Optional[AbstractWindowSplitter] = None,
98
98
  refit_every_n_windows: Optional[int] = 1,
99
99
  **kwargs,
100
100
  ):
@@ -111,11 +111,15 @@ class MultiWindowBacktestingModel(AbstractTimeSeriesModel):
111
111
 
112
112
  oof_predictions_per_window = []
113
113
  global_fit_start_time = time.time()
114
+ model: Optional[AbstractTimeSeriesModel] = None
114
115
 
115
116
  for window_index, (train_fold, val_fold) in enumerate(val_splitter.split(train_data)):
116
117
  logger.debug(f"\tWindow {window_index}")
118
+
117
119
  # refit_this_window is always True for the 0th window
118
120
  refit_this_window = window_index % refit_every_n_windows == 0
121
+ assert window_index != 0 or refit_this_window
122
+
119
123
  if time_limit is None:
120
124
  time_left_for_window = None
121
125
  else:
@@ -148,6 +152,7 @@ class MultiWindowBacktestingModel(AbstractTimeSeriesModel):
148
152
  else:
149
153
  time_left_for_prediction = time_limit - (time.time() - global_fit_start_time)
150
154
 
155
+ assert model is not None
151
156
  model.score_and_cache_oof(
152
157
  val_fold, store_val_score=True, store_predict_time=True, time_limit=time_left_for_prediction
153
158
  )
@@ -172,11 +177,13 @@ class MultiWindowBacktestingModel(AbstractTimeSeriesModel):
172
177
 
173
178
  # Only the model trained on most recent data is saved & used for prediction
174
179
  self.most_recent_model = model
175
- self.most_recent_model_folder = most_recent_refit_window
180
+ assert self.most_recent_model is not None
181
+
182
+ self.most_recent_model_folder = most_recent_refit_window # type: ignore
176
183
  self.predict_time = self.most_recent_model.predict_time
177
- self.fit_time = time.time() - global_fit_start_time - self.predict_time
184
+ self.fit_time = time.time() - global_fit_start_time - self.predict_time # type: ignore
178
185
  self._oof_predictions = oof_predictions_per_window
179
- self.val_score = np.mean([info["val_score"] for info in self.info_per_val_window])
186
+ self.val_score = np.mean([info["val_score"] for info in self.info_per_val_window]) # type: ignore
180
187
 
181
188
  def get_info(self) -> dict:
182
189
  info = super().get_info()
@@ -227,7 +234,7 @@ class MultiWindowBacktestingModel(AbstractTimeSeriesModel):
227
234
  train_fn_kwargs["init_params"]["model_base_kwargs"] = self.get_params()
228
235
  return train_fn_kwargs
229
236
 
230
- def save(self, path: str = None, verbose=True) -> str:
237
+ def save(self, path: Optional[str] = None, verbose: bool = True) -> str:
231
238
  most_recent_model = self.most_recent_model
232
239
  self.most_recent_model = None
233
240
  save_path = super().save(path, verbose)
@@ -238,32 +245,36 @@ class MultiWindowBacktestingModel(AbstractTimeSeriesModel):
238
245
  most_recent_model.save()
239
246
  return save_path
240
247
 
241
- def persist(self):
248
+ def persist(self) -> Self:
242
249
  if self.most_recent_model is None:
243
250
  raise ValueError(f"{self.name} must be fit before persisting")
244
251
  self.most_recent_model.persist()
252
+ return self
245
253
 
246
254
  @classmethod
247
255
  def load(
248
256
  cls, path: str, reset_paths: bool = True, load_oof: bool = False, verbose: bool = True
249
257
  ) -> AbstractTimeSeriesModel:
250
258
  model = super().load(path=path, reset_paths=reset_paths, load_oof=load_oof, verbose=verbose)
251
- most_recent_model_path = os.path.join(model.path, model.most_recent_model_folder)
252
- model.most_recent_model = model.model_base_type.load(
253
- most_recent_model_path,
254
- reset_paths=reset_paths,
255
- verbose=verbose,
256
- )
259
+ if model.most_recent_model_folder is not None:
260
+ most_recent_model_path = os.path.join(model.path, model.most_recent_model_folder)
261
+ model.most_recent_model = model.model_base_type.load(
262
+ most_recent_model_path,
263
+ reset_paths=reset_paths,
264
+ verbose=verbose,
265
+ )
257
266
  return model
258
267
 
259
268
  def convert_to_refit_full_template(self) -> AbstractTimeSeriesModel:
260
269
  # refit_model is an instance of base model type, not MultiWindowBacktestingModel
270
+ assert self.most_recent_model is not None, "Most recent model is None. Model must be fit first."
261
271
  refit_model = self.most_recent_model.convert_to_refit_full_template()
262
272
  refit_model.rename(self.name + ag.constants.REFIT_FULL_SUFFIX)
263
273
  return refit_model
264
274
 
265
275
  def convert_to_refit_full_via_copy(self) -> AbstractTimeSeriesModel:
266
276
  # refit_model is an instance of base model type, not MultiWindowBacktestingModel
277
+ assert self.most_recent_model is not None, "Most recent model is None. Model must be fit first."
267
278
  refit_model = self.most_recent_model.convert_to_refit_full_via_copy()
268
279
  refit_model.rename(self.name + ag.constants.REFIT_FULL_SUFFIX)
269
280
  return refit_model
@@ -1,7 +1,7 @@
1
1
  from abc import ABCMeta
2
2
  from dataclasses import dataclass
3
3
  from inspect import isabstract
4
- from typing import Dict, List, Union
4
+ from typing import Union
5
5
 
6
6
 
7
7
  @dataclass
@@ -18,7 +18,7 @@ class ModelRegistry(ABCMeta):
18
18
  See, https://github.com/faif/python-patterns.
19
19
  """
20
20
 
21
- REGISTRY: Dict[str, ModelRecord] = {}
21
+ REGISTRY: dict[str, ModelRecord] = {}
22
22
 
23
23
  def __new__(cls, name, bases, attrs):
24
24
  new_cls = super().__new__(cls, name, bases, attrs)
@@ -61,5 +61,5 @@ class ModelRegistry(ABCMeta):
61
61
  return cls._get_model_record(alias).ag_priority
62
62
 
63
63
  @classmethod
64
- def available_aliases(cls) -> List[str]:
64
+ def available_aliases(cls) -> list[str]:
65
65
  return sorted(cls.REGISTRY.keys())