autogluon.timeseries 1.0.1b20240304__py3-none-any.whl → 1.4.1b20251210__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/__init__.py +3 -2
- autogluon/timeseries/configs/hyperparameter_presets.py +62 -0
- autogluon/timeseries/configs/predictor_presets.py +84 -0
- autogluon/timeseries/dataset/ts_dataframe.py +339 -186
- autogluon/timeseries/learner.py +192 -60
- autogluon/timeseries/metrics/__init__.py +55 -11
- autogluon/timeseries/metrics/abstract.py +96 -25
- autogluon/timeseries/metrics/point.py +186 -39
- autogluon/timeseries/metrics/quantile.py +47 -20
- autogluon/timeseries/metrics/utils.py +6 -6
- autogluon/timeseries/models/__init__.py +13 -7
- autogluon/timeseries/models/abstract/__init__.py +2 -2
- autogluon/timeseries/models/abstract/abstract_timeseries_model.py +533 -273
- autogluon/timeseries/models/abstract/model_trial.py +10 -10
- autogluon/timeseries/models/abstract/tunable.py +189 -0
- autogluon/timeseries/models/autogluon_tabular/__init__.py +2 -0
- autogluon/timeseries/models/autogluon_tabular/mlforecast.py +369 -215
- autogluon/timeseries/models/autogluon_tabular/per_step.py +513 -0
- autogluon/timeseries/models/autogluon_tabular/transforms.py +67 -0
- autogluon/timeseries/models/autogluon_tabular/utils.py +3 -51
- autogluon/timeseries/models/chronos/__init__.py +4 -0
- autogluon/timeseries/models/chronos/chronos2.py +361 -0
- autogluon/timeseries/models/chronos/model.py +738 -0
- autogluon/timeseries/models/chronos/utils.py +369 -0
- autogluon/timeseries/models/ensemble/__init__.py +35 -2
- autogluon/timeseries/models/ensemble/{abstract_timeseries_ensemble.py → abstract.py} +50 -26
- autogluon/timeseries/models/ensemble/array_based/__init__.py +3 -0
- autogluon/timeseries/models/ensemble/array_based/abstract.py +236 -0
- autogluon/timeseries/models/ensemble/array_based/models.py +73 -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 +167 -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/ensemble_selection.py +167 -0
- autogluon/timeseries/models/ensemble/per_item_greedy.py +162 -0
- autogluon/timeseries/models/ensemble/weighted/__init__.py +8 -0
- autogluon/timeseries/models/ensemble/weighted/abstract.py +40 -0
- autogluon/timeseries/models/ensemble/weighted/basic.py +78 -0
- autogluon/timeseries/models/ensemble/weighted/greedy.py +57 -0
- autogluon/timeseries/models/gluonts/__init__.py +3 -1
- autogluon/timeseries/models/gluonts/abstract.py +583 -0
- autogluon/timeseries/models/gluonts/dataset.py +109 -0
- autogluon/timeseries/models/gluonts/{torch/models.py → models.py} +185 -44
- autogluon/timeseries/models/local/__init__.py +1 -10
- autogluon/timeseries/models/local/abstract_local_model.py +150 -97
- autogluon/timeseries/models/local/naive.py +31 -23
- autogluon/timeseries/models/local/npts.py +6 -2
- autogluon/timeseries/models/local/statsforecast.py +99 -112
- autogluon/timeseries/models/multi_window/multi_window_model.py +99 -40
- autogluon/timeseries/models/registry.py +64 -0
- autogluon/timeseries/models/toto/__init__.py +3 -0
- autogluon/timeseries/models/toto/_internal/__init__.py +9 -0
- autogluon/timeseries/models/toto/_internal/backbone/__init__.py +3 -0
- autogluon/timeseries/models/toto/_internal/backbone/attention.py +196 -0
- autogluon/timeseries/models/toto/_internal/backbone/backbone.py +262 -0
- autogluon/timeseries/models/toto/_internal/backbone/distribution.py +70 -0
- autogluon/timeseries/models/toto/_internal/backbone/kvcache.py +136 -0
- autogluon/timeseries/models/toto/_internal/backbone/rope.py +89 -0
- autogluon/timeseries/models/toto/_internal/backbone/rotary_embedding_torch.py +342 -0
- autogluon/timeseries/models/toto/_internal/backbone/scaler.py +305 -0
- autogluon/timeseries/models/toto/_internal/backbone/transformer.py +333 -0
- autogluon/timeseries/models/toto/_internal/dataset.py +165 -0
- autogluon/timeseries/models/toto/_internal/forecaster.py +423 -0
- autogluon/timeseries/models/toto/dataloader.py +108 -0
- autogluon/timeseries/models/toto/hf_pretrained_model.py +118 -0
- autogluon/timeseries/models/toto/model.py +236 -0
- autogluon/timeseries/predictor.py +826 -305
- autogluon/timeseries/regressor.py +253 -0
- autogluon/timeseries/splitter.py +10 -31
- autogluon/timeseries/trainer/__init__.py +2 -3
- autogluon/timeseries/trainer/ensemble_composer.py +439 -0
- autogluon/timeseries/trainer/model_set_builder.py +256 -0
- autogluon/timeseries/trainer/prediction_cache.py +149 -0
- autogluon/timeseries/trainer/trainer.py +1298 -0
- autogluon/timeseries/trainer/utils.py +17 -0
- autogluon/timeseries/transforms/__init__.py +2 -0
- autogluon/timeseries/transforms/covariate_scaler.py +164 -0
- autogluon/timeseries/transforms/target_scaler.py +149 -0
- autogluon/timeseries/utils/constants.py +10 -0
- autogluon/timeseries/utils/datetime/base.py +38 -20
- autogluon/timeseries/utils/datetime/lags.py +18 -16
- autogluon/timeseries/utils/datetime/seasonality.py +14 -14
- autogluon/timeseries/utils/datetime/time_features.py +17 -14
- autogluon/timeseries/utils/features.py +317 -53
- autogluon/timeseries/utils/forecast.py +31 -17
- autogluon/timeseries/utils/timer.py +173 -0
- autogluon/timeseries/utils/warning_filters.py +44 -6
- autogluon/timeseries/version.py +2 -1
- autogluon.timeseries-1.4.1b20251210-py3.11-nspkg.pth +1 -0
- {autogluon.timeseries-1.0.1b20240304.dist-info → autogluon_timeseries-1.4.1b20251210.dist-info}/METADATA +71 -47
- autogluon_timeseries-1.4.1b20251210.dist-info/RECORD +103 -0
- {autogluon.timeseries-1.0.1b20240304.dist-info → autogluon_timeseries-1.4.1b20251210.dist-info}/WHEEL +1 -1
- autogluon/timeseries/configs/presets_configs.py +0 -11
- autogluon/timeseries/evaluator.py +0 -6
- autogluon/timeseries/models/ensemble/greedy_ensemble.py +0 -170
- autogluon/timeseries/models/gluonts/abstract_gluonts.py +0 -550
- autogluon/timeseries/models/gluonts/torch/__init__.py +0 -0
- autogluon/timeseries/models/presets.py +0 -325
- autogluon/timeseries/trainer/abstract_trainer.py +0 -1144
- autogluon/timeseries/trainer/auto_trainer.py +0 -74
- autogluon.timeseries-1.0.1b20240304-py3.8-nspkg.pth +0 -1
- autogluon.timeseries-1.0.1b20240304.dist-info/RECORD +0 -58
- {autogluon.timeseries-1.0.1b20240304.dist-info → autogluon_timeseries-1.4.1b20251210.dist-info/licenses}/LICENSE +0 -0
- {autogluon.timeseries-1.0.1b20240304.dist-info → autogluon_timeseries-1.4.1b20251210.dist-info/licenses}/NOTICE +0 -0
- {autogluon.timeseries-1.0.1b20240304.dist-info → autogluon_timeseries-1.4.1b20251210.dist-info}/namespace_packages.txt +0 -0
- {autogluon.timeseries-1.0.1b20240304.dist-info → autogluon_timeseries-1.4.1b20251210.dist-info}/top_level.txt +0 -0
- {autogluon.timeseries-1.0.1b20240304.dist-info → autogluon_timeseries-1.4.1b20251210.dist-info}/zip-safe +0 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import time
|
|
3
|
+
from typing import Any, Protocol, overload, runtime_checkable
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
from autogluon.core.models import AbstractModel
|
|
9
|
+
from autogluon.tabular.registry import ag_model_registry as tabular_ag_model_registry
|
|
10
|
+
from autogluon.timeseries.dataset import TimeSeriesDataFrame
|
|
11
|
+
from autogluon.timeseries.utils.features import CovariateMetadata
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@runtime_checkable
|
|
17
|
+
class CovariateRegressor(Protocol):
|
|
18
|
+
def is_fit(self) -> bool: ...
|
|
19
|
+
|
|
20
|
+
def fit(self, data: TimeSeriesDataFrame, time_limit: float | None = None, **kwargs) -> "CovariateRegressor": ...
|
|
21
|
+
|
|
22
|
+
def transform(self, data: TimeSeriesDataFrame) -> TimeSeriesDataFrame: ...
|
|
23
|
+
|
|
24
|
+
def fit_transform(
|
|
25
|
+
self, data: TimeSeriesDataFrame, time_limit: float | None = None, **kwargs
|
|
26
|
+
) -> TimeSeriesDataFrame: ...
|
|
27
|
+
|
|
28
|
+
def inverse_transform(
|
|
29
|
+
self,
|
|
30
|
+
predictions: TimeSeriesDataFrame,
|
|
31
|
+
known_covariates: TimeSeriesDataFrame,
|
|
32
|
+
static_features: pd.DataFrame | None,
|
|
33
|
+
) -> TimeSeriesDataFrame: ...
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class GlobalCovariateRegressor(CovariateRegressor):
|
|
37
|
+
"""Predicts target values from the covariates for the same observation.
|
|
38
|
+
|
|
39
|
+
The model construct the feature matrix using known_covariates and static_features.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
model_name
|
|
44
|
+
Name of the tabular regression model. See ``autogluon.tabular.registry.ag_model_registry`` or
|
|
45
|
+
`the documentation <https://auto.gluon.ai/stable/api/autogluon.tabular.models.html>`_ for the list of available
|
|
46
|
+
tabular models.
|
|
47
|
+
model_hyperparameters
|
|
48
|
+
Hyperparameters passed to the tabular regression model.
|
|
49
|
+
eval_metric
|
|
50
|
+
Metric provided as ``eval_metric`` to the tabular regression model. Must be compatible with `problem_type="regression"`.
|
|
51
|
+
refit_during_predict
|
|
52
|
+
If True, the model will be re-trained every time ``fit_transform`` is called. If False, the model will only be
|
|
53
|
+
trained the first time that ``fit_transform`` is called, and future calls to ``fit_transform`` will only perform a
|
|
54
|
+
``transform``.
|
|
55
|
+
max_num_samples
|
|
56
|
+
If not None, training dataset passed to regression model will contain at most this many rows.
|
|
57
|
+
covariate_metadata
|
|
58
|
+
Metadata object describing the covariates available in the dataset.
|
|
59
|
+
target
|
|
60
|
+
Name of the target column.
|
|
61
|
+
validation_fraction
|
|
62
|
+
Fraction of observations that are reserved as the validation set during training (starting from the end of each
|
|
63
|
+
time series).
|
|
64
|
+
fit_time_fraction
|
|
65
|
+
The fraction of the time_limit that will be reserved for model training. The remainder (1 - fit_time_fraction)
|
|
66
|
+
will be reserved for prediction.
|
|
67
|
+
|
|
68
|
+
If the estimated prediction time exceeds ``(1 - fit_time_fraction) * time_limit``, the regressor will be disabled.
|
|
69
|
+
include_static_features
|
|
70
|
+
If True, static features will be included as features for the regressor.
|
|
71
|
+
include_item_id
|
|
72
|
+
If True, item_id will be included as a categorical feature for the regressor.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(
|
|
76
|
+
self,
|
|
77
|
+
model_name: str = "CAT",
|
|
78
|
+
model_hyperparameters: dict[str, Any] | None = None,
|
|
79
|
+
eval_metric: str = "mean_absolute_error",
|
|
80
|
+
refit_during_predict: bool = False,
|
|
81
|
+
max_num_samples: int | None = 500_000,
|
|
82
|
+
covariate_metadata: CovariateMetadata | None = None,
|
|
83
|
+
target: str = "target",
|
|
84
|
+
validation_fraction: float | None = 0.1,
|
|
85
|
+
fit_time_fraction: float = 0.5,
|
|
86
|
+
include_static_features: bool = True,
|
|
87
|
+
include_item_id: bool = False,
|
|
88
|
+
):
|
|
89
|
+
self.target = target
|
|
90
|
+
self.model_type = tabular_ag_model_registry.key_to_cls(model_name)
|
|
91
|
+
self.model_name = model_name
|
|
92
|
+
self.model_hyperparameters = model_hyperparameters or {}
|
|
93
|
+
self.refit_during_predict = refit_during_predict
|
|
94
|
+
self.tabular_eval_metric = eval_metric
|
|
95
|
+
self.max_num_samples = max_num_samples
|
|
96
|
+
self.validation_fraction = validation_fraction
|
|
97
|
+
self.fit_time_fraction = fit_time_fraction
|
|
98
|
+
self.include_static_features = include_static_features
|
|
99
|
+
self.include_item_id = include_item_id
|
|
100
|
+
|
|
101
|
+
self.model: AbstractModel | None = None
|
|
102
|
+
self.disabled = False
|
|
103
|
+
self.covariate_metadata = covariate_metadata or CovariateMetadata()
|
|
104
|
+
|
|
105
|
+
def is_fit(self) -> bool:
|
|
106
|
+
return self.model is not None
|
|
107
|
+
|
|
108
|
+
def fit(self, data: TimeSeriesDataFrame, time_limit: float | None = None, **kwargs) -> "CovariateRegressor":
|
|
109
|
+
"""Fit the tabular regressor on the target column using covariates as features."""
|
|
110
|
+
start_time = time.monotonic()
|
|
111
|
+
tabular_df = self._get_tabular_df(data, static_features=data.static_features, include_target=True)
|
|
112
|
+
tabular_df = tabular_df.query(f"{self.target}.notnull()")
|
|
113
|
+
|
|
114
|
+
median_ts_length = data.num_timesteps_per_item().median()
|
|
115
|
+
features_to_drop = [self.target]
|
|
116
|
+
if not self.include_item_id:
|
|
117
|
+
features_to_drop += [TimeSeriesDataFrame.ITEMID]
|
|
118
|
+
if self.validation_fraction is not None:
|
|
119
|
+
grouped_df = tabular_df.groupby(TimeSeriesDataFrame.ITEMID, observed=False, sort=False)
|
|
120
|
+
val_size = max(int(self.validation_fraction * median_ts_length), 1)
|
|
121
|
+
train_df = self._subsample_df(grouped_df.head(-val_size))
|
|
122
|
+
val_df = self._subsample_df(grouped_df.tail(val_size))
|
|
123
|
+
X = train_df.drop(columns=features_to_drop)
|
|
124
|
+
y = train_df[self.target]
|
|
125
|
+
X_val = val_df.drop(columns=features_to_drop)
|
|
126
|
+
y_val = val_df[self.target]
|
|
127
|
+
else:
|
|
128
|
+
tabular_df = self._subsample_df(tabular_df)
|
|
129
|
+
X = tabular_df.drop(columns=features_to_drop)
|
|
130
|
+
y = tabular_df[self.target]
|
|
131
|
+
X_val = None
|
|
132
|
+
y_val = None
|
|
133
|
+
|
|
134
|
+
self.model = self.model_type(
|
|
135
|
+
problem_type="regression",
|
|
136
|
+
hyperparameters={
|
|
137
|
+
**self.model_hyperparameters,
|
|
138
|
+
"ag_args_fit": {"predict_1_batch_size": 10000}, # needed to compute predict_1_time
|
|
139
|
+
},
|
|
140
|
+
eval_metric=self.tabular_eval_metric,
|
|
141
|
+
# Has no effect since the model won't be saved to disk.
|
|
142
|
+
# We provide path to avoid https://github.com/autogluon/autogluon/issues/4832
|
|
143
|
+
path="",
|
|
144
|
+
name=self.model_type.__name__,
|
|
145
|
+
)
|
|
146
|
+
if time_limit is not None:
|
|
147
|
+
time_limit_fit = self.fit_time_fraction * (time_limit - (time.monotonic() - start_time))
|
|
148
|
+
else:
|
|
149
|
+
time_limit_fit = None
|
|
150
|
+
# Don't fit if all features are constant to avoid autogluon.core.utils.exceptions.NoValidFeatures
|
|
151
|
+
if (X.nunique() <= 1).all():
|
|
152
|
+
logger.warning("\tDisabling the covariate_regressor since all features are constant.")
|
|
153
|
+
self.disabled = True
|
|
154
|
+
else:
|
|
155
|
+
self.model.fit(X=X, y=y, X_val=X_val, y_val=y_val, time_limit=time_limit_fit, **kwargs)
|
|
156
|
+
|
|
157
|
+
if time_limit is not None:
|
|
158
|
+
time_left = time_limit - (time.monotonic() - start_time)
|
|
159
|
+
assert self.model.predict_1_time is not None
|
|
160
|
+
estimated_predict_time = self.model.predict_1_time * len(data)
|
|
161
|
+
if estimated_predict_time > time_left:
|
|
162
|
+
logger.warning(
|
|
163
|
+
f"\tDisabling the covariate_regressor since {estimated_predict_time=:.1f} exceeds {time_left=:.1f}."
|
|
164
|
+
)
|
|
165
|
+
self.disabled = True
|
|
166
|
+
return self
|
|
167
|
+
|
|
168
|
+
def transform(self, data: TimeSeriesDataFrame) -> TimeSeriesDataFrame:
|
|
169
|
+
"""Subtract the tabular regressor predictions from the target column."""
|
|
170
|
+
if not self.disabled:
|
|
171
|
+
y_pred = self._predict(data, static_features=data.static_features)
|
|
172
|
+
data = data.assign(**{self.target: data[self.target] - y_pred})
|
|
173
|
+
return data
|
|
174
|
+
|
|
175
|
+
def fit_transform(
|
|
176
|
+
self, data: TimeSeriesDataFrame, time_limit: float | None = None, **kwargs
|
|
177
|
+
) -> TimeSeriesDataFrame:
|
|
178
|
+
if not self.is_fit() or self.refit_during_predict:
|
|
179
|
+
self.fit(data=data, time_limit=time_limit, **kwargs)
|
|
180
|
+
return self.transform(data=data)
|
|
181
|
+
|
|
182
|
+
def inverse_transform(
|
|
183
|
+
self,
|
|
184
|
+
predictions: TimeSeriesDataFrame,
|
|
185
|
+
known_covariates: TimeSeriesDataFrame,
|
|
186
|
+
static_features: pd.DataFrame | None,
|
|
187
|
+
) -> TimeSeriesDataFrame:
|
|
188
|
+
"""Add the tabular regressor predictions to the target column."""
|
|
189
|
+
if not self.disabled:
|
|
190
|
+
y_pred = self._predict(known_covariates, static_features=static_features)
|
|
191
|
+
predictions = predictions.assign(**{col: predictions[col] + y_pred for col in predictions.columns})
|
|
192
|
+
return predictions
|
|
193
|
+
|
|
194
|
+
def _predict(self, data: TimeSeriesDataFrame, static_features: pd.DataFrame | None) -> np.ndarray:
|
|
195
|
+
"""Construct the tabular features matrix and make predictions"""
|
|
196
|
+
assert self.model is not None, "CovariateRegressor must be fit before calling predict."
|
|
197
|
+
tabular_df = self._get_tabular_df(data, static_features=static_features)
|
|
198
|
+
if not self.include_item_id:
|
|
199
|
+
tabular_df = tabular_df.drop(columns=[TimeSeriesDataFrame.ITEMID])
|
|
200
|
+
return self.model.predict(X=tabular_df)
|
|
201
|
+
|
|
202
|
+
def _get_tabular_df(
|
|
203
|
+
self,
|
|
204
|
+
data: TimeSeriesDataFrame,
|
|
205
|
+
static_features: pd.DataFrame | None = None,
|
|
206
|
+
include_target: bool = False,
|
|
207
|
+
) -> pd.DataFrame:
|
|
208
|
+
"""Construct a tabular dataframe from known covariates and static features."""
|
|
209
|
+
available_columns = [TimeSeriesDataFrame.ITEMID] + self.covariate_metadata.known_covariates
|
|
210
|
+
if include_target:
|
|
211
|
+
available_columns += [self.target]
|
|
212
|
+
tabular_df = (
|
|
213
|
+
pd.DataFrame(data).reset_index()[available_columns].astype({TimeSeriesDataFrame.ITEMID: "category"})
|
|
214
|
+
)
|
|
215
|
+
if static_features is not None and self.include_static_features:
|
|
216
|
+
tabular_df = pd.merge(tabular_df, static_features, on=TimeSeriesDataFrame.ITEMID)
|
|
217
|
+
return tabular_df
|
|
218
|
+
|
|
219
|
+
def _subsample_df(self, df: pd.DataFrame) -> pd.DataFrame:
|
|
220
|
+
"""Randomly subsample the dataframe if it contains more than self.max_num_samples rows."""
|
|
221
|
+
if self.max_num_samples is not None and len(df) > self.max_num_samples:
|
|
222
|
+
df = df.sample(n=self.max_num_samples)
|
|
223
|
+
return df
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@overload
|
|
227
|
+
def get_covariate_regressor(covariate_regressor: None, target: str, covariate_metadata: CovariateMetadata) -> None: ...
|
|
228
|
+
@overload
|
|
229
|
+
def get_covariate_regressor(
|
|
230
|
+
covariate_regressor: str | dict, target: str, covariate_metadata: CovariateMetadata
|
|
231
|
+
) -> CovariateRegressor: ...
|
|
232
|
+
def get_covariate_regressor(
|
|
233
|
+
covariate_regressor: str | dict | None, target: str, covariate_metadata: CovariateMetadata
|
|
234
|
+
) -> CovariateRegressor | None:
|
|
235
|
+
"""Create a CovariateRegressor object based on the value of the `covariate_regressor` hyperparameter."""
|
|
236
|
+
if covariate_regressor is None:
|
|
237
|
+
return None
|
|
238
|
+
elif len(covariate_metadata.known_covariates + covariate_metadata.static_features) == 0:
|
|
239
|
+
logger.info(
|
|
240
|
+
"\tSkipping covariate_regressor since the dataset contains no known_covariates or static_features."
|
|
241
|
+
)
|
|
242
|
+
return None
|
|
243
|
+
else:
|
|
244
|
+
if isinstance(covariate_regressor, str):
|
|
245
|
+
return GlobalCovariateRegressor(covariate_regressor, target=target, covariate_metadata=covariate_metadata)
|
|
246
|
+
elif isinstance(covariate_regressor, dict):
|
|
247
|
+
return GlobalCovariateRegressor(
|
|
248
|
+
**covariate_regressor, target=target, covariate_metadata=covariate_metadata
|
|
249
|
+
)
|
|
250
|
+
else:
|
|
251
|
+
raise ValueError(
|
|
252
|
+
f"Invalid value for covariate_regressor {covariate_regressor} of type {type(covariate_regressor)}"
|
|
253
|
+
)
|
autogluon/timeseries/splitter.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
from typing import Iterator
|
|
1
|
+
from typing import Iterator
|
|
2
2
|
|
|
3
|
-
from .dataset
|
|
3
|
+
from autogluon.timeseries.dataset import TimeSeriesDataFrame
|
|
4
4
|
|
|
5
5
|
__all__ = [
|
|
6
6
|
"AbstractWindowSplitter",
|
|
@@ -13,6 +13,9 @@ class AbstractWindowSplitter:
|
|
|
13
13
|
self.prediction_length = prediction_length
|
|
14
14
|
self.num_val_windows = num_val_windows
|
|
15
15
|
|
|
16
|
+
def split(self, data: TimeSeriesDataFrame) -> Iterator[tuple[TimeSeriesDataFrame, TimeSeriesDataFrame]]:
|
|
17
|
+
raise NotImplementedError
|
|
18
|
+
|
|
16
19
|
|
|
17
20
|
class ExpandingWindowSplitter(AbstractWindowSplitter):
|
|
18
21
|
"""For each train / validation split, training data includes all available past data.
|
|
@@ -30,21 +33,21 @@ class ExpandingWindowSplitter(AbstractWindowSplitter):
|
|
|
30
33
|
|
|
31
34
|
Parameters
|
|
32
35
|
----------
|
|
33
|
-
prediction_length
|
|
36
|
+
prediction_length
|
|
34
37
|
Length of the forecast horizon.
|
|
35
|
-
num_val_windows
|
|
38
|
+
num_val_windows
|
|
36
39
|
Number of windows to generate from each time series in the dataset.
|
|
37
|
-
val_step_size
|
|
40
|
+
val_step_size
|
|
38
41
|
The end of each subsequent window is moved this many time steps forward.
|
|
39
42
|
"""
|
|
40
43
|
|
|
41
|
-
def __init__(self, prediction_length: int, num_val_windows: int = 1, val_step_size:
|
|
44
|
+
def __init__(self, prediction_length: int, num_val_windows: int = 1, val_step_size: int | None = None):
|
|
42
45
|
super().__init__(prediction_length=prediction_length, num_val_windows=num_val_windows)
|
|
43
46
|
if val_step_size is None:
|
|
44
47
|
val_step_size = prediction_length
|
|
45
48
|
self.val_step_size = val_step_size
|
|
46
49
|
|
|
47
|
-
def split(self, data: TimeSeriesDataFrame) -> Iterator[
|
|
50
|
+
def split(self, data: TimeSeriesDataFrame) -> Iterator[tuple[TimeSeriesDataFrame, TimeSeriesDataFrame]]:
|
|
48
51
|
"""Generate train and validation folds for a time series dataset."""
|
|
49
52
|
for window_idx in range(1, self.num_val_windows + 1):
|
|
50
53
|
val_end = -(self.num_val_windows - window_idx) * self.val_step_size
|
|
@@ -54,27 +57,3 @@ class ExpandingWindowSplitter(AbstractWindowSplitter):
|
|
|
54
57
|
train_data = data.slice_by_timestep(None, train_end)
|
|
55
58
|
val_data = data.slice_by_timestep(None, val_end)
|
|
56
59
|
yield train_data, val_data
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class AbstractTimeSeriesSplitter:
|
|
60
|
-
def __init__(self, *args, **kwargs):
|
|
61
|
-
raise ValueError(
|
|
62
|
-
"`AbstractTimeSeriesSplitter` has been deprecated. "
|
|
63
|
-
"Please use `autogluon.timeseries.splitter.ExpandingWindowSplitter` instead."
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class MultiWindowSplitter(AbstractTimeSeriesSplitter):
|
|
68
|
-
def __init__(self, *args, **kwargs):
|
|
69
|
-
raise ValueError(
|
|
70
|
-
"`MultiWindowSplitter` has been deprecated. "
|
|
71
|
-
"Please use `autogluon.timeseries.splitter.ExpandingWindowSplitter` instead."
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
class LastWindowSplitter(MultiWindowSplitter):
|
|
76
|
-
def __init__(self, *args, **kwargs):
|
|
77
|
-
raise ValueError(
|
|
78
|
-
"`LastWindowSplitter` has been deprecated. "
|
|
79
|
-
"Please use `autogluon.timeseries.splitter.ExpandingWindowSplitter` instead."
|
|
80
|
-
)
|