Skip to content

Time-Series Models API

SeasonalResidualDetector

Python
SeasonalResidualDetector(season_length: int, *, key: str | None = None, alpha: float = 0.2, beta: float = 0.05, gamma: float = 0.1, residual_alpha: float = 0.05, min_scale: float = 1e-06, normalize: bool = True)

Score departures from a seasonal one-step-ahead forecast.

The model learns additive Holt-Winters level, trend, and seasonal components for one finite numeric feature sampled at a fixed cadence. Every successful learning call advances one seasonal position. There is no timestamp or gap inference: preprocess missing observations before using this detector.

Parameters:

Name Type Description Default
season_length int

Known number of observations in a cycle, at least two.

required
key str | None

Fixed feature name, or infer it on the first successful learning.

None
alpha float

Level smoothing weight in [0, 1].

0.2
beta float

Trend smoothing weight in [0, 1] (the usual beta-star parameter).

0.05
gamma float

Seasonal smoothing weight in [0, 1-alpha], using prior level and trend in the seasonal update.

0.1
residual_alpha float

Absolute forecast-error smoothing weight in (0, 1].

0.05
min_scale float

Positive, finite floor for the residual scale, in input units.

1e-06
normalize bool

Divide absolute residual by the previously learned residual scale when true; otherwise return absolute residual in input units.

True
Notes

Exactly two cycles initialize the model. Their mean difference gives the per-observation trend. Detrended observations at each seasonal position are averaged to initialize seasonality, and the second cycle mean is advanced to its final position to initialize level. The initial residual scale is the mean absolute error of that fitted warm-up model; subsequent errors are genuinely one-step-ahead and exponentially faded. Warm-up scoring returns zero with no forecast or residual.

Scores use only previously learned state and are non-negative, without a probability interpretation or fixed upper bound. Learning every event adapts both the forecast and scale to anomalies. Skipping an update also skips its seasonal position; this API requires every time step to be learned. State is O(season_length), with O(1) work per event after the O(season_length) initialization. Unrepresentable arithmetic raises OverflowError without changing learned state.

References

Hyndman and Athanasopoulos, Forecasting: Principles and Practice, 3rd ed., additive Holt-Winters component equations: https://otexts.com/fpp3/holt-winters.html

is_ready property

Python
is_ready: bool

Whether two complete cycles have been learned.

residual_scale property

Python
residual_scale: float

Previously learned mean absolute error, including the configured floor.

reset

Python
reset() -> None

Clear learned components, readiness, and any inferred feature name.

explain_one

Python
explain_one(x: dict[str, float]) -> tuple[float, float | None, float | None]

Return (score, forecast, signed residual) without learning.

Before readiness return (0.0, None, None). A positive residual means the candidate exceeds its prior forecast; a negative one means it falls below. Repeated calls neither advance seasonal phase nor lock a name.

score_one

Python
score_one(x: dict[str, float]) -> float

Return the absolute, optionally scaled prior forecast residual.

learn_one

Python
learn_one(x: dict[str, float]) -> None

Learn one fixed-cadence observation, independently of scoring calls.

MultivariateRollingMatrixProfile

Python
MultivariateRollingMatrixProfile(subsequence_length: int, window_size: int | None = None, *, normalize: bool = True, exclusion_zone: int | None = None)

Exact, causal scores for aligned multivariate subsequences.

For each eligible historical interval, compute each channel's Euclidean distance to the newest subsequence and take the largest channel distance. The score is the minimum of these maxima, so all channels must match the same historical interval. Higher scores mean greater joint novelty.

Parameters:

Name Type Description Default
subsequence_length int

Number of consecutive events per subsequence, at least two.

required
window_size int | None

Retained event capacity including the candidate, defaulting to 16 * subsequence_length. Must be at least subsequence_length + exclusion_zone + 1.

None
normalize bool

Independently population z-normalize each channel's windows when true. Otherwise use raw Euclidean distances; channels with larger units can dominate the score.

True
exclusion_zone int | None

Exclude reference starts within this many positions of the query start. Defaults to ceil(subsequence_length / 4). Set to subsequence_length - 1 for nonoverlapping matches.

