Skip to content

AutoADAM

Ivan Svetunkov edited this page Jun 16, 2026 · 10 revisions

title: AutoADAM — Automatic ADAM Model Selection slug: AutoADAM summary: Automatic distribution and ARIMA-order selection on top of ADAM. status: stable applies_to: [r, python] related: [ADAM, Model-Specification, Loss-Functions]

AutoADAM - Automatic ADAM Model Selection

AutoADAM (Python) / auto.adam() (R) is the automatic model selection extension of ADAM. It estimates models with different configurations and returns the best one based on the selected information criterion.

Function signatures

R

auto.adam(data, model = "ZXZ", lags = c(frequency(data)),
          orders = list(ar = c(3, 3), i = c(2, 1), ma = c(3, 3), select = TRUE),
          formula = NULL, regressors = c("use", "select", "adapt"),
          occurrence = c("none", "auto", "fixed", "general",
                         "odds-ratio", "inverse-odds-ratio", "direct"),
          distribution = c("dnorm", "dlaplace", "ds", "dgnorm",
                           "dlnorm", "dinvgauss", "dgamma"),
          outliers = c("ignore", "use", "select"), level = 0.99,
          h = 0, holdout = FALSE,
          persistence = NULL, phi = NULL,
          initial = c("backcasting", "optimal", "two-stage", "complete"),
          arma = NULL,
          ic = c("AICc", "AIC", "BIC", "BICc"),
          bounds = c("usual", "admissible", "none"),
          silent = TRUE, parallel = FALSE,
          ets = c("conventional", "adam"), ...)

Python

class AutoADAM(ADAM):
    def __init__(
        self,
        model: str | list[str] = "ZXZ",
        lags: int | list[int] | None = None,
        ar_order: int | list[int] | None = None,
        i_order: int | list[int] | None = None,
        ma_order: int | list[int] | None = None,
        orders: dict | None = None,
        arima_select: bool = False,
        distribution: str | list[str] | None = None,
        outliers: Literal["ignore", "use", "select"] = "ignore",
        level: float = 0.99,
        constant: bool | float = False,
        ic: Literal["AIC", "AICc", "BIC", "BICc"] = "AICc",
        loss: str = "likelihood",
        h: int | None = None,
        holdout: bool = False,
        bounds: Literal["usual", "admissible", "none"] = "usual",
        initial: str | dict | None = "backcasting",
        regressors: Literal["use", "select", "adapt"] = "use",
        verbose: int = 0,
        ets: Literal["conventional", "adam"] = "conventional",
        **kwargs,
    ) -> None: ...

Overview

While ADAM/adam() allows selecting ETS components and explanatory variables, it does not automatically select the most suitable distribution. It has support for ARIMA order selection, but in practice what this does is call for AutoADAM/auto.adam(), which does all the heavy lifting.

In comparison with ADAM/adam(), AutoADAM/auto.adam() supports:

  1. Distribution selection: Testing multiple probability distributions (Normal, Laplace, S, Generalised Normal, Log-Normal, Inverse Gaussian, Gamma) and selecting the best one based on IC
  2. ARIMA order selection: When arima_select=True (Python) or orders=list(..., select=TRUE) (R/Python), automatically selecting optimal AR, I, and MA orders. See ARIMA orders precedence below.
  3. Outlier detection: Optionally detecting and handling outliers (R only)
  4. Parallel processing: Supporting parallel estimation for faster computation (R only)

Although (2) and (3) are available in ADAM/adam() as well, in practice they just delegate to AutoADAM/auto.adam().

Python Usage

Basic Distribution Selection

from smooth import AutoADAM

# Select best distribution among Normal, Laplace, and S
model = AutoADAM(model="XXX", distribution=["dnorm","dlaplace","ds"])
model.fit(y)
print(model)

# Test all available distributions (this is the default when distribution is not specified)
model = AutoADAM(model="ZZZ",
                 distribution=["dnorm","dlaplace","ds","dgnorm",
                               "dlnorm","dinvgauss","dgamma"])
