Reasoning & Evaluation

When Did the World Change? Changepoint Detection From Page's CUSUM to Bayesian Online Inference

CUSUM has been provably optimal since 1986, yet on the first human-annotated changepoint benchmark a detector that never reports a change beat most of the field under default settings. Seventy years of changepoint theory, from Page's cumulative sum to Bayesian run-length posteriors, is a story about what you are willing to assume, and what each assumption buys you in detection delay.

In the first benchmark built from human-annotated real-world series, a baseline that always answers "no change happened" scored an average F1 of 0.645 on univariate data with default settings, higher than nine of the thirteen real methods it was compared against (van den Burg & Williams, 2020, arXiv:2003.06222). The best default performer was the oldest method, binary segmentation from 1974. None of this contradicts theory. CUSUM is exactly optimal for the problem it was designed for, and has been known to be since 1986. The trouble is that the problem carries assumptions, and most production failures come from those assumptions rather than from the algorithm.

Changepoint detection asks when the process generating a series stopped being the same process. The methods split along two axes that matter more than any algorithmic detail: must you decide now, as each point arrives, or can you look at the whole series afterwards; and how much do you claim to know about the before and after distributions?

Why this matters: Every changepoint detector trades detection delay against false alarms, and the exchange rate is set by what the method assumes: a known baseline, a known shift size, a segment model, a penalty, a hazard rate. Knowing which assumption a detector is spending lets you predict how it will fail on your data before it pages anyone at 3 a.m.

TL;DR

  • CUSUM is exactly optimal for a narrow question. Page's 1954 recursion \(S_t = \max(0, S_{t-1} + \ell_t)\) minimises worst-case detection delay at a fixed false-alarm rate when both pre- and post-change distributions are known (Lorden 1971 asymptotically, Moustakides 1986 exactly).
  • Accumulation beats thresholds on small shifts only. CUSUM with \(k = 0.5\), \(h = 4\) (336 observations between false alarms) detects a 1σ shift in 8.4 on average, a 3σ Shewhart chart in about 44; at a 3σ jump Shewhart wins, 2.00 to 2.19.
  • Offline segmentation is penalised optimisation. Exact optimal partitioning is \(O(n^2)\); PELT prunes it to expected \(O(n)\), but only when the number of changes grows linearly with series length.
  • BOCPD replaces a threshold with a posterior over run length, at linear cost per step unless pruned. Tuned, it topped the 2020 benchmark, though not significantly ahead of binary segmentation.
  • Defaults dominate. Kernel changepoint analysis scored F1 0.124 on defaults and 0.686 tuned.
  • Production wins are offline and human-reviewed. MongoDB replaced a threshold system where about 100 auto-filed tickets yielded one useful one with changepoint review at an estimated 40 to 80 percent false-positive rate.

At a Glance

flowchart LR
    X["Stream or series"]:::blue --> Q{"Decide now or afterwards?"}:::slate
    Q -->|"online, known before and after"| C["CUSUM or Shiryaev-Roberts"]:::purple
    Q -->|"online, unknown after"| B["BOCPD run-length posterior"]:::purple
    Q -->|"offline, whole series"| O["Penalised segmentation"]:::purple
    C --> A1["Alarm time"]:::teal
    B --> A2["P(change) per step"]:::teal
    O --> A3["Segment boundaries"]:::teal
    A1 --> R["Assumption risk"]:::rose
    A2 --> R
    A3 --> R
    classDef blue fill:#1e40af,stroke:#3b82f6,stroke-width:1px,color:#fff
    classDef purple fill:#6d28d9,stroke:#a78bfa,stroke-width:1px,color:#fff
    classDef teal fill:#0e7490,stroke:#22d3ee,stroke-width:1px,color:#fff
    classDef rose fill:#be123c,stroke:#fb7185,stroke-width:1px,color:#fff
    classDef slate fill:#334155,stroke:#64748b,stroke-width:1px,color:#e2e8f0

Each family is only as good as its model of "no change".

From the Factory Floor to the Run-Length Posterior

Walter Shewhart's control charts of the 1920s judged each sample alone against three-standard-deviation limits. That catches a machine gone suddenly wrong and misses one drifting by 1σ, where every point looks ordinary.

