mirror of
https://github.com/wassname/pytorch-ts.git
synced 2026-07-15 11:25:33 +08:00
140 lines
4.9 KiB
Python
140 lines
4.9 KiB
Python
# 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.
|
|
|
|
# Standard library imports
|
|
from typing import List, Optional, Tuple
|
|
|
|
# Third-party imports
|
|
import numpy as np
|
|
from pandas.tseries.frequencies import to_offset
|
|
|
|
from .utils import get_granularity
|
|
|
|
|
|
def _make_lags(middle: int, delta: int) -> np.ndarray:
|
|
"""
|
|
Create a set of lags around a middle point including +/- delta
|
|
"""
|
|
return np.arange(middle - delta, middle + delta + 1).tolist()
|
|
|
|
|
|
def get_lags_for_frequency(
|
|
freq_str: str, lag_ub: int = 1200, num_lags: Optional[int] = None
|
|
) -> List[int]:
|
|
"""
|
|
Generates a list of lags that that are appropriate for the given frequency string.
|
|
|
|
By default all frequencies have the following lags: [1, 2, 3, 4, 5, 6, 7].
|
|
Remaining lags correspond to the same `season` (+/- `delta`) in previous `k` cycles.
|
|
Here `delta` and `k` are chosen according to the existing code.
|
|
|
|
Parameters
|
|
----------
|
|
|
|
freq_str
|
|
Frequency string of the form [multiple][granularity] such as "12H", "5min", "1D" etc.
|
|
|
|
lag_ub
|
|
The maximum value for a lag.
|
|
|
|
num_lags
|
|
Maximum number of lags; by default all generated lags are returned
|
|
"""
|
|
|
|
multiple, granularity = get_granularity(freq_str)
|
|
|
|
# Lags are target values at the same `season` (+/- delta) but in the previous cycle.
|
|
def _make_lags_for_minute(multiple, num_cycles=3):
|
|
# We use previous ``num_cycles`` hours to generate lags
|
|
return [_make_lags(k * 60 // multiple, 2) for k in range(1, num_cycles + 1)]
|
|
|
|
def _make_lags_for_hour(multiple, num_cycles=7):
|
|
# We use previous ``num_cycles`` days to generate lags
|
|
return [_make_lags(k * 24 // multiple, 1) for k in range(1, num_cycles + 1)]
|
|
|
|
def _make_lags_for_day(multiple, num_cycles=4):
|
|
# We use previous ``num_cycles`` weeks to generate lags
|
|
# We use the last month (in addition to 4 weeks) to generate lag.
|
|
return [_make_lags(k * 7 // multiple, 1) for k in range(1, num_cycles + 1)] + [
|
|
_make_lags(30 // multiple, 1)
|
|
]
|
|
|
|
def _make_lags_for_week(multiple, num_cycles=3):
|
|
# We use previous ``num_cycles`` years to generate lags
|
|
# Additionally, we use previous 4, 8, 12 weeks
|
|
return [_make_lags(k * 52 // multiple, 1) for k in range(1, num_cycles + 1)] + [
|
|
[4 // multiple, 8 // multiple, 12 // multiple]
|
|
]
|
|
|
|
def _make_lags_for_month(multiple, num_cycles=3):
|
|
# We use previous ``num_cycles`` years to generate lags
|
|
return [_make_lags(k * 12 // multiple, 1) for k in range(1, num_cycles + 1)]
|
|
|
|
# multiple, granularity = get_granularity(freq_str)
|
|
offset = to_offset(freq_str)
|
|
|
|
if offset.name == "M":
|
|
lags = _make_lags_for_month(offset.n)
|
|
elif offset.name == "W-SUN":
|
|
lags = _make_lags_for_week(offset.n)
|
|
elif offset.name == "D":
|
|
lags = _make_lags_for_day(offset.n) + _make_lags_for_week(offset.n / 7.0)
|
|
elif offset.name == "B":
|
|
# todo find good lags for business day
|
|
lags = []
|
|
elif offset.name == "H":
|
|
lags = (
|
|
_make_lags_for_hour(offset.n)
|
|
+ _make_lags_for_day(offset.n / 24.0)
|
|
+ _make_lags_for_week(offset.n / (24.0 * 7))
|
|
)
|
|
# minutes
|
|
elif offset.name == "T":
|
|
lags = (
|
|
_make_lags_for_minute(offset.n)
|
|
+ _make_lags_for_hour(offset.n / 60.0)
|
|
+ _make_lags_for_day(offset.n / (60.0 * 24))
|
|
+ _make_lags_for_week(offset.n / (60.0 * 24 * 7))
|
|
)
|
|
else:
|
|
raise Exception("invalid frequency")
|
|
|
|
# flatten lags list and filter
|
|
lags = [int(lag) for sub_list in lags for lag in sub_list if 7 < lag <= lag_ub]
|
|
lags = [1, 2, 3, 4, 5, 6, 7] + sorted(list(set(lags)))
|
|
|
|
return lags[:num_lags]
|
|
|
|
|
|
def get_fourier_lags_for_frequency(freq_str: str, num_lags: Optional[int] = None) -> List[int]:
|
|
offset = to_offset(freq_str)
|
|
granularity = 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]
|