None
Notes
  • Each event contains one or more consistently named finite numeric features representing one aligned observation. The first successful learning call establishes the schema; scoring never commits it.
  • Query before learning. score_one, match_one, and explain_one are read-only; learning needs no preceding query.
  • Warm-up returns zero and no match until subsequence_length + exclusion_zone events have been learned. Thereafter every valid event has an eligible reference, including during eviction. Equal scores choose the earliest retained start.
  • Normalization removes per-channel level and amplitude differences. Two constant windows have distance zero; exactly one constant window gives distance sqrt(subsequence_length) for that channel.
  • With d channels, scoring costs typically O(d * W * log(W)) with direct numerical fallback up to O(d * W * m). Learning costs O(d * m); retained state and working memory are O(d * W).
  • This exposes the newest causal profile entry and its common match, not a historical profile or global motif ranking. Raw scores beyond the floating-point range raise OverflowError.
References

Matrix Profile for Anomaly Detection on Multidimensional Time Series. Uses the pre-max aggregation with a causal, bounded reference window. https://arxiv.org/abs/2409.09298

n_samples_seen property

Python
n_samples_seen: int

Number of successfully learned events since initialization or reset.

n_history property

Python
n_history: int

Number of retained observations, at most window_size.

is_ready property

Python
is_ready: bool

Whether the next valid event has an eligible reference subsequence.

reset

Python
reset() -> None

Clear history, schema, and absolute indices; preserve configuration.

learn_one

Python
learn_one(x: dict[str, float]) -> None

Learn an aligned observation and its window statistics without scoring.

score_one

Python
score_one(x: dict[str, float]) -> float

Return the minimum largest-channel distance without learning.

match_one

Python
match_one(x: dict[str, float]) -> tuple[float, int | None]

Return (score, reference_start) without changing learned state.

The absolute, zero-based index counts learned events since reset. Before readiness, return (0.0, None). Later learning may evict the returned match.

explain_one

Python
explain_one(x: dict[str, float]) -> tuple[float, int | None, dict[str, float]]

Return score, common reference start, and its channel distances.

The fresh mapping follows sorted schema order and describes distances at the selected common interval, not each channel's individual nearest match. Its maximum equals the score. Before readiness, return (0.0, None, {}). This method does not learn or advance indices.

RollingMatrixProfile

Python
RollingMatrixProfile(subsequence_length: int, window_size: int | None = None, *, normalize: bool = True, exclusion_zone: int | None = None)

Exact, causal anomaly scores for the newest scalar subsequence.

Each score is the minimum distance from the subsequence ending at the candidate event to an eligible preceding subsequence in the latest window_size values, including that candidate. Higher distances mean greater novelty. History and temporary memory are bounded by the window.

Parameters:

Name Type Description Default
subsequence_length int

Number of consecutive values per subsequence, at least two.

required
window_size int | None

Total retained sample capacity, defaulting to 16 * subsequence_length. Must be at least subsequence_length + exclusion_zone + 1.

None
normalize bool

Use population z-normalized Euclidean distance when true; otherwise use ordinary Euclidean distance, preserving level and amplitude differences.

True
exclusion_zone int | None

Exclude references whose start is within this many positions of the query start. Defaults to ceil(subsequence_length / 4). Set to subsequence_length - 1 to require nonoverlapping matches.

None
Notes
  • Input contains exactly one consistently named finite numeric feature.
  • Call score_one or match_one before learn_one. Scoring is read-only, and learning does not require a preceding score call.
  • Warm-up returns 0.0 and no match until subsequence_length + exclusion_zone samples have been learned. Thereafter, every valid event has an eligible reference.
  • Normalized distance between two constant windows is zero, even at different levels; between a constant and a nonconstant it is sqrt(subsequence_length). Use raw mode for level anomalies.
  • A fresh FFT distance profile screens matches on each scored event; direct distances resolve potential minima. Typical scoring work is O(window_size * log(window_size)) with a numerical fallback of at most O(window_size * subsequence_length). Learning takes O(subsequence_length) work.
  • This model exposes the newest left-profile entry, not a historical matrix profile or a global motif/discord ranking. Raw distances exceeding the floating-point range raise OverflowError.
