autogluon.timeseries 1.4.1b20251016__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 (90) 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 +97 -86
  4. autogluon/timeseries/learner.py +70 -35
  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 +5 -5
  9. autogluon/timeseries/metrics/utils.py +4 -4
  10. autogluon/timeseries/models/__init__.py +2 -1
  11. autogluon/timeseries/models/abstract/abstract_timeseries_model.py +52 -39
  12. autogluon/timeseries/models/abstract/model_trial.py +2 -1
  13. autogluon/timeseries/models/abstract/tunable.py +8 -8
  14. autogluon/timeseries/models/autogluon_tabular/mlforecast.py +58 -62
  15. autogluon/timeseries/models/autogluon_tabular/per_step.py +26 -15
  16. autogluon/timeseries/models/autogluon_tabular/transforms.py +11 -9
  17. autogluon/timeseries/models/chronos/__init__.py +2 -1
  18. autogluon/timeseries/models/chronos/chronos2.py +395 -0
  19. autogluon/timeseries/models/chronos/model.py +126 -88
  20. autogluon/timeseries/models/chronos/{pipeline/utils.py → utils.py} +69 -37
  21. autogluon/timeseries/models/ensemble/__init__.py +36 -2
  22. autogluon/timeseries/models/ensemble/abstract.py +14 -46
  23. autogluon/timeseries/models/ensemble/array_based/__init__.py +3 -0
  24. autogluon/timeseries/models/ensemble/array_based/abstract.py +240 -0
  25. autogluon/timeseries/models/ensemble/array_based/models.py +185 -0
  26. autogluon/timeseries/models/ensemble/array_based/regressor/__init__.py +12 -0
  27. autogluon/timeseries/models/ensemble/array_based/regressor/abstract.py +88 -0
  28. autogluon/timeseries/models/ensemble/array_based/regressor/linear_stacker.py +186 -0
  29. autogluon/timeseries/models/ensemble/array_based/regressor/per_quantile_tabular.py +94 -0
  30. autogluon/timeseries/models/ensemble/array_based/regressor/tabular.py +107 -0
  31. autogluon/timeseries/models/ensemble/{greedy.py → ensemble_selection.py} +41 -61
  32. autogluon/timeseries/models/ensemble/per_item_greedy.py +172 -0
  33. autogluon/timeseries/models/ensemble/weighted/__init__.py +8 -0
  34. autogluon/timeseries/models/ensemble/weighted/abstract.py +45 -0
  35. autogluon/timeseries/models/ensemble/{basic.py → weighted/basic.py} +25 -22
  36. autogluon/timeseries/models/ensemble/weighted/greedy.py +62 -0
  37. autogluon/timeseries/models/gluonts/abstract.py +32 -31
  38. autogluon/timeseries/models/gluonts/dataset.py +11 -11
  39. autogluon/timeseries/models/gluonts/models.py +0 -7
  40. autogluon/timeseries/models/local/__init__.py +0 -7
  41. autogluon/timeseries/models/local/abstract_local_model.py +15 -18
  42. autogluon/timeseries/models/local/naive.py +2 -2
  43. autogluon/timeseries/models/local/npts.py +7 -1
  44. autogluon/timeseries/models/local/statsforecast.py +12 -12
  45. autogluon/timeseries/models/multi_window/multi_window_model.py +39 -24
  46. autogluon/timeseries/models/registry.py +3 -4
  47. autogluon/timeseries/models/toto/_internal/backbone/attention.py +3 -4
  48. autogluon/timeseries/models/toto/_internal/backbone/backbone.py +6 -6
  49. autogluon/timeseries/models/toto/_internal/backbone/rope.py +4 -9
  50. autogluon/timeseries/models/toto/_internal/backbone/rotary_embedding_torch.py +342 -0
  51. autogluon/timeseries/models/toto/_internal/backbone/scaler.py +2 -3
  52. autogluon/timeseries/models/toto/_internal/backbone/transformer.py +10 -10
  53. autogluon/timeseries/models/toto/_internal/dataset.py +2 -2
  54. autogluon/timeseries/models/toto/_internal/forecaster.py +8 -8
  55. autogluon/timeseries/models/toto/dataloader.py +4 -4
  56. autogluon/timeseries/models/toto/hf_pretrained_model.py +97 -16
  57. autogluon/timeseries/models/toto/model.py +35 -20
  58. autogluon/timeseries/predictor.py +527 -155
  59. autogluon/timeseries/regressor.py +27 -30
  60. autogluon/timeseries/splitter.py +3 -27
  61. autogluon/timeseries/trainer/ensemble_composer.py +444 -0
  62. autogluon/timeseries/trainer/model_set_builder.py +9 -9
  63. autogluon/timeseries/trainer/prediction_cache.py +16 -16
  64. autogluon/timeseries/trainer/trainer.py +300 -278
  65. autogluon/timeseries/trainer/utils.py +17 -0
  66. autogluon/timeseries/transforms/covariate_scaler.py +8 -8
  67. autogluon/timeseries/transforms/target_scaler.py +15 -15
  68. autogluon/timeseries/utils/constants.py +10 -0
  69. autogluon/timeseries/utils/datetime/lags.py +1 -3
  70. autogluon/timeseries/utils/datetime/seasonality.py +1 -3
  71. autogluon/timeseries/utils/features.py +31 -14
  72. autogluon/timeseries/utils/forecast.py +6 -7
  73. autogluon/timeseries/utils/timer.py +173 -0
  74. autogluon/timeseries/version.py +1 -1
  75. autogluon.timeseries-1.4.1b20251218-py3.11-nspkg.pth +1 -0
  76. {autogluon.timeseries-1.4.1b20251016.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/METADATA +39 -27
  77. autogluon_timeseries-1.4.1b20251218.dist-info/RECORD +103 -0
  78. {autogluon.timeseries-1.4.1b20251016.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/WHEEL +1 -1
  79. autogluon/timeseries/evaluator.py +0 -6
  80. autogluon/timeseries/models/chronos/pipeline/__init__.py +0 -10
  81. autogluon/timeseries/models/chronos/pipeline/base.py +0 -160
  82. autogluon/timeseries/models/chronos/pipeline/chronos.py +0 -544
  83. autogluon/timeseries/models/chronos/pipeline/chronos_bolt.py +0 -580
  84. autogluon.timeseries-1.4.1b20251016-py3.9-nspkg.pth +0 -1
  85. autogluon.timeseries-1.4.1b20251016.dist-info/RECORD +0 -90
  86. {autogluon.timeseries-1.4.1b20251016.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info/licenses}/LICENSE +0 -0
  87. {autogluon.timeseries-1.4.1b20251016.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info/licenses}/NOTICE +0 -0
  88. {autogluon.timeseries-1.4.1b20251016.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/namespace_packages.txt +0 -0
  89. {autogluon.timeseries-1.4.1b20251016.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/top_level.txt +0 -0
  90. {autogluon.timeseries-1.4.1b20251016.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
@@ -25,9 +25,11 @@ class TotoModel(AbstractTimeSeriesModel):
25
25
  architecture that autoregressively outputs parametric distribution forecasts. More details can be found on
26
26
  `Hugging Face <https://huggingface.co/Datadog/Toto-Open-Base-1.0>`_ and `GitHub <https://github.com/DataDog/toto>`_.
27
27
 
28
- The AutoGluon implementation of Toto is on a port of the original implementation. It is optimized for easy maintenance
29
- with the rest of the AutoGluon model zoo, and does not feature some important optimizations such as xformers and flash-attention
30
- available in the original model repository. The AutoGluon implementation of Toto requires a CUDA-compatible GPU.
28
+ The AutoGluon implementation of Toto is on a port of the original implementation. AutoGluon supports Toto for
29
+ **inference only**, i.e., the model will not be trained or fine-tuned on the provided training data. Toto is optimized
30
+ for easy maintenance with the rest of the AutoGluon model zoo, and does not feature some important optimizations such
31
+ as xformers and flash-attention available in the original model repository. The AutoGluon implementation of Toto
32
+ requires a CUDA-compatible GPU.
31
33
 
32
34
  References
33
35
  ----------
@@ -59,12 +61,12 @@ class TotoModel(AbstractTimeSeriesModel):
59
61
 
60
62
  def __init__(
61
63
  self,
62
- path: Optional[str] = None,
63
- name: Optional[str] = None,
64
- hyperparameters: Optional[dict[str, Any]] = None,
65
- 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,
66
68
  prediction_length: int = 1,
67
- covariate_metadata: Optional[CovariateMetadata] = None,
69
+ covariate_metadata: CovariateMetadata | None = None,
68
70
  target: str = "target",
69
71
  quantile_levels: Sequence[float] = (0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9),
70
72
  eval_metric: Any = None,
@@ -85,9 +87,9 @@ class TotoModel(AbstractTimeSeriesModel):
85
87
  eval_metric=eval_metric,
86
88
  )
87
89
 
88
- self._forecaster: Optional[TotoForecaster] = None
90
+ self._forecaster: TotoForecaster | None = None
89
91
 
90
- def save(self, path: Optional[str] = None, verbose: bool = True) -> str:
92
+ def save(self, path: str | None = None, verbose: bool = True) -> str:
91
93
  forecaster = self._forecaster
92
94
  self._forecaster = None
93
95
  path = super().save(path=path, verbose=verbose)
@@ -108,7 +110,7 @@ class TotoModel(AbstractTimeSeriesModel):
108
110
 
109
111
  return torch.cuda.is_available()
110
112
 
111
- 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]:
112
114
  return {"num_cpus": 1, "num_gpus": 1}
113
115
 
114
116
  def load_forecaster(self):
@@ -124,7 +126,7 @@ class TotoModel(AbstractTimeSeriesModel):
124
126
 
125
127
  hyperparameters = self.get_hyperparameters()
126
128
  pretrained_model = TotoPretrainedModel.from_pretrained(
127
- self.model_path,
129
+ model_id=self.model_path,
128
130
  config=TotoConfig.from_pretrained(self.model_path),
129
131
  device_map=hyperparameters["device"],
130
132
  )
@@ -145,9 +147,21 @@ class TotoModel(AbstractTimeSeriesModel):
145
147
  "num_samples": 256,
146
148
  "device": "cuda",
147
149
  "context_length": 4096,
148
- "compile_model": True,
150
+ "compile_model": False,
149
151
  }
150
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
+
151
165
  @property
152
166
  def allowed_hyperparameters(self) -> list[str]:
153
167
  return super().allowed_hyperparameters + [
@@ -169,10 +183,10 @@ class TotoModel(AbstractTimeSeriesModel):
169
183
  def _fit(
170
184
  self,
171
185
  train_data: TimeSeriesDataFrame,
172
- val_data: Optional[TimeSeriesDataFrame] = None,
173
- time_limit: Optional[float] = None,
174
- num_cpus: Optional[int] = None,
175
- 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,
176
190
  verbosity: int = 2,
177
191
  **kwargs,
178
192
  ) -> None:
@@ -180,7 +194,7 @@ class TotoModel(AbstractTimeSeriesModel):
180
194
  self.load_forecaster()
181
195
 
182
196
  def _predict(
183
- self, data: TimeSeriesDataFrame, known_covariates: Optional[TimeSeriesDataFrame] = None, **kwargs
197
+ self, data: TimeSeriesDataFrame, known_covariates: TimeSeriesDataFrame | None = None, **kwargs
184
198
  ) -> TimeSeriesDataFrame:
185
199
  import torch
186
200
 
@@ -196,6 +210,7 @@ class TotoModel(AbstractTimeSeriesModel):
196
210
  dataset = TotoInferenceDataset(
197
211
  target_df=data.fill_missing_values("auto"),
198
212
  max_context_length=hyperparameters["context_length"],
213
+ target_column=self.target,
199
214
  )
200
215
  loader = TotoDataLoader(
201
216
  dataset,
@@ -212,7 +227,7 @@ class TotoModel(AbstractTimeSeriesModel):
212
227
  masked_timeseries,
213
228
  prediction_length=self.prediction_length,
214
229
  num_samples=hyperparameters["num_samples"],
215
- samples_per_batch=32,
230
+ samples_per_batch=self._get_sample_batch_size(),
216
231
  )
217
232
 
218
233
  batch_means.append(forecast.mean.cpu().numpy())