Skip to content

Commit

Permalink
Merge branch 'master' into feat/lags_per_component
Browse files Browse the repository at this point in the history
  • Loading branch information
madtoinou authored Sep 14, 2023
2 parents edf8554 + a6ceb5d commit 1235e59
Show file tree
Hide file tree
Showing 34 changed files with 904 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ but cannot always guarantee backwards compatibility. Changes that may **break co
- Added a new argument `start_format` to `historical_forecasts()`, `backtest()` and `gridsearch` that allows to use an integer `start` either as the index position or index value/label for `series` indexed with a `pd.RangeIndex`. [#1866](https://github.com/unit8co/darts/pull/1866) by [Antoine Madrona](https://github.com/madtoinou).
- Added `RINorm` (Reversible Instance Norm) as an input normalization option for all `TorchForecastingModel` except `RNNModel`. Activate it with model creation parameter `use_reversible_instance_norm`. [#1969](https://github.com/unit8co/darts/pull/1969) by [Dennis Bader](https://github.com/dennisbader).
- Reduced the size of the Darts docker image `unit8/darts:latest`, and included all optional models as well as dev requirements. [#1878](https://github.com/unit8co/darts/pull/1878) by [Alex Colpitts](https://github.com/alexcolpitts96).
- Added short examples in the docstring of all the models, including covariates usage and some model-specific parameters. [#1956](https://github.com/unit8co/darts/pull/1956) by [Antoine Madrona](https://github.com/madtoinou).
- All `RegressionModel`s now support component/column-specific lags for target, past, and future covariates series. [#1962](https://github.com/unit8co/darts/pull/1962) by [Antoine Madrona](https://github.com/madtoinou).

**Fixed**
Expand Down
8 changes: 3 additions & 5 deletions darts/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@
from darts.models.forecasting.tft_model import TFTModel
from darts.models.forecasting.tide_model import TiDEModel
from darts.models.forecasting.transformer_model import TransformerModel


except ModuleNotFoundError:
logger.warning(
"Support for Torch based models not available. "
Expand All @@ -51,17 +49,17 @@
try:
from darts.models.forecasting.lgbm import LightGBMModel
except ModuleNotFoundError:
LightGBMModel = NotImportedModule(module_name="LightGBM")
LightGBMModel = NotImportedModule(module_name="LightGBM", warn=False)

try:
from darts.models.forecasting.prophet_model import Prophet
except ImportError:
Prophet = NotImportedModule(module_name="Prophet")
Prophet = NotImportedModule(module_name="Prophet", warn=False)

try:
from darts.models.forecasting.catboost_model import CatBoostModel
except ModuleNotFoundError:
CatBoostModel = NotImportedModule(module_name="CatBoost")
CatBoostModel = NotImportedModule(module_name="CatBoost", warn=False)

try:
from darts.models.forecasting.croston import Croston
Expand Down
25 changes: 24 additions & 1 deletion darts/models/forecasting/arima.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,37 @@ def __init__(
.. highlight:: python
.. code-block:: python
def encode_year(idx):
return (idx.year - 1950) / 50
add_encoders={
'cyclic': {'future': ['month']},
'datetime_attribute': {'future': ['hour', 'dayofweek']},
'position': {'future': ['relative']},
'custom': {'future': [lambda idx: (idx.year - 1950) / 50]},
'custom': {'future': [encode_year]},
'transformer': Scaler()
}
..
Examples
--------
>>> from darts.datasets import AirPassengersDataset
>>> from darts.models import ARIMA
>>> from darts.utils.timeseries_generation import datetime_attribute_timeseries
>>> series = AirPassengersDataset().load()
>>> # optionally, use some future covariates; e.g. the value of the month encoded as a sine and cosine series
>>> future_cov = datetime_attribute_timeseries(series, "month", cyclic=True, add_length=6)
>>> # define ARIMA parameters
>>> model = ARIMA(p=12, d=1, q=2)
>>> model.fit(series, future_covariates=future_cov)
>>> pred = model.predict(6, future_covariates=future_cov)
>>> pred.values()
array([[451.36489334],
[416.88972829],
[443.10520391],
[481.07892911],
[502.11286509],
[555.50153984]])
"""
super().__init__(add_encoders=add_encoders)
self.order = p, d, q
Expand Down
25 changes: 24 additions & 1 deletion darts/models/forecasting/auto_arima.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,37 @@ def __init__(
.. highlight:: python
.. code-block:: python
def encode_year(idx):
return (idx.year - 1950) / 50
add_encoders={
'cyclic': {'future': ['month']},
'datetime_attribute': {'future': ['hour', 'dayofweek']},
'position': {'future': ['relative']},
'custom': {'future': [lambda idx: (idx.year - 1950) / 50]},
'custom': {'future': [encode_year]},
'transformer': Scaler()
}
..
Examples
--------
>>> from darts.datasets import AirPassengersDataset
>>> from darts.models import AutoARIMA
>>> from darts.utils.timeseries_generation import holidays_timeseries
>>> series = AirPassengersDataset().load()
>>> # optionally, use some future covariates; e.g. the value of the month encoded as a sine and cosine series
>>> future_cov = datetime_attribute_timeseries(series, "month", cyclic=True, add_length=6)
>>> # define some boundaries for the parameters
>>> model = AutoARIMA(start_p=8, max_p=12, start_q=1)
>>> model.fit(series, future_covariates=future_cov)
>>> pred = model.predict(6, future_covariates=future_cov)
>>> pred.values()
array([[449.79716178],
[416.31180633],
[445.28005229],
[485.27121314],
[507.61787454],
[561.26993332]])
"""
super().__init__(add_encoders=add_encoders)
self.model = PmdAutoARIMA(*autoarima_args, **autoarima_kwargs)
Expand Down
82 changes: 82 additions & 0 deletions darts/models/forecasting/baselines.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,22 @@ def __init__(self):
This model has no parameter, and always predicts the
mean value of the training series.
Examples
--------
>>> from darts.datasets import AirPassengersDataset
>>> from darts.models import NaiveMean
>>> series = AirPassengersDataset().load()
>>> model = NaiveMean()
>>> model.fit(series)
>>> pred = model.predict(6)
>>> pred.values()
array([[280.29861111],
[280.29861111],
[280.29861111],
[280.29861111],
[280.29861111],
[280.29861111]])
"""
super().__init__()
self.mean_val = None
Expand Down Expand Up @@ -63,6 +79,23 @@ def __init__(self, K: int = 1):
----------
K
the number of last time steps of the training set to repeat
Examples
--------
>>> from darts.datasets import AirPassengersDataset
>>> from darts.models import NaiveSeasonal
>>> series = AirPassengersDataset().load()
# prior analysis suggested seasonality of 12
>>> model = NaiveSeasonal(K=12)
>>> model.fit(series)
>>> pred = model.predict(6)
>>> pred.values()
array([[417.],
[391.],
[419.],
[461.],
[472.],
[535.]])
"""
super().__init__()
self.last_k_vals = None
Expand Down Expand Up @@ -106,6 +139,22 @@ def __init__(self):
and extends it in the future. For a training series of length :math:`T`, we have:
.. math:: \\hat{y}_{T+h} = y_T + h\\left( \\frac{y_T - y_1}{T - 1} \\right)
Examples
--------
>>> from darts.datasets import AirPassengersDataset
>>> from darts.models import NaiveDrift
>>> series = AirPassengersDataset().load()
>>> model = NaiveDrift()
>>> model.fit(series)
>>> pred = model.predict(6)
>>> pred.values()
array([[434.23776224],
[436.47552448],
[438.71328671],
[440.95104895],
[443.18881119],
[445.42657343]])
"""
super().__init__()

Expand Down Expand Up @@ -147,6 +196,22 @@ def __init__(self, input_chunk_length: int = 1):
----------
input_chunk_length
The size of the sliding window used to calculate the moving average
Examples
--------
>>> from darts.datasets import AirPassengersDataset
>>> from darts.models import NaiveMovingAverage
>>> series = AirPassengersDataset().load()
# using the average of the last 6 months
>>> model = NaiveMovingAverage(input_chunk_length=6)
>>> pred = model.predict(6)
>>> pred.values()
array([[503.16666667],
[483.36111111],
[462.9212963 ],
[455.40817901],
[454.47620885],
[465.22224366]])
"""
super().__init__()
self.input_chunk_length = input_chunk_length
Expand Down Expand Up @@ -217,6 +282,23 @@ def __init__(
List of forecasting models whose predictions to ensemble
show_warnings
Whether to show warnings related to models covariates support.
Examples
--------
>>> from darts.datasets import AirPassengersDataset
>>> from darts.models import NaiveEnsembleModel, NaiveSeasonal, LinearRegressionModel
>>> series = AirPassengersDataset().load()
>>> # defining the ensemble
>>> model = NaiveEnsembleModel([NaiveSeasonal(K=12), LinearRegressionModel(lags=4)])
>>> model.fit(series)
>>> pred = model.predict(6)
>>> pred.values()
array([[439.23152974],
[431.41161602],
[439.72888401],
[453.70180806],
[454.96757177],
[485.16604194]])
"""
super().__init__(
models=models,
Expand Down
30 changes: 30 additions & 0 deletions darts/models/forecasting/block_rnn_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,36 @@ def encode_year(idx):
----------
.. [1] T. Kim et al. "Reversible Instance Normalization for Accurate Time-Series Forecasting against
Distribution Shift", https://openreview.net/forum?id=cGDAkQo1C0p
Examples
--------
>>> from darts.datasets import WeatherDataset
>>> from darts.models import BlockRNNModel
>>> series = WeatherDataset().load()
>>> # predicting atmospheric pressure
>>> target = series['p (mbar)'][:100]
>>> # optionally, use past observed rainfall (pretending to be unknown beyond index 100)
>>> past_cov = series['rain (mm)'][:100]
>>> # predict 6 pressure values using the 12 past values of pressure and rainfall, as well as the 6 temperature
>>> model = BlockRNNModel(
>>> input_chunk_length=12,
>>> output_chunk_length=6,
>>> n_rnn_layers=2,
>>> n_epochs=50,
>>> )
>>> model.fit(target, past_covariates=past_cov)
>>> pred = model.predict(6)
>>> pred.values()
array([[4.97979827],
[3.9707572 ],
[5.27869295],
[5.19697244],
[5.28424783],
[5.22497681]])
.. note::
`RNN example notebook <https://unit8co.github.io/darts/examples/04-RNN-examples.html>`_ presents techniques
that can be used to improve the forecasts quality compared to this simple usage example.
"""
super().__init__(**self._extract_torch_model_params(**self.model_params))

Expand Down
29 changes: 29 additions & 0 deletions darts/models/forecasting/catboost_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,35 @@ def encode_year(idx):
that all target `series` have the same static covariate dimensionality in ``fit()`` and ``predict()``.
**kwargs
Additional keyword arguments passed to `catboost.CatBoostRegressor`.
Examples
--------
>>> from darts.datasets import WeatherDataset
>>> from darts.models import CatBoostModel
>>> series = WeatherDataset().load()
>>> # predicting atmospheric pressure
>>> target = series['p (mbar)'][:100]
>>> # optionally, use past observed rainfall (pretending to be unknown beyond index 100)
>>> past_cov = series['rain (mm)'][:100]
>>> # optionally, use future temperatures (pretending this component is a forecast)
>>> future_cov = series['T (degC)'][:106]
>>> # predict 6 pressure values using the 12 past values of pressure and rainfall, as well as the 6 temperature
>>> # values corresponding to the forecasted period
>>> model = CatBoostModel(
>>> lags=12,
>>> lags_past_covariates=12,
>>> lags_future_covariates=[0,1,2,3,4,5],
>>> output_chunk_length=6
>>> )
>>> model.fit(target, past_covariates=past_cov, future_covariates=future_cov)
>>> pred = model.predict(6)
>>> pred.values()
array([[1006.4153701 ],
[1006.41907237],
[1006.30872957],
[1006.28614154],
[1006.22355514],
[1006.21607546]])
"""
kwargs["random_state"] = random_state # seed for tree learner
self.kwargs = kwargs
Expand Down
22 changes: 21 additions & 1 deletion darts/models/forecasting/croston.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,14 @@ def __init__(
.. highlight:: python
.. code-block:: python
def encode_year(idx):
return (idx.year - 1950) / 50
add_encoders={
'cyclic': {'future': ['month']},
'datetime_attribute': {'future': ['hour', 'dayofweek']},
'position': {'future': ['relative']},
'custom': {'future': [lambda idx: (idx.year - 1950) / 50]},
'custom': {'future': [encode_year]},
'transformer': Scaler()
}
..
Expand All @@ -74,6 +77,23 @@ def __init__(
.. [2] Ruud H. Teunter, Aris A. Syntetos, and M. Zied Babai.
Intermittent demand: Linking forecasting to inventory obsolescence.
European Journal of Operational Research, 214(3):606 – 615, 2011.
Examples
--------
>>> from darts.datasets import AirPassengersDataset
>>> from darts.models import Croston
>>> series = AirPassengersDataset().load()
>>> # use the optimized version to automatically select best alpha parameter
>>> model = Croston(version="optimized")
>>> model.fit(series)
>>> pred = model.predict(6)
>>> pred.values()
array([[461.7666],
[461.7666],
[461.7666],
[461.7666],
[461.7666],
[461.7666]])
"""
super().__init__(add_encoders=add_encoders)
raise_if_not(
Expand Down
33 changes: 33 additions & 0 deletions darts/models/forecasting/dlinear.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,39 @@ def encode_year(idx):
Are Transformers Effective for Time Series Forecasting?. arXiv preprint arXiv:2205.13504.
.. [2] T. Kim et al. "Reversible Instance Normalization for Accurate Time-Series Forecasting against
Distribution Shift", https://openreview.net/forum?id=cGDAkQo1C0p
Examples
--------
>>> from darts.datasets import WeatherDataset
>>> from darts.models import DLinearModel
>>> series = WeatherDataset().load()
>>> # predicting atmospheric pressure
>>> target = series['p (mbar)'][:100]
>>> # optionally, use past observed rainfall (pretending to be unknown beyond index 100)
>>> past_cov = series['rain (mm)'][:100]
>>> # optionally, use future temperatures (pretending this component is a forecast)
>>> future_cov = series['T (degC)'][:106]
>>> # predict 6 pressure values using the 12 past values of pressure and rainfall, as well as the 6 temperature
>>> # values corresponding to the forecasted period
>>> model = DLinearModel(
>>> input_chunk_length=6,
>>> output_chunk_length=6,
>>> n_epochs=20,
>>> )
>>> model.fit(target, past_covariates=past_cov, future_covariates=future_cov)
>>> pred = model.predict(6)
>>> pred.values()
array([[667.20957388],
[666.76986848],
[666.67733306],
[666.06625381],
[665.8529289 ],
[665.75320573]])
.. note::
This simple usage example produces poor forecasts. In order to obtain better performance, user should
transform the input data, increase the number of epochs, use a validation set, optimize the hyper-
parameters, ...
"""
super().__init__(**self._extract_torch_model_params(**self.model_params))

Expand Down
Loading

0 comments on commit 1235e59

Please sign in to comment.