E. S. Page's answer was to stop judging points and start accumulating evidence (Page, 1954, "Continuous Inspection Schemes", Biometrika). His cumulative sum adds up small deviations and forgets them when they stop pointing the same way.

Albert Shiryaev framed the question as Bayesian: a change time with a geometric prior, and the stopping rule minimising expected delay under a false-alarm constraint (Shiryaev, 1963). S. W. Roberts reached a related statistic comparing control charts (Roberts, 1966, Technometrics); the names are now joined as Shiryaev-Roberts. Gary Lorden supplied the minimax criterion that made CUSUM a theorem (Lorden, 1971), George Moustakides proved it exactly optimal under that criterion (Moustakides, 1986), and Moshe Pollak proposed a rival criterion with a randomised Shiryaev-Roberts start (Pollak, 1985).

Offline, Scott and Knott's recursive splitting (1974, Biometrics) became binary segmentation. Exact dynamic programming over segmentations was made practical by PELT (Killick, Fearnhead & Eckley, 2012, arXiv:1101.1438). And in 2007 Adams and MacKay (arXiv:0710.3742) and, independently, Fearnhead and Liu wrote down exact online recursions over the time since the last change.

timeline
    title Changepoint detection, 1954 to 2020
    1954 : Page publishes CUSUM in Biometrika
    1963 : Shiryaev frames quickest detection with a geometric prior
    1971 : Lorden proves CUSUM asymptotically minimax
    1974 : Scott and Knott introduce binary segmentation
    1985 : Pollak criterion and randomised Shiryaev-Roberts
         : Moustakides proves exact CUSUM optimality in 1986
    2007 : Adams and MacKay publish BOCPD
    2012 : PELT makes exact penalised segmentation near linear
    2014 : Twitter EDM breakout detection runs daily in production
    2020 : van den Burg and Williams annotated benchmark
         : MongoDB reports E-Divisive in performance CI

[IMAGE: Two stacked panels over the same 200-point series with a 1σ mean shift at t=120. Top: raw points with Shewhart 3σ limits, no point outside. Bottom: CUSUM statistic near zero until t=120, then climbing past h=4 around t=128. Caption: "The same shift is invisible to a pointwise rule and obvious to an accumulator."]

How Sequential and Retrospective Detection Actually Work

The likelihood ratio underneath everything

Let observations be independent with density \(f_0\) before an unknown time \(\nu\) and \(f_1\) from \(\nu\) on. The classical detectors are all built from the per-observation log-likelihood ratio

\[ \ell_t = \log \frac{f_1(x_t)}{f_0(x_t)}, \]

negative in expectation before the change and positive after. Its post-change mean is the KL divergence \(I = D_{\mathrm{KL}}(f_1 \,\|\, f_0)\), the evidence each new observation contributes. For a Gaussian shift from \(\mu_0\) to \(\mu_0 + \delta\) with variance \(\sigma^2\),

\[ \ell_t = \frac{\delta}{\sigma^2}\left(x_t - \mu_0 - \frac{\delta}{2}\right), \qquad I = \frac{\delta^2}{2\sigma^2}. \]

The \(\delta/2\) is CUSUM's reference value \(k\). It is not picked by taste; it falls out of the likelihood ratio, so a detector for a 1σ shift uses \(k = 0.5\sigma\). The quadratic in \(I\) explains why small shifts are expensive: halve the shift and each sample carries a quarter of the evidence.

Page's recursion is a maximum over unknown change times

With \(\nu\) known, the test would sum \(\ell_t\) from \(\nu\) to now. It is unknown, so take the most favourable candidate, which collapses to a one-line recursion because the best start either extends yesterday's or restarts today:

\[ S_n = \max_{1 \le \nu \le n+1} \sum_{t=\nu}^{n} \ell_t = \max\bigl(0,\; S_{n-1} + \ell_n\bigr), \qquad T = \inf\{ n : S_n \ge h \}. \]

The reset to zero is the mechanism. Without it the sum is a random walk with negative drift, and post-change evidence must first climb out of a deep hole. With it, the statistic idles near zero and climbs the moment the drift turns positive. A free by-product is the change-time estimate: the last time \(S\) touched zero before the alarm.

What "optimal" means, precisely

