Summary
ResidualBOCPD runs bounded-memory Bayesian online changepoint detection (Adams &
MacKay style) on a residual/innovation series. It returns a binary signal when the
posterior mass on a new run length exceeds a threshold, plus that change probability.
Update API
import rtta
ind = rtta.ResidualBOCPD(
max_run_length=128, hazard=0.01, threshold=0.5, min_variance=1e-6
)
result = ind.update(residual)
# result.signal ∈ {0, 1}, result.probability # P(run length = 0) after update
advance(...) updates state without returning a result.
last_probability() exposes the same probability as result.probability.
Theory Of Operation
BOCPD maintains a posterior over the time since the last changepoint (run length). Under a constant hazard rate \(h\), run lengths grow with probability \(1-h\) or reset with probability \(h\). Observation likelihoods are Gaussian with online mean/variance per run-length hypothesis. Bounding the support to \(\{0,\ldots,R_{\max}\}\) keeps memory and time \(O(R_{\max})\) per tick.
Applied to residuals, a high \(P(r_t=0)\) indicates the data prefer starting a new regime relative to continuing previous residual statistics—i.e., a model-based changepoint.
Recurrence
Let \(R_{\max}\) be max_run_length, hazard \(h\), threshold \(\tau\). Maintain for each
run length \(r \in \{0,\ldots,R_{\max}\}\) a probability \(\pi_t(r)\), mean \(\mu_t(r)\),
variance \(v_t(r)\), and count \(n_t(r)\).
First observation: \(\pi_0(0)=1\), \(\mu_0(0)=r_0\), \(v_0(0)=0\), \(n_0(0)=1\); signal 0.
Thereafter, for each active run \(r\) with \(\pi_{t-1}(r)>0\):
Growth and change messages:
Run statistics on growth use Welford-style updates with count \(n' = \min(n_{t-1}(r)+1, R_{\max})\):
Changepoint mass at run 0 is initialized with \(\mu=r_t\), \(v=0\), \(n=1\). Normalize \(\tilde{\pi}_t\) to \(\pi_t\). Outputs:
Implementation Notes
The recurrence is implemented in src/rtta/indicator.cpp in class ResidualBOCPD, which
wraps BoundedBOCPD (core_.update / last_probability).
