models.forecaster_recursive_model_full

models.forecaster_recursive_model_full

Full-featured base forecasting model with Bayesian tuning and SHAP.

This module extends ForecasterRecursiveModel from spotforecast2-safe with real Bayesian hyperparameter search (Optuna) and SHAP-based feature importance (shap.TreeExplainer).

Examples

from spotforecast2.models import ForecasterRecursiveModelFull

model = ForecasterRecursiveModelFull(iteration=0)
assert hasattr(model, "tune")
assert hasattr(model, "get_global_shap_feature_importance")
print(f"n_trials={model.n_trials}, iteration={model.iteration}")
n_trials=10, iteration=0

Classes

Name Description
ForecasterRecursiveModelFull ForecasterRecursiveModel with real Bayesian tuning and SHAP.

ForecasterRecursiveModelFull

models.forecaster_recursive_model_full.ForecasterRecursiveModelFull(
    iteration,
    n_trials=_DEFAULT_N_TRIALS,
    on_missing='passthrough',
    **kwargs,
)

ForecasterRecursiveModel with real Bayesian tuning and SHAP.

This class overrides the two stubs in spotforecast2-safe:

  • tune() — performs a full Bayesian hyperparameter search using bayesian_search_forecaster (Optuna).
  • get_global_shap_feature_importance() — computes global SHAP values using shap.TreeExplainer.

Parameters

Name Type Description Default
iteration int Training iteration index (0-based). required
n_trials int Number of Optuna trials for Bayesian search. _DEFAULT_N_TRIALS
on_missing OnMissing How tune() should treat NaN rows when calling load_timeseries(). Defaults to "passthrough" since the next step (LinearlyInterpolateTS) imputes the gaps. 'passthrough'
**kwargs Any Forwarded to ForecasterRecursiveModel. {}

Examples

from spotforecast2.models import ForecasterRecursiveModelFull

model = ForecasterRecursiveModelFull(iteration=0)
assert model.n_trials == 10
assert model.iteration == 0
assert hasattr(model, "tune")
assert hasattr(model, "get_global_shap_feature_importance")
print(f"n_trials={model.n_trials}, iteration={model.iteration}")
print(f"on_missing={model.on_missing}")
n_trials=10, iteration=0
on_missing=passthrough

Methods

Name Description
get_global_shap_feature_importance Return global SHAP-based feature importances.
tune Tune the forecaster via Bayesian search (Optuna).
get_global_shap_feature_importance
models.forecaster_recursive_model_full.ForecasterRecursiveModelFull.get_global_shap_feature_importance(
    frac=0.1,
)

Return global SHAP-based feature importances.

Uses shap.TreeExplainer on the underlying estimator to compute mean absolute SHAP values across a random sample of the training data.

Parameters
Name Type Description Default
frac float Fraction of training data to sample (0 < frac <= 1). 0.1
Returns
Name Type Description
pd.Series pd.Series: Feature importances sorted descending. Empty
pd.Series if the model has not been tuned.
Raises
Name Type Description
ValueError If the forecaster has not been initialized.
Examples
import numpy as np
import pandas as pd
from spotforecast2.models import ForecasterRecursiveLGBMFull

rng = np.random.default_rng(0)
y = pd.Series(
    rng.random(30),
    index=pd.date_range("2023-01-01", periods=30, freq="h", tz="UTC"),
    name="load",
)

# Untuned: best_params is None so an empty Series is returned.
model_untuned = ForecasterRecursiveLGBMFull(iteration=0, lags=3)
model_untuned.forecaster.fit(y=y)
X_train_u, y_train_u = model_untuned.forecaster.create_train_X_y(y=y)
model_untuned._get_training_data = lambda: (X_train_u, y_train_u)

result_empty = model_untuned.get_global_shap_feature_importance()
assert isinstance(result_empty, pd.Series)
assert len(result_empty) == 0
print(f"Untuned result dtype: {result_empty.dtype}")
╭─────────────────────────────── IgnoredArgumentWarning ───────────────────────────────╮
 The number of bins has been reduced from 10 to 1 due to duplicated edges caused by   
 repeated predicted values.                                                           
                                                                                      
 Category : spotforecast2.exceptions.IgnoredArgumentWarning                           
 Location :                                                                           
 /opt/hostedtoolcache/Python/3.13.13/x64/lib/python3.13/site-packages/spotforecast2_s 
 afe/preprocessing/_binner.py:259                                                     
 Suppress : warnings.simplefilter('ignore', category=IgnoredArgumentWarning)          
╰──────────────────────────────────────────────────────────────────────────────────────╯
Model is not tuned — returning empty Series.
Untuned result dtype: float64
import numpy as np
import pandas as pd
from spotforecast2.models import ForecasterRecursiveLGBMFull

rng = np.random.default_rng(0)
y = pd.Series(
    rng.random(30),
    index=pd.date_range("2023-01-01", periods=30, freq="h", tz="UTC"),
    name="load",
)

model = ForecasterRecursiveLGBMFull(iteration=0, lags=3)
model.forecaster.fit(y=y)

# Set best_params and best_lags to bypass the early-return guard.
model.best_params = {}
model.best_lags = [1, 2, 3]

# Supply pre-computed training matrices to avoid live data loading.
X_train, y_train = model.forecaster.create_train_X_y(y=y)
model._get_training_data = lambda: (X_train, y_train)

importance = model.get_global_shap_feature_importance(frac=1.0)
assert isinstance(importance, pd.Series)
assert set(importance.index) == {"lag_1", "lag_2", "lag_3"}
print(f"Feature importance index: {list(importance.index)}")
print(importance)
╭─────────────────────────────── IgnoredArgumentWarning ───────────────────────────────╮
 The number of bins has been reduced from 10 to 1 due to duplicated edges caused by   
 repeated predicted values.                                                           
                                                                                      
 Category : spotforecast2.exceptions.IgnoredArgumentWarning                           
 Location :                                                                           
 /opt/hostedtoolcache/Python/3.13.13/x64/lib/python3.13/site-packages/spotforecast2_s 
 afe/preprocessing/_binner.py:259                                                     
 Suppress : warnings.simplefilter('ignore', category=IgnoredArgumentWarning)          
╰──────────────────────────────────────────────────────────────────────────────────────╯
Feature importance index: ['lag_1', 'lag_2', 'lag_3']
lag_1    0.0
lag_2    0.0
lag_3    0.0
dtype: float64
tune
models.forecaster_recursive_model_full.ForecasterRecursiveModelFull.tune()

Tune the forecaster via Bayesian search (Optuna).

Loads time-series data, builds exogenous features, and runs bayesian_search_forecaster over the search space registered for self.name in SEARCH_SPACES.

After tuning the model is fitted with the best parameters and, if self.save_model_to_file is True, persisted to disk.

Raises
Name Type Description
KeyError If self.name is not in SEARCH_SPACES.
Examples
from spotforecast2.models import ForecasterRecursiveLGBMFull

model = ForecasterRecursiveLGBMFull(iteration=0)
assert callable(model.tune)
print(f"tune is callable: {callable(model.tune)}")
print(f"n_trials={model.n_trials}, name={model.name}")
tune is callable: True
n_trials=10, name=lgbm