From c107d37c768916d2c606f71b46b0f50ad8b8c1d3 Mon Sep 17 00:00:00 2001 From: cngmid Date: Thu, 8 May 2025 09:53:15 +0200 Subject: [PATCH 1/6] PR for issue 1823 --- pytorch_forecasting/utils/_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytorch_forecasting/utils/_utils.py b/pytorch_forecasting/utils/_utils.py index af93006cf..b4810ef15 100644 --- a/pytorch_forecasting/utils/_utils.py +++ b/pytorch_forecasting/utils/_utils.py @@ -272,7 +272,7 @@ def concat_sequences( if isinstance(sequences[0], rnn.PackedSequence): return rnn.pack_sequence(sequences, enforce_sorted=False) elif isinstance(sequences[0], torch.Tensor): - return torch.cat(sequences, dim=1) + return torch.cat(sequences, dim=0) elif isinstance(sequences[0], (tuple, list)): return tuple( concat_sequences([sequences[ii][i] for ii in range(len(sequences))]) From a9d8fa3000eb3e5b341014fc0fdea1ec804a26b9 Mon Sep 17 00:00:00 2001 From: cngmid Date: Thu, 8 May 2025 11:22:27 +0200 Subject: [PATCH 2/6] excluding python 3.13 from test and comment nunpy __array_wrap__ warning --- .github/workflows/test.yml | 2 +- pytest.ini | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ccbb25b33..625441e71 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -122,7 +122,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 diff --git a/pytest.ini b/pytest.ini index 457863f87..7180dd345 100644 --- a/pytest.ini +++ b/pytest.ini @@ -26,3 +26,4 @@ filterwarnings = ignore:The dataloader, [\_\s]+ \d+, does not have many workers which may be a bottleneck.:UserWarning ignore:Consider increasing the value of the `num_workers` argument`:UserWarning ignore::UserWarning + ignore:__array_wrap__ must accept context From e0d620e6a60cb897c8d4a73e2e983ac3f32ae5ba Mon Sep 17 00:00:00 2001 From: cngmid Date: Fri, 9 May 2025 11:25:43 +0200 Subject: [PATCH 3/6] reverting changes to test.yml and pytest.ini --- .github/workflows/test.yml | 2 +- pytest.ini | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 625441e71..ccbb25b33 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -122,7 +122,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v4 diff --git a/pytest.ini b/pytest.ini index 7180dd345..457863f87 100644 --- a/pytest.ini +++ b/pytest.ini @@ -26,4 +26,3 @@ filterwarnings = ignore:The dataloader, [\_\s]+ \d+, does not have many workers which may be a bottleneck.:UserWarning ignore:Consider increasing the value of the `num_workers` argument`:UserWarning ignore::UserWarning - ignore:__array_wrap__ must accept context From 21ee21816c0e8ca3d8c20114f9d9d1597d8b9682 Mon Sep 17 00:00:00 2001 From: cngmid Date: Thu, 15 May 2025 15:54:51 +0200 Subject: [PATCH 4/6] Added test for modified functionality --- .../test_temporal_fusion_transformer.py | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/tests/test_models/test_temporal_fusion_transformer.py b/tests/test_models/test_temporal_fusion_transformer.py index 24c249bd5..03e9ea43b 100644 --- a/tests/test_models/test_temporal_fusion_transformer.py +++ b/tests/test_models/test_temporal_fusion_transformer.py @@ -10,7 +10,10 @@ import pytest import torch -from pytorch_forecasting import TimeSeriesDataSet +from pytorch_forecasting import ( + Baseline, + TimeSeriesDataSet +) from pytorch_forecasting.data import NaNLabelEncoder from pytorch_forecasting.data.encoders import GroupNormalizer, MultiNormalizer from pytorch_forecasting.metrics import ( @@ -27,6 +30,7 @@ optimize_hyperparameters, ) from pytorch_forecasting.utils._dependencies import _get_installed_packages +from pytorch_forecasting.data.examples import generate_ar_data if sys.version.startswith("3.6"): # python 3.6 does not have nullcontext from contextlib import contextmanager @@ -521,3 +525,43 @@ def test_no_exogenous_variable(): return_y=True, return_index=True, ) + +def test_correct_prediction_concatenation(): + data = generate_ar_data(seasonality=10.0, timesteps=100, n_series=2, seed=42) + data["static"] = 2 + data["date"] = pd.Timestamp("2020-01-01") + pd.to_timedelta(data.time_idx, "D") + data.head() + + # create dataset and dataloaders + max_encoder_length = 20 + max_prediction_length = 5 + + training_cutoff = data["time_idx"].max() - max_prediction_length + + context_length = max_encoder_length + prediction_length = max_prediction_length + + training = TimeSeriesDataSet( + data[lambda x: x.time_idx <= training_cutoff], + time_idx="time_idx", + target="value", + categorical_encoders={"series": NaNLabelEncoder().fit(data.series)}, + group_ids=["series"], + # only unknown variable is "value" - and N-Beats can also not take any additional variables + time_varying_unknown_reals=["value"], + max_encoder_length=context_length, + max_prediction_length=prediction_length, + ) + + batch_size = 71 + train_dataloader = training.to_dataloader( + train=True, batch_size=batch_size, num_workers=0) + + baseline_model = Baseline() + predictions = baseline_model.predict( + train_dataloader, return_x=True, return_y=True, + trainer_kwargs=dict(logger=None, accelerator="cpu") + ) + + # The predicted output and the target should have the same size. + assert predictions.output.size() == predictions.y[0].size() From 3722a0461a73d77489c28fbfbcc0a6eb943680f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20Kir=C3=A1ly?= Date: Thu, 15 May 2025 19:29:54 +0200 Subject: [PATCH 5/6] lint --- pytorch_forecasting/data/timeseries/_timeseries.py | 2 +- pytorch_forecasting/models/base/_base_model.py | 2 +- pytorch_forecasting/utils/_utils.py | 4 ++-- tests/test_models/test_temporal_fusion_transformer.py | 10 ++++------ 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/pytorch_forecasting/data/timeseries/_timeseries.py b/pytorch_forecasting/data/timeseries/_timeseries.py index 30fe9e0bb..f384367aa 100644 --- a/pytorch_forecasting/data/timeseries/_timeseries.py +++ b/pytorch_forecasting/data/timeseries/_timeseries.py @@ -2348,7 +2348,7 @@ def __getitem__(self, idx: int) -> tuple[dict[str, torch.Tensor], torch.Tensor]: @staticmethod def _collate_fn( - batches: list[tuple[dict[str, torch.Tensor], torch.Tensor]] + batches: list[tuple[dict[str, torch.Tensor], torch.Tensor]], ) -> tuple[dict[str, torch.Tensor], torch.Tensor]: """ Collate function to combine items into mini-batch for dataloader. diff --git a/pytorch_forecasting/models/base/_base_model.py b/pytorch_forecasting/models/base/_base_model.py index f7b14488f..1aa865dff 100644 --- a/pytorch_forecasting/models/base/_base_model.py +++ b/pytorch_forecasting/models/base/_base_model.py @@ -133,7 +133,7 @@ def _concatenate_output( str, List[Union[List[torch.Tensor], torch.Tensor, bool, int, str, np.ndarray]], ] - ] + ], ) -> Dict[ str, Union[torch.Tensor, np.ndarray, List[Union[torch.Tensor, int, bool, str]]] ]: diff --git a/pytorch_forecasting/utils/_utils.py b/pytorch_forecasting/utils/_utils.py index b4810ef15..eb850b1e7 100644 --- a/pytorch_forecasting/utils/_utils.py +++ b/pytorch_forecasting/utils/_utils.py @@ -233,7 +233,7 @@ def autocorrelation(input, dim=0): def unpack_sequence( - sequence: Union[torch.Tensor, rnn.PackedSequence] + sequence: Union[torch.Tensor, rnn.PackedSequence], ) -> Tuple[torch.Tensor, torch.Tensor]: """ Unpack RNN sequence. @@ -257,7 +257,7 @@ def unpack_sequence( def concat_sequences( - sequences: Union[List[torch.Tensor], List[rnn.PackedSequence]] + sequences: Union[List[torch.Tensor], List[rnn.PackedSequence]], ) -> Union[torch.Tensor, rnn.PackedSequence]: """ Concatenate RNN sequences. diff --git a/tests/test_models/test_temporal_fusion_transformer.py b/tests/test_models/test_temporal_fusion_transformer.py index 03e9ea43b..369cb0e7a 100644 --- a/tests/test_models/test_temporal_fusion_transformer.py +++ b/tests/test_models/test_temporal_fusion_transformer.py @@ -10,12 +10,10 @@ import pytest import torch -from pytorch_forecasting import ( - Baseline, - TimeSeriesDataSet -) +from pytorch_forecasting import Baseline, TimeSeriesDataSet from pytorch_forecasting.data import NaNLabelEncoder from pytorch_forecasting.data.encoders import GroupNormalizer, MultiNormalizer +from pytorch_forecasting.data.examples import generate_ar_data from pytorch_forecasting.metrics import ( CrossEntropy, MQF2DistributionLoss, @@ -30,7 +28,6 @@ optimize_hyperparameters, ) from pytorch_forecasting.utils._dependencies import _get_installed_packages -from pytorch_forecasting.data.examples import generate_ar_data if sys.version.startswith("3.6"): # python 3.6 does not have nullcontext from contextlib import contextmanager @@ -547,7 +544,8 @@ def test_correct_prediction_concatenation(): target="value", categorical_encoders={"series": NaNLabelEncoder().fit(data.series)}, group_ids=["series"], - # only unknown variable is "value" - and N-Beats can also not take any additional variables + # only unknown variable is "value" + # and N-Beats can also not take any additional variables time_varying_unknown_reals=["value"], max_encoder_length=context_length, max_prediction_length=prediction_length, From 890d264783db1f517f878cb0734da8fbe196d9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20Kir=C3=A1ly?= Date: Fri, 16 May 2025 21:17:31 +0200 Subject: [PATCH 6/6] linting --- .../test_models/test_temporal_fusion_transformer.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/test_models/test_temporal_fusion_transformer.py b/tests/test_models/test_temporal_fusion_transformer.py index 369cb0e7a..f0eab8671 100644 --- a/tests/test_models/test_temporal_fusion_transformer.py +++ b/tests/test_models/test_temporal_fusion_transformer.py @@ -523,6 +523,7 @@ def test_no_exogenous_variable(): return_index=True, ) + def test_correct_prediction_concatenation(): data = generate_ar_data(seasonality=10.0, timesteps=100, n_series=2, seed=42) data["static"] = 2 @@ -553,13 +554,16 @@ def test_correct_prediction_concatenation(): batch_size = 71 train_dataloader = training.to_dataloader( - train=True, batch_size=batch_size, num_workers=0) + train=True, batch_size=batch_size, num_workers=0 + ) baseline_model = Baseline() predictions = baseline_model.predict( - train_dataloader, return_x=True, return_y=True, - trainer_kwargs=dict(logger=None, accelerator="cpu") + train_dataloader, + return_x=True, + return_y=True, + trainer_kwargs=dict(logger=None, accelerator="cpu"), ) - + # The predicted output and the target should have the same size. assert predictions.output.size() == predictions.y[0].size()