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.
- autogluon/timeseries/configs/hyperparameter_presets.py +7 -21
- autogluon/timeseries/configs/predictor_presets.py +23 -39
- autogluon/timeseries/dataset/ts_dataframe.py +97 -86
- autogluon/timeseries/learner.py +70 -35
- autogluon/timeseries/metrics/__init__.py +4 -4
- autogluon/timeseries/metrics/abstract.py +8 -8
- autogluon/timeseries/metrics/point.py +9 -9
- autogluon/timeseries/metrics/quantile.py +5 -5
- autogluon/timeseries/metrics/utils.py +4 -4
- autogluon/timeseries/models/__init__.py +2 -1
- autogluon/timeseries/models/abstract/abstract_timeseries_model.py +52 -39
- autogluon/timeseries/models/abstract/model_trial.py +2 -1
- autogluon/timeseries/models/abstract/tunable.py +8 -8
- autogluon/timeseries/models/autogluon_tabular/mlforecast.py +58 -62
- autogluon/timeseries/models/autogluon_tabular/per_step.py +26 -15
- autogluon/timeseries/models/autogluon_tabular/transforms.py +11 -9
- autogluon/timeseries/models/chronos/__init__.py +2 -1
- autogluon/timeseries/models/chronos/chronos2.py +395 -0
- autogluon/timeseries/models/chronos/model.py +126 -88
- autogluon/timeseries/models/chronos/{pipeline/utils.py → utils.py} +69 -37
- autogluon/timeseries/models/ensemble/__init__.py +36 -2
- autogluon/timeseries/models/ensemble/abstract.py +14 -46
- autogluon/timeseries/models/ensemble/array_based/__init__.py +3 -0
- autogluon/timeseries/models/ensemble/array_based/abstract.py +240 -0
- autogluon/timeseries/models/ensemble/array_based/models.py +185 -0
- autogluon/timeseries/models/ensemble/array_based/regressor/__init__.py +12 -0
- autogluon/timeseries/models/ensemble/array_based/regressor/abstract.py +88 -0
- autogluon/timeseries/models/ensemble/array_based/regressor/linear_stacker.py +186 -0
- autogluon/timeseries/models/ensemble/array_based/regressor/per_quantile_tabular.py +94 -0
- autogluon/timeseries/models/ensemble/array_based/regressor/tabular.py +107 -0
- autogluon/timeseries/models/ensemble/{greedy.py → ensemble_selection.py} +41 -61
- autogluon/timeseries/models/ensemble/per_item_greedy.py +172 -0
- autogluon/timeseries/models/ensemble/weighted/__init__.py +8 -0
- autogluon/timeseries/models/ensemble/weighted/abstract.py +45 -0
- autogluon/timeseries/models/ensemble/{basic.py → weighted/basic.py} +25 -22
- autogluon/timeseries/models/ensemble/weighted/greedy.py +62 -0
- autogluon/timeseries/models/gluonts/abstract.py +32 -31
- autogluon/timeseries/models/gluonts/dataset.py +11 -11
- autogluon/timeseries/models/gluonts/models.py +0 -7
- autogluon/timeseries/models/local/__init__.py +0 -7
- autogluon/timeseries/models/local/abstract_local_model.py +15 -18
- autogluon/timeseries/models/local/naive.py +2 -2
- autogluon/timeseries/models/local/npts.py +7 -1
- autogluon/timeseries/models/local/statsforecast.py +12 -12
- autogluon/timeseries/models/multi_window/multi_window_model.py +39 -24
- autogluon/timeseries/models/registry.py +3 -4
- autogluon/timeseries/models/toto/_internal/backbone/attention.py +3 -4
- autogluon/timeseries/models/toto/_internal/backbone/backbone.py +6 -6
- autogluon/timeseries/models/toto/_internal/backbone/rope.py +4 -9
- autogluon/timeseries/models/toto/_internal/backbone/rotary_embedding_torch.py +342 -0
- autogluon/timeseries/models/toto/_internal/backbone/scaler.py +2 -3
- autogluon/timeseries/models/toto/_internal/backbone/transformer.py +10 -10
- autogluon/timeseries/models/toto/_internal/dataset.py +2 -2
- autogluon/timeseries/models/toto/_internal/forecaster.py +8 -8
- autogluon/timeseries/models/toto/dataloader.py +4 -4
- autogluon/timeseries/models/toto/hf_pretrained_model.py +97 -16
- autogluon/timeseries/models/toto/model.py +35 -20
- autogluon/timeseries/predictor.py +527 -155
- autogluon/timeseries/regressor.py +27 -30
- autogluon/timeseries/splitter.py +3 -27
- autogluon/timeseries/trainer/ensemble_composer.py +444 -0
- autogluon/timeseries/trainer/model_set_builder.py +9 -9
- autogluon/timeseries/trainer/prediction_cache.py +16 -16
- autogluon/timeseries/trainer/trainer.py +300 -278
- autogluon/timeseries/trainer/utils.py +17 -0
- autogluon/timeseries/transforms/covariate_scaler.py +8 -8
- autogluon/timeseries/transforms/target_scaler.py +15 -15
- autogluon/timeseries/utils/constants.py +10 -0
- autogluon/timeseries/utils/datetime/lags.py +1 -3
- autogluon/timeseries/utils/datetime/seasonality.py +1 -3
- autogluon/timeseries/utils/features.py +31 -14
- autogluon/timeseries/utils/forecast.py +6 -7
- autogluon/timeseries/utils/timer.py +173 -0
- autogluon/timeseries/version.py +1 -1
- autogluon.timeseries-1.4.1b20251218-py3.11-nspkg.pth +1 -0
- {autogluon.timeseries-1.4.1b20251016.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/METADATA +39 -27
- autogluon_timeseries-1.4.1b20251218.dist-info/RECORD +103 -0
- {autogluon.timeseries-1.4.1b20251016.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/WHEEL +1 -1
- autogluon/timeseries/evaluator.py +0 -6
- autogluon/timeseries/models/chronos/pipeline/__init__.py +0 -10
- autogluon/timeseries/models/chronos/pipeline/base.py +0 -160
- autogluon/timeseries/models/chronos/pipeline/chronos.py +0 -544
- autogluon/timeseries/models/chronos/pipeline/chronos_bolt.py +0 -580
- autogluon.timeseries-1.4.1b20251016-py3.9-nspkg.pth +0 -1
- autogluon.timeseries-1.4.1b20251016.dist-info/RECORD +0 -90
- {autogluon.timeseries-1.4.1b20251016.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info/licenses}/LICENSE +0 -0
- {autogluon.timeseries-1.4.1b20251016.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info/licenses}/NOTICE +0 -0
- {autogluon.timeseries-1.4.1b20251016.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/namespace_packages.txt +0 -0
- {autogluon.timeseries-1.4.1b20251016.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/top_level.txt +0 -0
- {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
|
-
|
|
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:
|
|
19
|
-
output_distribution_kwargs:
|
|
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
|
-
|
|
76
|
-
|
|
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
|
-
|
|
96
|
+
new_state[new_key] = new_state.pop(old_key)
|
|
97
|
+
|
|
98
|
+
return new_state
|
|
95
99
|
|
|
96
100
|
@classmethod
|
|
97
|
-
def
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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,
|
|
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.
|
|
29
|
-
|
|
30
|
-
|
|
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:
|
|
63
|
-
name:
|
|
64
|
-
hyperparameters:
|
|
65
|
-
freq:
|
|
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:
|
|
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:
|
|
90
|
+
self._forecaster: TotoForecaster | None = None
|
|
89
91
|
|
|
90
|
-
def save(self, path:
|
|
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,
|
|
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":
|
|
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:
|
|
173
|
-
time_limit:
|
|
174
|
-
num_cpus:
|
|
175
|
-
num_gpus:
|
|
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:
|
|
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=
|
|
230
|
+
samples_per_batch=self._get_sample_batch_size(),
|
|
216
231
|
)
|
|
217
232
|
|
|
218
233
|
batch_means.append(forecast.mean.cpu().numpy())
|