smooth.ADAM

class smooth.ADAM(model='ZXZ', lags=None, ar_order=0, i_order=0, ma_order=0, arima_select=False, constant=False, regressors='use', distribution=None, loss='likelihood', loss_horizon=None, outliers='ignore', outliers_level=0.99, ic='AICc', bounds='usual', occurrence='none', persistence=None, phi=None, initial='backcasting', n_iterations=None, arma=None, verbose=0, h=None, holdout=False, fast=False, lambda_param=None, frequency=None, profiles_recent_provided=False, profiles_recent_table=None, nlopt_initial=None, nlopt_upper=None, nlopt_lower=None, nlopt_kargs=None, reg_lambda=None, gnorm_shape=None, smoother='lowess', **kwargs)

ADAM: Augmented Dynamic Adaptive Model for Time Series Forecasting.

ADAM is an advanced state-space modeling framework that combines ETS (Error, Trend, Seasonal) and ARIMA components into a unified Single Source of Error (SSOE) model. It provides a flexible, data-driven approach to time series forecasting with automatic model selection, parameter estimation, and prediction intervals.

Mathematical Form:

The ADAM model is specified in state-space form as:

\[ \begin{align}\begin{aligned}y_t &= o_t(w(v_{t-l}) + h(x_t, a_{t-1}) + r(v_{t-l})\epsilon_t)\\v_t &= f(v_{t-l}, a_{t-1}) + g(v_{t-l}, a_{t-1}, x_t)\epsilon_t\end{aligned}\end{align} \]

where:

  • \(y_t\): Observed value at time t

  • \(o_t\): Occurrence indicator (Bernoulli variable for intermittent data, 1 otherwise)

  • \(v_t\): State vector (level, trend, seasonal, ARIMA components)

  • \(l\): Vector of lags

  • \(x_t\): Vector of exogenous variables

  • \(a_t\): Parameters for exogenous variables

  • \(w(\cdot)\): Measurement function

  • \(r(\cdot)\): Error function (additive or multiplicative)

  • \(f(\cdot)\): Transition function (state evolution)

  • \(g(\cdot)\): Persistence function (smoothing parameters)

  • \(\epsilon_t\): Error term (various distributions supported)

Key Features:

  1. Unified Framework: Seamlessly combines ETS and ARIMA in a single model

  2. Multiple Seasonality: Supports multiple seasonal periods (e.g., daily + weekly)

  3. Automatic Selection: Branch & Bound algorithm for efficient model selection

  4. Flexible Distributions: Normal, Laplace, Gamma, Log-Normal, and more

  5. Intermittent Demand: Built-in occurrence models for sparse data

  6. External Regressors: Include covariates with adaptive or fixed coefficients

  7. Scikit-learn Compatible: Familiar .fit() and .predict() API

Model Specification:

Models are specified using a string notation:

  • ETS Models: “ETS” where E=Error, T=Trend, S=Seasonal

    • E (Error): “A” (Additive), “M” (Multiplicative)

    • T (Trend): “N” (None), “A” (Additive), “Ad” (Additive Damped), “M” (Multiplicative), “Md” (Multiplicative Damped)

    • S (Seasonal): “N” (None), “A” (Additive), “M” (Multiplicative)

    Examples: “ANN” (Simple Exponential Smoothing), “AAN” (Holt’s Linear), “AAA” (Holt-Winters Additive)

  • Automatic Selection:

    • “ZZZ”: Select best model using Branch & Bound

    • “XXX”: Select only additive components

    • “YYY”: Select only multiplicative components

    • “ZXZ”: Auto-select error and seasonal, additive trend only (default, safer)

    • “FFF”: Full search across all 30 ETS model types

  • ARIMA Models: Specified via ar_order, i_order, ma_order parameters

    • Supports seasonal ARIMA: SARIMA(p,d,q)(P,D,Q)m

    • Multiple seasonality: e.g., hourly data with daily (24) and weekly (168) patterns

Supported Error Distributions:

  • Normal (distribution="dnorm"): Default for additive errors

  • Gamma (distribution="dgamma"): Default for multiplicative errors

  • Laplace (distribution="dlaplace"): For heavy-tailed errors (MAE loss)

  • Log-Normal (distribution="dlnorm"): For positive-only data

  • Inverse Gaussian (distribution="dinvgauss"): For skewed positive data

  • S distribution (distribution="ds"): For extremely heavy-tailed data

  • Generalized Normal (distribution="dgnorm"): Flexible shape parameter

