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.
- autogluon/timeseries/configs/hyperparameter_presets.py +7 -21
- autogluon/timeseries/configs/predictor_presets.py +23 -39
- autogluon/timeseries/dataset/ts_dataframe.py +32 -34
- autogluon/timeseries/learner.py +67 -33
- 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 +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 +30 -26
- autogluon/timeseries/models/autogluon_tabular/per_step.py +12 -10
- autogluon/timeseries/models/autogluon_tabular/transforms.py +2 -2
- autogluon/timeseries/models/chronos/__init__.py +2 -1
- autogluon/timeseries/models/chronos/chronos2.py +395 -0
- autogluon/timeseries/models/chronos/model.py +29 -24
- autogluon/timeseries/models/chronos/utils.py +5 -5
- autogluon/timeseries/models/ensemble/__init__.py +17 -10
- autogluon/timeseries/models/ensemble/abstract.py +13 -9
- autogluon/timeseries/models/ensemble/array_based/__init__.py +2 -2
- autogluon/timeseries/models/ensemble/array_based/abstract.py +24 -31
- autogluon/timeseries/models/ensemble/array_based/models.py +146 -11
- autogluon/timeseries/models/ensemble/array_based/regressor/__init__.py +2 -0
- autogluon/timeseries/models/ensemble/array_based/regressor/abstract.py +6 -5
- autogluon/timeseries/models/ensemble/array_based/regressor/linear_stacker.py +186 -0
- autogluon/timeseries/models/ensemble/array_based/regressor/per_quantile_tabular.py +44 -83
- autogluon/timeseries/models/ensemble/array_based/regressor/tabular.py +21 -55
- autogluon/timeseries/models/ensemble/ensemble_selection.py +167 -0
- autogluon/timeseries/models/ensemble/per_item_greedy.py +172 -0
- autogluon/timeseries/models/ensemble/weighted/abstract.py +7 -3
- autogluon/timeseries/models/ensemble/weighted/basic.py +26 -13
- autogluon/timeseries/models/ensemble/weighted/greedy.py +20 -145
- autogluon/timeseries/models/gluonts/abstract.py +30 -29
- autogluon/timeseries/models/gluonts/dataset.py +9 -9
- autogluon/timeseries/models/gluonts/models.py +0 -7
- autogluon/timeseries/models/local/__init__.py +0 -7
- autogluon/timeseries/models/local/abstract_local_model.py +13 -16
- 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 +38 -23
- 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 +30 -17
- autogluon/timeseries/predictor.py +517 -129
- autogluon/timeseries/regressor.py +18 -23
- autogluon/timeseries/splitter.py +2 -2
- autogluon/timeseries/trainer/ensemble_composer.py +323 -129
- autogluon/timeseries/trainer/model_set_builder.py +9 -9
- autogluon/timeseries/trainer/prediction_cache.py +16 -16
- autogluon/timeseries/trainer/trainer.py +235 -144
- autogluon/timeseries/trainer/utils.py +3 -4
- autogluon/timeseries/transforms/covariate_scaler.py +7 -7
- autogluon/timeseries/transforms/target_scaler.py +8 -8
- 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 +22 -9
- autogluon/timeseries/utils/forecast.py +1 -2
- autogluon/timeseries/utils/timer.py +173 -0
- autogluon/timeseries/version.py +1 -1
- {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/METADATA +23 -21
- autogluon_timeseries-1.4.1b20251218.dist-info/RECORD +103 -0
- autogluon_timeseries-1.4.1b20251115.dist-info/RECORD +0 -96
- /autogluon.timeseries-1.4.1b20251115-py3.9-nspkg.pth → /autogluon.timeseries-1.4.1b20251218-py3.11-nspkg.pth +0 -0
- {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/WHEEL +0 -0
- {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/licenses/LICENSE +0 -0
- {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/licenses/NOTICE +0 -0
- {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/namespace_packages.txt +0 -0
- {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/top_level.txt +0 -0
- {autogluon_timeseries-1.4.1b20251115.dist-info → autogluon_timeseries-1.4.1b20251218.dist-info}/zip-safe +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from typing import Any
|
|
1
|
+
from typing import Any
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def get_hyperparameter_presets() -> dict[str, dict[str,
|
|
4
|
+
def get_hyperparameter_presets() -> dict[str, dict[str, dict[str, Any] | list[dict[str, Any]]]]:
|
|
5
5
|
return {
|
|
6
6
|
"very_light": {
|
|
7
7
|
"Naive": {},
|
|
@@ -31,32 +31,18 @@ def get_hyperparameter_presets() -> dict[str, dict[str, Union[dict[str, Any], li
|
|
|
31
31
|
"default": {
|
|
32
32
|
"SeasonalNaive": {},
|
|
33
33
|
"AutoETS": {},
|
|
34
|
-
"NPTS": {},
|
|
35
34
|
"DynamicOptimizedTheta": {},
|
|
36
35
|
"RecursiveTabular": {},
|
|
37
36
|
"DirectTabular": {},
|
|
38
37
|
"TemporalFusionTransformer": {},
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
"Chronos": [
|
|
42
|
-
{
|
|
43
|
-
"ag_args": {"name_suffix": "ZeroShot"},
|
|
44
|
-
"model_path": "bolt_base",
|
|
45
|
-
},
|
|
38
|
+
"Chronos2": [
|
|
39
|
+
{},
|
|
46
40
|
{
|
|
47
|
-
"ag_args": {"name_suffix": "
|
|
48
|
-
"model_path": "
|
|
41
|
+
"ag_args": {"name_suffix": "SmallFineTuned"},
|
|
42
|
+
"model_path": "autogluon/chronos-2-small",
|
|
49
43
|
"fine_tune": True,
|
|
50
|
-
"
|
|
51
|
-
"covariate_regressor": {"model_name": "CAT", "model_hyperparameters": {"iterations": 1_000}},
|
|
44
|
+
"eval_during_fine_tune": True,
|
|
52
45
|
},
|
|
53
46
|
],
|
|
54
|
-
"TiDE": {
|
|
55
|
-
"encoder_hidden_dim": 256,
|
|
56
|
-
"decoder_hidden_dim": 256,
|
|
57
|
-
"temporal_hidden_dim": 64,
|
|
58
|
-
"num_batches_per_epoch": 100,
|
|
59
|
-
"lr": 1e-4,
|
|
60
|
-
},
|
|
61
47
|
},
|
|
62
48
|
}
|
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
|
-
from . import get_hyperparameter_presets
|
|
6
|
-
|
|
7
5
|
TIMESERIES_PRESETS_ALIASES = dict(
|
|
8
|
-
chronos="chronos_small",
|
|
9
6
|
best="best_quality",
|
|
10
7
|
high="high_quality",
|
|
11
8
|
medium="medium_quality",
|
|
@@ -16,13 +13,33 @@ TIMESERIES_PRESETS_ALIASES = dict(
|
|
|
16
13
|
|
|
17
14
|
|
|
18
15
|
def get_predictor_presets() -> dict[str, Any]:
|
|
19
|
-
hp_presets = get_hyperparameter_presets()
|
|
20
|
-
|
|
21
16
|
predictor_presets = dict(
|
|
22
|
-
best_quality={"hyperparameters": "default", "num_val_windows":
|
|
17
|
+
best_quality={"hyperparameters": "default", "num_val_windows": "auto", "refit_every_n_windows": "auto"},
|
|
23
18
|
high_quality={"hyperparameters": "default"},
|
|
24
19
|
medium_quality={"hyperparameters": "light"},
|
|
25
20
|
fast_training={"hyperparameters": "very_light"},
|
|
21
|
+
# Chronos-2 models
|
|
22
|
+
chronos2={
|
|
23
|
+
"hyperparameters": {"Chronos2": {"model_path": "autogluon/chronos-2"}},
|
|
24
|
+
"skip_model_selection": True,
|
|
25
|
+
},
|
|
26
|
+
chronos2_small={
|
|
27
|
+
"hyperparameters": {"Chronos2": {"model_path": "autogluon/chronos-2-small"}},
|
|
28
|
+
"skip_model_selection": True,
|
|
29
|
+
},
|
|
30
|
+
chronos2_ensemble={
|
|
31
|
+
"hyperparameters": {
|
|
32
|
+
"Chronos2": [
|
|
33
|
+
{"model_path": "autogluon/chronos-2", "ag_args": {"name_suffix": "ZeroShot"}},
|
|
34
|
+
{
|
|
35
|
+
"model_path": "autogluon/chronos-2-small",
|
|
36
|
+
"fine_tune": True,
|
|
37
|
+
"eval_during_fine_tune": True,
|
|
38
|
+
"ag_args": {"name_suffix": "SmallFineTuned"},
|
|
39
|
+
},
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
},
|
|
26
43
|
# Chronos-Bolt models
|
|
27
44
|
bolt_tiny={
|
|
28
45
|
"hyperparameters": {"Chronos": {"model_path": "bolt_tiny"}},
|
|
@@ -40,39 +57,6 @@ def get_predictor_presets() -> dict[str, Any]:
|
|
|
40
57
|
"hyperparameters": {"Chronos": {"model_path": "bolt_base"}},
|
|
41
58
|
"skip_model_selection": True,
|
|
42
59
|
},
|
|
43
|
-
# Original Chronos models
|
|
44
|
-
chronos_tiny={
|
|
45
|
-
"hyperparameters": {"Chronos": {"model_path": "tiny"}},
|
|
46
|
-
"skip_model_selection": True,
|
|
47
|
-
},
|
|
48
|
-
chronos_mini={
|
|
49
|
-
"hyperparameters": {"Chronos": {"model_path": "mini"}},
|
|
50
|
-
"skip_model_selection": True,
|
|
51
|
-
},
|
|
52
|
-
chronos_small={
|
|
53
|
-
"hyperparameters": {"Chronos": {"model_path": "small"}},
|
|
54
|
-
"skip_model_selection": True,
|
|
55
|
-
},
|
|
56
|
-
chronos_base={
|
|
57
|
-
"hyperparameters": {"Chronos": {"model_path": "base"}},
|
|
58
|
-
"skip_model_selection": True,
|
|
59
|
-
},
|
|
60
|
-
chronos_large={
|
|
61
|
-
"hyperparameters": {"Chronos": {"model_path": "large", "batch_size": 8}},
|
|
62
|
-
"skip_model_selection": True,
|
|
63
|
-
},
|
|
64
|
-
chronos_ensemble={
|
|
65
|
-
"hyperparameters": {
|
|
66
|
-
"Chronos": {"model_path": "small"},
|
|
67
|
-
**hp_presets["light_inference"],
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
chronos_large_ensemble={
|
|
71
|
-
"hyperparameters": {
|
|
72
|
-
"Chronos": {"model_path": "large", "batch_size": 8},
|
|
73
|
-
**hp_presets["light_inference"],
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
60
|
)
|
|
77
61
|
|
|
78
62
|
# update with aliases
|
|
@@ -7,7 +7,7 @@ import reprlib
|
|
|
7
7
|
from collections.abc import Iterable
|
|
8
8
|
from itertools import islice
|
|
9
9
|
from pathlib import Path
|
|
10
|
-
from typing import TYPE_CHECKING, Any, Final,
|
|
10
|
+
from typing import TYPE_CHECKING, Any, Final, Type, overload
|
|
11
11
|
|
|
12
12
|
import numpy as np
|
|
13
13
|
import pandas as pd
|
|
@@ -122,10 +122,10 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
122
122
|
|
|
123
123
|
def __init__(
|
|
124
124
|
self,
|
|
125
|
-
data:
|
|
126
|
-
static_features:
|
|
127
|
-
id_column:
|
|
128
|
-
timestamp_column:
|
|
125
|
+
data: pd.DataFrame | str | Path | Iterable,
|
|
126
|
+
static_features: pd.DataFrame | str | Path | None = None,
|
|
127
|
+
id_column: str | None = None,
|
|
128
|
+
timestamp_column: str | None = None,
|
|
129
129
|
num_cpus: int = -1,
|
|
130
130
|
*args,
|
|
131
131
|
**kwargs,
|
|
@@ -149,7 +149,7 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
149
149
|
else:
|
|
150
150
|
raise ValueError(f"data must be a pd.DataFrame, Iterable, string or Path (received {type(data)}).")
|
|
151
151
|
super().__init__(data=data, *args, **kwargs) # type: ignore
|
|
152
|
-
self._static_features:
|
|
152
|
+
self._static_features: pd.DataFrame | None = None
|
|
153
153
|
if static_features is not None:
|
|
154
154
|
self.static_features = self._construct_static_features(static_features, id_column=id_column)
|
|
155
155
|
|
|
@@ -168,8 +168,8 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
168
168
|
def _construct_tsdf_from_data_frame(
|
|
169
169
|
cls,
|
|
170
170
|
df: pd.DataFrame,
|
|
171
|
-
id_column:
|
|
172
|
-
timestamp_column:
|
|
171
|
+
id_column: str | None = None,
|
|
172
|
+
timestamp_column: str | None = None,
|
|
173
173
|
) -> pd.DataFrame:
|
|
174
174
|
df = df.copy()
|
|
175
175
|
if id_column is not None:
|
|
@@ -272,9 +272,9 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
272
272
|
def from_data_frame(
|
|
273
273
|
cls,
|
|
274
274
|
df: pd.DataFrame,
|
|
275
|
-
id_column:
|
|
276
|
-
timestamp_column:
|
|
277
|
-
static_features_df:
|
|
275
|
+
id_column: str | None = None,
|
|
276
|
+
timestamp_column: str | None = None,
|
|
277
|
+
static_features_df: pd.DataFrame | None = None,
|
|
278
278
|
) -> TimeSeriesDataFrame:
|
|
279
279
|
"""Construct a ``TimeSeriesDataFrame`` from a pandas DataFrame.
|
|
280
280
|
|
|
@@ -315,10 +315,10 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
315
315
|
@classmethod
|
|
316
316
|
def from_path(
|
|
317
317
|
cls,
|
|
318
|
-
path:
|
|
319
|
-
id_column:
|
|
320
|
-
timestamp_column:
|
|
321
|
-
static_features_path:
|
|
318
|
+
path: str | Path,
|
|
319
|
+
id_column: str | None = None,
|
|
320
|
+
timestamp_column: str | None = None,
|
|
321
|
+
static_features_path: str | Path | None = None,
|
|
322
322
|
) -> TimeSeriesDataFrame:
|
|
323
323
|
"""Construct a ``TimeSeriesDataFrame`` from a CSV or Parquet file.
|
|
324
324
|
|
|
@@ -396,8 +396,8 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
396
396
|
@classmethod
|
|
397
397
|
def _construct_static_features(
|
|
398
398
|
cls,
|
|
399
|
-
static_features:
|
|
400
|
-
id_column:
|
|
399
|
+
static_features: pd.DataFrame | str | Path,
|
|
400
|
+
id_column: str | None = None,
|
|
401
401
|
) -> pd.DataFrame:
|
|
402
402
|
if isinstance(static_features, (str, Path)):
|
|
403
403
|
static_features = load_pd.load(str(static_features))
|
|
@@ -421,7 +421,7 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
421
421
|
return self._static_features
|
|
422
422
|
|
|
423
423
|
@static_features.setter
|
|
424
|
-
def static_features(self, value:
|
|
424
|
+
def static_features(self, value: pd.DataFrame | None):
|
|
425
425
|
# if the current item index is not a multiindex, then we are dealing with a single
|
|
426
426
|
# item slice. this should only happen when the user explicitly requests only a
|
|
427
427
|
# single item or during `slice_by_timestep`. In this case we do not set static features
|
|
@@ -454,7 +454,7 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
454
454
|
|
|
455
455
|
self._static_features = value
|
|
456
456
|
|
|
457
|
-
def infer_frequency(self, num_items:
|
|
457
|
+
def infer_frequency(self, num_items: int | None = None, raise_if_irregular: bool = False) -> str:
|
|
458
458
|
"""Infer the time series frequency based on the timestamps of the observations.
|
|
459
459
|
|
|
460
460
|
Parameters
|
|
@@ -570,7 +570,7 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
570
570
|
return obj
|
|
571
571
|
|
|
572
572
|
def __finalize__( # noqa
|
|
573
|
-
self: TimeSeriesDataFrame, other, method:
|
|
573
|
+
self: TimeSeriesDataFrame, other, method: str | None = None, **kwargs
|
|
574
574
|
) -> TimeSeriesDataFrame:
|
|
575
575
|
super().__finalize__(other=other, method=method, **kwargs)
|
|
576
576
|
# when finalizing the copy/slice operation, we use the property setter to stay consistent
|
|
@@ -602,9 +602,7 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
602
602
|
after = TimeSeriesDataFrame(data_after, static_features=self.static_features)
|
|
603
603
|
return before, after
|
|
604
604
|
|
|
605
|
-
def slice_by_timestep(
|
|
606
|
-
self, start_index: Optional[int] = None, end_index: Optional[int] = None
|
|
607
|
-
) -> TimeSeriesDataFrame:
|
|
605
|
+
def slice_by_timestep(self, start_index: int | None = None, end_index: int | None = None) -> TimeSeriesDataFrame:
|
|
608
606
|
"""Select a subsequence from each time series between start (inclusive) and end (exclusive) indices.
|
|
609
607
|
|
|
610
608
|
This operation is equivalent to selecting a slice ``[start_index : end_index]`` from each time series, and then
|
|
@@ -907,8 +905,8 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
907
905
|
return super().sort_index(*args, **kwargs) # type: ignore
|
|
908
906
|
|
|
909
907
|
def get_model_inputs_for_scoring(
|
|
910
|
-
self, prediction_length: int, known_covariates_names:
|
|
911
|
-
) -> tuple[TimeSeriesDataFrame,
|
|
908
|
+
self, prediction_length: int, known_covariates_names: list[str] | None = None
|
|
909
|
+
) -> tuple[TimeSeriesDataFrame, TimeSeriesDataFrame | None]:
|
|
912
910
|
"""Prepare model inputs necessary to predict the last ``prediction_length`` time steps of each time series in the dataset.
|
|
913
911
|
|
|
914
912
|
Parameters
|
|
@@ -938,8 +936,8 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
938
936
|
def train_test_split(
|
|
939
937
|
self,
|
|
940
938
|
prediction_length: int,
|
|
941
|
-
end_index:
|
|
942
|
-
suffix:
|
|
939
|
+
end_index: int | None = None,
|
|
940
|
+
suffix: str | None = None,
|
|
943
941
|
) -> tuple[TimeSeriesDataFrame, TimeSeriesDataFrame]:
|
|
944
942
|
"""Generate a train/test split from the given dataset.
|
|
945
943
|
|
|
@@ -984,7 +982,7 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
984
982
|
|
|
985
983
|
def convert_frequency(
|
|
986
984
|
self,
|
|
987
|
-
freq:
|
|
985
|
+
freq: str | pd.DateOffset,
|
|
988
986
|
agg_numeric: str = "mean",
|
|
989
987
|
agg_categorical: str = "first",
|
|
990
988
|
num_cpus: int = -1,
|
|
@@ -1003,7 +1001,7 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
1003
1001
|
|
|
1004
1002
|
Parameters
|
|
1005
1003
|
----------
|
|
1006
|
-
freq :
|
|
1004
|
+
freq : str | pd.DateOffset
|
|
1007
1005
|
Frequency to which the data should be converted. See `pandas frequency aliases <https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases>`_
|
|
1008
1006
|
for supported values.
|
|
1009
1007
|
agg_numeric : {"max", "min", "sum", "mean", "median", "first", "last"}, default = "mean"
|
|
@@ -1130,14 +1128,14 @@ class TimeSeriesDataFrame(pd.DataFrame):
|
|
|
1130
1128
|
def reindex(*args, **kwargs) -> Self: ... # type: ignore
|
|
1131
1129
|
|
|
1132
1130
|
@overload
|
|
1133
|
-
def __new__(cls, data: pd.DataFrame, static_features:
|
|
1131
|
+
def __new__(cls, data: pd.DataFrame, static_features: pd.DataFrame | None = None) -> Self: ... # type: ignore
|
|
1134
1132
|
@overload
|
|
1135
1133
|
def __new__(
|
|
1136
1134
|
cls,
|
|
1137
|
-
data:
|
|
1138
|
-
static_features:
|
|
1139
|
-
id_column:
|
|
1140
|
-
timestamp_column:
|
|
1135
|
+
data: pd.DataFrame | str | Path | Iterable,
|
|
1136
|
+
static_features: pd.DataFrame | str | Path | None = None,
|
|
1137
|
+
id_column: str | None = None,
|
|
1138
|
+
timestamp_column: str | None = None,
|
|
1141
1139
|
num_cpus: int = -1,
|
|
1142
1140
|
*args,
|
|
1143
1141
|
**kwargs,
|
autogluon/timeseries/learner.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import reprlib
|
|
3
3
|
import time
|
|
4
|
-
from typing import Any, Literal,
|
|
4
|
+
from typing import Any, Literal, Type
|
|
5
5
|
|
|
6
6
|
import pandas as pd
|
|
7
7
|
|
|
@@ -25,12 +25,12 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
25
25
|
self,
|
|
26
26
|
path_context: str,
|
|
27
27
|
target: str = "target",
|
|
28
|
-
known_covariates_names:
|
|
28
|
+
known_covariates_names: list[str] | None = None,
|
|
29
29
|
trainer_type: Type[TimeSeriesTrainer] = TimeSeriesTrainer,
|
|
30
|
-
eval_metric:
|
|
30
|
+
eval_metric: str | TimeSeriesScorer | None = None,
|
|
31
31
|
prediction_length: int = 1,
|
|
32
32
|
cache_predictions: bool = True,
|
|
33
|
-
ensemble_model_type:
|
|
33
|
+
ensemble_model_type: Type | None = None,
|
|
34
34
|
**kwargs,
|
|
35
35
|
):
|
|
36
36
|
super().__init__(path_context=path_context)
|
|
@@ -41,7 +41,7 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
41
41
|
self.prediction_length = prediction_length
|
|
42
42
|
self.quantile_levels = kwargs.get("quantile_levels", [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
|
|
43
43
|
self.cache_predictions = cache_predictions
|
|
44
|
-
self.freq:
|
|
44
|
+
self.freq: str | None = None
|
|
45
45
|
self.ensemble_model_type = ensemble_model_type
|
|
46
46
|
|
|
47
47
|
self.feature_generator = TimeSeriesFeatureGenerator(
|
|
@@ -55,14 +55,15 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
55
55
|
def fit(
|
|
56
56
|
self,
|
|
57
57
|
train_data: TimeSeriesDataFrame,
|
|
58
|
-
hyperparameters:
|
|
59
|
-
val_data:
|
|
60
|
-
hyperparameter_tune_kwargs:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
hyperparameters: str | dict,
|
|
59
|
+
val_data: TimeSeriesDataFrame | None = None,
|
|
60
|
+
hyperparameter_tune_kwargs: str | dict | None = None,
|
|
61
|
+
ensemble_hyperparameters: dict[str, Any] | list[dict[str, Any]] | None = None,
|
|
62
|
+
time_limit: float | None = None,
|
|
63
|
+
num_val_windows: tuple[int, ...] = (1,),
|
|
64
|
+
val_step_size: int | None = None,
|
|
65
|
+
refit_every_n_windows: int | None = 1,
|
|
66
|
+
random_seed: int | None = None,
|
|
66
67
|
**kwargs,
|
|
67
68
|
) -> None:
|
|
68
69
|
self._time_limit = time_limit
|
|
@@ -95,7 +96,7 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
95
96
|
)
|
|
96
97
|
|
|
97
98
|
assert issubclass(self.trainer_type, TimeSeriesTrainer)
|
|
98
|
-
self.trainer:
|
|
99
|
+
self.trainer: TimeSeriesTrainer | None = self.trainer_type(**trainer_init_kwargs)
|
|
99
100
|
self.trainer_path = self.trainer.path
|
|
100
101
|
self.save()
|
|
101
102
|
|
|
@@ -112,6 +113,7 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
112
113
|
val_data=val_data,
|
|
113
114
|
hyperparameters=hyperparameters,
|
|
114
115
|
hyperparameter_tune_kwargs=hyperparameter_tune_kwargs,
|
|
116
|
+
ensemble_hyperparameters=ensemble_hyperparameters,
|
|
115
117
|
excluded_model_types=kwargs.get("excluded_model_types"),
|
|
116
118
|
time_limit=time_limit,
|
|
117
119
|
random_seed=random_seed,
|
|
@@ -122,9 +124,9 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
122
124
|
|
|
123
125
|
def _align_covariates_with_forecast_index(
|
|
124
126
|
self,
|
|
125
|
-
known_covariates:
|
|
127
|
+
known_covariates: TimeSeriesDataFrame | None,
|
|
126
128
|
data: TimeSeriesDataFrame,
|
|
127
|
-
) ->
|
|
129
|
+
) -> TimeSeriesDataFrame | None:
|
|
128
130
|
"""Select the relevant item_ids and timestamps from the known_covariates dataframe.
|
|
129
131
|
|
|
130
132
|
If some of the item_ids or timestamps are missing, an exception is raised.
|
|
@@ -163,10 +165,10 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
163
165
|
def predict(
|
|
164
166
|
self,
|
|
165
167
|
data: TimeSeriesDataFrame,
|
|
166
|
-
known_covariates:
|
|
167
|
-
model:
|
|
168
|
+
known_covariates: TimeSeriesDataFrame | None = None,
|
|
169
|
+
model: str | AbstractTimeSeriesModel | None = None,
|
|
168
170
|
use_cache: bool = True,
|
|
169
|
-
random_seed:
|
|
171
|
+
random_seed: int | None = None,
|
|
170
172
|
**kwargs,
|
|
171
173
|
) -> TimeSeriesDataFrame:
|
|
172
174
|
data = self.feature_generator.transform(data)
|
|
@@ -184,8 +186,8 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
184
186
|
def score(
|
|
185
187
|
self,
|
|
186
188
|
data: TimeSeriesDataFrame,
|
|
187
|
-
model:
|
|
188
|
-
metric:
|
|
189
|
+
model: str | AbstractTimeSeriesModel | None = None,
|
|
190
|
+
metric: str | TimeSeriesScorer | None = None,
|
|
189
191
|
use_cache: bool = True,
|
|
190
192
|
) -> float:
|
|
191
193
|
data = self.feature_generator.transform(data)
|
|
@@ -194,8 +196,8 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
194
196
|
def evaluate(
|
|
195
197
|
self,
|
|
196
198
|
data: TimeSeriesDataFrame,
|
|
197
|
-
model:
|
|
198
|
-
metrics:
|
|
199
|
+
model: str | None = None,
|
|
200
|
+
metrics: str | TimeSeriesScorer | list[str | TimeSeriesScorer] | None = None,
|
|
199
201
|
use_cache: bool = True,
|
|
200
202
|
) -> dict[str, float]:
|
|
201
203
|
data = self.feature_generator.transform(data)
|
|
@@ -203,15 +205,15 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
203
205
|
|
|
204
206
|
def get_feature_importance(
|
|
205
207
|
self,
|
|
206
|
-
data:
|
|
207
|
-
model:
|
|
208
|
-
metric:
|
|
209
|
-
features:
|
|
210
|
-
time_limit:
|
|
208
|
+
data: TimeSeriesDataFrame | None = None,
|
|
209
|
+
model: str | None = None,
|
|
210
|
+
metric: str | TimeSeriesScorer | None = None,
|
|
211
|
+
features: list[str] | None = None,
|
|
212
|
+
time_limit: float | None = None,
|
|
211
213
|
method: Literal["naive", "permutation"] = "permutation",
|
|
212
214
|
subsample_size: int = 50,
|
|
213
|
-
num_iterations:
|
|
214
|
-
random_seed:
|
|
215
|
+
num_iterations: int | None = None,
|
|
216
|
+
random_seed: int | None = None,
|
|
215
217
|
relative_scores: bool = False,
|
|
216
218
|
include_confidence_band: bool = True,
|
|
217
219
|
confidence_level: float = 0.99,
|
|
@@ -272,9 +274,9 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
272
274
|
|
|
273
275
|
def leaderboard(
|
|
274
276
|
self,
|
|
275
|
-
data:
|
|
277
|
+
data: TimeSeriesDataFrame | None = None,
|
|
276
278
|
extra_info: bool = False,
|
|
277
|
-
extra_metrics:
|
|
279
|
+
extra_metrics: list[str | TimeSeriesScorer] | None = None,
|
|
278
280
|
use_cache: bool = True,
|
|
279
281
|
) -> pd.DataFrame:
|
|
280
282
|
if data is not None:
|
|
@@ -301,7 +303,7 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
301
303
|
return learner_info
|
|
302
304
|
|
|
303
305
|
def persist_trainer(
|
|
304
|
-
self, models:
|
|
306
|
+
self, models: Literal["all", "best"] | list[str] = "all", with_ancestors: bool = False
|
|
305
307
|
) -> list[str]:
|
|
306
308
|
"""Loads models and trainer in memory so that they don't have to be
|
|
307
309
|
loaded during predictions
|
|
@@ -329,3 +331,35 @@ class TimeSeriesLearner(AbstractLearner):
|
|
|
329
331
|
|
|
330
332
|
def refit_full(self, model: str = "all") -> dict[str, str]:
|
|
331
333
|
return self.load_trainer().refit_full(model=model)
|
|
334
|
+
|
|
335
|
+
def backtest_predictions(
|
|
336
|
+
self,
|
|
337
|
+
data: TimeSeriesDataFrame | None,
|
|
338
|
+
model_names: list[str],
|
|
339
|
+
num_val_windows: int | None = None,
|
|
340
|
+
val_step_size: int | None = None,
|
|
341
|
+
use_cache: bool = True,
|
|
342
|
+
) -> dict[str, list[TimeSeriesDataFrame]]:
|
|
343
|
+
if data is not None:
|
|
344
|
+
data = self.feature_generator.transform(data)
|
|
345
|
+
return self.load_trainer().backtest_predictions(
|
|
346
|
+
model_names=model_names,
|
|
347
|
+
data=data,
|
|
348
|
+
num_val_windows=num_val_windows,
|
|
349
|
+
val_step_size=val_step_size,
|
|
350
|
+
use_cache=use_cache,
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
def backtest_targets(
|
|
354
|
+
self,
|
|
355
|
+
data: TimeSeriesDataFrame | None,
|
|
356
|
+
num_val_windows: int | None = None,
|
|
357
|
+
val_step_size: int | None = None,
|
|
358
|
+
) -> list[TimeSeriesDataFrame]:
|
|
359
|
+
if data is not None:
|
|
360
|
+
data = self.feature_generator.transform(data)
|
|
361
|
+
return self.load_trainer().backtest_targets(
|
|
362
|
+
data=data,
|
|
363
|
+
num_val_windows=num_val_windows,
|
|
364
|
+
val_step_size=val_step_size,
|
|
365
|
+
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from pprint import pformat
|
|
4
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, Sequence, Type
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
|
|
@@ -54,10 +54,10 @@ EXPERIMENTAL_METRICS: dict[str, Type[TimeSeriesScorer]] = {
|
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
def check_get_evaluation_metric(
|
|
57
|
-
eval_metric:
|
|
57
|
+
eval_metric: str | TimeSeriesScorer | Type[TimeSeriesScorer] | None,
|
|
58
58
|
prediction_length: int,
|
|
59
|
-
seasonal_period:
|
|
60
|
-
horizon_weight:
|
|
59
|
+
seasonal_period: int | None = None,
|
|
60
|
+
horizon_weight: Sequence[float] | np.ndarray | None = None,
|
|
61
61
|
) -> TimeSeriesScorer:
|
|
62
62
|
"""Factory method for TimeSeriesScorer objects.
|
|
63
63
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import warnings
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import Sequence, overload
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import pandas as pd
|
|
@@ -52,13 +52,13 @@ class TimeSeriesScorer:
|
|
|
52
52
|
optimum: float = 0.0
|
|
53
53
|
optimized_by_median: bool = False
|
|
54
54
|
needs_quantile: bool = False
|
|
55
|
-
equivalent_tabular_regression_metric:
|
|
55
|
+
equivalent_tabular_regression_metric: str | None = None
|
|
56
56
|
|
|
57
57
|
def __init__(
|
|
58
58
|
self,
|
|
59
59
|
prediction_length: int = 1,
|
|
60
|
-
seasonal_period:
|
|
61
|
-
horizon_weight:
|
|
60
|
+
seasonal_period: int | None = None,
|
|
61
|
+
horizon_weight: Sequence[float] | None = None,
|
|
62
62
|
):
|
|
63
63
|
self.prediction_length = int(prediction_length)
|
|
64
64
|
if self.prediction_length < 1:
|
|
@@ -192,7 +192,7 @@ class TimeSeriesScorer:
|
|
|
192
192
|
return self.optimum - self.score(*args, **kwargs)
|
|
193
193
|
|
|
194
194
|
@staticmethod
|
|
195
|
-
def _safemean(array:
|
|
195
|
+
def _safemean(array: np.ndarray | pd.Series) -> float:
|
|
196
196
|
"""Compute mean of a numpy array-like object, ignoring inf, -inf and nan values."""
|
|
197
197
|
return float(np.mean(array[np.isfinite(array)]))
|
|
198
198
|
|
|
@@ -240,13 +240,13 @@ class TimeSeriesScorer:
|
|
|
240
240
|
@overload
|
|
241
241
|
@staticmethod
|
|
242
242
|
def check_get_horizon_weight(
|
|
243
|
-
horizon_weight:
|
|
243
|
+
horizon_weight: Sequence[float] | np.ndarray, prediction_length: int
|
|
244
244
|
) -> np.ndarray: ...
|
|
245
245
|
|
|
246
246
|
@staticmethod
|
|
247
247
|
def check_get_horizon_weight(
|
|
248
|
-
horizon_weight:
|
|
249
|
-
) ->
|
|
248
|
+
horizon_weight: Sequence[float] | np.ndarray | None, prediction_length: int
|
|
249
|
+
) -> np.ndarray | None:
|
|
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
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import warnings
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Sequence
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
import pandas as pd
|
|
@@ -279,13 +279,13 @@ class MASE(TimeSeriesScorer):
|
|
|
279
279
|
def __init__(
|
|
280
280
|
self,
|
|
281
281
|
prediction_length: int = 1,
|
|
282
|
-
seasonal_period:
|
|
283
|
-
horizon_weight:
|
|
282
|
+
seasonal_period: int | None = None,
|
|
283
|
+
horizon_weight: Sequence[float] | None = None,
|
|
284
284
|
):
|
|
285
285
|
super().__init__(
|
|
286
286
|
prediction_length=prediction_length, seasonal_period=seasonal_period, horizon_weight=horizon_weight
|
|
287
287
|
)
|
|
288
|
-
self._past_abs_seasonal_error:
|
|
288
|
+
self._past_abs_seasonal_error: pd.Series | None = None
|
|
289
289
|
|
|
290
290
|
def save_past_metrics(
|
|
291
291
|
self, data_past: TimeSeriesDataFrame, target: str = "target", seasonal_period: int = 1, **kwargs
|
|
@@ -353,13 +353,13 @@ class RMSSE(TimeSeriesScorer):
|
|
|
353
353
|
def __init__(
|
|
354
354
|
self,
|
|
355
355
|
prediction_length: int = 1,
|
|
356
|
-
seasonal_period:
|
|
357
|
-
horizon_weight:
|
|
356
|
+
seasonal_period: int | None = None,
|
|
357
|
+
horizon_weight: Sequence[float] | None = None,
|
|
358
358
|
):
|
|
359
359
|
super().__init__(
|
|
360
360
|
prediction_length=prediction_length, seasonal_period=seasonal_period, horizon_weight=horizon_weight
|
|
361
361
|
)
|
|
362
|
-
self._past_squared_seasonal_error:
|
|
362
|
+
self._past_squared_seasonal_error: pd.Series | None = None
|
|
363
363
|
|
|
364
364
|
def save_past_metrics(
|
|
365
365
|
self, data_past: TimeSeriesDataFrame, target: str = "target", seasonal_period: int = 1, **kwargs
|
|
@@ -471,8 +471,8 @@ class WCD(TimeSeriesScorer):
|
|
|
471
471
|
self,
|
|
472
472
|
alpha: float = 0.5,
|
|
473
473
|
prediction_length: int = 1,
|
|
474
|
-
seasonal_period:
|
|
475
|
-
horizon_weight:
|
|
474
|
+
seasonal_period: int | None = None,
|
|
475
|
+
horizon_weight: Sequence[float] | None = None,
|
|
476
476
|
):
|
|
477
477
|
super().__init__(
|
|
478
478
|
prediction_length=prediction_length, seasonal_period=seasonal_period, horizon_weight=horizon_weight
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Sequence
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
import pandas as pd
|
|
@@ -92,13 +92,13 @@ class SQL(TimeSeriesScorer):
|
|
|
92
92
|
def __init__(
|
|
93
93
|
self,
|
|
94
94
|
prediction_length: int = 1,
|
|
95
|
-
seasonal_period:
|
|
96
|
-
horizon_weight:
|
|
95
|
+
seasonal_period: int | None = None,
|
|
96
|
+
horizon_weight: Sequence[float] | None = None,
|
|
97
97
|
):
|
|
98
98
|
super().__init__(
|
|
99
99
|
prediction_length=prediction_length, seasonal_period=seasonal_period, horizon_weight=horizon_weight
|
|
100
100
|
)
|
|
101
|
-
self._past_abs_seasonal_error:
|
|
101
|
+
self._past_abs_seasonal_error: pd.Series | None = None
|
|
102
102
|
|
|
103
103
|
def save_past_metrics(
|
|
104
104
|
self, data_past: TimeSeriesDataFrame, target: str = "target", seasonal_period: int = 1, **kwargs
|