-
Notifications
You must be signed in to change notification settings - Fork 0
Home
RegimeChange is an R package for detecting structural breaks and regime changes in time series data. It provides a unified interface to both frequentist and Bayesian methods, with particular emphasis on robust performance in challenging scenarios including low signal-to-noise ratios, subtle variance changes, autocorrelated data, and heavy-tailed distributions.
Regime change detection addresses a fundamental philosophical question:
How do we distinguish a real change from the inherent variability of the world?
Every observable system exhibits fluctuations. The central question is: is this observed fluctuation "noise" (random variation within the same regime) or "signal" (evidence that the system transitioned to a qualitatively different state)?
We assume the world can be described through "regimes" or "states" characterized by parameters
We do not observe
The statistic
There exists an irresolvable epistemological tension between two types of error:
| Error | Technical Name | Consequence |
|---|---|---|
| Detecting change where there is none | False alarm (Type I) | Acting unnecessarily |
| Not detecting a real change | Delayed detection (Type II) | Failing to react in time |
The decision threshold represents precisely this negotiation: how much evidence do we demand before declaring that the world has changed?
This structure appears across diverse domains:
| Domain | Question | ||
|---|---|---|---|
| Economics | Expansion | Recession | When did the cycle change? |
| Medicine | Stable patient | Deterioration | When did the crisis begin? |
| Finance | Stable market | Bubble/crash | When did the regime change? |
| Ecology | Balanced ecosystem | Disturbed | When did the collapse occur? |
| Manufacturing | Process under control | Defective | When did it go out of adjustment? |
| Climatology | Stationary climate | Climate change | When did the trend begin? |
| Epidemiology | Endemic | Outbreak | When did the epidemic start? |
| Electrical engineering | Normal operation | Failure/transient | When did the event occur? |
The likelihood ratio:
has a deep informational interpretation: it measures how surprising observation
Changepoint detection is a fundamental problem in time series analysis with applications in finance, quality control, climatology, and genomics. While several R packages address this problem, practitioners frequently encounter difficulties with:
- Autocorrelated data: Most methods assume independence, leading to inflated false positive rates
- Subtle changes: Low SNR or small variance shifts often go undetected
- Outliers and heavy tails: Standard Gaussian assumptions break down with contaminated data
- Method selection: No single algorithm dominates across all scenarios
RegimeChange addresses these challenges through adaptive variance floors for numerical stability, optional pre-whitening for autocorrelated series, robust M-estimation for heavy-tailed data, and ensemble methods that leverage multiple algorithms.
| Package | Language | Strengths | Limitations |
|---|---|---|---|
changepoint |
R (C backend) | Optimized PELT, stable, mature | Frequentist only, no online, limited uncertainty |
tidychangepoint |
R | Tidyverse interface, unifies methods | Wrapper, adds no new algorithms |
ruptures |
Python | Very complete for offline | Not Bayesian, not online |
bayesian_changepoint_detection |
Python | BOCPD with PyTorch | Bayesian only, doesn't integrate other methods |
Kats (Meta) |
Python | BOCPD, well documented | Meta ecosystem, heavy dependencies |
RegimeChange provides:
- Integration of frequentist AND Bayesian methods
- Online mode with streaming updates
- Rigorous uncertainty quantification
- Multivariate series support
- Detection of multiple types of change
- High-performance backend (Julia) with friendly API (R)
- Deep learning for complex patterns (optional)
- Unified paradigms: frequentist, Bayesian, and deep learning in a coherent API
- Both modes: offline for research, online for production
- Native uncertainty: estimations come with confidence intervals
- Performance + Usability: optional Julia backend, tidyverse-compatible R interface
# Install from GitHub
# install.packages("devtools")
devtools::install_github("IsadoreNabi/RegimeChange")library(RegimeChange)
# Generate data with a changepoint at t=200
set.seed(42)
data <- c(rnorm(200, 0, 1), rnorm(200, 2, 1))
# Detect using PELT
result <- detect_regimes(data, method = "pelt")
print(result)
# For autocorrelated data, enable AR correction
result_ar <- detect_regimes(data, method = "pelt", correct_ar = TRUE)
# For data with outliers or heavy tails, enable robust estimation
result_robust <- detect_regimes(data, method = "pelt", robust = TRUE)The library detects changes in different statistical properties:
- Location: Mean, Trend, Level
- Dispersion: Variance, Range
- Dependence: Autocorrelation, Cross-correlation, Structure
- Distribution: Shape, Tails, Mode
| Type | Parameter | Hypothesis | Example |
|---|---|---|---|
| Mean |
|
Level change in GDP | |
| Variance |
|
Volatility increase | |
| Mean and Variance | Joint change | Economic regime transition | |
| Trend |
|
|
Start of inflationary trend |
| Autocorrelation |
|
Change in persistence | |
| Distribution |
|
General non-parametric change |
Simple change (one point):
A single changepoint
Multiple changes (k points):
Multiple changepoints
# The user can specify what to look for
detect_regimes(
data,
type = c("mean", "variance", "both", "trend", "distribution"),
n_changepoints = c("single", "multiple", "unknown"),
min_segment_length = 30 # Minimum observations per regime
)The detection methods are organized into three main families:
- Frequentist: PELT, BinSeg, CUSUM, Wild BinSeg, FPOP, E-Divisive, Kernel CPD
- Bayesian: BOCPD (Adams-MacKay), Shiryaev-Roberts
- Deep Learning: Autoencoders, TCN, Transformer, CPC, Ensemble
The foundational method. Accumulates deviations from a target value.
Statistic:
Decision: Alarm when
Complexity:
Use: Mean change detection, single changepoint.
detect_regimes(data, method = "cusum", threshold = 4)The gold standard for multiple changepoints.
Idea: Dynamic programming with pruning to find optimal segmentation.
Objective function:
where
Complexity:
Supported penalties: AIC, BIC, MBIC, MDL, manual.
# PELT (default) - O(n) optimal partitioning
detect_regimes(data, method = "pelt", penalty = "MBIC")
# With AR correction for autocorrelated data
detect_regimes(data, method = "pelt", correct_ar = TRUE)
# With robust estimation for outliers/heavy tails
detect_regimes(data, method = "pelt", robust = TRUE)Recursive divide and conquer.
Algorithm:
- Find the best changepoint in the entire dataset
- If significant, split into two segments
- Apply recursively to each segment
Complexity:
Limitation: Does not guarantee global optimum (greedy).
detect_regimes(data, method = "binseg", n_changepoints = 3)Improvement on Binary Segmentation with random intervals.
Idea: Instead of searching the entire interval, search M random intervals and take the best.
Advantage: More robust to nearby changes.
detect_regimes(data, method = "wbs", n_intervals = 100)Optimized version of PELT with functional pruning.
Complexity:
fpop_detect(data, penalty = "BIC")Non-parametric method using energy distance.
Idea: Use energy distance to detect changes in complete distribution.
Advantage: No parametric distribution assumption.
edivisive_detect(data, min_size = 30)Idea: Map data to Hilbert space and detect changes in that space.
Advantage: Captures changes in complex data structure.
kernel_cpd_detect(data, kernel = "rbf")Reference: Adams & MacKay (2007)
Central idea: Maintain a posterior distribution over the "run length" (time since last change).
Joint distribution:
Components:
-
Predictive:
$P(x_t | r_t, x^{(r)})$ — probability of datum given run length -
Changepoint prior:
$P(r_t | r_{t-1})$ — prior on change occurrence (typically geometric) -
Message:
$P(r_{t-1}, x_{1:t-1})$ — recursion from previous step
Supported conjugate models:
- Normal with known variance (Normal-Normal)
- Normal with unknown mean and variance (Normal-Gamma)
- Poisson (Gamma-Poisson)
- Multivariate (Normal-Wishart)
Complexity per observation:
# Bayesian Online Changepoint Detection
detect_regimes(data, method = "bocpd")
# Custom prior specification
prior <- normal_gamma(mu0 = 0, kappa0 = 0.1, alpha0 = 1, beta0 = 1)
detect_regimes(data, method = "bocpd", prior = prior)Statistic:
Interpretation: Sum of likelihood ratios from all possible past changepoints.
Advantage: Asymptotically optimal for minimizing detection delay.
shiryaev_roberts(data, threshold = 100)Note: These methods require optional dependencies (keras, tensorflow).
Idea: Train autoencoder on "normal" data, detect change when reconstruction error increases.
autoencoder_detect(data, window_size = 50, threshold = 2.0)Convolutional architecture for sequence modeling.
tcn_detect(data, window_size = 100)Attention-based architecture for capturing long-range dependencies.
transformer_detect(data, window_size = 100)Self-supervised representation learning for change detection.
cpc_detect(data, window_size = 50)Combine multiple deep learning detectors.
ensemble_dl_detect(data, methods = c("autoencoder", "tcn"))Context: Retrospective analysis. Complete dataset is available.
Question: "When did the changes occur?"
Characteristics:
- Can look forward and backward
- Seeks globally optimal segmentation
- No temporal constraint
Appropriate algorithms: PELT, Binary Segmentation, WBS, FPOP, E-Divisive
Use cases:
- Historical analysis of economic series
- Study of past climate changes
- Scientific research in general
Context: Real-time surveillance. Data arrives sequentially.
Question: "Is a change occurring now?"
Characteristics:
- Only sees past and present
- Must decide immediately
- Trade-off speed vs false alarms
Appropriate algorithms: CUSUM, BOCPD, Shiryaev-Roberts
Key metrics:
-
ARL$_0$: Average Run Length under
$H_0$ (average time to false alarm) -
ARL$_1$: Average Run Length under
$H_1$ (average detection delay)
Use cases:
- Industrial monitoring
- Epidemiological surveillance
- Fraud detection
- Algorithmic trading
# Initialize detector
detector <- regime_detector(method = "bocpd")
# Process streaming data
for (x in new_observations) {
result <- update(detector, x)
if (result$alarm) {
message("Changepoint detected at time ", result$time)
detector <- reset(detector)
}
}# Offline mode (default)
result <- detect_regimes(data, mode = "offline", method = "pelt")
# Online mode via regime_detector
detector <- regime_detector(method = "bocpd", prior = normal_gamma())
for (x in data_stream) {
result <- update(detector, x)
if (result$alarm) {
handle_regime_change(result)
}
}Every changepoint estimate must be accompanied by an uncertainty measure.
This is what distinguishes a scientifically rigorous library from a purely practical tool.
How confident are we that the change occurred exactly at
Representation:
- Confidence interval:
$[\hat{\tau} - \delta, \hat{\tau} + \delta]$ - Complete posterior distribution:
$P(\tau | \text{data})$
How confident are we that there is a change at all?
Representation:
- p-value (frequentist)
- Bayes Factor (Bayesian)
- Posterior probability of change
How many changes are there really?
Representation:
- Distribution over number of changes
- Optimal penalty (BIC, MDL)
bootstrap_changepoint <- function(data, method, B = 1000) {
estimates <- numeric(B)
for (b in 1:B) {
# Resample blocks to preserve dependence
data_boot <- block_bootstrap(data)
estimates[b] <- detect(data_boot, method)$changepoint
}
# Confidence interval
ci <- quantile(estimates, c(0.025, 0.975))
return(list(
estimate = detect(data, method)$changepoint,
ci = ci,
se = sd(estimates),
distribution = estimates
))
}BOCPD naturally produces
# Probability of change at each point
prob_change <- bocpd_result$posterior[, 1] # run length = 0
# Most probable changepoint
map_changepoint <- which.max(prob_change)
# Credible interval
credible_interval <- hpd_interval(prob_change, prob = 0.95)# Every detection function returns:
result <- list(
# Point estimates
changepoints = c(45, 120, 380),
# Location uncertainty
confidence_intervals = list(
c(42, 48),
c(115, 125),
c(375, 385)
),
# Existence uncertainty
existence_probability = c(0.95, 0.88, 0.72),
# Segment information
segments = list(
list(start = 1, end = 45, params = list(mean = 2.3, var = 0.5)),
list(start = 46, end = 120, params = list(mean = 5.1, var = 0.8))
# ...
),
# Diagnostics
information_criterion = list(BIC = 234.5, AIC = 228.1),
# Complete posterior (if applicable)
posterior = matrix(...) # P(change at t) for each t
)With
- Synchronous change: All series change at the same point
- Asynchronous change: Different series change at different points
- Correlation change: Dependence structure changes, even if marginals don't
Let
Before change:
After change:
The change can be in:
-
$\boldsymbol{\mu}$ (mean vector) -
$\boldsymbol{\Sigma}$ (covariance matrix, including correlations) - Both
Use Normal-Wishart predictive distribution:
Prior:
Update: Conjugate formulas for updating hyperparameters.
prior <- normal_wishart(mu0 = rep(0, d), kappa0 = 1,
nu0 = d + 1, Psi0 = diag(d))
result <- bocpd(data_matrix, prior = prior)For high dimension (
Idea: Find direction
sparse_projection_cpd(data_matrix, sparsity = 5)# Data: n × d matrix
data <- matrix(...)
# Detect synchronous changes
result <- detect_regimes(data,
type = "multivariate",
sync = TRUE)
# Detect changes per series
result <- detect_regimes(data,
type = "multivariate",
sync = FALSE,
share_changepoints = FALSE)
# Detect correlation change
result <- detect_regimes(data,
type = "correlation",
method = "normal_wishart")We conducted comprehensive benchmarks comparing RegimeChange against established R packages: changepoint (Killick & Eckley, 2014), wbs (Fryzlewicz, 2014), not (Baranowski et al., 2019), and ecp (James & Matteson, 2015). Tests were performed with 50 replications per scenario, using synthetic data under maximum difficulty conditions.
17 scenarios
| Rank | Method | Mean F1 | Package |
|---|---|---|---|
| 1 | RC_auto | 0.804 | RegimeChange |
| 2 | ECP_pkg | 0.788 | ecp |
| 3 | CP_binseg | 0.777 | changepoint |
| 4 | RC_cusum | 0.761 | RegimeChange |
| 5 | NOT_pkg | 0.722 | not |
| 6 | CP_pelt | 0.720 | changepoint |
| 7 | RC_pelt | 0.719 | RegimeChange |
| 8 | RC_wbs_mean | 0.681 | RegimeChange |
| 9 | RC_wbs | 0.654 | RegimeChange |
| 10 | RC_binseg | 0.652 | RegimeChange |
| 11 | WBS_pkg | 0.634 | wbs |
| 12 | RC_ediv | 0.612 | RegimeChange |
| 13 | RC_not | 0.514 | RegimeChange |
RegimeChange's automatic method selector (RC_auto) achieves the highest overall F1 score, outperforming all reference packages.
| Scenario | Best RC | Best Reference | Winner |
|---|---|---|---|
| Mean δ=3 (easy) | 1.000 | 1.000 | Tie |
| Mean δ=2 (medium) | 1.000 | 1.000 | Tie |
| Mean δ=1 (hard) | 0.980 | 0.980 | Tie |
| Mean δ=0.5 (very hard) | 0.773 | 0.760 | RC (+0.01) |
| Variance 4:1 | 0.980 | 0.980 | Tie |
| Variance 2:1 | 0.667 | 0.400 | RC (+0.27) |
| Multi-CP (3 changes) | 1.000 | 1.000 | Tie |
| Multi-CP (5 changes) | 1.000 | 1.000 | Tie |
| AR(0.3)+change | 1.000 | 1.000 | Tie |
| AR(0.5)+change | 1.000 | 0.983 | RC (+0.02) |
| AR(0.7)+change | 0.900 | 0.720 | RC (+0.18) |
| 2% outliers | 1.000 | 0.967 | RC (+0.03) |
| 5% outliers | 1.000 | 0.963 | RC (+0.04) |
| 10% outliers | 0.993 | 0.973 | RC (+0.02) |
| t-dist (df=5) | 1.000 | 1.000 | Tie |
| t-dist (df=3) | 1.000 | 0.993 | RC (+0.01) |
| t-dist (df=2) | 0.967 | 0.983 | Ref (+0.02) |
Summary: RegimeChange wins or ties in 16 of 17 scenarios. The only loss is marginal (0.017 in t-dist df=2).
| Scenario | RegimeChange | Reference | Improvement |
|---|---|---|---|
| Subtle variance (2:1) | 0.667 | 0.400 | +67% |
| Strong AR (ρ=0.7) | 0.900 | 0.720 | +25% |
| 5% outliers | 1.000 | 0.963 | +4% |
| Heavy tails t(df=3) | 1.000 | 0.993 | +1% |
10 scenarios
| Scenario | RC_pelt | CP_pelt | RC_robust | RC_ediv | ECP_pkg |
|---|---|---|---|---|---|
| Clean (baseline) | 1.00±0.00 | 1.00±0.00 | 0.98±0.08 | 0.77±0.20 | 0.99±0.07 |
| 2% outliers | 0.24±0.12 | 0.52±0.26 | 1.00±0.00 | 0.81±0.17 | 0.99±0.07 |
| 5% outliers | 0.14±0.04 | 0.23±0.12 | 0.99±0.05 | 0.82±0.17 | 0.99±0.07 |
| 10% outliers | 0.11±0.08 | 0.17±0.19 | 0.99±0.05 | 0.85±0.18 | 1.00±0.00 |
| 15% outliers | 0.12±0.09 | 0.17±0.25 | 1.00±0.00 | 0.75±0.31 | 0.96±0.12 |
| t-dist (df=5) | 0.89±0.19 | 0.97±0.12 | 1.00±0.00 | 0.78±0.18 | 1.00±0.00 |
| t-dist (df=3) | 0.50±0.21 | 0.72±0.26 | 1.00±0.00 | 0.78±0.17 | 0.97±0.12 |
| t-dist (df=2) | 0.26±0.17 | 0.38±0.32 | 1.00±0.00 | 0.82±0.18 | 0.97±0.12 |
| Mixture (10%) | 0.30±0.14 | 0.64±0.33 | 0.99±0.05 | 0.77±0.18 | 0.97±0.12 |
| 5% Cauchy | 0.41±0.20 | 0.51±0.22 | 1.00±0.00 | 0.77±0.19 | 0.97±0.10 |
| Rank | Method | Mean F1 |
|---|---|---|
| 1 | RC_robust | 0.998 |
| 2 | ECP_pkg | 0.979 |
| 3 | RC_ediv | 0.795 |
| 4 | CP_pelt | 0.479 |
| 5 | RC_pelt | 0.331 |
Key Finding: RC_robust achieves near-perfect performance (F1 = 0.998) across all contamination scenarios, with perfect scores (F1 = 1.00) in 6 of 9 challenging scenarios. This represents a 108% improvement over the best reference package (changepoint PELT at F1 = 0.479) on contaminated data.
Where RegimeChange excels:
- Contaminated data: RC_robust achieves F1 = 0.998 vs. CP_pelt at 0.479 (+108%)
- Subtle variance changes: RC achieves 0.667 vs. reference 0.400 (+67%)
- Autocorrelated series: RC achieves 0.900 vs. reference 0.720 for AR(0.7) (+25%)
- Overall ranking: RC_auto achieves highest mean F1 (0.804) across all methods
Where RegimeChange ties:
- Standard scenarios with clear mean shifts: Perfect detection (F1 = 1.00)
- Multiple changepoint scenarios: Excellent detection (F1 ≥ 0.995)
Where references have slight advantage:
- Very heavy tails (t-dist df=2): ECP achieves 0.983 vs. RC 0.967 (margin: 0.016)
| Data Characteristics | Recommended Settings | Expected F1 |
|---|---|---|
| Clean iid data | default | 0.95+ |
| Mild contamination (2-5%) | robust = TRUE |
0.99+ |
| Heavy contamination (10%+) | robust = TRUE |
0.99+ |
| Heavy tails (t-dist, Cauchy) | robust = TRUE |
0.99+ |
| Autocorrelated (AR) | correct_ar = TRUE |
0.95+ |
| Subtle variance changes | type = "both" |
0.65+ |
| Unknown data quality | detect_regimes(data, method = "auto") |
0.80+ |
Recommendation: For real-world data where contamination or heavy tails are possible, robust = TRUE is strongly recommended. The computational overhead is modest, and the robustness gains are substantial.
library(RegimeChange)
library(changepoint)
# Example 1: AR(0.7) scenario
set.seed(123)
ar_data <- as.numeric(arima.sim(list(ar = 0.7), n = 400))
ar_data[201:400] <- ar_data[201:400] + 2 # Add mean shift
cp_result <- cpt.meanvar(ar_data, method = "PELT", penalty = "MBIC")
rc_result <- detect_pelt(ar_data, "both", "MBIC", 5)
rc_result_cusum <- cusum(ar_data)
# RC_cusum typically closer to true changepoint at 200
# Example 2: Contaminated data (5% outliers)
set.seed(456)
clean_data <- c(rnorm(200, 0), rnorm(200, 2))
outlier_idx <- sample(400, 20)
contaminated <- clean_data
contaminated[outlier_idx] <- contaminated[outlier_idx] +
sample(c(-10, 10), 20, replace = TRUE)
# Standard methods fail
cp_result <- cpts(cpt.mean(contaminated, method = "PELT", penalty = "MBIC"))
# Often misses the true changepoint or finds spurious ones
# Robust method succeeds
rc_result <- detect_pelt(contaminated, "mean", "MBIC", 5, robust = TRUE)
rc_result$changepoints # Typically close to 200Hausdorff Distance:
Interpretation: Maximum distance between an estimated point and the nearest true one.
Rand Index:
where TP, TN, FP, FN are defined over pairs of points:
- TP: Same segment in truth and estimation
- TN: Different segment in truth and estimation
- FP: Same estimated segment, different true segment
- FN: Different estimated segment, same true segment
Adjusted Rand Index: Corrected for chance.
Interpretation: Weighted average of IoU (Intersection over Union) for each segment.
Given a tolerance margin
-
TP: Change detected within
$\pm M$ of a true one - FP: Change detected with no nearby true one
- FN: True change with no nearby detection
Trade-off: Increasing threshold
Measured at different time horizons after the change.
Per time window.
# Evaluate result against ground truth
result <- detect_regimes(data, method = "pelt")
metrics <- evaluate(result, true_changepoints = c(100, 250), tolerance = 10)
print(metrics)
# Available metrics
hausdorff_distance(result$changepoints, true_cps)
f1_score(result$changepoints, true_cps, tolerance = 10)
rand_index(result, true_cps)
adjusted_rand_index(result, true_cps)
covering_metric(result, true_cps)
precision_score(result$changepoints, true_cps, tolerance = 10)
recall_score(result$changepoints, true_cps, tolerance = 10)
mean_absolute_error(result$changepoints, true_cps)
rmse_changepoints(result$changepoints, true_cps)The library includes:
- Synthetic datasets with known ground truth
- Real reference datasets (economic, industrial, well-log)
- Comparison function between methods
# Compare multiple methods
benchmark <- compare_methods(
data = benchmark_data,
methods = c("pelt", "bocpd", "wbs", "cusum"),
true_changepoints = true_cps
)
# Automatic visualization
plot(benchmark)When enabled, RegimeChange uses:
- Adaptive winsorization: Outliers beyond 3 MADs are clipped
- Huber M-estimation: Loss function with 95% efficiency at normal
- Qn scale estimator: More efficient than MAD (82% vs 37%)
- Iteratively reweighted least squares: For joint location-scale estimation
This provides a breakdown point of 50% (maximum theoretical) while maintaining high efficiency for clean data.
- AR(1) coefficient estimated via Yule-Walker (or robust median-based method if
robust = TRUE) - Applied only when
$|\rho| > 0.1$ and$n > 30$ - Changepoint indices automatically adjusted for the lost observation
"R Usability, Julia Performance, Statistical Rigor"
Principles:
- Tidyverse-compatible R API
- Optional intensive computations in Julia
- Native R visualization (ggplot2)
- Extensibility for new methods
RegimeChange/
├── DESCRIPTION
├── NAMESPACE
├── LICENSE
├── README.md
├── R/
│ ├── data.R # Dataset documentation
│ ├── detect.R # Main function detect_regimes()
│ ├── evaluation.R # Metrics and benchmarking
│ ├── imports.R # Package imports
│ ├── julia_backend.R # Julia connection via JuliaCall
│ ├── methods_advanced.R # FPOP, Kernel CPD, E-Divisive
│ ├── methods_bayesian.R # BOCPD, Shiryaev-Roberts
│ ├── methods_deeplearning.R # Autoencoder, TCN, Transformer
│ ├── methods_frequentist.R # PELT, CUSUM, BinSeg, WBS
│ ├── priors.R # Prior distributions
│ ├── visualization.R # Plotting functions
│ └── zzz.R # Package initialization
├── inst/
│ └── julia/
│ └── RegimeChangeJulia.jl
├── man/
├── tests/
│ ├── testthat.R
│ └── testthat/
├── vignettes/
│ ├── introduction.Rmd
│ ├── offline-detection.Rmd
│ └── bayesian-methods.Rmd
└── data/
The optional Julia backend provides high-performance implementations:
# Initialize Julia (optional, for better performance)
init_julia()
# Check availability
julia_available()
julia_status()
# Benchmark R vs Julia backends
benchmark_backends(data, method = "pelt")Julia module exports: pelt_detect, fpop_detect, bocpd_detect, cusum_detect, kernel_cpd_detect, wbs_detect, segneigh_detect, pelt_multivariate
#' Detect regime changes in time series
#'
#' @param data Numeric vector, ts, or matrix for multivariate
#' @param method Algorithm: "pelt", "bocpd", "cusum", "wbs",
#' "shiryaev", etc.
#' @param type Change type: "mean", "variance", "both", "trend",
#' "distribution"
#' @param mode Operation mode: "offline" (default), "online"
#' @param penalty For offline methods: "BIC", "AIC", "MBIC", "MDL",
#' or numeric
#' @param min_segment Minimum segment length
#' @param prior List with prior specification (for Bayesian methods)
#' @param threshold Detection threshold (for online/CUSUM methods)
#' @param correct_ar Logical: apply AR(1) correction?
#' @param robust Logical: use robust estimation?
#' @param ... Additional method-specific arguments
#'
#' @return Object of class "regime_result"
detect_regimes <- function(data, method = "pelt", ...)# Normal-Gamma prior for BOCPD
normal_gamma(mu0 = 0, kappa0 = 1, alpha0 = 1, beta0 = 1)
# Normal prior with known variance
normal_known_var(mu0 = 0, sigma0 = 1, known_var = 1)
# Normal-Wishart prior for multivariate
normal_wishart(mu0, kappa0, nu0, Psi0)
# Poisson-Gamma prior
poisson_gamma(alpha0 = 1, beta0 = 1)
# Inverse-Gamma prior for variance
inverse_gamma_var(alpha0 = 1, beta0 = 1)
# Hazard rate priors
geometric_hazard(lambda = 0.01)
constant_hazard(rate = 0.01)
negbin_hazard(alpha = 1, beta = 1)# Create online detector
detector <- regime_detector(method = "bocpd", prior = normal_gamma())
# Update with new observation
result <- update(detector, x)
# Reset after detection
detector <- reset(detector)# Plot detection results
plot(result) # S3 method
plot(result, type = "posterior") # Posterior probabilities
plot(result, type = "segments") # Segment visualization
# Additional plots
plot_summary(result)
plot_interactive(result) # Requires plotly
plot_compare(result1, result2) # Compare methods# Evaluate against ground truth
evaluate(result, true_changepoints, tolerance = 5)
# Individual metrics
f1_score(detected, true, tolerance)
hausdorff_distance(detected, true)
rand_index(result, true)
adjusted_rand_index(result, true)
covering_metric(result, true)
precision_score(detected, true, tolerance)
recall_score(detected, true, tolerance)
# Compare methods
compare_methods(data, methods = c("pelt", "bocpd"),
true_changepoints = true_cps)RegimeChange is designed to complement equation discovery workflows:
| Library | Question |
|---|---|
| RegimeChange | When do the system's properties change? |
| EmpiricalDynamics | What is the equation governing the system? |
Potential workflow: Instead of searching for ONE equation for the entire dataset, discover different equations for each regime:
- Graph-based changepoint detection (Sulem et al., 2024)
- Improved multivariate optimization for
$p >> n$ - Additional deep learning architectures
- Real-time dashboard for online monitoring
-
Very short series: For
$n < 100$ , standard PELT implementations may be preferable -
High-dimensional data: Multivariate support is available but not yet optimized for
$p >> n$ -
Computational cost: Robust estimation is
$O(n^2)$ vs$O(n)$ for standard PELT; disable for very large datasets -
AR + heavy contamination: When both issues are present,
robust = TRUEalone typically works better than combining both corrections - Deep learning methods: Require optional dependencies (keras, tensorflow) and may need tuning for specific domains
- Page, E. S. (1954). Continuous inspection schemes. Biometrika.
- Basseville, M., & Nikiforov, I. (1993). Detection of Abrupt Changes: Theory and Application.
- Killick, R., Fearnhead, P., & Eckley, I. A. (2012). Optimal detection of changepoints with a linear computational cost. Journal of the American Statistical Association, 107(500), 1590-1598.
- Killick, R., & Eckley, I. A. (2014). changepoint: An R package for changepoint analysis. Journal of Statistical Software, 58(3), 1-19.
- Adams, R. P., & MacKay, D. J. (2007). Bayesian online changepoint detection. arXiv preprint arXiv:0710.3742.
- Tartakovsky, A. G., & Moustakides, G. V. (2010). State-of-the-art in Bayesian changepoint detection. Sequential Analysis.
- Li, J., Fearnhead, P., Fryzlewicz, P., & Wang, T. (2024). Automatic change-point detection in time series via deep learning. JRSS-B.
- Gupta, M., Wadhvani, R., & Rasool, A. (2022). Real-time change-point detection. Expert Systems with Applications.
- Rousseeuw, P. J., & Croux, C. (1993). Alternatives to the median absolute deviation. Journal of the American Statistical Association, 88(424), 1273-1283.
- Huber, P. J. (1981). Robust Statistics. John Wiley & Sons.
- Truong, C., Oudre, L., & Vayatis, N. (2020). ruptures: change point detection in Python.
- Baumer, B. et al. (2025). tidychangepoint: A Unified Framework. R package.
- Fryzlewicz, P. (2014). Wild binary segmentation for multiple change-point detection. Annals of Statistics, 42(6), 2243-2281.
- Baranowski, R., Chen, Y., & Fryzlewicz, P. (2019). Narrowest-over-threshold detection of multiple change points and change-point-like features. Journal of the Royal Statistical Society: Series B, 81(3), 649-672.
- James, N. A., & Matteson, D. S. (2015). ecp: An R package for nonparametric multiple change point analysis of multivariate data. Journal of Statistical Software, 62(7), 1-25.
| Term | Definition |
|---|---|
| Changepoint | Point in time where the statistical properties of a series change |
| Regime | Time period with homogeneous statistical properties |
| Run length | Time elapsed since the last changepoint |
| ARL | Average Run Length: average time until a decision |
| Hazard rate | Instantaneous probability that a change occurs |
| Posterior | Probability distribution after observing the data |
| PELT | Pruned Exact Linear Time: optimal segmentation algorithm |
| BOCPD | Bayesian Online Changepoint Detection |
| CUSUM | Cumulative Sum: cumulative statistic for detection |
@software{regimechange2024,
title = {RegimeChange: Robust Changepoint Detection for Time Series},
author = {Gómez Julián, José Mauricio},
year = {2024},
url = {https://github.com/IsadoreNabi/RegimeChange}
}MIT © José Mauricio Gómez Julián