-
Notifications
You must be signed in to change notification settings - Fork 22
OM models the probability of demand occurrence for intermittent time series. It implements the occurrence part of the iETS framework as a state-space model with a Bernoulli likelihood and one of several link functions. Available in both R (om(), omg(), auto.om()) and Python (OM, OMG, AutoOM).
Note: iETS refers to the full model for demand sizes and demand occurrence. OM (oETS) refers to the occurrence part only. See ADAM for the full iETS model.
om(data, model = "ZXZ", lags = c(frequency(data)),
orders = list(ar = c(0), i = c(0), ma = c(0), select = FALSE),
constant = FALSE, formula = NULL,
regressors = c("use", "select", "adapt"),
occurrence = c("auto", "fixed", "odds-ratio", "inverse-odds-ratio",
"direct", "general"),
loss = c("likelihood", "MSE", "MAE", "HAM", "LASSO", "RIDGE"),
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"),
ets = c("conventional", "adam"),
silent = TRUE, ...)omg() (general two-sub-model OM) and auto.om() (automatic occurrence-type selection) share the same parameter style; see OMG and AutoOM sections below.
class OM(ADAM):
def __init__(
self,
model: str | list[str] = "ZXZ",
lags: list[int] | None = None,
ar_order: int | list[int] = 0,
i_order: int | list[int] = 0,
ma_order: int | list[int] = 0,
orders: dict | None = None,
constant: bool = False,
formula: str | None = None,
regressors: Literal["use", "select", "adapt"] = "use",
occurrence: str = "odds-ratio",
loss: str | Callable = "likelihood",
reg_lambda: float | None = None,
h: int = 0,
holdout: bool = False,
persistence: dict | float | None = None,
phi: float | None = None,
initial: dict | str = "backcasting",
n_iterations: int | None = None,
arma: dict | None = None,
ic: Literal["AIC", "AICc", "BIC", "BICc"] = "AICc",
bounds: Literal["usual", "admissible", "none"] = "usual",
verbose: int = 0,
nlopt_kargs: dict | None = None,
ets: Literal["conventional", "adam"] = "conventional",
**kwargs,
) -> None: ...Passing occurrence="auto" or occurrence="general" to OM(...) returns an OMG instance via __new__ redirect; otherwise it returns an OM. AutoOM(...).fit(...) returns the best OM or OMG per the R auto.om() convention.
The iETS framework decomposes intermittent demand as:
y_t = o_t × z_t
Where o_t ∈ {0, 1} is the binary occurrence indicator and z_t is the demand size (modelled separately - see ADAM). OM focuses on the occurrence part:
o_t ~ Bernoulli(p_t)
p_t = link(μ_{a,t}, μ_{b,t})
Where p_t ∈ (0, 1) is the probability of non-zero demand, and μ_{a,t}, μ_{b,t} are conditional expectations of unobservable latent variables a_t and b_t. Each follows its own ADAM model - which may be pure ETS, pure ARIMA, or their combination, optionally extended with external regressors. For example, for OM with ETS(M,N,N) sub-model:
a_t = l_{a,t-1}(1 + ε_{a,t})
l_{a,t} = l_{a,t-1}(1 + α_a ε_{a,t})
μ_{a,t} = l_{a,t-1}
And similarly for b_t. The link function and the restrictions on μ_{a,t} and μ_{b,t} determine the occurrence subtype.
Because each sub-model can be ETS, ARIMA, or their ETSX/ARIMAX variants (with regressors), the full class is called OM regardless of internal model type. The notation of specific variants follows the underlying sub-model:
| Underlying sub-model | Name | Example model name |
|---|---|---|
| ETS only | oETS | oETS(MNN)[O] |
| ARIMA only | oARIMA | oARIMA(1,0,0)[O] |
| ETS + regressors | oETSX | oETSX(MNN)[O] |
| ARIMA + regressors | oARIMAX | oARIMAX(1,0,0)[O] |
| ETS + ARIMA | oETS+ARIMA | oETS(MNN)[O]+ARIMA(1,0,0) |
| ETS + ARIMA + regressors | oETS+ARIMAX | oETSX(MNN)[O]+ARIMA(1,0,0) |
All variants are fitted through the same OM / om() interface by combining the model, orders, and formula / X parameters.
| Type | Code | Link formula | Description |
|---|---|---|---|
| OM_F | "fixed" |
p = T₁/T | Constant probability; no optimisation |
| OM_O | "odds-ratio" |
p = μₐ/(μₐ+1) | Logistic-style; μ_b fixed at 1 |
| OM_I | "inverse-odds-ratio" |
p = 1/(1+μ_b) | Inverse logistic; Croston-related; μ_a fixed at 1 |
| OM_D | "direct" |
p = μₐ | Direct probability; TSB-like; μₐ ∈ [0,1] |
| OM_G | "general" |
p = μₐ/(μₐ+μ_b) | Both sub-models evolve - calls OMG
|
| OM_A | "auto" |
- | Automatic selection between the five above via AutoOM
|
Where T₁ is the count of non-zero observations and T is the total number of observations.
Constant probability - no optimisation, no state equation:
o_t ~ Bernoulli(p)
p̂ = T₁/T
For an ETS-based OM_F the sub-model is forced to "ANN" with α = 0.
Sets μ_b = 1:
p_t = μ_{a,t} / (μ_{a,t} + 1)
Equivalent to a logistic transform of the latent state a_t. The a_t sub-model can be ETS, ARIMA, or ETSX/ARIMAX.
Sets μ_a = 1:
p_t = 1 / (1 + μ_{b,t})
Related to Croston's method when 1 + b_t represents demand inter-arrival intervals.
Imposes μ_a + μ_b = 1 with μ_a ∈ [0, 1]:
p_t = μ_{a,t} = min(l_{a,t-1}, 1)
Analogous to the TSB (Teunter–Syntetos–Babai) method, modelling the probability directly as a bounded state.
No restrictions - both a_t and b_t evolve with their own independent ADAM models:
p_t = μ_{a,t} / (μ_{a,t} + μ_{b,t})
Most flexible but requires the most parameters. Implemented via OMG / omg().
iADAM is the model that joins the demand occurrence with the demand sizes parts. Here is an example with the iETS, i.e. model that has ETS components only:
iETS(E,T,S)_X(E,T,S)(E,T,S)
- First brackets: ETS model for demand sizes (
z_tcomponent) - Subscript letter: Occurrence subtype (F, O, I, D, G)
- Second brackets: ETS model for
a_t - Third brackets: ETS model for
b_t(only for OM_G)
Examples:
-
iETS(M,N,N)_F: Fixed probability, MNN for sizes -
iETS(M,M,N)_O(M,N,N): Odds-ratio, MMN for sizes, MNN for occurrence -
iETS(M,N,N)_G(M,N,N)(A,A,N): General, different sub-models fora_tandb_t
When discussing the occurrence part alone, the bracket shows the sub-model type, e.g. oETS(MNN)[O], oARIMA(1,0,0)[O], oETS(MNN)[O]+ARIMA(1,0,0).
OM is the single entry point. It transparently dispatches to specialised classes:
| Call | Returns |
|---|---|
OM(occurrence="fixed") |
OM instance |
OM(occurrence="odds-ratio") |
OM instance |
OM(occurrence="inverse-odds-ratio") |
OM instance |
OM(occurrence="direct") |
OM instance |
OM(occurrence="general") |
OMG instance |
OM(occurrence="auto") |
AutoOM instance (before .fit()); calling .fit() returns the best OM or OMG
|
Users only need to import OM; the other classes (OMG, AutoOM) are available for explicit use.
OM uses the same three-letter ETS codes as ADAM (Error–Trend–Seasonal). The same wildcards apply:
-
"Z"- auto-select from {A, M} -
"X"- auto-select from {N, A, Ad, M, Md} -
"N"- force None
Default: model="ZXZ". Check ADAM for mode details.
For occurrence="fixed" the model is forced to "ANN" (constant probability, α = 0).
OM also supports ARIMA components (via orders, ar_order, i_order, ma_order) and external regressors (via formula / regressors). The oes() R function is an ETS-only wrapper of om() that disables ARIMA and formula support - see OES.
library(smooth)
y <- rbinom(120, 1, 0.6)
# Fixed probability (no smoothing)
m_fixed <- om(y, occurrence="fixed")
# Odds-ratio (logistic link)
m <- om(y, model="MNN", occurrence="odds-ratio")
forecast(m, h=12)
# Inverse odds-ratio (Croston-related)
m <- om(y, model="MNN", occurrence="inverse-odds-ratio")
# Direct (TSB-like)
m <- om(y, model="MNN", occurrence="direct")
# With holdout validation
m <- om(y, model="MNN", occurrence="odds-ratio", h=12, holdout=TRUE)
# With seasonal lags
m <- om(y, model="MNA", lags=c(1, 7), occurrence="odds-ratio")from smooth import OM
import numpy as np
y = np.array([0,1,0,0,1,1,0,1,0,0,1]*10, dtype=float)
# Fixed probability (no smoothing)
m_fixed = OM(occurrence="fixed")
m_fixed.fit(y)
# Odds-ratio (logistic link)
m = OM(model="MNN", occurrence="odds-ratio")
m.fit(y)
fc = m.predict(h=12)
fc.mean # pd.Series of probability forecasts ∈ [0,1]
# Inverse odds-ratio (Croston-related)
m = OM(model="MNN", occurrence="inverse-odds-ratio")
m.fit(y)
# Direct (TSB-like)
m = OM(model="MNN", occurrence="direct")
m.fit(y)
# With holdout validation
m = OM(model="MNN", occurrence="odds-ratio", h=12, holdout=True)
m.fit(y)
# With seasonal lags
m = OM(model="MNA", lags=[1, 7], occurrence="odds-ratio")
m.fit(y)# Pure ARIMA(1,0,0) — oARIMA(1,0,0)[O]
m <- om(y, model="NNN", orders=list(ar=1, i=0, ma=0), occurrence="odds-ratio")
# ETS + ARIMA — oETS(MNN)[O]+ARIMA(1,0,0)
m <- om(y, model="MNN", orders=list(ar=1, i=0, ma=0), occurrence="odds-ratio")# Pure ARIMA(1,0,0) — oARIMA(1,0,0)[O]
m = OM(model="NNN", ar_order=1, occurrence="odds-ratio")
m.fit(y)
# ETS + ARIMA — oETS(MNN)[O]+ARIMA(1,0,0)
m = OM(model="MNN", ar_order=1, occurrence="odds-ratio")
m.fit(y)X <- matrix(runif(120), ncol=1)
colnames(X) <- "x1"
# oETSX — ETS with fixed regressor
m <- om(y, model="MNN", occurrence="odds-ratio", formula=~x1, xreg=X)
# Automatic regressor selection
m <- om(y, model="MNN", occurrence="odds-ratio", formula=~x1, xreg=X,
regressors="select")X = np.random.rand(len(y), 1)
# oETSX — ETS with fixed regressor
m = OM(model="MNN", occurrence="odds-ratio", regressors="use")
m.fit(y, X=X)
# Automatic regressor selection
m = OM(model="MNN", occurrence="odds-ratio", regressors="select")
m.fit(y, X=X)# Same ETS model for both sub-models
m <- omg(y, modelA="MNN", modelB="MNN", h=12)
# Different ETS models for a_t and b_t
m <- omg(y, modelA="MNN", modelB="AAN", h=12)
# Access individual sub-model states
m$modelA$states # sub-model A states
m$modelB$states # sub-model B states
# Seasonal data
m <- omg(y, modelA="MNA", modelB="MNA", lags=c(1, 7))from smooth import OMG
# Same model for both sub-models
m = OMG(model_a="MNN", model_b="MNN")
m.fit(y)
print(m.model_name) # "oETS[G](MNN)(MNN)"
# Different models for a_t and b_t
m = OMG(model_a="MNN", model_b="AAN")
m.fit(y)
# Access individual sub-model fitted values
m.model_a.fitted # sub-model A probabilities (odds-ratio side)
m.model_b.fitted # sub-model B probabilities (inverse-odds-ratio side)
# Seasonal data
m = OMG(model_a="MNA", model_b="MNA", lags=[1, 7])
m.fit(y)actuals(omg_obj) (R) and OMG.actuals (Python) return the binary occurrence indicator (0/1) built from the original input series, with the same class (ts / zoo / numeric) as actuals(om(y)) would on the same series. Previously the omg-level actuals lost the ts/zoo metadata; the top-level omg object now stores the input series under $data so the class is preserved.
# Try all types, select best by AICc
m <- auto.om(y, model="ZXZ", ic="AICc")
m$occurrence # winning type, e.g. "odds-ratio"
forecast(m, h=12)
# Restrict candidates to a subset
m <- auto.om(y, model="MNN",
occurrence=c("odds-ratio", "inverse-odds-ratio", "general"),
ic="AICc")from smooth import AutoOM
# Try all types, select best by AICc — returns OM or OMG directly
m = AutoOM(model="ZXZ", ic="AICc").fit(y)
print(m.model_name) # e.g. "oETS(MNN)[O]"
print(m.time_elapsed_) # total selection time in seconds
fc = m.predict(h=12)
# Restrict candidates to a subset
m = AutoOM(model="MNN",
occurrence=["odds-ratio", "inverse-odds-ratio", "general"]).fit(y)Support for the inference/output methods differs between the R and Python implementations:
| Method | R om
|
R omg
|
Python OM
|
Python OMG
|
|---|---|---|---|---|
print() / str()
|
✓ | ✓ | ✓ | ✓ |
coef() / .coef (+ .coef_names) |
✓ | ✓ | ✓ | ✓ |
vcov() |
✓ (vcov.om) |
✓ (vcov.omg) |
✗ | ✗ |
confint() |
✓ (via confint.adam) |
✓ (confint.omg) |
✗ | ✗ |
summary() |
✓ (summary.om) |
✓ (summary.omg) |
✗ | ✗ |
Python limitation:
vcov(),confint()andsummary()are not yet available for Python occurrence models.OMinherits them fromADAM, but they currently raiseValueError: Unknown distribution: plogisbecause the cumulative-logistic occurrence distribution is not handled in the Fisher Information path;OMGdoes not define them at all. For Gaussian-family models useADAM— see Coefficients-and-Parameters and Visualisation-and-Output.
y <- rbinom(120, 1, 0.6)
# Single occurrence model
m <- om(y, model="MNN", occurrence="odds-ratio")
summary(m) # estimates, standard errors, confidence intervals
vcov(m) # covariance matrix (inverted Fisher Information)
confint(m) # 95% confidence intervals
# General model: joint covariance / intervals over both sub-models
g <- omg(y, modelA="MNN", modelB="MNN")
summary(g) # A: / B: prefixed parameter blocks
confint(g, level=0.9)from smooth import OM, OMG
m = OM(model="MNN", occurrence="odds-ratio")
m.fit(y)
print(m) # concise model report
m.coef # estimated parameter vector (NDArray)
m.coef_names # matching parameter labels
g = OMG(model_a="MNN", model_b="MNN")
g.fit(y)
print(g.model_name) # "oETS[G](MNN)(MNN)"
g.model_a.fitted # sub-model A probabilities
g.model_b.fitted # sub-model B probabilities| Parameter | Type (R) | Type (Python) | Default (R / Python) | Description |
|---|---|---|---|---|
data / y
|
vector/ts | NDArray | - | Binary or non-binary series; binarised automatically (non-zero → 1) |
model |
character | str | "ZXZ" |
ETS specification or wildcard |
lags |
vector | int/List[int]/None |
frequency(y) / [1]
|
Seasonal period(s) |
orders |
list | Dict/None | zeros | ARIMA orders as list(ar=, i=, ma=) / {"ar":, "i":, "ma":}
|
ar_order |
- | int/List[int] | 0 | AR order(s) (Python alternative to orders) |
i_order |
- | int/List[int] | 0 | Integration order(s) |
ma_order |
- | int/List[int] | 0 | MA order(s) |
occurrence |
character | str |
"auto" / "odds-ratio"
|
Link function type; see link table above |
constant |
logical | bool | FALSE / False | Include constant/drift term |
formula |
formula | str/None | NULL / None | External regressors formula |
regressors |
character | str | "use" |
Regressor handling: "use", "select", or "adapt"
|
persistence |
vector | Dict[str,float]/None | NULL / None | Fixed smoothing parameters; keys "alpha", "beta", "gamma"
|
phi |
numeric | float/None | NULL / None | Damping parameter |
initial |
character | str/Dict | "backcasting" |
Initialisation: "backcasting", "optimal", "two-stage", "complete"
|
arma |
list | Dict/None | NULL / None | Fixed ARMA coefficients |
loss |
character / function | str / Callable | "likelihood" |
Optimisation objective. Single-step strings: "likelihood" (Bernoulli on the predicted probability), "MSE", "MAE", "HAM" (on the probability-scale residual ot - p_t), "LASSO" / "RIDGE" (regularised — pair with lambda / reg_lambda). A callable (actual, fitted, B) → scalar is also accepted for a custom loss. See Loss-Functions for the full menu and formulas. |
lambda (R) / reg_lambda (Python) |
numeric | float / None | 0 | Penalty weight for "LASSO" / "RIDGE" — 0 is unregularised, 1 is pure penalty. Acts on the parameter vector B (for OM) or the joint concat(B_A, B_B) (for OM). |
ic |
character | str | "AICc" |
Information criterion: "AIC", "AICc", "BIC", "BICc"
|
bounds |
character | str | "usual" |
Parameter bounds: "usual", "admissible", "none"
|
h |
integer | int | 0 | Forecast horizon |
holdout |
logical | bool | FALSE / False | Hold out last h observations for validation |
verbose |
- | int | 0 | Verbosity level (Python only; R uses silent) |
nlopt_kargs |
... |
Dict/None | NULL / None | Advanced NLopt options (Python) / extra ... args (R) |
ets |
character | str | "conventional" |
ETS formulation: "conventional" (Hyndman et al. 2008) or "adam" (ADAM reformulation). Experimental. |
All om() / OM parameters apply to each sub-model. The following are unique to omg() / OMG, exposing per-sub-model control via _a / _b suffixes:
| Parameter (R) | Parameter (Python) | Default (R / Python) | Description |
|---|---|---|---|
modelA |
model_a |
"MNN" |
ETS spec for sub-model A (odds-ratio side) |
modelB |
model_b |
same as modelA / model_a
|
ETS spec for sub-model B (inverse-odds-ratio side) |
ordersA |
orders_a |
zeros | ARIMA orders for sub-model A |
ordersB |
orders_b |
same as ordersA / orders_a
|
ARIMA orders for sub-model B |
constantA |
constant_a |
FALSE / False | Constant/drift for sub-model A |
constantB |
constant_b |
FALSE / False | Constant/drift for sub-model B |
persistenceA |
persistence_a |
NULL / None | Fixed smoothing for sub-model A |
persistenceB |
persistence_b |
NULL / None | Fixed smoothing for sub-model B |
phiA |
phi_a |
NULL / None | Damping for sub-model A |
phiB |
phi_b |
NULL / None | Damping for sub-model B |
armaA |
arma_a |
NULL / None | Fixed ARMA coefficients for sub-model A |
armaB |
arma_b |
NULL / None | Fixed ARMA coefficients for sub-model B |
formulaA |
formula_a |
NULL / None | Regressor formula for sub-model A |
formulaB |
formula_b |
NULL / None | Regressor formula for sub-model B |
regressorsA |
regressors_a |
"use" |
Regressor handling for sub-model A |
regressorsB |
regressors_b |
"use" |
Regressor handling for sub-model B |
All om() / OM parameters apply and are forwarded to every candidate model (including both sub-models of the general/OMG candidate). The following are unique to auto.om() / AutoOM:
| Parameter (R) | Parameter (Python) | Type (R) | Type (Python) | Default (R / Python) | Description |
|---|---|---|---|---|---|
occurrence |
occurrence |
character vector | List[str] | all 5 types | Occurrence types to compare; subset to restrict candidates |
parallel |
— | logical/integer | — | FALSE | Fit candidates in parallel using foreach (R only) |
ets |
ets |
character | str | "conventional" |
ETS formulation forwarded to every candidate: "conventional" or "adam"
|
| Attribute (R) | Attribute (Python) | Type | Description |
|---|---|---|---|
modelName(m) |
m.model_name |
str | Full name, e.g. "oETS(MNN)[O]"
|
fitted(m) |
m.fitted |
NDArray | In-sample probability estimates ∈ (0,1) |
residuals(m) |
m.residuals |
NDArray | o_t − p̂_t |
m$states |
m.states |
NDArray | State matrix (components × T+lags) |
m$persistence |
m.persistence_vector |
Dict | Smoothing parameters {"alpha": ..., ...}
|
m$phi |
m.phi_ |
float/None | Damping parameter |
m$transition |
m.transition |
NDArray | Transition matrix F |
m$measurement |
m.measurement |
NDArray | Measurement matrix W |
m$initial |
m.initial_value |
Dict | Initial states |
coef(m) |
m.coef |
NDArray | Estimated parameter vector B |
logLik(m) |
m.loglik |
float | Log-likelihood (Bernoulli) |
AIC(m) |
m.aic |
float | AIC |
AICc(m) |
m.aicc |
float | Corrected AIC |
BIC(m) |
m.bic |
float | BIC |
BICc(m) |
m.bicc |
float | Corrected BIC |
m$lossValue |
m.loss_value |
float | Value of loss function |
m$distribution |
m.distribution_ |
str | Always "plogis"
|
m$scale |
m.scale / m.sigma
|
float |
nan (no scale for Bernoulli) |
m$occurrence |
m._om_occurrence |
str | Occurrence type used |
nobs(m) |
m.nobs |
int | Number of in-sample observations |
m$accuracy |
m.accuracy |
Dict/None | Holdout accuracy (when holdout=True) |
OM inherits all ADAM attributes; see ADAM for the full list.
omg() / OMG returns an object with all standard OM fitted attributes plus:
| Attribute (R) | Attribute (Python) | Description |
|---|---|---|
m$modelA |
m.model_a |
Fitted om / OM sub-model A (odds-ratio side) |
m$modelB |
m.model_b |
Fitted om / OM sub-model B (inverse-odds-ratio side) |
modelName(m) |
m.model_name |
"oETS[G](MNN)(MNN)" |
fitted(m) |
m.fitted |
Combined probability a_t/(a_t + b_t)
|
coef(m) |
m.coef |
Joint parameter vector [B_A, B_B]
|
auto.om() / AutoOM.fit() returns the best-fitting om / OM or omg / OMG object directly. All standard OM or OMG fitted attributes are available on the returned model. One additional attribute is set:
| Attribute (R) | Attribute (Python) | Description |
|---|---|---|
m$timeElapsed |
m.time_elapsed_ |
Total selection time (seconds) |
# om()
m <- om(y, model="MNN", occurrence="odds-ratio")
modelName(m) # "oETS(MNN)[O]"
fitted(m) # in-sample probabilities
residuals(m) # o_t - p̂_t
m$states # state matrix
m$persistence # smoothing parameters
logLik(m)
AIC(m); AICc(m); BIC(m)
coef(m)
forecast(m, h=12)
# omg()
g <- omg(y, modelA="MNN", modelB="MNN")
g$modelA # fitted sub-model A
g$modelB # fitted sub-model B
fitted(g) # combined probability p_t = a/(a+b)
logLik(g); AIC(g)
# auto.om() — returns the best om or omg directly
a <- auto.om(y, model="ZXZ")
a$occurrence # selected type, e.g. "odds-ratio"
a$timeElapsed # selection time in seconds
forecast(a, h=12)# OM
m = OM(model="MNN", occurrence="odds-ratio")
m.fit(y)
m.model_name # "oETS(MNN)[O]"
m.fitted # in-sample probability estimates
m.residuals # o_t - p̂_t
m.states # state matrix
m.persistence_vector # {"alpha": ..., ...}
m.aic; m.aicc; m.bic; m.bicc
fc = m.predict(h=12)
fc.mean # pd.Series of probability forecasts ∈ [0,1]
# OMG
g = OMG(model_a="MNN", model_b="MNN")
g.fit(y)
g.model_a.fitted # sub-model A probabilities
g.model_b.fitted # sub-model B probabilities
g.fitted # combined probability p_t = a/(a+b)
g.loglik; g.aic
# AutoOM — fit() returns the best OM or OMG directly
a = AutoOM(model="ZXZ").fit(y)
a.model_name # e.g. "oETS(MNN)[O]"
a.time_elapsed_ # total selection time in seconds
fc = a.predict(h=12)OM.predict() returns probability forecasts (mean ∈ [0,1]). The interval and level parameters are accepted for API compatibility but interval estimation for binary occurrence is not currently supported.
To forecast full intermittent demand (occurrence × demand sizes), pass the fitted OM as the occurrence argument of ADAM.fit():
occ_model = OM(model="MNN", occurrence="odds-ratio")
occ_model.fit(y)
from smooth import ADAM
demand_model = ADAM(model="MNN")
demand_model.fit(y, occurrence=occ_model)
fc = demand_model.predict(h=12)In R:
occ_model <- om(y, model="MNN", occurrence="odds-ratio")
demand_model <- adam(y, "MNN", occurrence=occ_model, h=12)- Svetunkov, I. (2023). Forecasting and Analytics with ADAM. Chapter 13: https://openforecast.org/adam/ADAMIntermittent.html
- Svetunkov, I. & Boylan, J.E. (2023). iETS: State space model for intermittent demand forecasting. International Journal of Production Economics, 265, 109013. DOI: 10.1016/j.ijpe.2023.109013
- ADAM - full iETS model (occurrence + demand sizes in one fit)
-
OES - R-only
oes()/oesg()ETS-only wrapper interface -
Fitted-Values-and-Forecasts -
predict()output format -
Residuals-and-Errors -
residuals(),rmultistep(),outlierdummy() -
Loss-Functions - full
lossmenu, LASSO/RIDGE regularisation, custom callable losses