Skip to content

Commit

Permalink
jose_comments
Browse files Browse the repository at this point in the history
  • Loading branch information
elephaint committed Dec 2, 2024
1 parent 046c5be commit 1855108
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 158 deletions.
18 changes: 9 additions & 9 deletions hierarchicalforecast/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from narwhals.typing import Frame, FrameT
from scipy.stats import norm
from scipy import sparse
from typing import Dict, List, Optional
from typing import Optional

import narwhals as nw
import numpy as np
Expand Down Expand Up @@ -104,7 +104,7 @@ class HierarchicalReconciliation:
[Rob J. Hyndman and George Athanasopoulos (2018). \"Forecasting principles and practice, Hierarchical and Grouped Series\".](https://otexts.com/fpp3/hierarchical.html)
"""

def __init__(self, reconcilers: List[HReconciler]):
def __init__(self, reconcilers: list[HReconciler]):
self.reconcilers = reconcilers
self.orig_reconcilers = copy.deepcopy(reconcilers) # TODO: elegant solution
self.insample = any([method.insample for method in reconcilers])
Expand All @@ -114,13 +114,13 @@ def _prepare_fit(
Y_hat_nw: Frame,
S_nw: Frame,
Y_nw: Optional[Frame],
tags: Dict[str, np.ndarray],
level: Optional[List[int]] = None,
tags: dict[str, np.ndarray],
level: Optional[list[int]] = None,
intervals_method: str = "normality",
id_col: str = "unique_id",
time_col: str = "ds",
target_col: str = "y",
) -> tuple[FrameT, FrameT, FrameT, List[str]]:
) -> tuple[FrameT, FrameT, FrameT, list[str]]:
"""
Performs preliminary wrangling and protections
"""
Expand Down Expand Up @@ -267,9 +267,9 @@ def reconcile(
self,
Y_hat_df: Frame,
S: Frame,
tags: Dict[str, np.ndarray],
tags: dict[str, np.ndarray],
Y_df: Optional[Frame] = None,
level: Optional[List[int]] = None,
level: Optional[list[int]] = None,
intervals_method: str = "normality",
num_samples: int = -1,
seed: int = 0,
Expand Down Expand Up @@ -505,9 +505,9 @@ def bootstrap_reconcile(
self,
Y_hat_df: Frame,
S_df: Frame,
tags: Dict[str, np.ndarray],
tags: dict[str, np.ndarray],
Y_df: Optional[Frame] = None,
level: Optional[List[int]] = None,
level: Optional[list[int]] = None,
intervals_method: str = "normality",
num_samples: int = -1,
num_seeds: int = 1,
Expand Down
24 changes: 12 additions & 12 deletions hierarchicalforecast/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from inspect import signature
from narwhals.typing import Frame, FrameT
from scipy.stats import multivariate_normal
from typing import Callable, Dict, List, Optional, Union
from typing import Callable, Optional, Union

# %% ../nbs/src/evaluation.ipynb 7
def _metric_protections(
Expand Down Expand Up @@ -349,14 +349,14 @@ class HierarchicalEvaluation:
**References:**<br>
"""

def __init__(self, evaluators: List[Callable]):
def __init__(self, evaluators: list[Callable]):
self.evaluators = evaluators

def evaluate(
self,
Y_hat_df: Frame,
Y_test_df: Frame,
tags: Dict[str, np.ndarray],
tags: dict[str, np.ndarray],
Y_df: Optional[Frame] = None,
benchmark: Optional[str] = None,
id_col: str = "unique_id",
Expand Down Expand Up @@ -458,16 +458,16 @@ def evaluate(
evaluation_index_np[i_level * len(fn_names) + i_fn, 1] = fn_name

evaluation_np = evaluation_np.reshape(-1, len(model_names))
evaluation_index_dict = {
"level": evaluation_index_np[:, 0],
"metric": evaluation_index_np[:, 1],
}
evaluation_index_nw = nw.from_dict(
evaluation_index_dict, native_namespace=native_namespace
evaluation_nw = nw.from_dict(
{
**{
"level": evaluation_index_np[:, 0],
"metric": evaluation_index_np[:, 1],
},
**dict(zip(model_names, evaluation_np.T)),
},
native_namespace=native_namespace,
)
evaluation_dict = dict(zip(model_names, evaluation_np.T))
evaluation_nw = evaluation_index_nw.with_columns(**evaluation_dict)
evaluation_nw = evaluation_nw[["level", "metric"] + model_names]

evaluation = evaluation_nw.to_native()

Expand Down
56 changes: 28 additions & 28 deletions hierarchicalforecast/methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from collections import OrderedDict
from concurrent.futures import ThreadPoolExecutor
from copy import deepcopy
from typing import Dict, List, Optional, Union
from typing import Optional, Union

import numpy as np
from quadprog import solve_qp
Expand Down Expand Up @@ -81,7 +81,7 @@ def _reconcile(
P: np.ndarray,
y_hat: np.ndarray,
SP: np.ndarray = None,
level: Optional[List[int]] = None,
level: Optional[list[int]] = None,
sampler: Optional[Union[Normality, PERMBU, Bootstrap]] = None,
):

Expand All @@ -101,7 +101,7 @@ def _reconcile(
return res

def predict(
self, S: np.ndarray, y_hat: np.ndarray, level: Optional[List[int]] = None
self, S: np.ndarray, y_hat: np.ndarray, level: Optional[list[int]] = None
):
"""Predict using reconciler.
Expand Down Expand Up @@ -194,7 +194,7 @@ def fit(
intervals_method: Optional[str] = None,
num_samples: Optional[int] = None,
seed: Optional[int] = None,
tags: Optional[Dict[str, np.ndarray]] = None,
tags: Optional[dict[str, np.ndarray]] = None,
):
"""Bottom Up Fit Method.
Expand Down Expand Up @@ -235,11 +235,11 @@ def fit_predict(
y_insample: Optional[np.ndarray] = None,
y_hat_insample: Optional[np.ndarray] = None,
sigmah: Optional[np.ndarray] = None,
level: Optional[List[int]] = None,
level: Optional[list[int]] = None,
intervals_method: Optional[str] = None,
num_samples: Optional[int] = None,
seed: Optional[int] = None,
tags: Optional[Dict[str, np.ndarray]] = None,
tags: Optional[dict[str, np.ndarray]] = None,
):
"""BottomUp Reconciliation Method.
Expand Down Expand Up @@ -300,7 +300,7 @@ def _get_PW_matrices(self, S, idx_bottom):

# %% ../nbs/src/methods.ipynb 27
def _get_child_nodes(
S: Union[np.ndarray, sparse.csr_matrix], tags: Dict[str, np.ndarray]
S: Union[np.ndarray, sparse.csr_matrix], tags: dict[str, np.ndarray]
):
if isinstance(S, sparse.spmatrix):
S = S.toarray()
Expand All @@ -324,8 +324,8 @@ def _get_child_nodes(
def _reconcile_fcst_proportions(
S: np.ndarray,
y_hat: np.ndarray,
tags: Dict[str, np.ndarray],
nodes: Dict[str, Dict[int, np.ndarray]],
tags: dict[str, np.ndarray],
nodes: dict[str, dict[int, np.ndarray]],
idx_top: int,
):
reconciled = np.zeros_like(y_hat)
Expand Down Expand Up @@ -369,7 +369,7 @@ def _get_PW_matrices(
S: np.ndarray,
y_hat: np.ndarray,
y_insample: np.ndarray,
tags: Optional[Dict[str, np.ndarray]] = None,
tags: Optional[dict[str, np.ndarray]] = None,
):

n_hiers, n_bottom = S.shape
Expand Down Expand Up @@ -416,7 +416,7 @@ def fit(
intervals_method: Optional[str] = None,
num_samples: Optional[int] = None,
seed: Optional[int] = None,
tags: Optional[Dict[str, np.ndarray]] = None,
tags: Optional[dict[str, np.ndarray]] = None,
idx_bottom: Optional[np.ndarray] = None,
):
"""TopDown Fit Method.
Expand Down Expand Up @@ -458,12 +458,12 @@ def fit_predict(
self,
S: np.ndarray,
y_hat: np.ndarray,
tags: Dict[str, np.ndarray],
tags: dict[str, np.ndarray],
idx_bottom: np.ndarray = None,
y_insample: Optional[np.ndarray] = None,
y_hat_insample: Optional[np.ndarray] = None,
sigmah: Optional[np.ndarray] = None,
level: Optional[List[int]] = None,
level: Optional[list[int]] = None,
intervals_method: Optional[str] = None,
num_samples: Optional[int] = None,
seed: Optional[int] = None,
Expand Down Expand Up @@ -540,7 +540,7 @@ def _get_PW_matrices(
S: sparse.csr_matrix,
y_hat: np.ndarray,
y_insample: np.ndarray,
tags: Optional[Dict[str, np.ndarray]] = None,
tags: Optional[dict[str, np.ndarray]] = None,
):
# Check if the data structure is strictly hierarchical.
if tags is not None and not is_strictly_hierarchical(S, tags):
Expand Down Expand Up @@ -625,9 +625,9 @@ def fit_predict(
self,
S: np.ndarray,
y_hat: np.ndarray,
tags: Dict[str, np.ndarray],
tags: dict[str, np.ndarray],
y_insample: Optional[np.ndarray] = None,
level: Optional[List[int]] = None,
level: Optional[list[int]] = None,
intervals_method: Optional[str] = None,
):
"""Middle Out Reconciliation Method.
Expand Down Expand Up @@ -727,11 +727,11 @@ def fit_predict(
self,
S: np.ndarray,
y_hat: np.ndarray,
tags: Dict[str, np.ndarray],
tags: dict[str, np.ndarray],
y_insample: Optional[np.ndarray] = None,
level: Optional[List[int]] = None,
level: Optional[list[int]] = None,
intervals_method: Optional[str] = None,
) -> Dict[str, np.ndarray]:
) -> dict[str, np.ndarray]:
# Check if the data structure is strictly hierarchical.
if not is_strictly_hierarchical(S, tags):
raise ValueError(
Expand Down Expand Up @@ -849,7 +849,7 @@ def _get_PW_matrices(
y_hat: np.ndarray,
y_insample: Optional[np.ndarray] = None,
y_hat_insample: Optional[np.ndarray] = None,
idx_bottom: Optional[List[int]] = None,
idx_bottom: Optional[list[int]] = None,
):
# shape residuals_insample (n_hiers, obs)
res_methods = ["wls_var", "mint_cov", "mint_shrink"]
Expand Down Expand Up @@ -954,7 +954,7 @@ def fit(
intervals_method: Optional[str] = None,
num_samples: Optional[int] = None,
seed: Optional[int] = None,
tags: Optional[Dict[str, np.ndarray]] = None,
tags: Optional[dict[str, np.ndarray]] = None,
idx_bottom: Optional[np.ndarray] = None,
):
"""MinTrace Fit Method.
Expand Down Expand Up @@ -1056,11 +1056,11 @@ def fit_predict(
y_insample: Optional[np.ndarray] = None,
y_hat_insample: Optional[np.ndarray] = None,
sigmah: Optional[np.ndarray] = None,
level: Optional[List[int]] = None,
level: Optional[list[int]] = None,
intervals_method: Optional[str] = None,
num_samples: Optional[int] = None,
seed: Optional[int] = None,
tags: Optional[Dict[str, np.ndarray]] = None,
tags: Optional[dict[str, np.ndarray]] = None,
):
"""MinTrace Reconciliation Method.
Expand Down Expand Up @@ -1130,7 +1130,7 @@ def _get_PW_matrices(
y_hat: np.ndarray,
y_insample: Optional[np.ndarray] = None,
y_hat_insample: Optional[np.ndarray] = None,
idx_bottom: Optional[List[int]] = None,
idx_bottom: Optional[list[int]] = None,
):
# shape residuals_insample (n_hiers, obs)
res_methods = ["wls_var", "mint_cov", "mint_shrink"]
Expand Down Expand Up @@ -1224,7 +1224,7 @@ def fit(
intervals_method: Optional[str] = None,
num_samples: Optional[int] = None,
seed: Optional[int] = None,
tags: Optional[Dict[str, np.ndarray]] = None,
tags: Optional[dict[str, np.ndarray]] = None,
idx_bottom: Optional[np.ndarray] = None,
):
# Clip the base forecasts if required to align them with their use in practice.
Expand Down Expand Up @@ -1414,7 +1414,7 @@ def fit(
intervals_method: Optional[str] = None,
num_samples: Optional[int] = None,
seed: Optional[int] = None,
tags: Optional[Dict[str, np.ndarray]] = None,
tags: Optional[dict[str, np.ndarray]] = None,
idx_bottom: Optional[np.ndarray] = None,
):
"""ERM Fit Method.
Expand Down Expand Up @@ -1463,11 +1463,11 @@ def fit_predict(
y_insample: Optional[np.ndarray] = None,
y_hat_insample: Optional[np.ndarray] = None,
sigmah: Optional[np.ndarray] = None,
level: Optional[List[int]] = None,
level: Optional[list[int]] = None,
intervals_method: Optional[str] = None,
num_samples: Optional[int] = None,
seed: Optional[int] = None,
tags: Optional[Dict[str, np.ndarray]] = None,
tags: Optional[dict[str, np.ndarray]] = None,
):
"""ERM Reconciliation Method.
Expand Down
4 changes: 2 additions & 2 deletions hierarchicalforecast/probabilistic_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# %% ../nbs/src/probabilistic_methods.ipynb 3
import warnings
from typing import Dict, Optional
from typing import Optional

import numpy as np
from scipy.stats import norm
Expand Down Expand Up @@ -263,7 +263,7 @@ class PERMBU:
def __init__(
self,
S: np.ndarray,
tags: Dict[str, np.ndarray],
tags: dict[str, np.ndarray],
y_hat: np.ndarray,
y_insample: np.ndarray,
y_hat_insample: np.ndarray,
Expand Down
Loading

0 comments on commit 1855108

Please sign in to comment.