Skip to content

Commit

Permalink
use scalers from coreforecast (#873)
Browse files Browse the repository at this point in the history
* use scalers from coreforecast

* update base class

* update docstrnig

* remove base scaler
  • Loading branch information
jmoralez authored Jan 25, 2024
1 parent 8a05d89 commit f3ff57b
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 29 deletions.
3 changes: 2 additions & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ channels:
- conda-forge
- pytorch
dependencies:
- coreforecast>=0.0.3
- hyperopt
- jupyterlab
- matplotlib
Expand All @@ -19,4 +20,4 @@ dependencies:
- black
- polars
- "ray[tune]>=2.2.0"
- utilsforecast>=0.0.24
- utilsforecast>=0.0.25
27 changes: 12 additions & 15 deletions nbs/core.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,13 @@
"import pandas as pd\n",
"import torch\n",
"import utilsforecast.processing as ufp\n",
"from utilsforecast.compat import DataFrame, Series, pl_DataFrame, pl_Series\n",
"from utilsforecast.grouped_array import GroupedArray\n",
"from utilsforecast.target_transforms import (\n",
" BaseTargetTransform,\n",
" LocalBoxCox,\n",
" LocalMinMaxScaler, \n",
" LocalRobustScaler, \n",
"from coreforecast.grouped_array import GroupedArray\n",
"from coreforecast.scalers import (\n",
" LocalMinMaxScaler,\n",
" LocalRobustScaler,\n",
" LocalStandardScaler,\n",
")\n",
"from utilsforecast.compat import DataFrame, Series, pl_DataFrame, pl_Series\n",
"from utilsforecast.validation import validate_freq\n",
"\n",
"from neuralforecast.tsdataset import TimeSeriesDataset\n",
Expand Down Expand Up @@ -233,7 +231,6 @@
" 'robust': lambda: LocalRobustScaler(scale='mad'),\n",
" 'robust-iqr': lambda: LocalRobustScaler(scale='iqr'),\n",
" 'minmax': LocalMinMaxScaler,\n",
" 'boxcox': LocalBoxCox,\n",
"}"
]
},
Expand Down Expand Up @@ -286,7 +283,7 @@
" Frequency of the data. Must be a valid pandas or polars offset alias, or an integer.\n",
" local_scaler_type : str, optional (default=None)\n",
" Scaler to apply per-serie to all features before fitting, which is inverted after predicting.\n",
" Can be 'standard', 'robust', 'robust-iqr', 'minmax' or 'boxcox'\n",
" Can be 'standard', 'robust', 'robust-iqr' or 'minmax'\n",
" \n",
" Returns\n",
" -------\n",
Expand All @@ -301,7 +298,7 @@
" if local_scaler_type is not None and local_scaler_type not in _type2scaler:\n",
" raise ValueError(f'scaler_type must be one of {_type2scaler.keys()}')\n",
" self.local_scaler_type = local_scaler_type\n",
" self.scalers_: Dict[str, BaseTargetTransform]\n",
" self.scalers_: Dict\n",
"\n",
" # Flags and attributes\n",
" self._fitted = False\n",
Expand All @@ -314,10 +311,10 @@
" for i, col in enumerate(dataset.temporal_cols):\n",
" if col == 'available_mask':\n",
" continue\n",
" self.scalers_[col] = _type2scaler[self.local_scaler_type]() \n",
" ga = GroupedArray(dataset.temporal[:, i].numpy(), dataset.indptr)\n",
" dataset.temporal[:, i] = torch.from_numpy(self.scalers_[col].fit_transform(ga))\n",
" \n",
" ga = GroupedArray(dataset.temporal[:, i].numpy(), dataset.indptr) \n",
" self.scalers_[col] = _type2scaler[self.local_scaler_type]().fit(ga)\n",
" dataset.temporal[:, i] = torch.from_numpy(self.scalers_[col].transform(ga))\n",
"\n",
" def _scalers_transform(self, dataset: TimeSeriesDataset) -> None:\n",
" if not self.scalers_:\n",
" return None\n",
Expand Down Expand Up @@ -1466,7 +1463,7 @@
")\n",
"\n",
"# CV\n",
"nf = NeuralForecast(models=models, freq='M', local_scaler_type='robust-iqr')\n",
"nf = NeuralForecast(models=models, freq='M', local_scaler_type='robust')\n",
"cv_res = nf.cross_validation(AirPassengersPanel)\n",
"# check that the forecasts are similar to the original values (originals are restored directly from the df)\n",
"np.testing.assert_allclose(\n",
Expand Down
19 changes: 7 additions & 12 deletions neuralforecast/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@
import pandas as pd
import torch
import utilsforecast.processing as ufp
from utilsforecast.compat import DataFrame, Series, pl_DataFrame, pl_Series
from utilsforecast.grouped_array import GroupedArray
from utilsforecast.target_transforms import (
BaseTargetTransform,
LocalBoxCox,
from coreforecast.grouped_array import GroupedArray
from coreforecast.scalers import (
LocalMinMaxScaler,
LocalRobustScaler,
LocalStandardScaler,
)
from utilsforecast.compat import DataFrame, Series, pl_DataFrame, pl_Series
from utilsforecast.validation import validate_freq

from .tsdataset import TimeSeriesDataset
Expand Down Expand Up @@ -147,7 +145,6 @@ def _insample_times(
"robust": lambda: LocalRobustScaler(scale="mad"),
"robust-iqr": lambda: LocalRobustScaler(scale="iqr"),
"minmax": LocalMinMaxScaler,
"boxcox": LocalBoxCox,
}

# %% ../nbs/core.ipynb 9
Expand Down Expand Up @@ -186,7 +183,7 @@ def __init__(
Frequency of the data. Must be a valid pandas or polars offset alias, or an integer.
local_scaler_type : str, optional (default=None)
Scaler to apply per-serie to all features before fitting, which is inverted after predicting.
Can be 'standard', 'robust', 'robust-iqr', 'minmax' or 'boxcox'
Can be 'standard', 'robust', 'robust-iqr' or 'minmax'
Returns
-------
Expand All @@ -203,7 +200,7 @@ def __init__(
if local_scaler_type is not None and local_scaler_type not in _type2scaler:
raise ValueError(f"scaler_type must be one of {_type2scaler.keys()}")
self.local_scaler_type = local_scaler_type
self.scalers_: Dict[str, BaseTargetTransform]
self.scalers_: Dict

# Flags and attributes
self._fitted = False
Expand All @@ -216,11 +213,9 @@ def _scalers_fit_transform(self, dataset: TimeSeriesDataset) -> None:
for i, col in enumerate(dataset.temporal_cols):
if col == "available_mask":
continue
self.scalers_[col] = _type2scaler[self.local_scaler_type]()
ga = GroupedArray(dataset.temporal[:, i].numpy(), dataset.indptr)
dataset.temporal[:, i] = torch.from_numpy(
self.scalers_[col].fit_transform(ga)
)
self.scalers_[col] = _type2scaler[self.local_scaler_type]().fit(ga)
dataset.temporal[:, i] = torch.from_numpy(self.scalers_[col].transform(ga))

def _scalers_transform(self, dataset: TimeSeriesDataset) -> None:
if not self.scalers_:
Expand Down
2 changes: 1 addition & 1 deletion settings.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ language = English
custom_sidebar = True
license = apache2
status = 2
requirements = numpy>=1.21.6 pandas>=1.3.5 torch>=2.0.0 pytorch-lightning>=2.0.0 ray[tune]>=2.2.0 optuna utilsforecast>=0.0.24 numba
requirements = coreforecast>=0.0.3 numpy>=1.21.6 pandas>=1.3.5 torch>=2.0.0 pytorch-lightning>=2.0.0 ray[tune]>=2.2.0 optuna utilsforecast>=0.0.25
dev_requirements = nbdev black mypy ruff matplotlib hyperopt polars pyarrow
nbs_path = nbs
doc_path = _docs
Expand Down

0 comments on commit f3ff57b

Please sign in to comment.