MovingWindow#
- class MovingWindow(change_score: BaseIntervalScorer | None = None, penalty: ArrayLike | float | None = None, penalty_scale: float = 1.0, agg: str = 'sum', bandwidth: ArrayLike | int | None = None, min_bandwidth: int = 5, selection_method: str = 'local_optimum', min_detection_fraction: float = 0.2, local_optimum_fraction: float = 0.8)[source][source]#
Moving window algorithm for multiple change-point detection.
The MOSUM (moving sum) algorithm [1], but generalized to allow for any penalised change score. The basic algorithm runs a test statistic for a single change-point across the data in a moving window fashion. In each window, the data is split into two equal halves with bandwidth samples on either side of a candidate change-point. This process generates a time series of penalised scores, which are used to generate candidate change-points as local maxima within intervals where the penalised scores are all above zero. The final set of change-points is selected from the candidate change-points using one of the selection methods described in [2].
Several of the extensions available in the mosum R package [2] are also available in this implementation, including the ability to use multiple bandwidths. The CUSUM-type boundary extension for computing the test statistic for candidate change- points less than bandwidth samples from the start and end of the data is also implemented by default.
- Parameters:
- change_scoreBaseIntervalScorer or None, default=None
Change score to use in the algorithm. Must be an instance of
BaseIntervalScorerwithscore_type="change_score". IfNone, defaults toCUSUM().Standard usage is to pass an unpenalised score and set
penaltyseparately. If the score already has tagpenalised=True, it owns its own aggregation and penalty, andpenalty/penalty_scale/aggare ignored.- penaltyfloat, array-like of shape (n_features,) or None, default=None
Penalty subtracted from the aggregated feature-wise score. A candidate changepoint is accepted only when the penalised score is positive.
float: scalar penalty subtracted from the aggregated score (seeagg).array-likeof lengthn_features, non-decreasing: elementiis the penalty fori+1features jointly affected; the detector picks theklargest feature scores maximisingsum(top_k) - penalty[k-1](handles sparse changes). A strictly linear array uses a faster code path. Only consistent with the defaultagg="sum".None: defaults tochange_score.get_default_penalty()(BIC-based) at fit time.
Ignored when
change_scoreis already penalised.- penalty_scalefloat, default=1.0
Multiplicative factor applied to the effective penalty (whether
penaltyis user-provided or the default). Use as a single scalar tuning knob that preserves the shape of array penalties. Must be positive. Ignored whenchange_scoreis already penalised.- agg{“sum”, “max”}, default=”sum”
How feature-wise raw scores are aggregated into a single score per interval before subtracting a scalar penalty:
"sum":sum(scores, axis=1) - penalty(dense change assumption)."max":max(scores, axis=1) - penalty(a single, unknown feature changes).
Ignored when
change_scoreis already aggregated. Must be"sum"whenpenaltyis array-valued (array penalties imply top-k aggregation).- bandwidthint, list of int, or None, default=None
The number of samples on either side of a candidate change-point. Must be 1 or greater. If
None, bandwidths are set automatically atfittime:"local_optimum"(default): up to 5 exponentially spaced bandwidths betweenmax(scorer.min_size, min_bandwidth)andmax(scorer.min_size, min_bandwidth, n_samples // 5)."detection_length": a single bandwidth ofmax(scorer.min_size, min_bandwidth, min(50, n_samples // 5)).
User-supplied values must all be
>= scorer.min_size(checked at fit). Multiple bandwidths use the bottom-up merging approach of [2].- min_bandwidthint, default=5
Lower bound on the automatically chosen bandwidth(s) when
bandwidth=None. Ignored whenbandwidthis provided. The effective minimum bandwidth used ismax(min_bandwidth, scorer.min_size), so the actual minimum may be larger than the value provided here when the change score requires more samples per segment. The default of 5 mitigates spurious detections from very small bandwidths.- selection_methodstr, default=”local_optimum”
The method used to select the final set of change-points from a set of candidate change-points. The options are:
"detection_length": Accepts a candidate change-point if themin_detection_fraction * bandwidthconsecutive penalised scores are above zero. Corresponds to the epsilon-criterion in [2]. This method is only available for a single bandwidth."local_optimum": Accepts a candidate change-point if it is the local maximum in the scores within a neighbourhood of sizelocal_optimum_fraction * bandwidth. Corresponds to the eta-criterion in [2]. This method is used within the “bottom-up” merging approach if multiple bandwidths are given.
- min_detection_fractionfloat, default=0.2
Minimum fraction of the bandwidth that must have consecutive positive penalised scores for a candidate to be accepted. Only used with
selection_method="detection_length". Must be in(0, 0.5).- local_optimum_fractionfloat, default=0.8
Neighbourhood size (as a fraction of bandwidth) for the local-optimum criterion. A candidate is accepted if it is the maximum within
local_optimum_fraction * bandwidthsamples of itself. Only used withselection_method="local_optimum". Must be>= 0.
- Attributes:
- change_score_BaseIntervalScorer
Fitted change score. Always the unpenalised scorer (whether user-provided or resolved from
None). Whenchange_scoreis already penalised, it is that fitted penalised scorer.- penalty_float, np.ndarray or None
Effective penalty actually used at detection time: the resolved base penalty multiplied by
penalty_scale.Nonewhenchange_scoreis inherently penalised, in which case the scorer owns its own penalty.- bandwidth_np.ndarray
Sorted array of bandwidths actually used at detect time.
Methods
fit(X[, y])Fit the detector to training data.
fit_predict(X[, y])Fit to data, then predict per-sample segment labels.
Get metadata routing of this object.
get_params([deep])Get parameters for this estimator.
predict(X)Detect changepoints, returning per-sample segment labels.
predict_all(X)Detect changepoints and return all outputs in a single pass.
Detect changepoints in a time series.
predict_scores(X[, return_index])Return the per-window moving-window scores evaluated on
X.set_params(**params)Set the parameters of this estimator.
References
[1]Eichinger, B., & Kirch, C. (2018). A MOSUM procedure for the estimation of multiple random change points.
Examples
>>> from skchange.new_api.detectors import MovingWindow >>> from skchange.datasets import generate_alternating_data >>> df = generate_alternating_data(n_segments=4, mean=10, segment_length=100, p=5) >>> detector = MovingWindow() >>> detector.fit_predict(df) ilocs 0 100 1 200 2 300
- fit(X: ArrayLike, y: ArrayLike | None = None) Self[source][source]#
Fit the detector to training data.
- Parameters:
- XArrayLike of shape (n_samples, n_features)
Training time series data.
- yArrayLike | None, default=None
Training labels. Exists for sklearn API compatibility (e.g. pipelines). This detector is unsupervised on single series, so it is ignored.
- Returns:
- self
Fitted detector instance.
- predict_all(X: ArrayLike) dict[source][source]#
Detect changepoints and return all outputs in a single pass.
- Parameters:
- XArrayLike of shape (n_samples, n_features)
Time series to analyze for changepoints.
- Returns:
- resultdict with keys:
"changepoints"np.ndarray of shape (n_changepoints,)Sorted integer indices of detected changepoints.
"scores"np.ndarray of shape (n_windows,)Penalised score for each evaluated window across all bandwidths.
"starts"np.ndarray of shape (n_windows,)Start index of each evaluated window.
"splits"np.ndarray of shape (n_windows,)Candidate changepoint (split) index of each window.
"ends"np.ndarray of shape (n_windows,)End index of each evaluated window.
"bws"np.ndarray of shape (n_windows,)Bandwidth used for each evaluated window.
- predict_changepoints(X: ArrayLike) ndarray[source][source]#
Detect changepoints in a time series.
- Parameters:
- XArrayLike of shape (n_samples, n_features)
Time series to analyze for changepoints.
- Returns:
- changepointsnp.ndarray of shape (n_changepoints,)
Sorted integer indices of detected changepoints. A changepoint at index
tmeans sampletis the first sample of a new segment, i.e. a structural break occurs between samplest-1andt. Empty array if no changepoints are detected.
- predict_scores(X: ArrayLike, return_index: bool = False) ndarray | tuple[ndarray, dict[str, ndarray]][source][source]#
Return the per-window moving-window scores evaluated on
X.Returns the penalised score for every (start, split, end) window evaluated across all active bandwidths, as a flat 1-D array. This is the raw output that
predictaggregates into a per-sample score before changepoint selection.For penalty calibration, use the free function
skchange.new_api.tuning.unpenalised_scores, which fits a clone of this detector with the penalty parameter set to zero and returns the resulting unpenalised scores.- Parameters:
- XArrayLike of shape (n_samples, n_features)
Time series to evaluate.
- return_indexbool, default=False
If
True, also return a dict locating each score on the time axis. See the Returns section for the keys.
- Returns:
- scoresnp.ndarray of shape (n_windows,)
Penalised score for each evaluated window, one entry per (start, split, end) triple across all active bandwidths. Returned alone when
return_index=False.- indexdict, optional
Only returned when
return_index=True. Contains:"starts": np.ndarray of shape (n_windows,) Start indices of each evaluated window."splits": np.ndarray of shape (n_windows,) Candidate changepoint (split) index of each window."ends": np.ndarray of shape (n_windows,) End indices of each evaluated window.
- fit_predict(X, y: ArrayLike | None = None, **fit_params) ndarray[source]#
Fit to data, then predict per-sample segment labels.
Equivalent to calling fit(X, y).predict(X).
- Parameters:
- XArrayLike of shape (n_samples, n_features)
Time series data.
- yNone
Ignored. Exists for sklearn API compatibility.
- **fit_paramsdict
Additional parameters passed to fit().
- Returns:
- labelsnp.ndarray of shape (n_samples,)
Dense integer segment labels, one per sample.
- get_metadata_routing()[source]#
Get metadata routing of this object.
Please check User Guide on how the routing mechanism works.
- Returns:
- routingMetadataRequest
A
MetadataRequestencapsulating routing information.
- get_params(deep=True)[source]#
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.
- predict(X: ArrayLike) ndarray[source]#
Detect changepoints, returning per-sample segment labels.
Default implementation calls predict_changepoints() and converts the changepoint indices to an array with segment labels per sample. Subclasses may override this directly when the algorithm natively produces labels.
- Parameters:
- XArrayLike of shape (n_samples, n_features)
Time series data.
- Returns:
- labelsnp.ndarray of shape (n_samples,)
Dense integer segment labels, one per sample. Segment 0 is the first segment, segment 1 the next, and so on.
Examples
>>> labels = detector.fit(X_train).predict(X_test) >>> labels.shape (n_samples,)
- set_params(**params)[source]#
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.