References

Matrix Profile I: All Pairs Similarity Joins for Time Series. https://doi.org/10.1109/ICDM.2016.0179

STUMPY exclusion and constant-subsequence conventions: https://stumpy.readthedocs.io/en/latest/api.html

n_samples_seen property

Python
n_samples_seen: int

Number of successfully learned events since initialization or reset.

n_history property

Python
n_history: int

Number of retained observations, at most window_size.

is_ready property

Python
is_ready: bool

Whether the next valid event has an eligible reference subsequence.

reset

Python
reset() -> None

Clear history, schema, and absolute indices; preserve configuration.

learn_one

Python
learn_one(x: dict[str, float]) -> None

Append one event and its window statistics without computing a score.

score_one

Python
score_one(x: dict[str, float]) -> float

Return the newest subsequence's nearest distance without learning.

match_one

Python
match_one(x: dict[str, float]) -> tuple[float, int | None]

Return (distance, reference_start) without changing learned state.

Indices count successfully learned events from zero since the last reset. Before readiness the result is (0.0, None). Equal distances choose the earliest retained start. Returned indices describe this query; later learning may evict the corresponding samples.

XLagDAMP

Python
XLagDAMP(subsequence_length: int, x_lag: int | None = None, start_index: int | None = None, eps: float = 1e-12)

Bases: BaseModel

Pure-online X-Lag Amnesic Discord Aware Matrix Profile detector.

Each event supplies one scalar time-series value. Once enough history is available, the model scores the subsequence ending at the current event by its z-normalized Euclidean distance to its nearest preceding subsequence. Higher scores indicate stronger left-discord candidates.

This implementation follows the authors' DAMP_X_Lag_Amnesic.m source:

  • backward processing only (lookahead=0), the authors' pure-online mode,
  • MASS_V2 distance profiles with population standard deviations,
  • iterative doubling starting at 2^nextpow2(8 * subsequence_length),
  • best-so-far early abandoning,
  • exact search over at most the most recent x_lag values.

X-Lag amnesia bounds both memory and worst-case search history. As in the reference algorithm, early-abandoned scores are approximate: they are bounded by the exact left-discord score and the current best-so-far score. The highest peaks are the meaningful discord candidates.

Parameters:

Name Type Description Default
subsequence_length int

Number of consecutive values in each subsequence.

required
x_lag int | None

Maximum number of values searched backward. Defaults to the authors' 16 * subsequence_length.

None
start_index int | None

One-based subsequence start index at which processing begins. Defaults to the authors' recommendation of at least four cycles, 4 * subsequence_length.

None
eps float

Numerical threshold used to reject constant subsequences.

1e-12
Notes
  • Input must contain exactly one consistently named numeric feature.
  • Scores are 0.0 before start_index is reached.
  • Constant subsequences are rejected, matching the reference implementation's input restriction.
  • State is bounded by x_lag + subsequence_length - 1 learned values.
References

Lu, Y., Wu, R., Mueen, A., Zuluaga, M. A., & Keogh, E. (2022). Matrix Profile XXIV: Scaling Time Series Anomaly Detection to Trillions of Datapoints and Ultra-fast Arriving Data Streams. https://doi.org/10.1145/3534678.3539271

Original authors' implementation and documentation: https://sites.google.com/view/discord-aware-matrix-profile/documentation

n_samples_seen property

Python
n_samples_seen: int

Number of values processed through learn_one.

n_history property

Python
n_history: int

Number of learned values retained in bounded history.

n_subsequences_processed property

Python
n_subsequences_processed: int

Number of subsequences processed after warmup.

best_score property

Python
best_score: float

Highest exact left-discord score observed so far.

last_score property

Python
last_score: float

Score computed during the most recent learn_one call.

is_ready property

Python
is_ready: bool

Whether the next event starts a processable subsequence.

reset

Python
reset() -> None

Reset learned state while preserving hyperparameters.

learn_one

Python
learn_one(x: dict[str, float]) -> None

Process one value and update the online DAMP state.

score_one

Python
score_one(x: dict[str, float]) -> float

Score the subsequence ending at this value without mutating state.