Part XIII: Trust, Safety, Evaluation, and Operations
Chapter 67: Interpretability and Root-Cause Analysis for Time Series

Root-cause graphs

"The alarm rang on the temperature sensor. The temperature sensor was the last one to notice."

A Downstream AI Agent

The Big Picture

Every earlier section in this chapter explains a single signal: which timestep mattered (67.1, 67.2), what counterfactual would flip the verdict (67.3), what archetype the window resembled (67.4). None of them answers the question an on-call engineer actually asks at 3 a.m.: which sensor, subsystem, or event started this, and how did it spread to the one that alarmed? In a coupled physical system the alarming variable is almost never the culprit; it is the tail end of a chain. A root-cause graph makes that chain explicit. It is a directed graph whose nodes are sensors or subsystems and whose edges encode "drives" or "causes," annotated with time lags. Given an anomaly, you localize the origin by reasoning over the graph rather than over any one series. This section builds the graph (structure discovery), then walks it (root-cause ranking), and is honest about when a graph edge means genuine causation versus a shared confounder.

This section assumes the probability and estimation background of Chapter 4, the change- and anomaly-detection machinery of Chapter 12 (something has to flag the anomaly before you can trace it), and the graph-over-sensors viewpoint of Chapter 54. A root-cause graph is that same sensor graph, but with edges that carry a causal, not merely correlational, claim.

Why correlation-based attribution cannot localize a cause

Attribution ranks inputs by how much they move the output of one model. In a plant with recirculating coolant, a pressure dip, a pump-current spike, and a downstream temperature rise are all mutually correlated and all "important" to any classifier of the fault. Attribution will happily highlight the temperature channel, because it moved the most, even though temperature is the symptom. What you need is the asymmetry: pump current changed first and caused pressure to fall, which caused temperature to climb. That asymmetry is exactly what a causal graph encodes and what a correlation heatmap discards. Formally we want a structural model in which each variable is a function of its causal parents plus noise,

$$ x_i(t) \;=\; f_i\!\big(\, \mathrm{pa}(x_i)_{\,t-\tau}\,,\ \varepsilon_i(t)\,\big), \qquad \tau \ge 1, $$

so that an intervention on a parent propagates to its children but not the reverse. The time lag \(\tau\) is a gift unique to sensor streams: causes precede effects, so temporal precedence breaks many of the symmetries that make causal discovery hard in static tabular data.

Discovering the graph: from Granger to PCMCI

The oldest operational tool is Granger causality: series \(A\) Granger-causes \(B\) if past values of \(A\) improve the prediction of \(B\) beyond \(B\)'s own past. It is a predictive, not interventional, notion, and it fails badly under hidden common drivers and instantaneous coupling, but for a first directed skeleton it is cheap and often enough. The modern constraint-based replacement is PCMCI and its successor PCMCI+ (Runge et al., Science Advances 2019; UAI 2020), built on conditional-independence testing across time lags. PCMCI runs in two stages: a condition-selection stage (a PC-style search) prunes each variable's candidate parents, then the momentary conditional-independence test controls false positives by conditioning on those parents, which is what tames the high autocorrelation typical of sensor data. The output is a time-lagged graph with an edge \(A_{t-\tau} \to B_t\) for each surviving dependency and an estimated lag.

Three design choices decide whether the discovered graph is trustworthy. First, the independence test must match the physics: partial correlation for near-linear couplings, a kernel or nearest-neighbor test (for example CMIknn) for the nonlinear valves and saturating actuators common in machinery. Second, inject known structure. You usually know the piping-and-instrumentation diagram, the network topology, or the mechanical adjacency; forbidding physically impossible edges and fixing known ones shrinks the search space and kills spurious links. Third, respect leakage discipline (Chapter 65): discover structure on healthy, pre-fault data only, then hold that graph fixed when a live anomaly arrives, or you will "discover" edges that are really the fault propagating.

Key Insight

Separate the two jobs cleanly. Structure discovery is a slow, offline, careful process that answers "how does this system normally couple?" and should run on curated healthy data with every physical prior you have. Root-cause localization is a fast, online process that takes the fixed graph plus a fresh anomaly and answers "where did this event begin?" Teams that conflate the two, re-running discovery on the anomalous window itself, get a graph dominated by the fault's own propagation and mistake the loudest symptom for the cause. Discover on calm water; navigate during the storm.

