MADRID¶
- class MADRID(min_length=8, max_length=None, step_size=1, train_test_split=None)[source]¶
Bases:
BaseSeriesAnomalyDetectorMADRID multi-length discord anomaly detector.
MADRID is a discord discovery algorithm that finds time series anomalies of all lengths at once [1], rather than committing to a single subsequence length. Instead of committing to a single subsequence length, MADRID runs the left-discord matrix-profile method DAMP for every subsequence length in a candidate set and combines the length-normalised discord profiles into a single per-point anomaly score. It is the faster successor of the MERLIN discord discovery algorithm.
For each candidate length
mthe algorithm computes an approximate left matrix profile with DAMP (the distance from each subsequence to its nearest neighbour that starts strictly to its left), normalises it bysqrt(m)so that profiles of different lengths are comparable, and stores it as a row of a multi-length discord table. Because DAMP prunes aggressively, only the per-length best discords carry an exactness guarantee, sopredictbuilds its pointwise scores from exactly those: each length’s top discord paints its length-normalised score onto the points that subsequence covers, combined across lengths with the maximum, and points covered by no top discord score zero. Every emitted value is one the algorithm actually evaluated. The complete multi-length output, including the approximate discord table, is available viapredict_discords. Higher scores indicate more anomalous points.Points before
train_test_splitform a warm-up (training) region that is only used as reference history and is always scored zero, mirroring DAMP’s left-discord definition.- Parameters:
- min_lengthint, default=8
Minimum subsequence length in the candidate set. Must be at least 4.
- max_lengthint or None, default=None
Maximum subsequence length in the candidate set. Must be at most half the length of the series. If
None, the reference implementation’s automatic mode is used: the maximum length is derived from the warm-up region assplit // 20and about 50 candidate lengths are sampled from the range instead of sweeping every integer, following the algorithm’s parameter-free motivation.- step_sizeint, default=1
Step between consecutive candidate subsequence lengths when
max_lengthis given: the candidate set isrange(min_length, max_length + 1, step_size). Ignored in automatic mode.- train_test_splitint, float or None, default=None
Location of the split point between the warm-up (training) region and the region searched for anomalies. An
intis used directly as the split index. Afloatin(0, 1)is interpreted as a fraction of the series length. IfNone, a warm-up ofmax(max_length, len(X) // 5)points is used. The split must satisfymax_length <= split <= len(X) - max_length.
Notes
Capabilities ¶ Missing Values
No
Multithreading
No
Univariate
Yes
Multivariate
No
References
[1]Yue Lu, Thirumalai Vinjamoor Akhil Srinivas, Takaaki Nakamura, Makoto Imamura and Eamonn Keogh, “Matrix Profile XXX: MADRID: A Hyper-Anytime and Parameter-Free Algorithm to Find Time Series Anomalies of All Lengths,” 2023 IEEE International Conference on Data Mining (ICDM), Shanghai, China, 2023, pp. 1199-1204.
Examples
>>> import numpy as np >>> from aeon.anomaly_detection.series.distance_based import MADRID >>> rng = np.random.default_rng(2) >>> X = np.sin(np.linspace(0, 12 * np.pi, 120)) + rng.normal(0, 0.05, 120) >>> X[70:78] = 2.5 # inject an anomalous flat segment >>> detector = MADRID(min_length=6, max_length=12, train_test_split=24) >>> scores = detector.fit_predict(X) >>> bool(65 <= int(np.argmax(scores)) <= 78) True
Methods
clone([random_state])Obtain a clone of the object with the same hyperparameters.
fit(X[, y, axis])Fit time series anomaly detector to X.
fit_predict(X[, y, axis])Fit time series anomaly detector and find anomalies for X.
get_class_tag(tag_name[, raise_error, ...])Get tag value from estimator class (only class tags).
Get class tags from estimator class and all its parent classes.
get_fitted_params([deep])Get fitted parameters.
get_params([deep])Get parameters for this estimator.
get_tag(tag_name[, raise_error, ...])Get tag value from estimator class.
get_tags()Get tags from estimator.
predict(X[, axis])Find anomalies in X.
Run MADRID and return the complete multi-length discord information.
reset([keep])Reset the object to a clean post-init state.
set_fit_request(*[, axis])Configure whether metadata should be requested to be passed to the
fitmethod.set_params(**params)Set the parameters of this estimator.
set_predict_request(*[, axis])Configure whether metadata should be requested to be passed to the
predictmethod.set_tags(**tag_dict)Set dynamic tags to given values.
- clone(random_state=None)[source]¶
Obtain a clone of the object with the same hyperparameters.
A clone is a different object without shared references, in post-init state. This function is equivalent to returning
sklearn.cloneofself. Equal in value totype(self)(**self.get_params(deep=False)).- Parameters:
- random_stateint, RandomState instance, or None, default=None
Sets the random state of the clone. If
None, the random state is not set. Ifint,random_stateis the seed used by the random number generator. IfRandomStateinstance,random_stateis the random number generator.
- Returns:
- estimatorobject
Instance of
type(self), clone of self (see above)
- fit(X, y=None, axis=1)[source]¶
Fit time series anomaly detector to X.
If the tag
fit_is_emptyis true, this just sets theis_fittedtag to true. Otherwise, it checksselfcan handleX, formatsXinto the structure required byselfthen passesX(and possiblyy) to_fit.- Parameters:
- Xone of aeon.base._base_series.VALID_SERIES_INPUT_TYPES
The time series to fit the model to. A valid aeon time series data structure. See aeon.base._base_series.VALID_SERIES_INPUT_TYPES for aeon supported types.
- yone of aeon.base._base_series.VALID_SERIES_INPUT_TYPES, default=None
The target values for the time series. A valid aeon time series data structure. See aeon.base._base_series.VALID_SERIES_INPUT_TYPES for aeon supported types.
- axisint
The time point axis of the input series if it is 2D. If
axis==0, it is assumed each column is a time series and each row is a time point. i.e. the shape of the data is(n_timepoints, n_channels).axis==1indicates the time series are in rows, i.e. the shape of the data is(n_channels, n_timepoints).
- Returns:
- BaseSeriesAnomalyDetector
The fitted estimator, reference to self.
- fit_predict(X, y=None, axis=1) ndarray[source]¶
Fit time series anomaly detector and find anomalies for X.
- Parameters:
- Xone of aeon.base._base_series.VALID_SERIES_INPUT_TYPES
The time series to fit the model to. A valid aeon time series data structure. See aeon.base._base_series.VALID_INPUT_TYPES for aeon supported types.
- yone of aeon.base._base_series.VALID_SERIES_INPUT_TYPES, default=None
The target values for the time series. A valid aeon time series data structure. See aeon.base._base_series.VALID_SERIES_INPUT_TYPES for aeon supported types.
- axisint, default=1
The time point axis of the input series if it is 2D. If
axis==0, it is assumed each column is a time series and each row is a time point. i.e. the shape of the data is(n_timepoints, n_channels).axis==1indicates the time series are in rows, i.e. the shape of the data is(n_channels, n_timepoints).
- Returns:
- np.ndarray
A boolean, int or float array of length len(X), where each element indicates whether the corresponding subsequence is anomalous or its anomaly score.
- classmethod get_class_tag(tag_name, raise_error=True, tag_value_default=None)[source]¶
Get tag value from estimator class (only class tags).
- Parameters:
- tag_namestr
Name of tag value.
- raise_errorbool, default=True
Whether a
ValueErroris raised when the tag is not found.- tag_value_defaultany type, default=None
Default/fallback value if tag is not found and error is not raised.
- Returns:
- tag_value
Value of the
tag_nametag in cls. If not found, returns an error ifraise_errorisTrue, otherwise it returnstag_value_default.
- Raises:
- ValueError
if
raise_errorisTrueandtag_nameis not inself.get_tags().keys()
Examples
>>> from aeon.classification import DummyClassifier >>> DummyClassifier.get_class_tag("capability:multivariate") True
- classmethod get_class_tags()[source]¶
Get class tags from estimator class and all its parent classes.
- Returns:
- collected_tagsdict
Dictionary of tag name and tag value pairs. Collected from
_tagsclass attribute via nested inheritance. These are not overridden by dynamic tags set byset_tagsor class__init__calls.
- get_fitted_params(deep=True)[source]¶
Get fitted parameters.
- State required:
Requires state to be “fitted”.
- Parameters:
- deepbool, default=True
If
True, will return the fitted parameters for this estimator and contained subobjects that are estimators.
- Returns:
- fitted_paramsdict
Fitted parameter names mapped to their values.
- get_params(deep=True)¶
Get parameters for this estimator.
- Parameters:
- deepbool, default=True
If True, will return the parameters for this estimator and contained subobjects that are estimators.
- Returns:
- paramsdict
Parameter names mapped to their values.
- get_tag(tag_name, raise_error=True, tag_value_default=None)[source]¶
Get tag value from estimator class.
Includes dynamic and overridden tags.
- Parameters:
- tag_namestr
Name of tag to be retrieved.
- raise_errorbool, default=True
Whether a
ValueErroris raised when the tag is not found.- tag_value_defaultany type, default=None
Default/fallback value if tag is not found and error is not raised.
- Returns:
- tag_value
Value of the
tag_nametag in self. If not found, returns an error ifraise_errorisTrue, otherwise it returnstag_value_default.
- Raises:
- ValueError
if raise_error is
Trueandtag_nameis not inself.get_tags().keys()
Examples
>>> from aeon.classification import DummyClassifier >>> d = DummyClassifier() >>> d.get_tag("capability:multivariate") True
- get_tags()[source]¶
Get tags from estimator.
Includes dynamic and overridden tags.
- Returns:
- collected_tagsdict
Dictionary of tag name and tag value pairs. Collected from
_tagsclass attribute via nested inheritance and then any overridden and new tags from__init__orset_tags.
- predict(X, axis=1) ndarray[source]¶
Find anomalies in X.
- Parameters:
- Xone of aeon.base._base_series.VALID_SERIES_INPUT_TYPES
The time series to fit the model to. A valid aeon time series data structure. See aeon.base._base_series.VALID_SERIES_INPUT_TYPES for aeon supported types.
- axisint, default=1
The time point axis of the input series if it is 2D. If
axis==0, it is assumed each column is a time series and each row is a time point. i.e. the shape of the data is(n_timepoints, n_channels).axis==1indicates the time series are in rows, i.e. the shape of the data is(n_channels, n_timepoints).
- Returns:
- np.ndarray
A boolean, int or float array of length len(X), where each element indicates whether the corresponding subsequence is anomalous or its anomaly score.
- predict_discords(X)[source]¶
Run MADRID and return the complete multi-length discord information.
Unlike
predict, which reduces to one guaranteed score per time point, this exposes everything the algorithm computes, mirroring the reference implementation’s output.- Parameters:
- Xnp.ndarray
One-dimensional time series.
- Returns:
- dict
lengths: the candidate subsequence lengthsm;scores: the best (length-normalised) discord score per length;locations: each best discord’s start position;discord_table: the raw (n_lengths, n) table. Positions pruned by DAMP hold unrefined estimates, so treat the table as approximate everywhere except the returned discord locations;best_interval:(start, end)of the overall best discord, i.e. the location and extent ofargmax(scores), matching the reference implementation’sbest_discord_loc.
- reset(keep=None)[source]¶
Reset the object to a clean post-init state.
After a
self.reset()call,selfis equal or similar in value totype(self)(**self.get_params(deep=False)), assuming no other attributes were kept usingkeep.- Detailed behaviour:
- removes any object attributes, except:
hyper-parameters (arguments of
__init__) object attributes containing double-underscores, i.e., the string “__”
runs
__init__with current values of hyperparameters (result ofget_params)- Not affected by the reset are:
object attributes containing double-underscores class and object methods, class attributes any attributes specified in the
keepargument temporary callback context attached by scikit-learn
- Parameters:
- keepNone, str, or list of str, default=None
If
None, all attributes are removed except hyperparameters. Ifstr, only the attribute with this name is kept. Iflistofstr, only the attributes with these names are kept.
- Returns:
- selfobject
Reference to self.
- Raises:
- TypeError
If ‘keep’ is not a string or a list of strings.
- set_fit_request(*, axis: bool | None | str = '$UNCHANGED$') MADRID¶
Configure whether metadata should be requested to be passed to the
fitmethod.Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with
enable_metadata_routing=True(seesklearn.set_config). Please check the User Guide on how the routing mechanism works.The options for each parameter are:
True: metadata is requested, and passed tofitif provided. The request is ignored if metadata is not provided.False: metadata is not requested and the meta-estimator will not pass it tofit.None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.str: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (
sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.Added in version 1.3.
- Parameters:
- axisstr, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED
Metadata routing for
axisparameter infit.
- Returns:
- selfobject
The updated object.
- set_params(**params)¶
Set the parameters of this estimator.
The method works on simple estimators as well as on nested objects (such as
Pipeline). The latter have parameters of the form<component>__<parameter>so that it’s possible to update each component of a nested object.- Parameters:
- **paramsdict
Estimator parameters.
- Returns:
- selfestimator instance
Estimator instance.
- set_predict_request(*, axis: bool | None | str = '$UNCHANGED$') MADRID¶
Configure whether metadata should be requested to be passed to the
predictmethod.Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with
enable_metadata_routing=True(seesklearn.set_config). Please check the User Guide on how the routing mechanism works.The options for each parameter are:
True: metadata is requested, and passed topredictif provided. The request is ignored if metadata is not provided.False: metadata is not requested and the meta-estimator will not pass it topredict.None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.str: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (
sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.Added in version 1.3.
- Parameters:
- axisstr, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED
Metadata routing for
axisparameter inpredict.
- Returns:
- selfobject
The updated object.