Distribution is auto-selected based on loss function if distribution=None.

Loss Functions:

  • loss="likelihood": Maximum likelihood estimation (default)

  • loss="MSE": Mean Squared Error

  • loss="MAE": Mean Absolute Error

  • loss="HAM": Half-Absolute Moment

  • loss="MSEh": Multi-step MSE (h-step ahead)

  • loss="LASSO": L1 regularization for variable selection

  • loss="RIDGE": L2 regularization for shrinkage

Multistep loss functions:

  • loss="MSEh": Mean Squared Error for specific h-steps ahead

  • loss="TMSE": Trace Mean Squared Error (sum of MSEh from 1 to h)

  • loss="GTMSE": Geometric Trace Mean Squared Error (sum of logs of MSEh from 1 to h)

  • loss="MSCE": Mean Squared Cumulative Error (sum of MSEh from 1 to h and covariances between them)

  • loss="GPL": Generalised Predictive Likelihood (minimum of the determinant of the covariance matrix of multistep errors)

Initialization Methods:

  • initial="optimal": Optimize all initial states (default)

  • initial="backcasting": Use backcasting to initialize states

  • initial="two-stage": Backcast then optimize

  • initial="complete": Pure backcasting without optimization

  • initial={"level": 100, ...}: Provide custom initial states

Workflow Example:

from smooth import ADAM
import numpy as np

# Generate sample data
y = np.array([112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118] * 3)

# Automatic model selection
model = ADAM(model="ZZZ", lags=[12], ic="AICc")
ADAM_fit = model.fit(y)
print(ADAM_fit)

# Generate 12-step ahead forecasts with intervals
forecasts = model.predict(h=12, calculate_intervals=True, level=0.95)
print(forecasts)

# Access fitted parameters
print(f"Model: {model.model_name}")
print(f"Alpha: {model.persistence_level_:.3f}")
print(f"AICc: {model.aicc}")

Attributes (After Fitting):

The model stores fitted results as attributes with trailing underscores (scikit-learn convention):

  • persistence_level_: Level smoothing parameter (α)

  • persistence_trend_: Trend smoothing parameter (β)

  • persistence_seasonal_: Seasonal smoothing parameter(s) (γ)

  • phi_: Damping parameter (φ)

  • initial_states_: Estimated initial states

  • arma_parameters_: AR/MA coefficients (if ARIMA)

Additional fitted attributes:

  • model_name: Full model specification string

  • coef: Estimated parameter vector B

  • states: State matrix over time

  • persistence_vector: Named persistence parameters

  • transition: Transition matrix

Performance Considerations:

  • Small Data (T < 100): Use “backcasting” initialization, it’s faster

  • Large Data (T > 1000): “optimal” initialization works well

  • Multiple Seasonality: Can be slow; consider simpler models first

  • Model Selection: “ZZZ” with Branch & Bound is much faster than “FFF” exhaustive search

Common Use Cases:

  1. Automatic Forecasting: ADAM(model="ZXZ", lags=[12]) - Let the model choose

  2. Intermittent Demand: ADAM(model="ANN", occurrence="auto") - For sparse data

  3. External Regressors: ADAM(model="AAN").fit(y, X=regressors) - Include covariates

  4. Multiple Seasonality: ADAM(model="AAA", lags=[24, 168]) - Hourly data with daily/weekly patterns

  5. ARIMA: ADAM(model="NNN", ar_order=1, i_order=1, ma_order=1) - Pure ARIMA(1,1,1)

  6. Custom Model: ADAM(model="MAM", persistence={"alpha": 0.3}) - Fix some parameters

Comparison to R’s smooth::adam:

This Python implementation is a direct translation of the R smooth package’s adam() function, maintaining mathematical equivalence while adapting to scikit-learn conventions:

  • R: adam(data, model="ZZZ", h=10) → Python: ADAM(model="ZZZ").fit(y).predict(h=10)

  • R: persistence=list(alpha=0.3) → Python: persistence={"alpha": 0.3}

  • R: orders=list(ar=c(1,1)) → Python: ar_order=[1, 1]