model.fit(y)

With ARIMA Order Selection

AutoADAM and ADAM share the following precedence rule for resolving the ARIMA-order arguments:

  1. orders (dict) takes precedence. When supplied, the scalar ar_order / i_order / ma_order parameters are ignored and a UserWarning is emitted. Order selection runs iff orders.get("select", arima_select) is true.
  2. Otherwise, the scalar triplet is used (when any of ar_order / i_order / ma_order carries a non-zero value). The scalars are treated as upper search bounds when arima_select=True, or as fixed orders when arima_select=False.
  3. Otherwise (no orders dict and no scalar values) the model is pure ETS — no ARIMA selection runs.

The default for arima_select in AutoADAM is False (was previously True); to enable ARIMA order selection you now have to opt in explicitly, either by passing arima_select=True or via orders={..., "select": True}. This matches the ADAM convention.

lags accepts either a scalar (lags=12) or a list (lags=[12]); both are equivalent.

# ETS + ARIMA, automatic I/MA/AR selection — scalar max orders (non-seasonal)
model = AutoADAM(model="XXN",
                 ar_order=2, i_order=2, ma_order=2, arima_select=True)
model.fit(y)

# Equivalent using the orders dict (preferred — explicit `select` flag)
model = AutoADAM(model="XXN",
                 orders={"ar": 2, "i": 2, "ma": 2, "select": True})
model.fit(y)

# Seasonal ARIMA selection — per-lag max orders as lists
model = AutoADAM(model="ZZZ",
                 lags=[1, 12],
                 ar_order=[3, 3], i_order=[2, 1], ma_order=[3, 3],
                 arima_select=True)
model.fit(y)

# Orders dict with per-lag lists
model = AutoADAM(model="ZZZ",
                 lags=[1, 12],
                 orders={"ar": [3, 3], "i": [2, 1], "ma": [3, 3], "select": True})
model.fit(y)

Verbose progress output

With verbose=True, AutoADAM prints distribution-selection progress in real time, mirroring R's auto.adam:

m = AutoADAM(model="ZZZ", distribution=["dnorm", "dlaplace", "ds"],
             verbose=True).fit(y)

prints

Evaluating models with different distributions... dnorm, dlaplace, ds, Done!
Selected distribution: dlaplace
Selected ARIMA orders: AR=[1], I=[1], MA=[1]

The internal fits during the selection loop remain silent regardless of verbose; only the orchestration messages are printed.

With Explanatory Variables

# With explanatory variables (passed as X to fit)
model = AutoADAM(model="AAN",
                 distribution=["dnorm","dlaplace"],
                 regressors="select")
model.fit(y, X)

Note: Parallel processing (parallel=) is not yet available in Python.

R Usage

Basic Distribution Selection

library(smooth)

# Select best distribution among Normal, Laplace, and S
model <- auto.adam(BJsales, "XXX",
                   distribution=c("dnorm","dlaplace","ds"),
                   h=12, holdout=TRUE)

# Test all available distributions
model <- auto.adam(y, "ZZZ",
                   distribution=c("dnorm","dlaplace","ds","dgnorm",
                                  "dlnorm","dinvgauss","dgamma"),
                   h=12, holdout=TRUE)

With ARIMA Order Selection

# ETS + ARIMA with automatic ARIMA order selection
# Test AR up to 2, I up to 2, MA up to 2
model <- auto.adam(BJsales, "XXN",
                   orders=list(ar=2, i=2, ma=2, select=TRUE),
                   distribution="default",
                   h=12, holdout=TRUE)

# Seasonal ARIMA selection
model <- auto.adam(AirPassengers, "ZZZ",
                   lags=c(1, 12),
                   orders=list(ar=c(3,3), i=c(2,1), ma=c(3,3), select=TRUE),
                   h=12, holdout=TRUE)

With Outlier Detection

Python Usage

from smooth import AutoADAM

# Include all detected outliers as fixed dummies
model = AutoADAM(model="ZZZ", lags=[1, 12],
                 outliers="use", level=0.99)