False alarms are measured by the average run length to false alarm, \(\mathrm{ARL}_0 = \mathbb{E}_\infty[T]\), the expected stopping time when no change occurs. Delay needs a definition, and the definition is where the field argues. Lorden took the pessimist's view, the worst change time and the worst pre-change history:

\[ \bar{D}(T) = \sup_{\nu \ge 1} \operatorname{ess\,sup} \; \mathbb{E}_\nu\!\left[(T - \nu + 1)^+ \,\middle|\, x_1, \dots, x_{\nu-1}\right]. \]

Among all rules with \(\mathrm{ARL}_0 \ge \gamma\), CUSUM minimises \(\bar{D}\) asymptotically, with

\[ \bar{D}(T_{\mathrm{CUSUM}}) \sim \frac{\log \gamma}{I} \quad (\gamma \to \infty), \]

and Moustakides showed the optimality is exact for every \(\gamma\). It is a scaling law, not a design tool: for \(\gamma = 336\) and a 1σ shift (\(I = 0.5\)) it predicts 11.6 observations against an exact 8.4. What it gets right is the shape of the trade. False alarms are bought logarithmically; delay is paid inversely in KL divergence.

Pollak found conditioning on the worst history too pessimistic and averaged over it instead, taking \(\sup_\nu \mathbb{E}_\nu[T - \nu \mid T \ge \nu]\). The natural statistic there sums likelihood ratios over candidate change times rather than maximising:

\[ R_n = \sum_{\nu=1}^{n} \prod_{t=\nu}^{n} e^{\ell_t} = (1 + R_{n-1})\,e^{\ell_n}. \]

Under no change \(R_n - n\) is a zero-mean martingale, so stopping at \(R_n \ge A\) guarantees \(\mathrm{ARL}_0 \ge A\). Pollak proved that starting \(R_0\) from the statistic's quasi-stationary distribution is third-order asymptotically optimal. Whether it was strictly minimax stayed open for twenty-five years, until Polunchenko and Tartakovsky gave a counterexample in which the strictly optimal rule is Shiryaev-Roberts started from a specially designed deterministic point (Polunchenko & Tartakovsky, 2010, Annals of Statistics 38(6)). Two criteria, two "best" procedures.

Even ARL0 is contested: Mei (Sequential Analysis, 2008) showed it can be infinite for schemes with finite delay under mixture pre-change models. A plainer caution: ARL is a mean of a roughly geometric distribution, so a detector with ARL0 of 336 fires within its first 100 in-control observations about a quarter of the time (\(1 - (1 - 1/336)^{100} \approx 0.26\)).

Retrospective segmentation as penalised optimisation

Offline, the question becomes where the boundaries are. Truong, Oudre and Vayatis organise every offline method into a segment cost, a search method, and a penalty or constraint on the number of changes (Truong et al., 2020, Signal Processing 167, arXiv:1801.00718). With changepoints \(\tau_{1:m}\) and per-change penalty \(\beta\):

\[ \min_{m,\,\tau_{1:m}} \; \sum_{i=0}^{m} \mathcal{C}\!\left(y_{(\tau_i+1):\tau_{i+1}}\right) + \beta m . \]

For a Gaussian mean change, \(\mathcal{C}\) is within-segment squared error. Optimal partitioning solves this exactly via \(F(t) = \min_{s < t}\,[F(s) + \mathcal{C}(y_{(s+1):t}) + \beta]\), which is \(O(n^2)\). PELT adds a pruning rule: if

\[ F(t) + \mathcal{C}\!\left(y_{(t+1):s}\right) + K \;\ge\; F(s) \]

(\(K = 0\) for a negative log-likelihood cost), then \(t\) can never again be the optimal last change and is deleted for good. Killick and colleagues prove expected linear cost under a condition that deserves more attention: the number of changes must grow linearly with series length. With a fixed number of changes their supplementary simulations show cost is no longer linear, and the no-pruning worst case stays \(O(n^2)\).

Binary segmentation finds the single best split, keeps it if the gain beats \(\beta\), and recurses, at \(O(n \log n)\). Truong et al. name its weakness: each split is estimated on a segment that may still contain other changes, so close changes are located imprecisely.

Kernels, and changes in anything

