File size: 1,961 Bytes
bdd9175
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
"""Seasonal discretization scale factor.

Maps a pandas frequency string to the model's seasonal scale factor
``s = base_seasonality / (samples per natural period)``, i.e. how many
context samples fall in one canonical seasonal cycle at that sampling rate.
"""
from __future__ import annotations

from typing import Optional

# Cycles per canonical day: the unit every scale factor is expressed against.
# ``tinycast.losses`` reads this so the seasonal lag the committing term folds
# at and the scale factor the model is conditioned on cannot drift apart.
BASE_SEASONALITY = 24.0


def seasonal_scale_factor(freq: str, domain: Optional[str] = None) -> float:
    """Seasonal scale factor for a pandas frequency string."""
    has_weekly = domain in ["Transport", "Healthcare", "Sales"]

    if freq == "4S":
        factor = BASE_SEASONALITY / (3600.0 / 4)
    elif freq == "10S":
        factor = BASE_SEASONALITY / 360
    elif freq == "T":
        factor = BASE_SEASONALITY / (24.0 * 60)
    elif freq[-1] == "T":
        n_min = int(freq[:-1])
        factor = BASE_SEASONALITY / (24 * 60 / n_min)
    elif freq == "H":
        factor = BASE_SEASONALITY / 24
    elif freq == "6H":
        factor = BASE_SEASONALITY / 4
    elif freq == "D":
        factor = BASE_SEASONALITY / 7 if has_weekly else BASE_SEASONALITY / 365
    elif freq[-1] == "D" and "WED" not in freq:
        n = int(freq[:-1])
        factor = BASE_SEASONALITY / 7 if has_weekly else BASE_SEASONALITY / 365
        factor *= n
    elif freq == "W" or "W-" in freq:
        factor = BASE_SEASONALITY / (365.0 / 7)
    elif freq == "M" or "M-" in freq or freq == "MS":
        factor = BASE_SEASONALITY / 12
    elif "Q" in freq:
        factor = BASE_SEASONALITY / 4.0
    elif "A" in freq:
        factor = BASE_SEASONALITY / 4.0
    else:
        raise NotImplementedError(
            f"{freq} not implemented. Add {freq} option to seasonal_scale_factor."
        )
    return factor