autogluon.timeseries 1.4.1b20251115__py3-none-any.whl → 1.4.1b20251218__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.

Potentially problematic release.


This version of autogluon.timeseries might be problematic. Click here for more details.

Files changed (82) hide show
  1. autogluon/timeseries/configs/hyperparameter_presets.py +7 -21
  2. autogluon/timeseries/configs/predictor_presets.py +23 -39
  3. autogluon/timeseries/dataset/ts_dataframe.py +32 -34
  4. autogluon/timeseries/learner.py +67 -33
  5. autogluon/timeseries/metrics/__init__.py +4 -4
  6. autogluon/timeseries/metrics/abstract.py +8 -8
  7. autogluon/timeseries/metrics/point.py +9 -9
  8. autogluon/timeseries/metrics/quantile.py +4 -4
  9. autogluon/timeseries/models/__init__.py +2 -1
  10. autogluon/timeseries/models/abstract/abstract_timeseries_model.py +52 -39
  11. autogluon/timeseries/models/abstract/model_trial.py +2 -1
  12. autogluon/timeseries/models/abstract/tunable.py +8 -8
  13. autogluon/timeseries/models/autogluon_tabular/mlforecast.py +30 -26
  14. autogluon/timeseries/models/autogluon_tabular/per_step.py +12 -10
  15. autogluon/timeseries/models/autogluon_tabular/transforms.py +2 -2
  16. autogluon/timeseries/models/chronos/__init__.py +2 -1
  17. autogluon/timeseries/models/chronos/chronos2.py +395 -0
  18. autogluon/timeseries/models/chronos/model.py +29 -24
  19. autogluon/timeseries/models/chronos/utils.py +5 -5
  20. autogluon/timeseries/models/ensemble/__init__.py +17 -10
  21. autogluon/timeseries/models/ensemble/abstract.py +13 -9
  22. autogluon/timeseries/models/ensemble/array_based/__init__.py +2 -2
  23. autogluon/timeseries/models/ensemble/array_based/abstract.py +24 -31
  24. autogluon/timeseries/models/ensemble/array_based/models.py +146 -11
  25. autogluon/timeseries/models/ensemble/array_based/regressor/__init__.py +2 -0
  26. autogluon/timeseries/models/ensemble/array_based/regressor/abstract.py +6 -5
  27. autogluon/timeseries/models/ensemble/array_based/regressor/linear_stacker.py +186 -0
  28. autogluon/timeseries/models/ensemble/array_based/regressor/per_quantile_tabular.py +44 -83
  29. autogluon/timeseries/models/ensemble/array_based/regressor/tabular.py +21 -55
  30. autogluon/timeseries/models/ensemble/ensemble_selection.py +167 -0
  31. autogluon/timeseries/models/ensemble/per_item_greedy.py +172 -0
  32. autogluon/timeseries/models/ensemble/weighted/abstract.py +7 -3
  33. autogluon/timeseries/models/ensemble/weighted/basic.py +26 -13
  34. autogluon/timeseries/models/ensemble/weighted/greedy.py +20 -145
  35. autogluon/timeseries/models/gluonts/abstract.py +30 -29
  36. autogluon/timeseries/models/gluonts/dataset.py +9 -9
  37. autogluon/timeseries/models/gluonts/models.py +0 -7
  38. autogluon/timeseries/models/local/__init__.py +0 -7
  39. autogluon/timeseries/models/local/abstract_local_model.py +13 -16
  40. autogluon/timeseries/models/local/naive.py +2 -2
  41. autogluon/timeseries/models/local/npts.py +7 -1
  42. autogluon/timeseries/models/local/statsforecast.py +12 -12
  43. autogluon/timeseries/models/multi_window/multi_window_model.py +38 -23
  44. autogluon/timeseries/models/registry.py +3 -4
  45. autogluon/timeseries/models/toto/_internal/backbone/attention.py +3 -4
  46. autogluon/timeseries/models/toto/_internal/backbone/backbone.py +6 -6
  47. autogluon/timeseries/models/toto/_internal/backbone/rope.py +4 -9
  48. autogluon/timeseries/models/toto/_internal/backbone/rotary_embedding_torch.py +342 -0
  49. autogluon/timeseries/models/toto/_internal/backbone/scaler.py +2 -3
  50. autogluon/timeseries/models/toto/_internal/backbone/transformer.py +10 -10
  51. autogluon/timeseries/models/toto/_internal/dataset.py +2 -2
  52. autogluon/timeseries/models/toto/_internal/forecaster.py +8 -8
  53. autogluon/timeseries/models/toto/dataloader.py +4 -4
  54. autogluon/timeseries/models/toto/hf_pretrained_model.py +97 -16
  55. autogluon/timeseries/models/toto/model.py +30 -17
  56. autogluon/timeseries/predictor.py +517 -129
  57. autogluon/timeseries/regressor.py +18 -23
  58. autogluon/timeseries/splitter.py +2 -2
  59. autogluon/timeseries/trainer/ensemble_composer.py +323 -129
  60. autogluon/timeseries/trainer/model_set_builder.py +9 -9
  61. autogluon/timeseries/trainer/prediction_cache.py +16 -16
  62. autogluon/timeseries/trainer/trainer.py +235 -144
  63. autogluon/timeseries/trainer/utils.py +3 -4
  64. autogluon/timeseries/transforms/covariate_scaler.py +7 -7
  65. autogluon/timeseries/transforms/target_scaler.py +8 -8
  66. autogluon/timeseries/utils/constants.py +10 -0
  67. autogluon/timeseries/utils/datetime/lags.py +1 -3
  68. autogluon/timeseries/utils/datetime/seasonality.py +1 -3
  69. autogluon/timeseries/utils/features.py +22 -9
  70. autogluon/timeseries/utils/forecast.py +1 -2
  71. autogluon/timeseries/utils/timer.py +173 -0
  72. autogluon/timeseries/version.py +1 -1
  73. {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/METADATA +23 -21
  74. autogluon_timeseries-1.4.1b20251218.dist-info/RECORD +103 -0
  75. autogluon_timeseries-1.4.1b20251115.dist-info/RECORD +0 -96
  76. /autogluon.timeseries-1.4.1b20251115-py3.9-nspkg.pth → /autogluon.timeseries-1.4.1b20251218-py3.11-nspkg.pth +0 -0
  77. {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/WHEEL +0 -0
  78. {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/licenses/LICENSE +0 -0
  79. {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/licenses/NOTICE +0 -0
  80. {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/namespace_packages.txt +0 -0
  81. {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/top_level.txt +0 -0
  82. {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/zip-safe +0 -0
@@ -1,5 +1,7 @@
1
+ import json
1
2
  import logging
2
- from typing import Optional
3
+ import os
4
+ from pathlib import Path
3
5
 
4
6
  from transformers import PretrainedConfig, PreTrainedModel
5
7
 
@@ -15,8 +17,8 @@ class TotoConfig(PretrainedConfig):
15
17
  embed_dim: int = 768,
16
18
  num_heads: int = 12,
17
19
  num_layers: int = 12,
18
- output_distribution_classes: Optional[list[str]] = None,
19
- output_distribution_kwargs: Optional[dict] = None,
20
+ output_distribution_classes: list[str] | None = None,
21
+ output_distribution_kwargs: dict | None = None,
20
22
  patch_size: int = 64,
21
23
  scale_factor_exponent: float = 10.0,
22
24
  spacewise_every_n_layers: int = 12,
@@ -69,12 +71,10 @@ class TotoPretrainedModel(PreTrainedModel):
69
71
  scale_factor_exponent=config.scale_factor_exponent,
70
72
  **getattr(config, "extra_kwargs", {}),
71
73
  )
72
- self._register_load_state_dict_pre_hook(self._remap_state_dict_keys_hook)
73
74
  self.post_init()
74
75
 
75
- def _remap_state_dict_keys_hook(
76
- self, state_dict, prefix, local_metadata, strict, missing_keys, unexpected_keys, error_msgs
77
- ):
76
+ @staticmethod
77
+ def _remap_state_dict_keys(state_dict):
78
78
  remap = {
79
79
  "mlp.0.w12.weight": "mlp.0.weight",
80
80
  "mlp.0.w12.bias": "mlp.0.bias",
@@ -82,6 +82,7 @@ class TotoPretrainedModel(PreTrainedModel):
82
82
  "mlp.0.w3.bias": "mlp.2.bias",
83
83
  }
84
84
 
85
+ new_state = {}
85
86
  keys_to_remap = []
86
87
  for key in list(state_dict.keys()):
87
88
  for old, new in remap.items():
@@ -90,11 +91,81 @@ class TotoPretrainedModel(PreTrainedModel):
90
91
  keys_to_remap.append((key, new_key))
91
92
  break
92
93
 
94
+ new_state = state_dict.copy()
93
95
  for old_key, new_key in keys_to_remap:
94
- state_dict[new_key] = state_dict.pop(old_key)
96
+ new_state[new_key] = new_state.pop(old_key)
97
+
98
+ return new_state
95
99
 
96
100
  @classmethod
97
- def from_pretrained(cls, model_name_or_path, config=None, torch_dtype=None, device_map=None, **kwargs):
101
+ def load_from_checkpoint(
102
+ cls,
103
+ checkpoint_path,
104
+ device_map: str = "cpu",
105
+ strict=True,
106
+ **model_kwargs,
107
+ ):
108
+ """
109
+ Custom checkpoint loading. Used to load a local
110
+ safetensors checkpoint with an optional config.json file.
111
+ """
112
+ import safetensors.torch as safetorch
113
+
114
+ if os.path.isdir(checkpoint_path):
115
+ safetensors_file = os.path.join(checkpoint_path, "model.safetensors")
116
+ else:
117
+ safetensors_file = checkpoint_path
118
+
119
+ if os.path.exists(safetensors_file):
120
+ model_state = safetorch.load_file(safetensors_file, device=device_map)
121
+ else:
122
+ raise FileNotFoundError(f"Model checkpoint not found at: {safetensors_file}")
123
+
124
+ # Load configuration from config.json if it exists.
125
+ config_file = os.path.join(checkpoint_path, "config.json")
126
+ config = {}
127
+ if os.path.exists(config_file):
128
+ with open(config_file, "r") as f:
129
+ config = json.load(f)
130
+
131
+ # Merge any extra kwargs into the configuration.
132
+ config.update(model_kwargs)
133
+
134
+ remapped_state_dict = cls._remap_state_dict_keys(model_state)
135
+
136
+ instance = cls(**config)
137
+
138
+ # Filter out unexpected keys
139
+ filtered_remapped_state_dict = {
140
+ k: v
141
+ for k, v in remapped_state_dict.items()
142
+ if k in instance.state_dict() and not k.endswith("rotary_emb.freqs")
143
+ }
144
+
145
+ instance.load_state_dict(filtered_remapped_state_dict, strict=strict)
146
+ instance.to(device_map) # type: ignore
147
+
148
+ return instance
149
+
150
+ @classmethod
151
+ def from_pretrained(
152
+ cls,
153
+ *,
154
+ model_id: str,
155
+ revision: str | None = None,
156
+ cache_dir: Path | str | None = None,
157
+ force_download: bool = False,
158
+ proxies: dict | None = None,
159
+ resume_download: bool | None = None,
160
+ local_files_only: bool = False,
161
+ token: str | bool | None = None,
162
+ device_map: str = "cpu",
163
+ strict: bool = False,
164
+ **model_kwargs,
165
+ ):
166
+ """Load Pytorch pretrained weights and return the loaded model."""
167
+ from huggingface_hub import constants, hf_hub_download
168
+
98
169
  transformers_logger = logging.getLogger("transformers.modeling_utils")
99
170
  original_level = transformers_logger.level
100
171
 
@@ -103,13 +174,23 @@ class TotoPretrainedModel(PreTrainedModel):
103
174
  # remapping hook is only called after the initial model loading.
104
175
  transformers_logger.setLevel(logging.ERROR)
105
176
 
106
- # Transformers follows a different load path that does not call load_state_dict hooks when
107
- # loading with explicit device maps. Here, we first load the model with no device maps and
108
- # move it.
109
- model = super().from_pretrained(model_name_or_path, config=config, torch_dtype=torch_dtype, **kwargs)
110
- if device_map is not None:
111
- model = model.to(device_map)
112
-
177
+ if os.path.isdir(model_id):
178
+ print("Loading weights from local directory")
179
+ model_file = os.path.join(model_id, constants.SAFETENSORS_SINGLE_FILE)
180
+ model = cls.load_from_checkpoint(model_file, device_map, strict, **model_kwargs)
181
+ else:
182
+ model_file = hf_hub_download(
183
+ repo_id=model_id,
184
+ filename=constants.SAFETENSORS_SINGLE_FILE,
185
+ revision=revision,
186
+ cache_dir=cache_dir,
187
+ force_download=force_download,
188
+ proxies=proxies,
189
+ resume_download=resume_download,
190
+ token=token,
191
+ local_files_only=local_files_only,
192
+ )
193
+ model = cls.load_from_checkpoint(model_file, device_map, strict, **model_kwargs)
113
194
  finally:
114
195
  transformers_logger.setLevel(original_level)
115
196
 
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  import os
3
- from typing import TYPE_CHECKING, Any, Optional, Sequence, Union
3
+ from typing import TYPE_CHECKING, Any, Sequence
4
4
 
5
5
  import numpy as np
6
6
  import pandas as pd
@@ -61,12 +61,12 @@ class TotoModel(AbstractTimeSeriesModel):
61
61
 
62
62
  def __init__(
63
63
  self,
64
- path: Optional[str] = None,
65
- name: Optional[str] = None,
66
- hyperparameters: Optional[dict[str, Any]] = None,
67
- freq: Optional[str] = None,
64
+ path: str | None = None,
65
+ name: str | None = None,
66
+ hyperparameters: dict[str, Any] | None = None,
67
+ freq: str | None = None,
68
68
  prediction_length: int = 1,
69
- covariate_metadata: Optional[CovariateMetadata] = None,
69
+ covariate_metadata: CovariateMetadata | None = None,
70
70
  target: str = "target",
71
71
  quantile_levels: Sequence[float] = (0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9),
72
72
  eval_metric: Any = None,
@@ -87,9 +87,9 @@ class TotoModel(AbstractTimeSeriesModel):
87
87
  eval_metric=eval_metric,
88
88
  )
89
89
 
90
- self._forecaster: Optional[TotoForecaster] = None
90
+ self._forecaster: TotoForecaster | None = None
91
91
 
92
- def save(self, path: Optional[str] = None, verbose: bool = True) -> str:
92
+ def save(self, path: str | None = None, verbose: bool = True) -> str:
93
93
  forecaster = self._forecaster
94
94
  self._forecaster = None
95
95
  path = super().save(path=path, verbose=verbose)
@@ -110,7 +110,7 @@ class TotoModel(AbstractTimeSeriesModel):
110
110
 
111
111
  return torch.cuda.is_available()
112
112
 
113
- def get_minimum_resources(self, is_gpu_available: bool = False) -> dict[str, Union[int, float]]:
113
+ def get_minimum_resources(self, is_gpu_available: bool = False) -> dict[str, int | float]:
114
114
  return {"num_cpus": 1, "num_gpus": 1}
115
115
 
116
116
  def load_forecaster(self):
@@ -126,7 +126,7 @@ class TotoModel(AbstractTimeSeriesModel):
126
126
 
127
127
  hyperparameters = self.get_hyperparameters()
128
128
  pretrained_model = TotoPretrainedModel.from_pretrained(
129
- self.model_path,
129
+ model_id=self.model_path,
130
130
  config=TotoConfig.from_pretrained(self.model_path),
131
131
  device_map=hyperparameters["device"],
132
132
  )
@@ -147,9 +147,21 @@ class TotoModel(AbstractTimeSeriesModel):
147
147
  "num_samples": 256,
148
148
  "device": "cuda",
149
149
  "context_length": 4096,
150
- "compile_model": True,
150
+ "compile_model": False,
151
151
  }
152
152
 
153
+ def _get_sample_batch_size(self) -> int:
154
+ num_samples = self.get_hyperparameter("num_samples")
155
+ batch_size = num_samples
156
+ while batch_size > 32:
157
+ for factor in range(2, int(batch_size**0.5) + 1):
158
+ if batch_size % factor == 0:
159
+ batch_size //= factor
160
+ break
161
+ else: # batch_size is prime
162
+ return batch_size
163
+ return batch_size
164
+
153
165
  @property
154
166
  def allowed_hyperparameters(self) -> list[str]:
155
167
  return super().allowed_hyperparameters + [
@@ -171,10 +183,10 @@ class TotoModel(AbstractTimeSeriesModel):
171
183
  def _fit(
172
184
  self,
173
185
  train_data: TimeSeriesDataFrame,
174
- val_data: Optional[TimeSeriesDataFrame] = None,
175
- time_limit: Optional[float] = None,
176
- num_cpus: Optional[int] = None,
177
- num_gpus: Optional[int] = None,
186
+ val_data: TimeSeriesDataFrame | None = None,
187
+ time_limit: float | None = None,
188
+ num_cpus: int | None = None,
189
+ num_gpus: int | None = None,
178
190
  verbosity: int = 2,
179
191
  **kwargs,
180
192
  ) -> None:
@@ -182,7 +194,7 @@ class TotoModel(AbstractTimeSeriesModel):
182
194
  self.load_forecaster()
183
195
 
184
196
  def _predict(
185
- self, data: TimeSeriesDataFrame, known_covariates: Optional[TimeSeriesDataFrame] = None, **kwargs
197
+ self, data: TimeSeriesDataFrame, known_covariates: TimeSeriesDataFrame | None = None, **kwargs
186
198
  ) -> TimeSeriesDataFrame:
187
199
  import torch
188
200
 
@@ -198,6 +210,7 @@ class TotoModel(AbstractTimeSeriesModel):
198
210
  dataset = TotoInferenceDataset(
199
211
  target_df=data.fill_missing_values("auto"),
200
212
  max_context_length=hyperparameters["context_length"],
213
+ target_column=self.target,
201
214
  )
202
215
  loader = TotoDataLoader(
203
216
  dataset,
@@ -214,7 +227,7 @@ class TotoModel(AbstractTimeSeriesModel):
214
227
  masked_timeseries,
215
228
  prediction_length=self.prediction_length,
216
229
  num_samples=hyperparameters["num_samples"],
217
- samples_per_batch=32,
230
+ samples_per_batch=self._get_sample_batch_size(),
218
231
  )
219
232
 
220
233
  batch_means.append(forecast.mean.cpu().numpy())