A squared-error cost cannot see a change in variance or shape. Harchaoui and Cappé (2007) moved the cost into a reproducing-kernel Hilbert space, where with a characteristic kernel a mean change in the embedding is a change in the whole distribution:

\[ \mathcal{C}_k(y_{a:b}) = \sum_{t=a}^{b} k(y_t, y_t) - \frac{1}{b-a+1} \sum_{s=a}^{b}\sum_{t=a}^{b} k(y_s, y_t). \]

Arlot, Celisse and Harchaoui added a model-selection penalty, proved an oracle inequality, and detected changes with constant mean and variance, at up to \(O((C_k + D_{\max})\,n^2)\) time (Arlot et al., 2019, JMLR 20, arXiv:1202.3878). Quadratic cost plus a bandwidth and penalty constants is what that flexibility costs.

BOCPD: a posterior over when the regime began

BOCPD tracks the run length \(r_t\), the observations since the last change. Under hazard \(H\) (constant \(1/\lambda\) for geometric segment lengths) it grows by one with probability \(1 - H\) or resets with probability \(H\):

\[ P(r_t, x_{1:t}) = \sum_{r_{t-1}} P(r_t \mid r_{t-1})\; P\!\left(x_t \mid r_{t-1}, x^{(r)}_{t}\right)\; P(r_{t-1}, x_{1:t-1}). \]

With a conjugate model each run length carries a few sufficient statistics, so every step is exact. Per-step time and memory are linear in the data seen; Adams and MacKay prune run lengths with tail mass below \(10^{-4}\), giving average cost on the order of the expected run length while the worst case stays linear (Adams & MacKay, 2007).

The conceptual difference from CUSUM is the post-change law. CUSUM needs \(f_1\) in advance; BOCPD needs only a prior over what a new segment looks like and learns it after the change. The worked example below prices that flexibility in samples.

Seeing It in Motion

Most operational bugs live in the detector's lifecycle transitions.

stateDiagram-v2
    [*] --> Calibrating
    Calibrating --> Monitoring : baseline fixed
    Monitoring --> Accumulating : S rises above 0
    Accumulating --> Monitoring : S resets to 0
    Accumulating --> Alarm : S reaches h
    Alarm --> Triage : estimate change time
    Triage --> Calibrating : real change, new baseline
    Triage --> Monitoring : false alarm, reset S

Libraries leave the Triage to Calibrating edge to you: after a real change the old \(\mu_0\) is wrong.

Offline tools follow the decomposition ruptures is built around:

flowchart TB
    subgraph Cost["Segment cost"]
        C1["L2 mean shift"]:::purple
        C2["Kernel RBF"]:::purple
    end
    subgraph Search["Search method"]
        S1["Optimal partitioning"]:::slate
        S2["PELT pruning"]:::emerald
        S3["Binary segmentation"]:::amber
    end
    subgraph Stop["Model complexity"]
        P1["Penalty beta per change"]:::slate
        P2["Fixed number of changes"]:::slate
    end
    Y["Complete series"]:::blue --> Cost
    Cost --> Search
    Search --> Stop
    Stop --> Z["Changepoint list"]:::teal
    classDef blue fill:#1e40af,stroke:#3b82f6,stroke-width:1px,color:#fff
    classDef purple fill:#6d28d9,stroke:#a78bfa,stroke-width:1px,color:#fff
    classDef teal fill:#0e7490,stroke:#22d3ee,stroke-width:1px,color:#fff
    classDef amber fill:#b45309,stroke:#fbbf24,stroke-width:1px,color:#fff
    classDef emerald fill:#047857,stroke:#34d399,stroke-width:1px,color:#fff
    classDef slate fill:#334155,stroke:#64748b,stroke-width:1px,color:#e2e8f0

A regression-hunting pipeline:

sequenceDiagram
    participant CI as CI perf runs
    participant Store as Result store
    participant Det as Changepoint job
    participant Rev as Human reviewer
    participant Tix as Ticket queue
    CI->>Store: append latency per commit
    Store->>Det: full history per test
    Det->>Det: E-Divisive or PELT over series
    Det->>Rev: ranked candidate changepoints
    Note over Rev: many candidates are noise
    Rev->>Tix: file confirmed regressions
    Rev-->>Det: acknowledge, suppress re-alerts

