Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update extension template for predict_quantiles #1780

Merged
merged 3 commits into from Dec 22, 2021
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
62 changes: 29 additions & 33 deletions extension_templates/forecasting.py
Expand Up @@ -20,12 +20,12 @@

Mandatory implements:
fitting - _fit(self, y, X=None, fh=None)
forecasting - _predict(self, fh=None, X=None, return_pred_int=False,
alpha=DEFAULT_ALPHA)
forecasting - _predict(self, fh=None, X=None)

Optional implements:
updating - _update(self, y, X=None, update_params=True):
fitted parameter inspection - get_fitted_params()
predicting quantiles - _predict_quantiles(self, fh, X=None, alpha=DEFAULT_ALPHA)

State:
fitted model/strategy - by convention, any attributes ending in "_"
Expand All @@ -44,7 +44,6 @@


from sktime.forecasting.base import BaseForecaster
from sktime.forecasting.base._base import DEFAULT_ALPHA

# todo: add any necessary imports here

Expand Down Expand Up @@ -90,8 +89,10 @@ class MyForecaster(BaseForecaster):
"requires-fh-in-fit": True, # is forecasting horizon already required in fit?
"X-y-must-have-same-index": True, # can estimator handle different X/y index?
"enforce_index_type": None, # index type that needs to be enforced in X/y
"capability:pred_int": False, # does forecaster implement predict_quantiles?
# deprecated and will be renamed to capability:predict_quantiles in 0.11.0
}
# in case of inheritance, concrete class should typically set tags
# in case of inheritance, concrete class should typically set tags
# alternatively, descendants can set tags in __init__ (avoid this if possible)

# todo: add any hyper-parameters and components to constructor
Expand Down Expand Up @@ -153,7 +154,7 @@ def _fit(self, y, X=None, fh=None):
# the clones, not the originals shoudld be used or fitted if needed

# todo: implement this, mandatory
def _predict(self, fh, X=None, return_pred_int=False, alpha=DEFAULT_ALPHA):
def _predict(self, fh, X=None):
"""Forecast time series at future horizon.

core logic
Expand All @@ -164,16 +165,11 @@ def _predict(self, fh, X=None, return_pred_int=False, alpha=DEFAULT_ALPHA):
Forecasting horizon
X : pd.DataFrame, optional (default=None)
Exogenous time series
return_pred_int : bool, optional (default=False)
If True, returns prediction intervals for given alpha values.
alpha : float or list, optional (default=0.95)

Returns
-------
y_pred : pd.Series
Point predictions
y_pred_int : pd.DataFrame - only if return_pred_int=True
Prediction intervals
"""

# implement here
Expand Down Expand Up @@ -215,42 +211,46 @@ def _update(self, y, X=None, update_params=True):

# todo: consider implementing this, optional
# if not implementing, delete the method
def _update_predict_single(
self,
y,
fh,
X=None,
update_params=True,
return_pred_int=False,
alpha=DEFAULT_ALPHA,
):
def _update_predict_single(self, y, fh, X=None, update_params=True):
"""Update forecaster and then make forecasts.

Implements default behaviour of calling update and predict
sequentially, but can be overwritten by subclasses
to implement more efficient updating algorithms when available.
"""
self.update(y, X, update_params=update_params)
return self.predict(fh, X, return_pred_int=return_pred_int, alpha=alpha)
return self.predict(fh, X)

# implement here
# IMPORTANT: avoid side effects to y, X, fh

# todo: consider implementing this, optional
# if not implementing, delete the method
def _compute_pred_int(self, alphas):
"""Calculate the prediction errors for each point.
def _predict_quantiles(self, fh, X=None, alpha=0.5):
"""
Compute/return prediction quantiles for a forecast.

Must be run *after* the forecaster has been fitted.

If alpha is iterable, multiple quantiles will be calculated.

Users can implement _predict_interval if calling it makes this faster.

Parameters
----------
alpha : float or list, optional (default=0.95)
A significance level or list of significance levels.
fh : int, list, np.array or ForecastingHorizon
Forecasting horizon
X : pd.DataFrame, optional (default=None)
Exogenous time series
alpha : float or list of float, optional (default=0.5)
A probability or list of, at which quantile forecasts are computed.

Returns
-------
errors : list of pd.Series
Each series in the list will contain the errors for each point in
the forecast for the corresponding alpha.
pred_quantiles : pd.DataFrame
Column has multi-index: first level is variable name from y in fit,
second level being quantile fractions for interval low-high.
Quantile fractions are 0.5 - c/2, 0.5 + c/2 for c in coverage.
Row index is fh. Entries are quantile forecasts, for var in col index,
at quantile probability in second col index, for the row index.
"""
# implement here

Expand All @@ -262,8 +262,6 @@ def _predict_moving_cutoff(
cv,
X=None,
update_params=True,
return_pred_int=False,
alpha=DEFAULT_ALPHA,
):
"""Make single-step or multi-step moving cutoff predictions.

Expand All @@ -273,8 +271,6 @@ def _predict_moving_cutoff(
cv : temporal cross-validation generator
X : pd.DataFrame
update_params : bool
return_pred_int : bool
alpha : float or array-like

Returns
-------
Expand Down