Croston's method and its variants for intermittent demand forecasting.

Classes

CrostonForecaster

class algorithms.timeseries.croston.CrostonForecaster(Regressor)

Croston's method for intermittent demand forecasting.

Intermittent demand series are mostly zero with occasional non-zero demands. Simple exponential smoothing applied directly to such a series is biased and updates at the wrong moments, because a long run of zeros drags the level down between demands. Croston's insight is to smooth two separate series: the sizes of the non-zero demands and the inter-arrival intervals between them. The per-period forecast is the ratio of the two.
Constructor
__init__(
    self,
    alpha: float = 0.1,
    variant: str = 'classic',
    alpha_prob: float | None = None,
)

Overview

  1. Walk through the series and record the non-zero demands and the
number of periods since the previous non-zero demand.
  1. Exponentially smooth the demand sizes into \hat{z}.
  2. Exponentially smooth the inter-arrival intervals into
\hat{p} (both updated only when a demand occurs).
  1. Form the per-period forecast \hat{y} = \hat{z} / \hat{p},
optionally multiplied by a bias-correction factor.
  1. The forecast is flat over the horizon.

Theory

Let z_j be the size of the j-th non-zero demand and q_j the number of periods since the previous one. On a period with a demand,

\hat{z}_j = \alpha z_j + (1 - \alpha) \hat{z}_{j-1}, \qquad \hat{p}_j = \alpha q_j + (1 - \alpha) \hat{p}_{j-1},

and on a period without demand both estimates are carried forward. The forecast is

\hat{y}_{n+h} = c \, \frac{\hat{z}}{\hat{p}},

with a variant-dependent correction factor c:

  • "classic": c = 1 (Croston, 1972).
  • "sba": c = 1 - \alpha/2, the Syntetos-Boylan
approximation, which removes the leading term of the inversion bias in E[\hat{z}/\hat{p}].
  • "sbj": c = 1 - \alpha/(2 - \alpha), the
Shale-Boylan-Johnston correction derived under Poisson arrivals.

The "tsb" variant (Teunter, Syntetos and Babai, 2011) replaces the interval by the demand probability \hat{d}, updated every period,

\hat{d}_t = \alpha_p \mathbb{1}[y_t > 0] + (1 - \alpha_p) \hat{d}_{t-1}, \qquad \hat{y}_{n+h} = \hat{d}_n \, \hat{z}_n ,

which lets the forecast decay when demand stops -- Croston's estimate never does, making it obsolescence-blind.

Parameters

alpha
float = 0.1
Smoothing parameter for demand sizes, and for intervals in the Croston-family variants. Must lie in (0, 1].
variant
{"classic", "sba", "sbj", "tsb"} = "classic"
Which estimator to use. See the Theory section.
alpha_prob
float = None
Smoothing parameter for the demand probability in the "tsb" variant. Defaults to alpha when None. Ignored by the other variants.

Attributes

demand_
float
Final smoothed non-zero demand size :math:`\hat{z}`.
interval_
float
Final smoothed inter-arrival interval :math:`\hat{p}`. Set to nan for the "tsb" variant, which does not estimate it.
probability_
float
Final smoothed demand probability :math:`\hat{d}`. Set to nan for the Croston-family variants.
correction_
float
Bias-correction factor :math:`c` applied to the ratio.
forecast_
float
The flat per-period forecast.
n_nonzero_
int
Number of non-zero demands in the training series.
fitted_values_
np.ndarray
In-sample one-step-ahead forecasts.
resid_
np.ndarray
In-sample residuals.
n_obs_
int
Number of training observations.

Notes

Complexity:

  • Training: O(n).
  • Prediction: O(h).
When to use CrostonForecaster:
  • Spare parts, slow-moving inventory and any series where most periods
are zero and the mean inter-demand interval exceeds about 1.3.
  • When the quantity of interest is the expected demand per period
for a safety-stock or reorder-point calculation.
  • Prefer "sba" over "classic" in practice: the ratio estimator
is biased upward, and the correction is essentially free.
  • Prefer "tsb" when items go obsolete and the forecast must decay
after demand stops.

References

Croston1972
Croston, J. D. (1972). Forecasting and stock control for intermittent demands. Operational Research Quarterly, 23(3), 289-303. :doi:`10.1057/jors.1972.50`
Syntetos2005
Syntetos, A. A., & Boylan, J. E. (2005). The accuracy of intermittent demand estimates. International Journal of Forecasting, 21(2), 303-314. :doi:`10.1016/j.ijforecast.2004.10.001`
Shale2006
Shale, E. A., Boylan, J. E., & Johnston, F. R. (2006). Forecasting for intermittent demand: the estimation of an unbiased average. Journal of the Operational Research Society, 57(5), 588-592. :doi:`10.1057/palgrave.jors.2602031`
Teunter2011
Teunter, R. H., Syntetos, A. A., & Babai, M. Z. (2011). Intermittent demand: linking forecasting to inventory obsolescence. European Journal of Operational Research, 214(3), 606-615. :doi:`10.1016/j.ejor.2011.05.018`
python
>>> import numpy as np
>>> from tuiml.algorithms.timeseries.croston import CrostonForecaster
>>> y = np.array([0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10], dtype=float)
>>> model = CrostonForecaster(alpha=0.1, variant="classic").fit(y)
>>> float(model.predict(steps=1)[0])
2.5
>>> sba = CrostonForecaster(alpha=0.1, variant="sba").fit(y)
>>> float(sba.predict(steps=1)[0])
2.375

Methods

get_parameter_schema (cls) -> Dict[str, Dict[str, Any]]

Return JSON Schema for constructor parameters.

get_capabilities (cls) -> List[str]

Return supported capabilities.

get_complexity (cls) -> str

Return complexity analysis.

get_references (cls) -> List[str]

Return academic citations.

fit (self, y: np.ndarray, X: Optional[np.ndarray]=None) -> 'CrostonForecaster'

Fit the Croston model to an intermittent demand series.

Parameters
y
np.ndarray of shape (n_samples,)
Demand per period. Zeros denote periods without demand.
X
np.ndarray = None
Ignored. Present for API consistency with regressors.
Returns
self
CrostonForecaster
Fitted estimator.
predict (self, steps: int=1, X: Optional[np.ndarray]=None) -> np.ndarray

Forecast the expected demand per period.

Parameters
steps
int = 1
Number of future time steps to forecast.
X
np.ndarray = None
Ignored. Present for API consistency with regressors.
Returns
forecast
np.ndarray of shape (steps,)
Flat per-period demand forecast.
fit_predict (self, y: np.ndarray, steps: int=1) -> np.ndarray

Fit the model and forecast in one call.

Parameters
y
np.ndarray of shape (n_samples,)
Demand per period.
steps
int = 1
Number of future time steps to forecast.
Returns
forecast
np.ndarray of shape (steps,)
Flat per-period demand forecast.