[IMAGE: Heatmap of a BOCPD run-length posterior, x-axis time, y-axis run length on a log scale, diagonal ridges dropping to zero at each detected change. Caption: "Each diagonal is a regime growing older; each drop to zero is a detected change."]

By the Numbers

Run lengths for a one-sided CUSUM on standardised Gaussian data with \(k = 0.5\), against a two-sided 3σ Shewhart chart:

True shift (σ) CUSUM \(h=4\) CUSUM \(h=5\) Shewhart 3σ Faster
0 (false alarms) 336 931 370 n/a
0.5 26.7 38.0 155 CUSUM, about 6x
1.0 8.38 10.4 43.9 CUSUM, about 5x
2.0 3.34 4.01 6.30 CUSUM
3.0 2.19 2.57 2.00 Shewhart

Sources: computed for this article with the Brook-Evans Markov-chain method and checked against the NIST/SEMATECH e-Handbook, 6.3.2.3.1, which agrees in every cell except \(h=5\) at 0.5σ (NIST prints 30.0; the chain gives 38.0). The 1σ CUSUM value was also confirmed by 20,000 simulated runs (8.39).

The evidence on real data comes from the Turing benchmark: 37 series, each annotated by five people, scored with package defaults ("Default") and with the best score over a hyperparameter grid chosen knowing the answers ("Oracle"). Univariate averages:

Method Default cover Default F1 Oracle cover Oracle F1 Search cost
binseg (1974) 0.672 0.698 0.774 0.873 \(O(n \log n)\)
pelt (2012) 0.652 0.674 0.772 0.864 expected \(O(n)\)
bocpd (2007) 0.594 0.662 0.783 0.886 \(O(n)\) per step
kcpa (kernel) 0.069 0.124 0.608 0.686 \(O(n^2)\)
ecp (energy) 0.470 0.560 0.693 0.773 permutation tests
zero (no changes) 0.566 0.645 0.566 0.645 none

Sources: van den Burg & Williams, 2020, Table 2, where median annotator agreement is reported as about 0.8 (cover) and 0.9 (F1); complexities from Truong et al., 2020, Killick et al., 2012 and Arlot et al., 2019. The authors stress that Oracle scores are unattainable in practice.

The zero baseline's score reflects, in the authors' words, that "many methods return a large number of false positives." And kcpa's jump from 0.124 to 0.686 says the method is not bad; its defaults are.

