-
Notifications
You must be signed in to change notification settings - Fork 22
AutoADAM
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.
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"), ...)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: ...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:
- Distribution selection: Testing multiple probability distributions (Normal, Laplace, S, Generalised Normal, Log-Normal, Inverse Gaussian, Gamma) and selecting the best one based on IC
-
ARIMA order selection: When
arima_select=True(Python) ororders=list(..., select=TRUE)(R/Python), automatically selecting optimal AR, I, and MA orders. See ARIMA orders precedence below. - Outlier detection: Optionally detecting and handling outliers (R only)
- 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().
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)AutoADAM and ADAM share the following precedence rule for resolving the ARIMA-order arguments:
-
orders(dict) takes precedence. When supplied, the scalarar_order/i_order/ma_orderparameters are ignored and aUserWarningis emitted. Order selection runs ifforders.get("select", arima_select)is true. -
Otherwise, the scalar triplet is used (when any of
ar_order/i_order/ma_ordercarries a non-zero value). The scalars are treated as upper search bounds whenarima_select=True, or as fixed orders whenarima_select=False. -
Otherwise (no
ordersdict 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)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 (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.
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)# 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)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)# 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)# 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
BJData <- cbind(BJsales, BJsales.lead)
model <- auto.adam(BJData, "AAN",
distribution=c("dnorm","dlaplace"),
regressors="select",
h=18, holdout=TRUE)| 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 | 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.
- Fit models with each specified distribution
- Calculate information criterion (AIC, AICc, BIC, or BICc) for each
- Return the model with the lowest IC value
When arima_select=True (Python) or orders=list(ar=..., i=..., ma=..., select=TRUE) (R):
- The function first selects optimal differencing orders (I)
- Then selects MA orders based on ACF of residuals and IC
- Then selects AR orders based on PACF of residuals and IC
- 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
| 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 |
For parallel execution in R, the following packages are required:
-
foreach(required) -
doMC(Linux/Mac) ordoParallel(all platforms)
Python: Parallel processing is not yet available in Python.
Returns an object of class "adam" (R) / AutoADAM instance (Python) with the same set of attributes as ADAM.
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")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)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)# 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)-
Parameter restrictions: When using
AutoADAM/auto.adam(), do not provide fixedpersistence,phi,initial,arma, orBparameters, as this contradicts the model selection purpose. -
Computation time: Testing multiple distributions and ARIMA orders can be time-consuming. Use
parallel=TRUE(R) to speed up computation. -
Pure ARIMA: For pure ARIMA models (no ETS), positive-only distributions (
dlnorm,dinvgauss,dgamma) are automatically excluded. -
Python default: In Python,
arima_select=Trueis the default inAutoADAM(unlikeADAMwhere it defaults toFalse). Setarima_select=Falseto skip ARIMA selection and perform distribution selection only.
- Svetunkov, I. (2023). Forecasting and Analytics with the Augmented Dynamic Adaptive Model (ADAM). Chapman and Hall/CRC. DOI: 10.1201/9781003452652. Online: https://openforecast.org/adam/.
- ARIMA selection: Section 15.2.
- Svetunkov, I. (2023). Smooth forecasting with the smooth package in R. arXiv:2301.01790. DOI: 10.48550/arXiv.2301.01790.