model.fit(y)

# Expand each outlier with lag/lead columns and let selection prune them
model = AutoADAM(model="ZZZ", lags=[1, 12],
                 outliers="select", level=0.99)
model.fit(y)

R Usage

# Detect outliers and include all of them as dummies
model <- auto.adam(AirPassengers, "PPP",
                   outliers="use",
                   distribution="default",
                   h=12, holdout=TRUE)

# Detect outliers and select significant ones (on the 1% level)
model <- auto.adam(AirPassengers, "ZZZ",
                   outliers="select",
                   level=0.99,
                   h=12, holdout=TRUE)

Parallel Processing

# Automatic core detection
model <- auto.adam(BJsales, "ZZZ",
                   parallel=TRUE,
                   h=12, holdout=TRUE)

# Specify number of cores
model <- auto.adam(BJsales, "ZZZ",
                   parallel=4,
                   h=12, holdout=TRUE)

With Explanatory Variables

# With explanatory variables
BJData <- cbind(BJsales, BJsales.lead)
model <- auto.adam(BJData, "AAN",
                   distribution=c("dnorm","dlaplace"),
                   regressors="select",
                   h=18, holdout=TRUE)

Parameters

Parameter Type (R) Type (Python) Default Description
data vector/ts/matrix ndarray/Series - Time series data (or matrix with response + regressors)
model character str/List[str] "ZXZ" ETS model specification (see ADAM)
lags numeric vector int / List[int] / None frequency(data) / None Seasonal lags. Python accepts either a scalar (lags=12) or a list (lags=[12]).
orders list dict / None see description / None ARIMA max orders. R default: list(ar=c(3,3),i=c(2,1),ma=c(3,3),select=TRUE). R: list with ar, i, ma, select. Python: dict with "ar", "i", "ma", optionally "select". When provided, the scalar ar_order/i_order/ma_order parameters below are ignored and a UserWarning is emitted.
ar_order - int / List[int] / None - / None Alternative to orders. Used only when orders=None. Interpreted as upper bounds for selection when arima_select=True, or as fixed orders when arima_select=False.
i_order - int / List[int] / None - / None Alternative to orders (see ar_order).
ma_order - int / List[int] / None - / None Alternative to orders (see ar_order).
arima_select - bool - / False Whether to run ARIMA order selection when only the scalar triplet is supplied. With orders={...}, orders.get("select", arima_select) decides. Default was previously True; changed to False so AutoADAM(...) with no ARIMA spec runs as pure ETS.
formula formula - NULL Formula for explanatory variables. Not in Python — pass X matrix directly to .fit().
regressors character str "use" How to handle regressors: "use", "select", "adapt"
occurrence character str "none" Occurrence model type (see OES)
distribution character vector str/List[str] all 7 distributions Distributions to test. Default: all of dnorm, dlaplace, ds, dgnorm, dlnorm, dinvgauss, dgamma.
outliers character str "ignore" Outlier handling: "ignore" skips detection; "use" includes detected dummies as fixed regressors; "select" expands each dummy with lag/lead columns and lets regressor selection choose which matter.
level numeric float 0.99 Confidence level for outlier detection.
h integer int 0 Forecast horizon
holdout logical bool FALSE / False Use holdout validation
persistence numeric vector list/None NULL / None Fixed smoothing parameters
phi numeric float/None NULL / None Fixed damping parameter
initial character str "backcasting" Initialization method
arma list dict/None NULL / None Fixed AR/MA parameters
ic character str "AICc" Information criterion for selection
bounds character str "usual" Parameter bounds
silent logical - TRUE Suppress output. Not applicable in Python.
parallel logical/integer - FALSE Parallel processing. Not yet in Python.
ets character str "conventional" ETS formulation: "conventional" or "adam".

Distribution Options

Distribution Code Description Constraints
Normal "dnorm" Gaussian distribution None
Laplace "dlaplace" Double exponential None
S "ds" S distribution None
Generalised Normal "dgnorm" Flexible shape parameter None
Log-Normal "dlnorm" For positive data y > 0
Inverse Gaussian "dinvgauss" For positive data y > 0
Gamma "dgamma" For positive data y > 0

