smooth.ES.fit

ES.fit(y, X=None)

Fit the ADAM model to time series data.

This method estimates the model parameters, selects the best model (if automatic selection is enabled), and prepares the model for forecasting. It implements the complete ADAM estimation pipeline: parameter checking, model architecture creation, state-space matrix construction, parameter optimization, and model preparation.

Estimation Process:

  1. Parameter Validation: Check all inputs via parameters_checker()

  2. Model Selection (if model_do="select"): Use Branch & Bound algorithm

  3. Model Architecture: Define components and lags via architector()

  4. Matrix Creation: Build state-space matrices via creator()

  5. Parameter Estimation: Optimize using NLopt via estimator()

  6. Model Preparation: Compute fitted values and final states via preparator()

After fitting, the model stores all results as attributes:

  • Estimated parameters (persistence_level_, phi_, etc.)

  • State-space matrices (states, transition, measurement)

  • Fitted values and residuals (fitted, residuals)

  • Information criteria (aic, aicc, bic, bicc)

  • Model specification (model_name, model_type)

Parameters:
  • y (array-like, shape (T,)) –

    Time series data to fit. Can be:

    • numpy.ndarray: Shape (T,) for univariate time series

    • pandas.Series: Will use index for time information if DatetimeIndex

    Data requirements:

    • Minimum length: Depends on model complexity. Rule of thumb: T ≥ 3 × (number of parameters)

    • Multiplicative models: Require strictly positive data (y > 0)

    • Missing values: Currently not supported in Python version

    • Frequency: Auto-detected from pandas Series with DatetimeIndex

  • X (array-like, shape (T, n_features), optional) –

    External regressors (explanatory variables). If provided:

    • Must have same length as y (T observations)

    • Each column is a separate regressor

    • Used only if regressors parameter was set in __init__

    • Can be adaptive (with persistence) or fixed coefficients

    Example:

    >>> X = np.column_stack([trend, holidays, temperature])
    >>> model.fit(y, X=X)
    

Returns:

self – The fitted model instance with populated attributes:

Fitted Parameters (scikit-learn style with trailing underscores):

  • persistence_level_: α (level smoothing), range [0, 1]

  • persistence_trend_: β (trend smoothing), range [0, α]

  • persistence_seasonal_: γ (seasonal smoothing), list if multiple

  • phi_: Damping parameter, range [0, 1]

  • arma_parameters_: AR/MA coefficients (if ARIMA)

  • initial_states_: Initial state values

Model Components (via properties):

  • model_name: Full model specification string

  • coef / B: Estimated parameter vector

  • states: State matrix over time

  • transition: Transition matrix

  • measurement: Measurement matrix

  • aic, aicc, bic, bicc: Information criteria

Return type:

ADAM

Raises:
  • ValueError – If data validation fails: - y contains NaN values - y has insufficient length for model complexity - Multiplicative model specified for non-positive data - X and y have mismatched lengths

  • RuntimeError – If optimization fails to converge. Check: - Model specification is appropriate for data - Initial values are reasonable (try different initial method) - Bounds are not too restrictive

Notes

Optimization Algorithm:

Uses NLopt’s Nelder-Mead simplex algorithm by default (derivative-free, robust). For large models or difficult optimization, consider:

  • Changing initial method

  • Adjusting bounds (bounds="usual" vs bounds="admissible")

  • Providing custom starting values via nlopt_initial parameter

Computational Complexity:

Fitting time depends on:

  • Sample size T: O(T) per function evaluation

  • Number of parameters k: ~40k function evaluations

  • Model selection: Estimates ~10-15 models for “ZZZ”

Typical fitting times:

  • T=100, simple ETS: ~0.1 seconds

  • T=1000, ETS with 2 seasonalities: ~1-2 seconds

  • T=1000, automatic selection: ~10-20 seconds

Model Selection Details:

When model_do="select":

  1. Branch & Bound explores model space efficiently

  2. Each candidate model is fully estimated

  3. Best model selected based on ic criterion

  4. Selected model is re-estimated with full optimization

To see which models were tested:

>>> model.fit(y)
>>> print(model.ic_selection)  # Dict of model names -> IC values

Holdout Validation:

If holdout=True in __init__:

  • Last h observations are withheld for validation

  • Model estimated on first T-h observations

  • Can use holdout for out-of-sample accuracy assessment

Two-Stage Initialization:

When initial="two-stage":

  1. Stage 1: Quick backcasting estimation for initial states

  2. Stage 2: Refined optimization starting from stage 1 results

Often provides better results than pure initial="optimal" for complex models.

Memory Usage:

  • State matrix: O(n_components × (T + max_lag)) floats

  • Modest for typical models (~1-10 MB)

  • Multiple seasonality can increase memory usage

See also

predict

Generate forecasts from fitted model

predict_intervals

Generate prediction intervals

estimator

Underlying estimation function

parameters_checker

Input validation function

Examples

Basic fitting:

>>> from smooth import ADAM
>>> import numpy as np
>>> y = np.array([
...     112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118
... ])
>>> model = ADAM(model="ANN", lags=[1])
>>> model.fit(y)
>>> print(f"Alpha: {model.persistence_level_:.3f}")

With external regressors:

>>> X = np.random.randn(len(y), 2)
>>> model = ADAM(model="AAN", regressors="use")
>>> model.fit(y, X=X)
>>> print(f"Coefficients: {model.coef}")

Automatic model selection:

>>> model = ADAM(model="ZZZ", lags=[12], ic="AICc")
>>> model.fit(y)
>>> print(f"Selected: {model.model_name}")
>>> print(f"AICc: {model.aicc}")

Access fitted values and residuals:

>>> model.fit(y)
>>> fitted = model.fitted
>>> residuals = model.residuals
>>> print(f"RMSE: {np.sqrt(np.mean(residuals**2)):.3f}")

Using pandas Series with datetime index:

>>> import pandas as pd
>>> dates = pd.date_range(
...     '2020-01-01', periods=len(y), freq='M'
... )
>>> y_series = pd.Series(y, index=dates)
>>> model.fit(y_series)
>>> # Frequency auto-detected from index

Parent Class: ES