Automatic forecasting procedure for time series data with strong seasonal effects and multiple seasons of historical data
—
Time series cross-validation and performance evaluation tools for Prophet model validation. Includes multiple performance metrics, rolling window analysis, and model comparison utilities.
Time series cross-validation functions for model evaluation.
def cross_validation(
model,
horizon,
period=None,
initial=None,
parallel=None,
cutoffs=None,
disable_tqdm=False,
extra_output_columns=None
):
"""
Perform time series cross-validation.
Parameters:
- model: Prophet, fitted Prophet model
- horizon: str or pd.Timedelta, forecast horizon (e.g., '30 days', '1 year')
- period: str or pd.Timedelta, period between cutoff dates (default: 0.5 * horizon)
- initial: str or pd.Timedelta, initial training period (default: 3 * horizon)
- parallel: str, parallelization method ('processes', 'threads', or None)
- cutoffs: list, custom cutoff dates (optional)
- disable_tqdm: bool, disable progress bar (default: False)
- extra_output_columns: list, additional columns to include in output
Returns:
- DataFrame with cross-validation results including 'ds', 'y', 'yhat', 'cutoff'
"""
def generate_cutoffs(df, horizon, initial, period):
"""
Generate cutoff dates for cross-validation.
Parameters:
- df: DataFrame, historical data with 'ds' column
- horizon: pd.Timedelta, forecast horizon
- initial: pd.Timedelta, initial training period
- period: pd.Timedelta, period between cutoffs
Returns:
- list of cutoff dates
"""
def single_cutoff_forecast(df, model, cutoff, horizon, predict_columns):
"""
Generate forecast for a single cutoff date.
Parameters:
- df: DataFrame, historical data
- model: Prophet, model template
- cutoff: datetime, cutoff date
- horizon: pd.Timedelta, forecast horizon
- predict_columns: list, columns to include in prediction
Returns:
- DataFrame with forecast for the cutoff period
"""Calculate various performance metrics from cross-validation results.
def performance_metrics(df, metrics=None, rolling_window=0.1, monthly=False):
"""
Compute performance metrics from cross-validation results.
Parameters:
- df: DataFrame, cross-validation results from cross_validation()
- metrics: list, list of metrics to compute (default: all available)
- rolling_window: float, rolling window proportion for aggregation (default: 0.1)
- monthly: bool, whether to compute monthly metrics (default: False)
Returns:
- DataFrame with performance metrics by horizon
"""
def mse(df, w):
"""
Mean squared error.
Parameters:
- df: DataFrame, forecast errors
- w: float, rolling window weight
Returns:
- float, MSE value
"""
def rmse(df, w):
"""
Root mean squared error.
Parameters:
- df: DataFrame, forecast errors
- w: float, rolling window weight
Returns:
- float, RMSE value
"""
def mae(df, w):
"""
Mean absolute error.
Parameters:
- df: DataFrame, forecast errors
- w: float, rolling window weight
Returns:
- float, MAE value
"""
def mape(df, w):
"""
Mean absolute percent error.
Parameters:
- df: DataFrame, forecast errors
- w: float, rolling window weight
Returns:
- float, MAPE value
"""
def mdape(df, w):
"""
Median absolute percent error.
Parameters:
- df: DataFrame, forecast errors
- w: float, rolling window weight
Returns:
- float, MDAPE value
"""
def smape(df, w):
"""
Symmetric mean absolute percentage error.
Parameters:
- df: DataFrame, forecast errors
- w: float, rolling window weight
Returns:
- float, SMAPE value
"""
def coverage(df, w):
"""
Coverage of uncertainty intervals.
Parameters:
- df: DataFrame, forecast with uncertainty intervals
- w: float, rolling window weight
Returns:
- float, coverage proportion
"""Helper functions for model diagnostics and metric computation.
def prophet_copy(m, cutoff=None):
"""
Copy a Prophet object for cross-validation.
Parameters:
- m: Prophet, model to copy
- cutoff: datetime, cutoff date for training data (optional)
Returns:
- Prophet, copied model
"""
def register_performance_metric(func):
"""
Register a custom performance metric function.
Parameters:
- func: function, custom metric function with signature func(df, w) -> float
Returns:
- None (registers metric globally)
"""
def rolling_mean_by_h(x, h, w, name):
"""
Compute rolling mean by forecast horizon.
Parameters:
- x: array, values to average
- h: array, forecast horizons
- w: float, rolling window proportion
- name: str, metric name
Returns:
- DataFrame with rolling mean by horizon
"""
def rolling_median_by_h(x, h, w, name):
"""
Compute rolling median by forecast horizon.
Parameters:
- x: array, values to compute median for
- h: array, forecast horizons
- w: float, rolling window proportion
- name: str, metric name
Returns:
- DataFrame with rolling median by horizon
"""PERFORMANCE_METRICS = {
'mse': mse,
'rmse': rmse,
'mae': mae,
'mape': mape,
'mdape': mdape,
'smape': smape,
'coverage': coverage
}
# Dictionary of registered performance metricsfrom prophet.diagnostics import cross_validation, performance_metrics
# Perform cross-validation
df_cv = cross_validation(
model,
horizon='30 days',
period='10 days',
initial='90 days'
)
# Compute performance metrics
df_p = performance_metrics(df_cv)
print(df_p)import numpy as np
# Register custom metric
def custom_metric(df, w):
return np.mean(np.abs(df['y'] - df['yhat']) / df['y'])
register_performance_metric(custom_metric)
# Compute metrics with custom metric
df_p = performance_metrics(df_cv, metrics=['rmse', 'custom_metric'])
# Plot cross-validation results
from prophet.plot import plot_cross_validation_metric
fig = plot_cross_validation_metric(df_cv, 'rmse')
fig.show()# Use parallel processing for faster cross-validation
df_cv = cross_validation(
model,
horizon='60 days',
period='30 days',
initial='180 days',
parallel='processes' # or 'threads'
)
# Monthly aggregated metrics
df_monthly = performance_metrics(df_cv, monthly=True)Install with Tessl CLI
npx tessl i tessl/pypi-prophet