References:

  • Svetunkov, I. (2023). Forecasting and Analytics with the Augmented Dynamic Adaptive Model. https://openforecast.org/adam/

  • Hyndman, R.J., et al. (2008). “Forecasting with Exponential Smoothing”

  • Svetunkov, I. & Boylan, J.E. (2017). “State-space ARIMA for supply-chain forecasting”

  • Svetunkov, I. & Kourentzes, N. & Killick, R. (2023). “Multi-step estimators and shrinkage effect in time series models”. DOI: 10.1007/s00180-023-01377-x

See also

adam.fit

Fit the ADAM model to data

adam.predict

Generate point forecasts

adam.predict_intervals

Generate prediction intervals

selector

Automatic model selection function

estimator

Parameter estimation function

forecaster

Forecasting function

print

Print the outputs of the ADAM class

Examples

Simple exponential smoothing:

>>> 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)
>>> forecasts = model.predict(h=6)
>>> print(forecasts)

Automatic model selection with multiple seasonality:

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

SARIMA(1,1,1)(1,1,1)₁₂:

>>> model = ADAM(
...     model="NNN",  # Pure ARIMA
...     ar_order=[1, 1],
...     i_order=[1, 1],
...     ma_order=[1, 1],
...     lags=[1, 12]
... )
>>> model.fit(y)
>>> forecasts = model.predict(h=12)

With external regressors:

>>> X = np.random.randn(len(y), 2)  # Two regressors
>>> X_future = np.random.randn(6, 2)  # Regressors for forecast period
>>> model = ADAM(model="AAN", regressors="use")
>>> model.fit(y, X=X)
>>> forecasts = model.predict(h=6, X=X_future)

Fix some parameters, estimate others:

>>> model = ADAM(
...     model="AAA",
...     lags=[12],
...     persistence={"alpha": 0.3},  # Fix alpha, estimate beta and gamma
...     initial="backcasting"
... )
>>> model.fit(y)

Intermittent demand forecasting:

>>> sparse_data = np.array([0, 0, 15, 0, 0, 23, 0, 0, 0, 18, 0, 0])
>>> model = ADAM(model="ANN", occurrence="auto")
>>> model.fit(sparse_data)
>>> forecasts = model.predict(h=6)  # Accounts for zero-demand probability

Methods

fit(y[, X])

Fit the ADAM model to time series data.

predict(h[, X, calculate_intervals, ...])

Generate point forecasts using the fitted ADAM model.

predict_intervals(h[, X, levels, side])

Generate prediction intervals using the fitted ADAM model.

select_best_model()

Select the best model based on information criteria and update model parameters.

summary([digits])

Generate a formatted summary of the fitted model.

Attributes

actuals

Return original in-sample data.

aic

Return Akaike Information Criterion.

aicc

Return corrected Akaike Information Criterion.

b_value

$B).

bic

Return Bayesian Information Criterion.

bicc

Return corrected Bayesian Information Criterion.

coef

Return estimated coefficients (parameter vector B).

constant_value

$constant).

data

$data).

distribution_

$distribution).

error_type

'A' (additive) or 'M' (multiplicative).

fitted

Return in-sample fitted values.

holdout_data

$holdout).

ic_weights

$ICw).

initial_type

$initialType).

initial_value

$initial).

is_combined

Return True if model is a combination of multiple models.

lags_used

Return the vector of lags used in the model.

loglik

Return log-likelihood of the fitted model.

loss_

$loss).

loss_value

$lossValue).

measurement

$measurement).

model_name

modelName()).

model_type

Return ETS model type code (e.g., 'AAN', 'AAA', 'MAdM').

models

$models).

n_param

$nParam).

nobs

Return number of observations used for fitting.

nparam

Return number of estimated parameters.

orders

Return ARIMA orders as dict with 'ar', 'i', 'ma' keys.

persistence_vector

$persistence).

phi_

$phi).

profile

$profile).

residuals

Return model residuals (errors from fitting).

scale

$scale).

sigma

Return scale/standard error estimate.

states

$states).

time_elapsed

Time taken to fit the model in seconds.

transition

$transition).