example_univariate_mean

library(changepoints)

This is a simple guide for offline multiple change points detection on univariate mean.

There are 3 methods implemented for this purpose:

  1. DP.univar: performs dynamic programming for univariate mean change points detection.
    • CV.search.DP.univar: perform grid search to select the tuning parameter (associated with the l_0 penalty) through Cross-Validation.
  2. BS.univar: performs standard binary segmentation for univariate mean change points detection.
    • BS.univar.CPD: Perform univariate mean change points detection based on binary segmentation with the threshold parameter automatically selected based on the sSIC score.
  3. WBS.univar: performs wild binary segmentation for univariate mean change points detection.
    • WBS.univar.CPD: Perform univariate mean change points detection based on wild binary segmentation with the threshold parameter automatically selected based on the sSIC score.

In addition, function local.refine.univar performs local refinement for an initial change point estimation.

Simulate data

delta = 5 # 2*delta represents the minimum gap between boundaries
sigma2 = 1 # error variance

set.seed(1234)
y = c(rep(0, 50), rep(2, 50), rep(0, 50), rep(-2, 50)) + rnorm(200, mean = 0, sd = sqrt(sigma2)) # univariate time series
cpt_true = c(50, 100, 150)
n = length(y) # sample size

Perform dynamic programming

gamma_set = c(0.01, 0.5, 1, 5, 10, 50) # a set of tuning parameters for DP
DP_result = CV.search.DP.univar(y, gamma_set, delta) # grid search through cross-validation
min_idx = which.min(DP_result$test_error) # select gamma achieves the minimum validation error
cpt_DP_hat = unlist(DP_result$cpt_hat[[min_idx]]) # estimated change points by DP
cpt_DP_hat
#> [1]  53  99 149
Hausdorff.dist(cpt_DP_hat, cpt_true)
#> [1] 3
cpt_DPlr_hat = local.refine.univar(cpt_DP_hat, y) # perform local refinement
cpt_DPlr_hat
#> [1]  51 100 150
Hausdorff.dist(cpt_DPlr_hat, cpt_true)
#> [1] 1

Perform standard binary segmentation with user specified threshold parameter

tau_BS = 4 # user specified threshold parameter for BS
BS_object = BS.univar(y, 1, n, delta)
BS_result = thresholdBS(BS_object, tau_BS)
BS_result
#> $BS_tree_trimmed
#>                                       levelName
#> 1 Binary Segmentation Tree Trimmed with tau = 4
#> 2  °--N150                                     
#> 3      °--N51                                  
#> 4          °--N100                             
#> 
#> $cpt_hat
#>   location     value level
#> 1      150 15.408017     1
#> 2       51  8.753484     2
#> 3      100 10.720866     3
cpt_BS_hat = sort(BS_result$cpt_hat[,1]) # estimated change points by BS
cpt_BS_hat
#> [1]  51 100 150
Hausdorff.dist(cpt_BS_hat, cpt_true)
#> [1] 1
cpt_BSlr_hat = local.refine.univar(cpt_BS_hat, y) # perform local refinement
cpt_BSlr_hat
#> [1]  51 100 150
Hausdorff.dist(cpt_BSlr_hat, cpt_true)
#> [1] 1

Perform standard binary segmentation with automatically tuned threshold parameter

BS_CPD_result = tuneBSunivar(BS_object, y)
BS_CPD_result$cpt
#> [1]  51 100 150
Hausdorff.dist(BS_CPD_result$cpt, cpt_true)
#> [1] 1
BS_CPD_LR = local.refine.univar(BS_CPD_result$cpt, y)
BS_CPD_LR
#> [1]  51 100 150
Hausdorff.dist(BS_CPD_LR, cpt_true)
#> [1] 1

Perform wild binary segmentation with user specified threshold parameter

tau_WBS = 4 # user specified threshold parameter for WBS
intervals = WBS.intervals(M = 300, lower = 1, upper = n)
WBS_object = WBS.univar(y, 1, n, intervals$Alpha, intervals$Beta, delta)
WBS_result = thresholdBS(WBS_object, tau_WBS)
WBS_result
#> $BS_tree_trimmed
#>                                       levelName
#> 1 Binary Segmentation Tree Trimmed with tau = 4
#> 2  °--N100                                     
#> 3      ¦--N51                                  
#> 4      °--N150                                 
#> 
#> $cpt_hat
#>   location     value level
#> 1      100 17.456657     1
#> 2       51 12.785814     2
#> 3      150  9.520455     2
cpt_WBS_hat = sort(WBS_result$cpt_hat[,1]) # estimated change points by WBS
cpt_WBS_hat
#> [1]  51 100 150
Hausdorff.dist(cpt_WBS_hat, cpt_true)
#> [1] 1
cpt_WBSlr_hat = local.refine.univar(cpt_WBS_hat, y) # perform local refinement
cpt_WBSlr_hat
#> [1]  51 100 150
Hausdorff.dist(cpt_WBSlr_hat, cpt_true)
#> [1] 1

Perform wild binary segmentation with automatically tuned threshold parameter

WBS_CPD_result = tuneBSunivar(WBS_object, y)
WBS_CPD_result$cpt
#> [1]  51 100 150
Hausdorff.dist(WBS_CPD_result$cpt, cpt_true)
#> [1] 1
WBS_CPD_LR = local.refine.univar(WBS_CPD_result$cpt, y)
WBS_CPD_LR
#> [1]  51 100 150
Hausdorff.dist(WBS_CPD_LR, cpt_true)
#> [1] 1