penalty_curve#

penalty_curve(detector, X: ArrayLike, y: ArrayLike | None = None, *, penalty_name: str, penalty_range: ArrayLike, scoring: str | Callable = 'n_changepoints') ndarray[source][source]#

Penalty curve.

Compute a score for a range of penalty values.

Intended as a utility for exploring and plotting results for different penalty values. Selecting a final value from the curve is left to the caller.

Parameters:
detectorestimator

Exposes fit, set_params, sklearn’s clone, and any prediction methods used by scoring.

Xarray-like of shape (n_samples, n_features)

Data to fit and score on.

yarray-like, optional, default=None

Reference passed as the third argument to scoring. Not passed to detector.fit — skchange detectors are unsupervised, so y is purely a scoring reference.

penalty_namestr

Detector parameter to vary. Any name accepted by set_params is allowed, including nested "<step>__<param>" syntax.

penalty_rangearray-like of shape (n_candidates,)

Candidate values. Order is preserved in the output.

scoringstr or callable, default=”n_changepoints”

Either a built-in scorer name ("n_changepoints", "n_segment_anomalies", "n_segments") or a callable with signature (detector, X, y=None) -> float. Built-in scorers ignore y.

Returns:
curvenp.ndarray of shape (n_candidates,)

Scorer output per penalty_range value, aligned 1:1 with the input.

Raises:
ValueError

penalty_range is empty or non-numeric, or scoring is an unknown built-in name.

TypeError

scoring is neither a string nor a callable.

Examples

>>> import numpy as np
>>> from skchange.new_api.detectors import SeededBinarySegmentation
>>> from skchange.new_api.tuning import penalty_curve
>>> rng = np.random.default_rng(0)
>>> X = rng.normal(size=(200, 1))
>>> penalty_range = np.array([1.0, 2.0, 3.0, 5.0])
>>> counts = penalty_curve(
...     SeededBinarySegmentation(), X,
...     penalty_name="penalty", penalty_range=penalty_range,
... )
>>> selected = penalty_range[counts <= 1].min()

Supervised scoring against reference changepoints, using make_detector_scorer to wrap a metric:

from skchange.new_api.metrics import (
    changepoint_f1_score,
    make_detector_scorer,
)

f1 = penalty_curve(
    detector, X, y_true_cps,
    penalty_name="penalty", penalty_range=penalty_range,
    scoring=make_detector_scorer(changepoint_f1_score),
)