Walking the graph to the origin

Given the fixed graph and a set of anomaly scores (one per node, from any detector in Chapter 37), localization ranks nodes by how likely each is the origin. The workhorse family is the anomaly-aware random walk, popularized by MonitorRank and RCA systems such as CloudRanger and MicroRCA. Intuition: start a random surfer at the alarming node and let it walk backward along causal edges, biased toward neighbors that are themselves anomalous. Nodes where the walk spends the most time are the probable roots, because causal ancestors of a real fault are anomalous and sit upstream. This is a personalized-PageRank computation over a transition matrix that blends graph topology with the anomaly signal. A second family is regression-based counterfactual scoring, exemplified by CIRCA (Li et al., KDD 2022): for each node, model it from its parents on healthy data, then at anomaly time measure how far the node deviates from what its parents predict; a large residual means the fault entered here rather than being inherited from upstream. RCD (Ikram et al., NeurIPS 2022) instead frames localization as hierarchical interventional discovery on the anomalous distribution. All three beat "rank by raw anomaly magnitude," because magnitude alone always crowns the symptom.

The code below implements the random-walk localizer end to end on a tiny four-sensor loop: a causal adjacency, per-node anomaly scores, a backward-biased transition matrix, and the stationary distribution that ranks candidate roots.

import numpy as np

# Nodes: 0=pump_current, 1=coolant_pressure, 2=flow_rate, 3=bearing_temp
# Causal edges A->B mean "A drives B" (discovered offline on healthy data)
edges = [(0, 1), (1, 2), (2, 3), (0, 3)]         # pump drives pressure -> flow -> temp
n = 4
A = np.zeros((n, n))
for a, b in edges:
    A[a, b] = 1.0                                 # forward causal adjacency

anom = np.array([0.9, 0.4, 0.3, 0.95])            # detector scores; temp (3) alarms loudest

# Walk BACKWARD along causes, biased toward anomalous upstream neighbors.
back = A.T.copy()                                 # child -> parent transitions
back *= anom[np.newaxis, :]                        # prefer stepping to anomalous parents
rowsum = back.sum(axis=1, keepdims=True)
back = np.divide(back, rowsum, out=np.zeros_like(back), where=rowsum > 0)

c = 0.15                                           # restart prob -> personalized PageRank
restart = anom / anom.sum()                        # restart onto anomalous nodes
r = restart.copy()
for _ in range(200):
    r = c * restart + (1 - c) * back.T @ r         # power iteration to stationary rank

for i in np.argsort(-r):
    print(f"node {i}: root-cause score {r[i]:.3f}  (anomaly {anom[i]:.2f})")
A minimal anomaly-aware random-walk root-cause localizer. The transition matrix walks from effects back to causes (A.T), weighted by each neighbor's anomaly score, and the personalized-PageRank restart re-seeds on anomalous nodes. Node 0 (pump current) should outrank node 3 (bearing temperature) despite temperature having the higher raw anomaly, because the walk keeps flowing upstream to the origin.

Run it and the pump current wins even though the temperature channel screamed louder: that inversion of raw anomaly ranking is the entire point of walking the graph instead of reading a heatmap.

Practical Example: the data-center cooling loop that blamed the wrong rack

An operator ran multivariate anomaly detection across a liquid-cooling loop serving a GPU hall: coolant-distribution-unit pump speed, supply and return coolant temperatures, per-rack inlet temperatures, and flow meters. A thermal-throttle alert fired on rack R-19's inlet temperature, the single loudest anomaly, and the first instinct was to inspect R-19. A root-cause graph discovered with PCMCI+ on a month of healthy telemetry, with the physical loop topology injected as forbidden and required edges, told a different story. The backward random walk placed most of its mass on the CDU pump-speed node, whose current had sagged eleven seconds before any rack warmed. A clogged strainer had cut flow across the whole loop; R-19 simply ran hottest by position. Replacing raw-magnitude ranking with graph localization pointed the technician at the strainer, not the innocent rack, and the counterfactual residual on the pump node (its speed far below what its control setpoint predicted) confirmed the fault entered there. The same discipline generalizes to cyber-physical intrusion tracing in Chapter 38, where you localize which compromised actuator seeded a cascade.