Note: Distributions requiring positive data (dlnorm, dinvgauss, dgamma) are automatically dropped if the data contains non-positive values and/or a pure ARIMA is estimated and the default list of distributions was not amended. The latter is done to avoid positive distributions with additive ARIMA nature.

Distribution Selection

  1. Fit models with each specified distribution
  2. Calculate information criterion (AIC, AICc, BIC, or BICc) for each
  3. Return the model with the lowest IC value

ARIMA Order Selection

When arima_select=True (Python) or orders=list(ar=..., i=..., ma=..., select=TRUE) (R):

  1. The function first selects optimal differencing orders (I)
  2. Then selects MA orders based on ACF of residuals and IC
  3. Then selects AR orders based on PACF of residuals and IC
  4. Checks additional IMA(d,d) and other restrictive types of models

The selection avoids redundant components when ETS is present:

  • If ETS has level (A or M error), non-seasonal d and q are set to 0
  • If ETS has damping, non-seasonal AR is set to 0
  • If ETS has seasonality, seasonal D and Q are set to 0

Outlier Handling

Option Description
"ignore" No outlier detection (default)
"use" Detect outliers at specified level and include them as dummy variables
"select" Detect outliers, create leads/lags, and select significant ones

Parallel Processing Requirements

For parallel execution in R, the following packages are required:

  • foreach (required)
  • doMC (Linux/Mac) or doParallel (all platforms)

Python: Parallel processing is not yet available in Python.

Output

Returns an object of class "adam" (R) / AutoADAM instance (Python) with the same set of attributes as ADAM.

Examples

Complete Workflow

Python

from smooth import AutoADAM

# 1. Basic automatic selection
model = AutoADAM(model="ZZZ", lags=[1, 12])
model.fit(y)

# 2. View selected model
print(model)

# 3. Forecast
forecasts = model.predict(h=24, interval="prediction")

R

library(smooth)

# 1. Basic automatic selection
model <- auto.adam(AirPassengers, "ZZZ",
                   lags=c(1,12),
                   h=12, holdout=TRUE,
                   silent=FALSE)

# 2. View selected model
print(model)
summary(model)

# 3. Diagnostics
plot(model, which=c(1,2,4,6))

# 4. Forecast
modelForecast <- forecast(model, h=24, interval="prediction")
plot(modelForecast)

ETS + ARIMA Selection

Python

model = AutoADAM(model="XXN",
                 lags=[1, 12],
                 ar_order=[2, 2], i_order=[2, 1], ma_order=[2, 2],
                 distribution=["dnorm","dlaplace","ds","dgnorm"])
model.fit(y)

R

# Select both ETS components and ARIMA orders
model <- auto.adam(AirPassengers, "XXN",
                   orders=list(ar=c(2,2), i=c(2,1), ma=c(2,2), select=TRUE),
                   lags=c(1, 12),
                   distribution=c("dnorm","dlaplace","ds","dgnorm"),
                   h=12, holdout=TRUE)

Important Notes

  1. Parameter restrictions: When using AutoADAM/auto.adam(), do not provide fixed persistence, phi, initial, arma, or B parameters, as this contradicts the model selection purpose.

  2. Computation time: Testing multiple distributions and ARIMA orders can be time-consuming. Use parallel=TRUE (R) to speed up computation.

  3. Pure ARIMA: For pure ARIMA models (no ETS), positive-only distributions (dlnorm, dinvgauss, dgamma) are automatically excluded.

  4. Python default: In Python, arima_select=True is the default in AutoADAM (unlike ADAM where it defaults to False). Set arima_select=False to skip ARIMA selection and perform distribution selection only.

References

See Also

  • ADAM - Base ADAM function
  • ES - Exponential Smoothing wrapper
  • MSARIMA - Multiple Seasonal ARIMA
  • OES - Occurrence ETS for intermittent demand
  • Home - Package overview

Clone this wiki locally