Time series segmentation in Python
Change point detection and state detection: 30+ algorithms, one scikit-learn-style API
Documentation · Live demo · Detectors · Metrics · Changelog
What is tsseg?
tsseg gathers classic and recent algorithms for time series segmentation behind a single API, with the metrics to evaluate them and an interactive demo to compare them. It covers the two faces of the problem:
| Change point detection | State detection | |
|---|---|---|
| Question | Where does the behaviour of the series change? | Which recurring state is each time point in? |
| Output | the sorted indices where a new segment starts | one integer label per time point |
| Example | [580, 1125, 2050, 2465, 3995] |
[0, 0, …, 2, 2, …, 1, 1, …, 0, 0, …] |
A motion-capture recording bundled with tsseg, as shown in the interactive demo: ground truth (top),
the change points of a change point detector (middle) and the states of a state detector (bottom).
Highlights
- One API for every method. Each detector is a scikit-learn estimator that
follows the segmenter interface of aeon:
fit,predict,fit_predict,get_params,clone. - Unsupervised or guided. Run a detector without knowing how many segments to expect, or pass the number of change points or states to its constructor when you know it. Tags tell which modes each detector supports.
- Metrics for both tasks. F1, covering, Hausdorff distance and Gaussian F1 for change points; ARI, AMI, NMI, their time sensitive counterparts, and the interpretable SMS for states.
- Light core, opt-in extras. The core needs NumPy, pandas, SciPy, scikit-learn and statsmodels. PyTorch, TensorFlow, Prophet or numba are installed only for the detectors that use them.
- Fast classics. PELT, BinSeg, BottomUp, DynP and Window run on a vendored copy of ruptures with an optional numba backend.
- Try it in the browser. The interactive demo loads a custom series, runs the detectors and compares their results, with nothing to install.
Installation
pip install tsseg
Most detectors work with this alone. Those built on heavier libraries need an
extra, for instance pip install "tsseg[torch]", or all of them at once with
pip install "tsseg[all]":
| Extra | Adds | For |
|---|---|---|
tsseg[accelerators] |
Numba, Cython | CLaP, ClaSP and E-Agglo (required); HDP-HSMM (speed-up) |
tsseg[aeon] |
aeon's time series classifiers | ClapDetector |
tsseg[torch] |
PyTorch | TireDetector, Time2StateDetector, E2USDDetector |
tsseg[tglad] |
PyTorch, NetworkX | TGLADDetector |
tsseg[tscp2] |
TensorFlow, TCN layer | TSCP2Detector |
tsseg[snlds] |
TensorFlow, TensorFlow Probability | SNLDSDetector |
tsseg[prophet] |
Prophet | ProphetDetector |
tsseg[beast] |
Rbeast | BeastDetector |
tsseg[changeforest] |
changeforest | ChangeForestDetector |
tsseg[docs] |
Sphinx toolchain | building the documentation |
tsseg[all] |
everything above |
FLUSSDetector needs stumpy (pip install stumpy), and AutoPlaitDetector a
C binary built from
c/autoplait (see
its documentation page).
The tsseg[patss] extra installs nothing: the deprecated PatssDetector needs
npbad, which is not on PyPI and must be installed by hand.
From source, with conda
make install needs conda in your PATH (or set in a .env file, see
.env.example):
git clone https://github.com/fchavelli/tsseg.git
cd tsseg
make install # creates the conda env and installs tsseg
conda activate tsseg-env
Or step by step:
conda env create -f environment.yml
conda activate tsseg-env
pip install -e ".[all]"
Without TensorFlow
Only TSCP2Detector (tsseg[tscp2]) and SNLDSDetector (tsseg[snlds]) need
TensorFlow. If it causes trouble on your platform, skip [all] and pick the
extras you need:
pip install -e ".[torch,prophet,aeon,accelerators]"
Quick start
Segment a motion-capture recording, then score both results against its ground
truth (the state detector needs pip install "tsseg[accelerators,aeon]"):
from tsseg import load_mocap
from tsseg.algorithms import BottomUpDetector, ClapDetector
from tsseg.algorithms.utils import extract_cps
from tsseg.metrics import Covering, StateMatchingScore
# 4 channels (arms and legs), one activity label per time point
X, y = load_mocap(trial=0) # X: (4579, 4), y: (4579,)
true_cps = extract_cps(y) # [ 588 1200 2006 2530 3282 4048]
# Change point detection: where does the movement change?
cps = BottomUpDetector(model="rbf", pen_scale="bic").fit_predict(X)
print(cps) # [ 580 1125 2050 2465 3995]
print(Covering().compute(true_cps, cps, n_timepoints=len(X))["score"]) # 0.748
# State detection: which activity is each time point in?
states = ClapDetector().fit_predict(X)
print(StateMatchingScore().compute(y, states)["score"]) # 0.700
Know how many segments to expect? Pass it to the constructor (guided mode):
from tsseg.algorithms import DynpDetector
print(DynpDetector(model="rbf", n_cps=6).fit_predict(X))
# [ 595 1145 2160 2455 3300 4115]
Detectors accept NumPy arrays of shape (n_timepoints, n_channels) (or 1-D for
univariate series), pandas Series and DataFrames. The
getting started guide
goes further.
Algorithms
Unsup.: runs without being told the number of change points or states.
Guided: takes that number in its constructor (n_cps, n_states, …).
📦: needs an optional dependency (see Installation).
Each name links to the documentation page of the detector.
Change point detection (22)
| Detector | Approach | Unsup. | Guided | Reference |
|---|---|---|---|---|
AMOCAmocDetector |
single best split | ✓ | Killick et al. (2012) | |
BEAST 📦BeastDetector |
Bayesian model averaging of trend and seasonality | ✓ | ✓ | Zhao et al. (2019), RSE |
BinSegBinSegDetector |
greedy top-down splitting | ✓ | ✓ | Bai (1997); Fryzlewicz (2014) |
BOCDBOCDDetector |
Bayesian run-length posterior | ✓ | ✓ | Adams & MacKay (2007) |
BottomUpBottomUpDetector |
greedy bottom-up merging | ✓ | ✓ | Keogh et al. (2001), ICDM |
changeforest 📦ChangeForestDetector |
random forest classifier between segments | ✓ | ✓ | Londschien et al. (2023), JMLR |
ChangeFinderChangeFinderDetector |
two-stage autoregressive outlier scores | ✓ | ✓ | Takeuchi & Yamanishi (2006), TKDE |
ClaSP 📦ClaspDetector |
classification score profile | ✓ | ✓ | Ermshaus et al. (2023), DMKD |
DynPDynpDetector |
exact dynamic programming | ✓ | Auger & Lawrence (1989) | |
E-Agglo 📦EAggloDetector |
agglomerative, energy distance | ✓ | Matteson & James (2014), JASA | |
ESPRESSOEspressoDetector |
entropy and shape of the matrix profile | ✓ | Deldari et al. (2020), UbiComp | |
FLUSS 📦FLUSSDetector |
arc curve of the matrix profile | ✓ | ✓ | Gharghabi et al. (2017), ICDM |
GGSGreedyGaussianDetector |
greedy Gaussian likelihood | ✓ | ✓ | Hallac et al. (2019), ADAC |
iCIDICIDDetector |
isolation distributional kernel | ✓ | Cao et al. (2024), JAIR | |
IGTSInformationGainDetector |
information gain, top-down | ✓ | ✓ | Sadri et al. (2017), PMC |
PELTPeltDetector |
exact penalised search with pruning | ✓ | Killick et al. (2012), JASA | |
Prophet 📦ProphetDetector |
trend change points of Prophet | ✓ | ✓ | Taylor & Letham (2018) |
RuLSIFRuLSIFDetector |
relative density-ratio estimation | ✓ | ✓ | Liu et al. (2013), Neural Netw. |
tGLAD 📦TGLADDetector |
changes of conditional independence graphs | ✓ | Imani & Shrivastava (2023) | |
TIRE 📦TireDetector |
autoencoder, time-invariant features | ✓ | ✓ | De Ryck et al. (2021), IEEE TSP |
TS-CP2 📦TSCP2Detector |
contrastive predictive coding | ✓ | ✓ | Deldari et al. (2021), WWW |
WindowWindowDetector |
sliding-window discrepancy | ✓ | ✓ | Basseville & Nikiforov (1993) |
State detection (9)
| Detector | Approach | Unsup. | Guided | Reference |
|---|---|---|---|---|
AutoPlait 📦AutoPlaitDetector |
MDL-based regime mining | ✓ | Matsubara et al. (2014), SIGMOD | |
CLaP 📦ClapDetector |
classification label profile | ✓ | ✓ | Ermshaus et al. (2024) |
E2USD 📦E2USDDetector |
dual-view embeddings, clustering | ✓ | ✓ | Lai et al. (2024), WWW |
Gaussian HMMGaussianHMMDetector |
hidden Markov model fitted by EM | ✓ | ✓ | Rabiner (1989) |
HDP-HSMMHdpHsmmDetector |
Bayesian nonparametric semi-Markov model | ✓ | ✓ | Johnson & Willsky (2013), JMLR |
HidalgoHidalgoDetector |
local intrinsic dimension | ✓ | Allegra et al. (2020), Sci. Rep. | |
SNLDS 📦SNLDSDetector |
switching nonlinear dynamical system (experimental) | ✓ | Dong et al. (2020), ICML | |
TICCTiccDetector |
Toeplitz inverse covariance clustering | ✓ | Hallac et al. (2017), KDD | |
Time2State 📦Time2StateDetector |
contrastive encoder, clustering | ✓ | ✓ | Wang et al. (2023), SIGMOD |
Also available: RandomDetector,
a random baseline for both tasks.
Evaluation metrics
Every metric returns a dictionary with at least a "score" key:
metric.compute(y_true, y_pred)["score"].
Change point detection, on sorted change point indices:
| Metric | What it measures |
|---|---|
F1Score |
precision and recall of the detected change points, within a margin |
GaussianF1Score |
F1 where each detection earns a reward that decays with its distance to the true change point |
Covering |
how well the predicted segments cover the true ones |
BidirectionalCovering |
covering in both directions, true to predicted and predicted to true |
HausdorffDistance |
the largest distance from a change point to the nearest one of the other set |
Tip: these metrics need the length of the series: pass
compute(y_true, y_pred, n_timepoints=len(X)).
State detection, on one label per time point:
| Metric | What it measures |
|---|---|
AdjustedRandIndex (ARI), AdjustedMutualInformation (AMI), NormalizedMutualInformation (NMI) |
agreement between the two labellings, as clusterings |
WeightedAdjustedRandIndex (WARI), WeightedNormalizedMutualInformation (WNMI) |
ARI and NMI with each time point weighted by its distance to the nearest true boundary |
StateMatchingScore (SMS) |
matches predicted to true states, then scores four types of errors |
WARI, WNMI and SMS come from Toward Interpretable Evaluation Measures for Time Series Segmentation (NeurIPS 2025).
Interactive demo
The tsseg demo on Hugging Face Spaces runs in the browser: load a series, run segmentation algorithms, then compare and evaluate their results, with nothing to install.
Contributing
Bug reports, questions and new detectors are welcome in the issues. From a clone:
make test # run the test suite, as in CI (long)
make test PYTEST_ARGS="-k PeltDetector" # run a selection of tests
make lint # ruff check + ruff format --check, as in CI
make docs # build the documentation, as in CI (needs tsseg[docs])
The contributing guide covers the development setup, the code style and the tests a new detector must pass.
Citation
If tsseg helps your work, please cite the ECML-PKDD 2026 paper:
@inproceedings{tsseg2026,
title = {tsseg: An Interactive Toolkit for Time Series Segmentation},
author = {Chavelli, F{\'e}lix and Ermshaus, Arik and Yang, Fan and Sch{\"a}fer, Patrick and Paparrizos, John and Boniol, Paul},
booktitle = {Machine Learning and Knowledge Discovery in Databases. Applied Data Science Track, Demo Track and Industrial Track},
series = {Lecture Notes in Computer Science},
year = {2026},
pages = {391--394},
publisher = {Springer Nature Switzerland},
doi = {10.1007/978-3-032-37685-5_41}
}
If you use WARI, WNMI or SMS, please also cite:
@inproceedings{chavelli2025interpretable,
title = {Toward Interpretable Evaluation Measures for Time Series Segmentation},
author = {Chavelli, F{\'e}lix and Boniol, Paul and Thomazo, Micha{\"e}l},
booktitle = {Advances in Neural Information Processing Systems},
year = {2025}
}
Each detector also cites its original paper on its documentation page.
Contributors
- Félix Chavelli (Inria, ENS, Paris)
- Arik Ermshaus (Humboldt-Universität, Berlin)
- Fan Yang (The Ohio State University, Columbus)
- Paul Boniol (Inria, ENS, Paris)
- Patrick Schäfer (Humboldt-Universität, Berlin)
- John Paparrizos (The Ohio State University, AUTh, Columbus)
License
tsseg is released under the AGPL-3.0.
Third-party components
Several algorithms bundle adapted or vendored code under their own licenses.
Components, licenses and sources
| Component | License | Source |
|---|---|---|
aeon (base, EAgglo, Hidalgo, HMM, IGTS) |
BSD-3 | aeon-toolkit/aeon |
ruptures/ (vendored v1.1.8) |
BSD-2 | deepcharles/ruptures |
bocd/ |
MIT | hildensia/bayesian_changepoint_detection |
beast/ (wraps Rbeast, not bundled) |
GPL-2.0-or-later | zhaokg/Rbeast |
clap/ (ClaSP / CLaP) |
BSD-3 | ermshaua/claspy |
ggs/ |
BSD-2 | cvxgrp/GGS |
icid/ |
GPLv3 | IsolationKernel/iCID |
patss/ |
MIT | KU Leuven DTAI |
rulsif/ (port of the authors' MATLAB code) |
MIT | anewgithubname/change_detection |
snlds/vendor/ |
Apache-2.0 | google-research/snlds |
tglad/vendor/ (uGLAD) |
Non-Commercial | Harshs27/tGLAD |
autoplait/ |
not specified | Matsubara et al. |
e2usd/ |
not specified | AI4CTS/E2Usd |
espresso/ |
not specified | cruiseresearchgroup/ESPRESSO |
ticc/ |
BSD-2 | davidhallac/TICC |
time2state/ |
MIT | Lab-ANT/Time2State |
tire/ |
not specified | De Ryck, De Vos & Bertrand (KU Leuven) |
tscp2/ |
not specified | Cruise Research Group |
Each directory above that bundles code under a published license contains a
copy of it (LICENSE, or LICENCE in patss/). The aeon license is copied in
eagglo/, hidalgo/, hmm/ and igts/, and also covers the base classes in
tsseg/algorithms/base.py. The sources marked not specified publish no
license. Rbeast, which beast/ only wraps, is installed by tsseg[beast];
tsseg follows the license of its R package, GPL (>= 2), although its PyPI
wheel declares MIT.
Metadata
Release files for tsseg 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tsseg-0.3.0.tar.gz | 2.3 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tsseg-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 3.7 MB
Release files / tsseg-0.3.0.tar.gz
| Download URL | tsseg-0.3.0.tar.gz |
|---|---|
| Size | 2.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
387efc6d104cd3833dd49f0f3a027f2fb2f95019265fd3f0758c023c9ee0c774
|
|
BLAKE2b-256 checksum How to use checksums |
8ae5b73fe040060e85d90b9fddfbb9a09ed5d3c03a2d7f38de5bb2984897fa2a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency logRelease files / tsseg-0.3.0-py3-none-any.whl
| Download URL | tsseg-0.3.0-py3-none-any.whl |
|---|---|
| Size | 1.4 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
784ab598f1a7958fca3595718c49ad5d80bf6d2d4ed3bb6869a8ab99bbfaa93d
|
|
BLAKE2b-256 checksum How to use checksums |
3638e8585e0478797628b3de81b5c9ad3fde765c0d87dc97cf3bf10c07ad0a87
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.
Transparency log