Library Shortcut

Hand-rolling PCMCI (the lagged conditional-independence search, the momentary-independence correction, per-test multiple-comparison control, and lag bookkeeping) is roughly 400 lines and easy to get subtly wrong. tigramite reduces it to about a dozen: wrap your array in a DataFrame, pick a conditional-independence test (ParCorr, GPDC, or CMIknn), and call PCMCIplus.run_pcmciplus(), which returns the lagged graph with p-values and link strengths, plotting utilities included. For the discovery of the skeleton on non-temporal or mixed data, causal-learn offers PC, FCI, and GES out of the box. Keep the random-walk localizer above hand-written (it is fifteen lines and you want control over the anomaly weighting); let the library own the statistically delicate structure discovery.

What a graph edge does and does not promise

A discovered edge is a claim conditioned on the variables you measured. Its three classic failure modes deserve naming so you distrust them on sight. Hidden confounders: an unmeasured driver (ambient temperature, supply voltage) makes two effects covary, and constraint-based search paints a spurious direct edge between them; only sensors you record can be parents, so instrument the plausible confounders or expect ghost edges. Instantaneous coupling: when the true lag is faster than your sampling interval, cause and effect land in the same sample and the precedence trick fails, which is why PCMCI+ adds explicit contemporaneous-link handling and why Chapter 3's sampling and synchronization discipline is a prerequisite, not a nicety: unsynchronized clocks manufacture false lags and reverse arrows. Non-stationarity: the coupling itself changes with operating regime, so a graph learned at idle misroutes at full load; discover per-regime or condition the tests on the regime label. Report edges with their independence-test p-values and lags, and treat the graph as a falsifiable hypothesis a domain expert signs off on, closer in spirit to the factor graphs of Chapter 11 than to a black box.

Research Frontier

Root-cause localization for time series is consolidating fast. On discovery, PCMCI+ (Runge, UAI 2020) and LPCMCI extend to contemporaneous and latent-confounded links, while differentiable structure learning (NOTEARS and dynamic DYNOTEARS, Pamfil et al., AISTATS 2020) casts the DAG search as continuous optimization that scales to hundreds of sensors. On localization, CIRCA (Li et al., KDD 2022) formalizes counterfactual regression scoring, RCD (Ikram et al., NeurIPS 2022) does hierarchical interventional discovery on the anomalous distribution, and BARO (Pham et al., FSE 2024) pairs robust Bayesian change detection with random-walk ranking. The live frontier is LLM-assisted root-cause reasoning, where an agent (Chapter 22) proposes edges from documentation and runbooks and a causal-discovery pass verifies them against telemetry, blending prior knowledge with data instead of choosing one. Faithfulness benchmarking of these localizers (Section 67.7) is still immature, so validate on injected-fault datasets where ground-truth roots are known.

Exercise

Take a multivariate industrial dataset with labeled fault origins (for example the Tennessee Eastman process or SWaT). (1) Split off the fault-free periods and discover a lagged graph with tigramite PCMCI+ under both ParCorr and CMIknn; compare how many edges each keeps and explain the difference in terms of nonlinearity. (2) Inject the process topology as forbidden and required edges and report how the discovered graph and its false-edge count change. (3) On held-out fault windows, run the random-walk localizer from this section and CIRCA-style residual scoring; report top-1 and top-3 root-cause accuracy against the labels, and give one fault where raw anomaly magnitude alone would have named the wrong node.

Self-Check

  1. Why does ranking nodes by raw anomaly magnitude systematically favor symptoms over causes, and how does a backward random walk correct this?
  2. You re-run causal discovery on the anomalous window to "get the most relevant graph." What error does this introduce, and what should you have done instead?
  3. Name two conditions under which a discovered edge \(A \to B\) does not license the interventional claim "changing \(A\) changes \(B\)," and say which measurement or sampling fix mitigates each.

What's Next

In Section 67.6, we put a human in the loop: TSInterpret and Captum give reviewers the tooling to inspect attributions, counterfactuals, prototypes, and the root-cause graphs of this section side by side, so an explanation becomes something an operator can interrogate, correct, and act on rather than merely read.