From 39d58d688c15fb32a3a09fbdace5e9477c1316f8 Mon Sep 17 00:00:00 2001 From: Kashif Rasul Date: Mon, 28 Dec 2020 12:25:49 +0100 Subject: [PATCH] added back fourier date feature --- pts/feature/fourier_date_feature.py | 69 +++++++++++++++++++++++++++++ pts/feature/lags.py | 28 ++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 pts/feature/fourier_date_feature.py create mode 100644 pts/feature/lags.py diff --git a/pts/feature/fourier_date_feature.py b/pts/feature/fourier_date_feature.py new file mode 100644 index 0000000..6912acd --- /dev/null +++ b/pts/feature/fourier_date_feature.py @@ -0,0 +1,69 @@ +# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). +# You may not use this file except in compliance with the License. +# A copy of the License is located at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# or in the "license" file accompanying this file. This file is distributed +# on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language governing +# permissions and limitations under the License. + +from typing import List + +import numpy as np +import pandas as pd +from pandas.tseries.frequencies import to_offset + +from gluonts.core.component import validated +from gluonts.time_feature import TimeFeature + + +class FourierDateFeatures(TimeFeature): + @validated() + def __init__(self, freq: str) -> None: + super().__init__() + # reocurring freq + freqs = [ + "month", + "day", + "hour", + "minute", + "weekofyear", + "weekday", + "dayofweek", + "dayofyear", + "daysinmonth", + ] + + assert freq in freqs + self.freq = freq + + def __call__(self, index: pd.DatetimeIndex) -> np.ndarray: + values = getattr(index, self.freq) + num_values = max(values) + 1 + steps = [x * 2.0 * np.pi / num_values for x in values] + return np.vstack([np.cos(steps), np.sin(steps)]) + +def fourier_time_features_from_frequency(freq_str: str) -> List[TimeFeature]: + offset = to_offset(freq_str) + multiple, granularity = offset.n, offset.name + + features = { + "M": ["weekofyear"], + "W": ["daysinmonth", "weekofyear"], + "D": ["dayofweek"], + "B": ["dayofweek", "dayofyear"], + "H": ["hour", "dayofweek"], + "min": ["minute", "hour", "dayofweek"], + "T": ["minute", "hour", "dayofweek"], + } + + assert granularity in features, f"freq {granularity} not supported" + + feature_classes: List[TimeFeature] = [ + FourierDateFeatures(freq=freq) for freq in features[granularity] + ] + return feature_classes \ No newline at end of file diff --git a/pts/feature/lags.py b/pts/feature/lags.py new file mode 100644 index 0000000..4836c4c --- /dev/null +++ b/pts/feature/lags.py @@ -0,0 +1,28 @@ +from typing import List, Optional + +from pandas.tseries.frequencies import to_offset + + +def lags_for_fourier_time_features_from_frequency( + freq_str: str, num_lags: Optional[int] = None +) -> List[int]: + offset = to_offset(freq_str) + multiple, granularity = offset.n, offset.name + + if granularity == "M": + lags = [[1, 12]] + elif granularity == "D": + lags = [[1, 7, 14]] + elif granularity == "B": + lags = [[1, 2]] + elif granularity == "H": + lags = [[1, 24, 168]] + elif granularity == "min": + lags = [[1, 4, 12, 24, 48]] + else: + lags = [[1]] + + # use less lags + output_lags = list([int(lag) for sub_list in lags for lag in sub_list]) + output_lags = sorted(list(set(output_lags))) + return output_lags[:num_lags]