Approach summary:Use a robust offline change-point detection method (PELT for optimal segmentation or Binary Segmentation for speed) with a cost function for mean/variance shifts on seasonally-adjusted data. Validate detections with statistical tests, bootstrapping, and business-rule gating before opening an RCA.Pseudocode (Python-style, cost = squared-error for mean shifts):python
# Inputs:
# x: 1D time series (e.g., daily active users)
# min_size: minimum segment length (e.g., 7 days)
# penalty: scalar penalty for adding a change point (e.g., BIC or lambda)
# seasonal_period: optional (e.g., 7 for weekly)
def preprocess(x, seasonal_period=None):
if seasonal_period:
# remove seasonal component (moving-average or STL)
x = x - seasonal_deseasonalize(x, seasonal_period)
x = smooth_outliers(x) # e.g., median filter
return x
def cost(seg):
# sum squared deviations from segment mean
mu = mean(seg)
return sum((seg - mu)**2)
def PELT(x, min_size, penalty):
n = len(x)
F = [0] + [inf]*n # best cost up to t
cp = [[] for _ in range(n+1)]
R = {0}
for t in range(1, n+1):
candidates = []
for s in list(R):
if t - s < min_size:
continue
c = F[s] + cost(x[s:t]) + penalty
candidates.append((c, s))
best_c, best_s = min(candidates)
F[t] = best_c
cp[t] = cp[best_s] + [best_s]
# prune: keep s in R if F[s] + cost(x[s:t]) + penalty <= F[t] + threshold
R = prune(R, F, x, t, penalty)
return cp[n] # list of change point indices
# Main usage:
x_proc = preprocess(x, seasonal_period=7)
cps = PELT(x_proc, min_size=7, penalty=choose_penalty(x_proc))
Key concepts and reasoning:- Preprocess: deseasonalize and smooth to avoid false positives from regular cycles or single-day spikes.- Cost function: squared-error detects mean shifts; other costs detect variance/Poisson shifts depending on metric.- Penalty controls sensitivity: use information criteria (BIC/AIC) or lambda tuned on historical labeled events. Larger penalty → fewer change points.- min_size prevents trivial short segments and enforces business relevance (e.g., avoid 1-day blips).Algorithmic complexity:- PELT: average O(n)–O(n log n) with pruning; worst-case O(n^2).- Binary segmentation: O(k n) where k detected splits (faster in practice).- Sliding-window or online methods (CUSUM): O(n) but for real-time needs.Handling multiple change points:- Use PELT or Segment Neighbourhood for multiple optimal changes.- Post-process: merge nearby cps within a merge_window (e.g., 3 days), compute effect size per segment (relative % change, Cohen’s d), drop if below business_threshold.Parameter selection for sensitivity:- Penalty: start with BIC: penalty = 0.5 * log(n) * params; then tune by: - Precision/recall on historical labeled shifts - Grid search with cross-validation (simulate injected shifts)- min_size: set by business cadence (e.g., weekly reporting → 7)- significance thresholds: bootstrap segment means to get p-values; require p < 0.01–0.05 and effect size > e.g., 5% change for alerting.Validation before triggering RCA:- Cross-check correlated metrics (sessions, new users): require at least one corroborating metric or product event.- Check for data pipeline issues (late-arriving rows, ETL job failures) and marker flags in ingestion logs.- Check seasonality/calendar (holidays) and marketing events (campaign flags).- Statistical validation: bootstrap the difference-in-means between adjacent segments to get confidence intervals; if CI excludes zero and effect size meets threshold, consider valid.- Human in loop: route high-impact detections (large % drop, >X users) to on-call analyst for quick review; auto-log lower-impact detections for periodic review.Practical BI considerations:- Expose parameters in dashboards (penalty, min_size) for product owners to tweak.- Provide visualization: time series with shaded segments, p-values, effect sizes, and related metrics.- Maintain a labeled history of true/false positives to continuously retrain/tune penalty and thresholds.