BNDM#
- class capymoa.drift.detectors.BNDM[source]#
Bases:
BaseDataDriftDetectorBayesian Nonparametric Detection Method
Uses a Pólya tree two-sample test to determine whether reference and test data come from the same distribution. The data is partitioned recursively using normal-distribution percentiles, and the partitions are compared using the Beta function.
Because the Pólya tree test is univariate, it is applied independently to each feature using the configured
threshold. Overall drift is reported when any feature flags drift. This detector does not return p-values, and thecorrectionparameter has no effect on its drift decisions. No Bonferroni correction is applied.Note
Data is normalized internally (mean-centered, scaled by IQR). Best suited for sudden changes; may struggle with subtle drift.
Example:#
>>> import numpy as np >>> from capymoa.drift.detectors import BNDM >>> rng = np.random.default_rng(42) >>> detector = BNDM(window_size=100, threshold=0.5) >>> detector.fit(rng.normal(0, 1, size=(200, 2))) >>> for x in rng.normal(3, 1, size=(100, 2)): ... detector.add_element(x) >>> detector.detected_change() True
Reference:#
Xuan, J., Lu, J., and Zhang, G. “Bayesian nonparametric unsupervised concept drift detection for data stream mining.” ACM Transactions on Intelligent Systems and Technology (2020).
- __init__(
- window_size: int,
- const: float = 1.0,
- threshold: float = 0.5,
- max_depth: int = 3,
- correction: Literal['bonferroni', 'none'] = 'bonferroni',
- auto_fit_samples: int | None = None,
Create a BNDM data drift detector.
- Parameters:
window_size – Number of observations in the sliding window.
const – Constant that scales the Pólya tree concentration parameters. Larger values give more weight to the prior.
threshold – Similarity below which drift is declared (per feature). Must be in
(0, 1).max_depth – Maximum depth of the Pólya tree recursion.
correction – Accepted for interface consistency with other detectors, but has no effect: this detector does not produce p-values, so no multiple-testing correction is applied to its drift decisions.
auto_fit_samples – Number of initial samples for auto-fit.
- Raises:
ValueError – If threshold not in
(0, 1)or max_depth < 1.
- _fit(X: ndarray) None[source]#
Store or preprocess the reference data.
Called by
fit()after validation. X is guaranteed to be a 2-Dnp.ndarraywith shape(n_samples, n_features).At minimum, implementations should set
self._X_ref = X.
- _test( ) DataDriftResult[source]#
Run the underlying statistical test or distance measure.
When
IS_UNIVARIATE = Truethis receives one feature at a time: both arrays are 1-D with shapes(n_ref,)and(n_test,). The subclass should setstatisticandp_value(if available) on the returned result.If
p_valueis set, the base class applies the configuredcorrectionand ignores the per-featureis_driftflag. Example:def _test(self, x_ref, x_test): stat, p = scipy.stats.ks_2samp(x_ref, x_test) return DataDriftResult( is_drift=False, statistic=stat, p_value=p )
If
p_valueis leftNone(distance- or score-based tests), the base class uses the per-featureis_driftflag directly andcorrectionhas no effect – the subclass is responsible for its own per-feature decision (e.g. comparing a distance to a threshold).When
IS_UNIVARIATE = Falsethis receives all features: both arrays are 2-D with shapes(n_ref, n_features)and(n_test, n_features). The subclass is responsible for the fullDataDriftResultincludingis_drift.
- add_element(element: float | ndarray) None[source]#
Add one observation and check for drift.
The observation is appended to a sliding window of size
window_size. Once full, the detector compares the window against the reference on every call.If the detector is not yet fitted and
auto_fit_samplesis set, those initial observations build the reference. No comparison happens until then. If it is not fitted and auto-fit is not enabled, this raisesRuntimeError.- Parameters:
element – A single observation – a scalar for univariate data, or a 1-D array for multivariate data.
- Raises:
RuntimeError – If the detector is not fitted and auto-fit mode is not enabled. Call
fit()first, or construct withauto_fit_samples.ValueError – If the observation has a different number of features than the reference.
- compare(
- X_test: ndarray,
One-shot batch comparison against the reference.
Unlike
add_element(), this does not update the internal window or detection history. It is useful for offline evaluation.auto_fit_samplesdoes not apply here; callfit()first.- Parameters:
X_test – Test data with the same number of features as the reference.
- Raises:
RuntimeError – If
fit()has not been called.ValueError – If X_test has a different number of features than the reference.
- Returns:
Comparison result.
- fit( ) None[source]#
Set the reference distribution.
This detector has
REQUIRES_FITset toTrue. Callfit()beforeadd_element()orcompare(), unlessauto_fit_sampleswas set soadd_element()can collect the reference. Callingfit()again replaces the reference (a sliding reference window).- Parameters:
X – Reference data, shape
(n_samples,)or(n_samples, n_features). May also be a pandas DataFrame, in which case column names are extracted automatically.feature_names – Optional names for each feature. If provided, must have length equal to the number of features. Overrides column names extracted from a DataFrame. When set, per-feature dicts in
DataDriftResultuse these names as keys instead of integer indices.
- Raises:
ValueError – If X is empty or feature_names length does not match the number of features.
- classmethod from_params( ) Any[source]#
Construct an instance from parameters produced by
get_params.
- reset(clean_history: bool = False) None[source]#
Reset the detector state.
- Parameters:
clean_history – If
True, also clear the reference data and detection history. IfFalse(default), only the sliding window and current result are cleared; the reference and detection indices are preserved.
- IS_UNIVARIATE: bool = True#
If
Truethe test is applied to each feature separately and results are combined. IfFalsethe test runs on the joint distribution.
- REQUIRES_FIT: bool = True#
Data drift detectors need a reference distribution. Call
fit()or setauto_fit_samplessoadd_element()can collect it.
- property is_fitted: bool#
Whether the reference distribution has been set.
Trueafterfit(), or afteradd_element()has collectedauto_fit_samplesobservations.
- property result: DataDriftResult | None#
Most recent comparison result, or
Noneduring warm-up.