Skip to main content

Scikit-learn-style weighted empirical risk minimization for changepoint detection

Project description

𐄷 Weighted ERM - fast & accurate change point regression

weightederm header

DOI

weightederm is a scikit-learn-style package for fast and accurate offline change point detection and estimation (or data segmentation) in regression settings via weighted empirical risk minimization (WERM). This is a robust, flexible implementation of the original research code (https://github.com/gabrielarpino/WeightedERM-reference.git) that is better suited for practical use.

It currently provides fixed- and CV-based estimators for:

Loss Fixed num_chgpts Unknown num_chgpts via CV
Least squares WERMLeastSquares WERMLeastSquaresCV
Huber WERMHuber WERMHuberCV
Logistic (binary) WERMLogistic WERMLogisticCV

Installation

Using pip

pip install weightederm

or

pip install git+https://github.com/gabrielarpino/weightederm.git

From root after cloning

Install from the repository root with standard Python packaging tools:

pip install .

For editable local development:

pip install -e .

If you are using uv, the equivalent setup command is:

uv sync

This repository is already source-installable: building with uv build produces both an sdist and a wheel.

Documentation

Page Contents
User Guide Algorithm overview, fixed vs CV workflow, penalties, predict() semantics, sklearn integration
Choosing an Estimator Decision guide: which loss, fixed vs CV, delta, penalty
Parameter Reference Every parameter for every class with practical guidance
Fitted Attributes Every post-fit() attribute explained

Quick Notes

  • Observations are assumed to be ordered.
  • num_signals = num_chgpts + 1.
  • delta constrains the changepoint search only; it does not currently change the prior weights.
  • CV defaults:
    • least squares / Huber: absolute-loss model selection
    • logistic: logistic-loss model selection
  • Set use_base_loss_for_cv=True on a CV estimator to score folds with the estimator's base loss instead.
  • Unpenalized logistic fits can fail on separable data. In that case weightederm raises rather than silently regularizing.

Minimum Working Examples

These examples are intentionally small, deterministic, and tested. They are not full reproductions of the benchmark notebook, but they follow the same spirit as minimal M1/M2/M3-style runs.

M1-style: fixed number of changepoints, sparse linear regression

# README_TEST_M1
import numpy as np
from weightederm import WERMLeastSquares

rng = np.random.default_rng(0)
n, p = 120, 20
true_cp = 60

X = rng.normal(size=(n, p))
beta_left = np.zeros(p)
beta_left[[0, 3]] = [2.0, -1.5]
beta_right = np.zeros(p)
beta_right[[0, 3]] = [-1.0, 2.5]

y = np.empty(n)
y[:true_cp] = X[:true_cp] @ beta_left + 0.2 * rng.normal(size=true_cp)
y[true_cp:] = X[true_cp:] @ beta_right + 0.2 * rng.normal(size=n - true_cp)

model = WERMLeastSquares(
    num_chgpts=1,
    delta=5,
    search_method="efficient",
    fit_intercept=False,
)
model.fit(X, y)

print("true changepoint:", true_cp)
print("estimated changepoint:", model.changepoints_[0])
assert abs(int(model.changepoints_[0]) - true_cp) <= 5

M2-style: unknown number of changepoints, sparse linear regression with CV

# README_TEST_M2
import numpy as np
from weightederm import WERMLeastSquaresCV

rng = np.random.default_rng(1)
n, p = 180, 10
true_cps = np.array([60, 120])

X = rng.normal(size=(n, p))
beta_1 = np.zeros(p)
beta_1[[0]] = [3.5]
beta_2 = np.zeros(p)
beta_2[[0, 1]] = [-3.0, 3.0]
beta_3 = np.zeros(p)
beta_3[[0, 1, 2]] = [2.5, -2.5, 2.5]

y = np.empty(n)
y[:60] = X[:60] @ beta_1 + 0.05 * rng.normal(size=60)
y[60:120] = X[60:120] @ beta_2 + 0.05 * rng.normal(size=60)
y[120:] = X[120:] @ beta_3 + 0.05 * rng.normal(size=60)

model = WERMLeastSquaresCV(
    max_num_chgpts=2,
    delta=5,
    cv=3,
    search_method="efficient",
    fit_intercept=False,
)
model.fit(X, y)

print("true changepoints:", true_cps.tolist())
print("selected num_chgpts:", model.best_num_chgpts_)
print("estimated changepoints:", model.changepoints_.tolist())
assert model.best_num_chgpts_ == 2
assert np.max(np.abs(model.changepoints_ - true_cps)) <= 5

M3-style: fixed number of changepoints, sparse logistic regression

# README_TEST_M3
import numpy as np
from weightederm import WERMLogistic

rng = np.random.default_rng(2)
n, p = 160, 12
true_cp = 80

X = rng.normal(size=(n, p))
beta_left = np.zeros(p)
beta_left[[0, 2]] = [2.5, -2.0]
beta_right = np.zeros(p)
beta_right[[0, 2]] = [-2.5, 2.0]

eta = np.empty(n)
eta[:true_cp] = X[:true_cp] @ beta_left
eta[true_cp:] = X[true_cp:] @ beta_right
prob = 1.0 / (1.0 + np.exp(-eta))
y = rng.binomial(1, prob)

model = WERMLogistic(
    num_chgpts=1,
    delta=5,
    search_method="efficient",
    fit_intercept=False,
    max_iter=300,
    tol=1e-6,
)
model.fit(X, y)

print("true changepoint:", true_cp)
print("estimated changepoint:", model.changepoints_[0])
assert abs(int(model.changepoints_[0]) - true_cp) <= 5

For fuller benchmark-style experiments, including normalized Hausdorff summaries and optional McScan comparison, see notebooks/reference_like_m123_benchmarks.ipynb.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

weightederm-0.1.1.tar.gz (19.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

weightederm-0.1.1-py3-none-any.whl (29.3 kB view details)

Uploaded Python 3

File details

Details for the file weightederm-0.1.1.tar.gz.

File metadata

  • Download URL: weightederm-0.1.1.tar.gz
  • Upload date:
  • Size: 19.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for weightederm-0.1.1.tar.gz
Algorithm Hash digest
SHA256 85ee09641b448be9bdb8efb76441d4312967da381ffae696dd607ea5f1bf9da6
MD5 af1852b70540ee3b10d007c75e61c9fc
BLAKE2b-256 436c3aafdcbc20a4df84b947f7d1ce1b1eca915d2982378648184da4fb10f5c9

See more details on using hashes here.

Provenance

The following attestation bundles were made for weightederm-0.1.1.tar.gz:

Publisher: python-publish.yml on gabrielarpino/weightederm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file weightederm-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: weightederm-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 29.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for weightederm-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b9c2e1e6d77ea1ceac8ceb201d04c5cfd9f2dcf2103430c2884575cc611d83e2
MD5 f1aa21043470a52306570a80e6408bee
BLAKE2b-256 21dc8ac12523fe8761c2b27f4b89a3553fc5253307d5e547237cd0668e15a077

See more details on using hashes here.

Provenance

The following attestation bundles were made for weightederm-0.1.1-py3-none-any.whl:

Publisher: python-publish.yml on gabrielarpino/weightederm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page