[IMAGE: Slope chart from each method's Default F1 (left) to its Oracle F1 (right), with the zero baseline as a flat reference line at 0.645. Caption: "The gap between default and tuned performance is larger than the gap between methods."]

A Concrete Example

Ten standardised latency residuals, in-control mean 0 and standard deviation 1, watching for a 1σ increase, so \(\ell_t = x_t - 0.5\). Unknown to the detector, the mean moved to 1 at \(t = 6\). Run CUSUM with \(h = 4\) (ARL0 about 336), Shiryaev-Roberts on the same ratios, and a 3σ Shewhart rule.

\(t\) \(x_t\) \(\ell_t\) \(S_t\) \(R_t\) Shewhart
1 0.2 −0.3 0 0.74 no
2 −0.5 −1.0 0 0.64 no
3 0.9 0.4 0.4 2.45 no
4 −0.3 −0.8 0 1.55 no
5 0.1 −0.4 0 1.71 no
6 1.4 0.9 0.9 6.66 no
7 0.8 0.3 1.2 10.34 no
8 1.9 1.4 2.6 46.0 no
9 1.6 1.1 3.7 141.2 no
10 1.2 0.7 4.4 286.3 no
  1. Steps 1 to 5. Four of five increments are negative, so \(S\) is pinned at zero. The blip at \(t = 3\) lifts it to 0.4 and the next point wipes it out: isolated evidence decays instead of compounding.
  2. Step 6, the change. \(x_6 = 1.4\) gives \(S_6 = 0.9\). A value that high occurs about 8 percent of the time with no change; alone it means nothing.
  3. Steps 7 to 9. Every increment is positive: 1.2, 2.6, 3.7. Even \(x_7 = 0.8\), below the new mean, adds evidence because it exceeds \(k = 0.5\).
  4. Step 10, the alarm. \(S_{10} = 3.7 + 0.7 = 4.4 \ge 4\). Delay is five observations, luckier than the 8.4 average.
  5. Estimating when. \(S\) last touched zero at \(t = 5\), so the change is placed at \(t = 6\). Exactly right.
  6. Shiryaev-Roberts multiplies instead of resetting and grows geometrically after the change. Threshold \(A = 100\) alarms at \(t = 9\); \(A = 300\) has not alarmed by \(t = 10\). Compare detectors at matched ARL0, never at matched numbers.
  7. Shewhart never fires: the largest value is 1.9.

Offline, squared error around the overall mean 0.73 is 6.08. The best single split is after \(t = 5\) (means 0.08 and 1.38), cutting error to 1.86, a gain of 4.23. Binary segmentation agrees on where; whether it declares a change depends on \(\beta\). A BIC-flavoured \(2 \ln 10 = 4.61\) rejects the split, \(\ln 10 = 2.30\) accepts it. On ten points, the penalty decides.

Finally BOCPD, given what CUSUM knew about the past (200 prior in-control points at mean 0) but not the post-change mean: a new segment's mean has a \(\mathcal{N}(0, 1)\) prior, hazard \(1/100\). The posterior probability that the old regime still holds is 0.96 at \(t = 5\), 0.85 at \(t = 8\), and 0.56 at \(t = 10\). When CUSUM alarms, BOCPD is near even odds, because CUSUM was told the shift size and BOCPD had to learn it. If the real shift differs from the assumed one, that advantage can reverse.

[IMAGE: Three aligned plots over t = 1 to 10: CUSUM S_t with a dashed line at h = 4 crossed at t = 10; log10 R_t with dashed lines at A = 100 and A = 300; BOCPD probability of the old regime falling from 0.99 to 0.56. A band marks the true change at t = 6. Caption: "Same ten points, three detectors, three moments of conviction."]

Where It Breaks

The baseline is an estimate

Every CUSUM figure above assumes \(\mu_0\) and \(\sigma\) are known. In practice they come from a calibration window. Underestimate \(\sigma\) by 10 percent and the \(h = 4\) design that promised ARL0 of 336 delivers about 166 by the same Markov-chain calculation: twice the false alarms. A rolling baseline fixes that and absorbs slow drift instead, so it is never detected.

Autocorrelation fakes persistence

Run-length theory assumes independence. Latency and traffic are positively autocorrelated, so consecutive deviations agree far more often than independence predicts, and CUSUM accumulates them as evidence. The remedy is to model seasonality and AR structure and monitor residuals. But a richer model is not automatically a better detector: in the benchmark, bocpd with a constant-mean Gaussian per segment beat prophet, which models trend and seasonality.

Misspecified tails turn outliers into changepoints

Under a Gaussian likelihood one 6σ outlier is so improbable that BOCPD opens a new segment for it. Knoblauch, Jewson and Damoulas replaced the update with a β-divergence and report cutting changepoint false discovery rates "from more than 90% to 0%" on real data (Knoblauch et al., 2018, NeurIPS, arXiv:1806.02261). Yet the benchmark ranked the robust variant below plain bocpd on average: robustness to outliers and accuracy on typical data are different targets. Twitter's EDM made the same bet with medians, because existing techniques were "not robust in the presence of anomalies" (James, Kejariwal & Matteson, 2014, arXiv:1411.7955).

The penalty is the model

Offline, \(\beta\) sets the number of changes, and the example flipped on \(\ln n\) versus \(2\ln n\). BIC-style penalties assume piecewise i.i.d. data under the chosen cost; when that fails they over-segment. PELT's linear time also has a precondition, changes growing with the series, which a decade of quiet data with two real shifts violates.

Permutation tests are non-deterministic

E-Divisive judges significance by random permutations. Engineers at DataStax building Hunter found "the results of Hunter were non-deterministic and varied from run to run" and switched to a Student's t-test (Fleming et al., 2023, arXiv:2301.03034). An alert that vanishes on re-run destroys trust fast.

After the alarm

A CUSUM reset to zero on the old baseline re-alarms within about \(h/I\) samples of a real change; only re-estimating the baseline stops it. BOCPD handles this better, since the new regime simply becomes the current run.

[IMAGE: Two CUSUM traces on an AR(1) series with phi = 0.6 and no change: raw data crossing h = 4 repeatedly, AR residuals staying mostly near zero. Caption: "Autocorrelation fakes the persistence CUSUM is built to detect."]

Alternative Designs

Design How it works Key advantage Key limitation Best when
Shewhart Threshold each point at 3σ Fastest on large jumps ARL about 44 at 1σ Sudden failures
CUSUM Max over change times, reset at 0 Exactly minimax for known laws Needs shift size and baseline Known metric and shift
Shiryaev-Roberts Sum over change times Clean ARL0 bound Less intuitive thresholds Change after long quiet period
Binary segmentation Greedy split, recurse Best default score in 2020 Imprecise on close changes Retrospective, few changes
PELT Pruned exact penalised DP Optimal, near linear Penalty choice Long series, many changes
Kernel CPD Penalised DP in an RKHS Any distributional change \(O(n^2)\), bandwidth tuning Variance or shape changes
BOCPD Posterior over run length Probabilities, unknown post-change law Hazard and prior sensitivity Online, unknown regimes
E-Divisive / EDM Energy distance, permutation test Nonparametric, robust Slow, non-deterministic Noisy ops and perf metrics

Two questions decide: must you decide online, and do you know the post-change distribution? Knowing both, CUSUM wins by theorem. Knowing neither but able to wait, penalised segmentation is the default, and binary segmentation is a hard baseline. BOCPD earns its cost when a calibrated probability is the output.

How It Is Used in Practice

Performance regression hunting is the clearest success. MongoDB runs E-Divisive means over each performance test's history in CI (Daly et al., 2020, ICPE, arXiv:2003.00584). Over five months their earlier threshold system filed 2,393 tickets, of which 160 were escalated and 24 judged useful: "on average 100 tickets in the first project reduced down to 1 useful ticket." The changepoint system found every regression those tickets tracked, and a sampled audit put its false-positive rate between 40 and 80 percent depending on how ambiguous cases were counted. Humans review every candidate.

Ops breakouts. Twitter's BreakoutDetection package implemented E-Divisive with Medians, which the paper describes as 3.5 times faster than a prior technique and "currently used on a daily basis at Twitter" (James et al., 2014). Its repository is archived.

Toolkits. Meta's Kats, released by Facebook's Infrastructure Data Science team in 2021, ships CUSUM, BOCPD and robust-statistic detectors side by side (Kats repository). ruptures implements the Truong decomposition in Python, and the R changepoint package supplied the defaults the 2020 benchmark used.

Two patterns recur: offline detection over a trailing window whenever hours of delay are acceptable, because it sees both sides of a candidate change; and a ranked review queue with suppression state instead of a pager.

[IMAGE: Mock performance dashboard: latency per commit over 300 commits with two changepoint markers, and a side panel ranking candidates by magnitude with Accept and Dismiss buttons. Caption: "In production, a changepoint is a candidate for a human, not an alert."]

Insights Worth Remembering

  1. The reference value is a product decision. \(k = \delta/2\) drops out of the likelihood ratio, so choosing \(k\) means choosing the smallest shift worth acting on.

  2. False alarms are bought logarithmically; delay is paid in KL divergence. Making false alarms ten times rarer costs a fixed number of samples. Halving the shift quadruples the delay.

  3. "Optimal" always names a criterion. CUSUM is exactly optimal under Lorden's worst case; under Pollak's criterion even the long-assumed optimal procedure turned out not to be strictly minimax.

  4. CUSUM's speed is borrowed from its assumptions. In the worked example it alarmed while BOCPD still gave the old regime 56 percent, only because CUSUM was told the post-change mean.

  5. "Never fire" is a serious baseline. It beat nine of thirteen methods on default F1 in the only human-annotated benchmark. Test every detector against doing nothing.

  6. Tuning explains more than method choice. kcpa moved from 0.124 to 0.686 with tuning, while the top tuned methods were statistically indistinguishable.

  7. Online is the expensive special case. Most production successes run offline over a window with a human in the loop.

Open Questions

How should a detector be tuned without labels? The benchmark authors call for automated tuning to close the Default-Oracle gap. No study has yet shown a label-free penalty or hazard selection that reliably approaches oracle performance on real data.

Is the ground truth stable enough? On the businv series annotators broadly agree on three changes, yet the best tuned method reached only 0.650 F1. Whether that reflects weak methods or a noisy consensus is unsettled.

Where does robustness belong? Robust likelihoods, robust statistics and post-hoc filtering all claim to cut outlier-driven false positives, but no head-to-head study compares them on the same operational data.

Is ARL0 the right currency for fleets? Ten thousand metrics each with ARL0 of 1,000 still produce ten false alarms per sampling interval. Windowed false-alarm probabilities are argued for; which criterion best predicts on-call burden is an open empirical question.

Do learned detectors beat classical ones on real series? The 2020 benchmark predates most deep and self-supervised detectors. As of September 2026, no benchmark of comparable scope shows them beating tuned binary segmentation on annotated real-world data.

Sources and Further Reading

  1. Page, E. S. (1954). "Continuous Inspection Schemes." Biometrika, 41(½), 100-115. doi:10.1093/biomet/41.1-2.100
  2. Shiryaev, A. N. (1963). "On Optimum Methods in Quickest Detection Problems." Theory of Probability and Its Applications, 8(1), 22-46. doi:10.1137/1108002
  3. Roberts, S. W. (1966). "A Comparison of Some Control Chart Procedures." Technometrics, 8(3), 411-430. doi:10.1080/00401706.1966.10490374
  4. Lorden, G. (1971). "Procedures for Reacting to a Change in Distribution." Annals of Mathematical Statistics, 42(6), 1897-1908. doi:10.1214/aoms/1177693055
  5. Pollak, M. (1985). "Optimal Detection of a Change in Distribution." Annals of Statistics, 13(1). doi:10.1214/aos/1176346587
  6. Moustakides, G. V. (1986). "Optimal Stopping Times for Detecting Changes in Distributions." Annals of Statistics, 14(4). doi:10.1214/aos/1176350164
  7. Polunchenko, A. S., & Tartakovsky, A. G. (2010). "On Optimality of the Shiryaev-Roberts Procedure for Detecting a Change in Distribution." Annals of Statistics, 38(6), 3445-3457. doi:10.1214/09-AOS775
  8. Scott, A. J., & Knott, M. (1974). "A Cluster Analysis Method for Grouping Means in the Analysis of Variance." Biometrics, 30(3). doi:10.2307/2529204
  9. Killick, R., Fearnhead, P., & Eckley, I. A. (2012). "Optimal Detection of Changepoints With a Linear Computational Cost." JASA, 107(500), 1590-1598. arXiv:1101.1438
  10. Adams, R. P., & MacKay, D. J. C. (2007). "Bayesian Online Changepoint Detection." arXiv:0710.3742
  11. Knoblauch, J., Jewson, J., & Damoulas, T. (2018). "Doubly Robust Bayesian Inference for Non-Stationary Streaming Data with β-Divergences." NeurIPS. arXiv:1806.02261
  12. Arlot, S., Celisse, A., & Harchaoui, Z. (2019). "A Kernel Multiple Change-point Algorithm via Model Selection." JMLR, 20. arXiv:1202.3878
  13. Truong, C., Oudre, L., & Vayatis, N. (2020). "Selective Review of Offline Change Point Detection Methods." Signal Processing, 167, 107299. arXiv:1801.00718
  14. van den Burg, G. J. J., & Williams, C. K. I. (2020). "An Evaluation of Change Point Detection Algorithms." arXiv:2003.06222
  15. James, N. A., Kejariwal, A., & Matteson, D. S. (2014). "Leveraging Cloud Data to Mitigate User Experience from 'Breaking Bad'." arXiv:1411.7955
  16. Daly, D., Brown, W., Ingo, H., O'Leary, J., & Bradford, D. (2020). "Change Point Detection in Software Performance Testing." ICPE 2020. arXiv:2003.00584
  17. Fleming, M., Kołaczkowski, P., Kumar, I., Das, S., McCarthy, S., Pattabhiraman, P., & Ingo, H. (2023). "Hunter: Using Change Point Detection to Hunt for Performance Regressions." arXiv:2301.03034
  18. NIST/SEMATECH. e-Handbook of Statistical Methods, 6.3.2.3.1, "Cusum Average Run Length." itl.nist.gov

Free to read, no ads, no sign-up. If it was useful you can buy me a coffee.