Skip to content

Commit 036fa07

Browse files
authored
Merge branch 'master' into issue-1329
2 parents efb4608 + cd93027 commit 036fa07

36 files changed

+2682
-994
lines changed

CHANGELOG.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
- `DeseasonalityTransform` ([#1307](https://github.com/tinkoff-ai/etna/pull/1307))
1111
-
1212
- Add extension with models from `statsforecast`: `StatsForecastARIMAModel`, `StatsForecastAutoARIMAModel`, `StatsForecastAutoCESModel`, `StatsForecastAutoETSModel`, `StatsForecastAutoThetaModel` ([#1295](https://github.com/tinkoff-ai/etna/pull/1297))
13+
- Notebook `feature_selection` ([#875](https://github.com/tinkoff-ai/etna/pull/875))
1314
-
14-
-
15+
- Implementation of PatchTS model ([#1277](https://github.com/tinkoff-ai/etna/pull/1277))
1516

1617
### Changed
1718
-
1819
-
19-
-
20-
-
20+
- Unify errors, warnings and checks in models ([#1312](https://github.com/tinkoff-ai/etna/pull/1312))
21+
- Remove upper limitation on version of numba ([#1321](https://github.com/tinkoff-ai/etna/pull/1321))
2122

2223
### Fixed
2324
- Pipeline ensembles fail in `etna forecast` CLI ([#1331](https://github.com/tinkoff-ai/etna/pull/1331))
2425
-
25-
-
26+
- Fix performance of `DeepARModel` and `TFTModel` ([#1322](https://github.com/tinkoff-ai/etna/pull/1322))
2627
- `mrmr` feature selection working with categoricals ([#1311](https://github.com/tinkoff-ai/etna/pull/1311))
27-
-
28+
- Fix version of `statsforecast` to 1.4 to avoid dependency conflicts during installation ([#1313](https://github.com/tinkoff-ai/etna/pull/1313))
29+
- Add inverse transformation into `predict` method of pipelines ([#1314](https://github.com/tinkoff-ai/etna/pull/1314))
2830

2931
### Removed
3032
- Building docker images with cuda 10.2 ([#1306](https://github.com/tinkoff-ai/etna/pull/1306))

README.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -175,15 +175,19 @@ We have also prepared a set of tutorials for an easy introduction:
175175
| [Get started](https://github.com/tinkoff-ai/etna/tree/master/examples/get_started.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/get_started.ipynb) |
176176
| [Backtest](https://github.com/tinkoff-ai/etna/tree/master/examples/backtest.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/backtest.ipynb) |
177177
| [EDA](https://github.com/tinkoff-ai/etna/tree/master/examples/EDA.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/EDA.ipynb) |
178-
| [Outliers](https://github.com/tinkoff-ai/etna/tree/master/examples/outliers.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/outliers.ipynb) |
179-
| [Clustering](https://github.com/tinkoff-ai/etna/tree/master/examples/clustering.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/clustering.ipynb) |
178+
| [Regressors and exogenous data](https://github.com/tinkoff-ai/etna/tree/master/examples/exogenous_data.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/exogenous_data.ipynb) |
179+
| [Custom model and transform](https://github.com/tinkoff-ai/etna/tree/master/examples/custom_transform_and_model.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/custom_transform_and_model.ipynb) |
180180
| [Deep learning models](https://github.com/tinkoff-ai/etna/tree/master/examples/NN_examples.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/NN_examples.ipynb) |
181181
| [Ensembles](https://github.com/tinkoff-ai/etna/tree/master/examples/ensembles.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/ensembles.ipynb) |
182-
| [Custom Transform and Model](https://github.com/tinkoff-ai/etna/tree/master/examples/custom_transform_and_model.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/custom_transform_and_model.ipynb) |
183-
| [Exogenous data](https://github.com/tinkoff-ai/etna/tree/master/examples/exogenous_data.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/exogenous_data.ipynb) |
184-
| [Forecasting strategies](https://github.com/tinkoff-ai/etna/blob/master/examples/forecasting_strategies.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/forecasting_strategies.ipynb) |
185-
| [Classification](https://github.com/tinkoff-ai/etna/blob/master/examples/classification.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/classification.ipynb) |
182+
| [Outliers](https://github.com/tinkoff-ai/etna/tree/master/examples/outliers.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/outliers.ipynb) |
183+
| [Forecasting strategies](https://github.com/tinkoff-ai/etna/tree/master/examples/forecasting_strategies.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/forecasting_strategies.ipynb) |
184+
| [Forecast interpretation](https://github.com/tinkoff-ai/etna/tree/master/examples/forecast_interpretation.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/forecast_interpretation.ipynb) |
185+
| [Clustering](https://github.com/tinkoff-ai/etna/tree/master/examples/clustering.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/clustering.ipynb) |
186+
| [AutoML](https://github.com/tinkoff-ai/etna/tree/master/examples/automl.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/automl.ipynb) |
187+
| [Inference: using saved pipeline on a new data](https://github.com/tinkoff-ai/etna/tree/master/examples/inference.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/inference.ipynb) |
186188
| [Hierarchical time series](https://github.com/tinkoff-ai/etna/blob/master/examples/hierarchical_pipeline.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/hierarchical_pipeline.ipynb) |
189+
| [Classification](https://github.com/tinkoff-ai/etna/blob/master/examples/classification.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/classification.ipynb) |
190+
| [Feature selection](https://github.com/tinkoff-ai/etna/blob/master/examples/feature_selection.ipynb) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/tinkoff-ai/etna/master?filepath=examples/feature_selection.ipynb) |
187191

188192
## Documentation
189193

etna/analysis/feature_relevance/relevance_table.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def _prepare_df(df: pd.DataFrame, df_exog: pd.DataFrame, segment: str, regressor
3636

3737
def get_statistics_relevance_table(df: pd.DataFrame, df_exog: pd.DataFrame) -> pd.DataFrame:
3838
"""Calculate relevance table with p-values from tsfresh.
39+
3940
Parameters
4041
----------
4142
df:

etna/models/deadline_ma.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ def get_model(self) -> "DeadlineMovingAverageModel":
9191
"""
9292
return self
9393

94+
def _check_not_used_columns(self, ts: TSDataset):
95+
columns = set(ts.columns.get_level_values("feature"))
96+
columns_not_used = columns.difference({"target"})
97+
if columns_not_used:
98+
warnings.warn(
99+
message=f"This model doesn't work with exogenous features. "
100+
f"Columns {columns_not_used} won't be used."
101+
)
102+
94103
def fit(self, ts: TSDataset) -> "DeadlineMovingAverageModel":
95104
"""Fit model.
96105
@@ -109,14 +118,8 @@ def fit(self, ts: TSDataset) -> "DeadlineMovingAverageModel":
109118
if freq not in self._freqs_available:
110119
raise ValueError(f"Freq {freq} is not supported! Use daily or hourly frequency!")
111120

121+
self._check_not_used_columns(ts)
112122
self._freq = freq
113-
114-
columns = set(ts.columns.get_level_values("feature"))
115-
if columns != {"target"}:
116-
warnings.warn(
117-
message=f"{type(self).__name__} does not work with any exogenous series or features. "
118-
f"It uses only target series for predict/\n "
119-
)
120123
return self
121124

122125
@staticmethod

etna/models/holt_winters.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,15 @@ def __init__(
201201
self._last_train_timestamp: Optional[pd.Timestamp] = None
202202
self._train_freq: Optional[str] = None
203203

204+
def _check_not_used_columns(self, df: pd.DataFrame):
205+
columns = df.columns
206+
columns_not_used = set(columns).difference({"target", "timestamp"})
207+
if columns_not_used:
208+
warnings.warn(
209+
message=f"This model doesn't work with exogenous features. "
210+
f"Columns {columns_not_used} won't be used."
211+
)
212+
204213
def fit(self, df: pd.DataFrame, regressors: List[str]) -> "_HoltWintersAdapter":
205214
"""
206215
Fit Holt-Winters' model.
@@ -217,8 +226,7 @@ def fit(self, df: pd.DataFrame, regressors: List[str]) -> "_HoltWintersAdapter":
217226
Fitted model
218227
"""
219228
self._train_freq = determine_freq(timestamps=df["timestamp"])
220-
221-
self._check_df(df)
229+
self._check_not_used_columns(df)
222230

223231
targets = df["target"]
224232
targets.index = df["timestamp"]
@@ -268,21 +276,11 @@ def predict(self, df: pd.DataFrame) -> np.ndarray:
268276
"""
269277
if self._result is None or self._model is None:
270278
raise ValueError("This model is not fitted! Fit the model before calling predict method!")
271-
self._check_df(df)
272279

273280
forecast = self._result.predict(start=df["timestamp"].min(), end=df["timestamp"].max())
274281
y_pred = forecast.values
275282
return y_pred
276283

277-
def _check_df(self, df: pd.DataFrame):
278-
columns = df.columns
279-
columns_not_used = set(columns).difference({"target", "timestamp"})
280-
if columns_not_used:
281-
warnings.warn(
282-
message=f"This model does not work with exogenous features and regressors.\n "
283-
f"{columns_not_used} will be dropped"
284-
)
285-
286284
def get_model(self) -> HoltWintersResultsWrapper:
287285
"""Get :py:class:`statsmodels.tsa.holtwinters.results.HoltWintersResultsWrapper` model that was fitted inside etna class.
288286
@@ -303,7 +301,7 @@ def _check_mul_components(self):
303301
if (model.trend is not None and model.trend == "mul") or (
304302
model.seasonal is not None and model.seasonal == "mul"
305303
):
306-
raise ValueError("Forecast decomposition is only supported for additive components!")
304+
raise NotImplementedError("Forecast decomposition is only supported for additive components!")
307305

308306
def _rescale_components(self, components: pd.DataFrame) -> pd.DataFrame:
309307
"""Rescale components when Box-Cox transform used."""
@@ -335,15 +333,17 @@ def forecast_components(self, df: pd.DataFrame) -> pd.DataFrame:
335333
raise ValueError("This model is not fitted!")
336334

337335
if df["timestamp"].min() <= self._last_train_timestamp:
338-
raise ValueError("To estimate in-sample prediction decomposition use `predict` method.")
336+
raise NotImplementedError(
337+
"This model can't make forecast decomposition on history data! "
338+
"Use method predict for in-sample prediction decomposition."
339+
)
339340

340341
horizon = determine_num_steps(
341342
start_timestamp=self._last_train_timestamp, end_timestamp=df["timestamp"].max(), freq=self._train_freq
342343
)
343344
horizon_steps = np.arange(1, horizon + 1)
344345

345346
self._check_mul_components()
346-
self._check_df(df)
347347

348348
level = fit_result.level.values
349349
trend = fit_result.trend.values
@@ -404,10 +404,12 @@ def predict_components(self, df: pd.DataFrame) -> pd.DataFrame:
404404
raise ValueError("This model is not fitted!")
405405

406406
if df["timestamp"].min() < self._first_train_timestamp or df["timestamp"].max() > self._last_train_timestamp:
407-
raise ValueError("To estimate out-of-sample prediction decomposition use `forecast` method.")
407+
raise NotImplementedError(
408+
"This model can't make prediction decomposition on future out-of-sample data! "
409+
"Use method forecast for future out-of-sample prediction decomposition."
410+
)
408411

409412
self._check_mul_components()
410-
self._check_df(df)
411413

412414
level = fit_result.level.values
413415
trend = fit_result.trend.values

etna/models/nn/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from etna.models.nn.mlp import MLPModel
77
from etna.models.nn.nbeats import NBeatsGenericModel
88
from etna.models.nn.nbeats import NBeatsInterpretableModel
9+
from etna.models.nn.patchts import PatchTSModel
910
from etna.models.nn.rnn import RNNModel
1011
from etna.models.nn.tft import TFTModel
1112
from etna.models.nn.utils import PytorchForecastingDatasetBuilder

0 commit comments

Comments
 (0)