guides.scores
Per-observation scores & the effect-modifier scan
flow.scores(df, node) returns each observation's score ψᵢ = ∂ℓᵢ/∂θ for the
node's interpretable shift coefficients — every LS weight (one column per
continuous parent, one per one-hot level for an ordinal parent) and every VC
term's beta0 (column named after the treatment). The computation is
analytic and exact (no autograd): shifts enter the latent additively, so
∂ℓᵢ/∂β = (∂ℓᵢ/∂sᵢ)·xᵢ with ∂ℓᵢ/∂s in closed form (src/tramdag/scores.py).
Pure read-out — no fitting or sampling code path is touched. At a fitted MLE
the per-column sums are ≈ 0 (pinned by tests, incl. a float64
finite-difference check).
Worked example: where does β(x) need to bend?
The score is the cheapest effect-modifier detector there is (model-based
recursive partitioning / structural-change logic — Zeileis & Hornik; Dandl et
al. 2024). Before fitting anything expensive: fit the cheap all-LS model
(seconds, deterministic), and scan the treatment-coefficient scores —
flow = td.CausalFlowDAG(all_ls_spec, seed=0)
flow.fit_classical(df) # seconds, exact MLE
scan = flow.effect_modifier_scan(df, node="Y", on="T")
# stat p_value crit_5pct flag
# X2 4.21 <0.001 1.3581 True <- true modifier
# X3 3.05 <0.001 1.3581 True <- true modifier
# X1 0.74 0.64 1.3581 False <- prognostic only
For each candidate covariate the scores are ordered by it and the scaled
cumulative sum B_j = Σ_{i≤j} ψ_(i) / (sd(ψ)·√n) is formed; under a stable
coefficient B is a Brownian bridge, so sup|B| has the Kolmogorov
distribution (5% critical value 1.358). A coefficient that truly varies with
the covariate makes the ordered scores drift — flagged covariates are the
measured shortlist of VC modifiers (docs/varying-coefficients.md):
spec["Y"] = td.ContinuousNode(
terms=[td.CS("X1", "X2", "X3"), td.VC("T", "X2", "X3")]
) # scan-informed
Notes: on resolves to the identified level-1-vs-0 contrast for a binary
ordinal LS treatment and to beta0 for a VC treatment. Candidates default
to every column of df except the node and on — modifiers need not be
parents. For few-level (heavily tied) candidates the ordering is only partial:
read the scan as a ranking diagnostic rather than an exact-size test. Scores
also enable influence-function analyses and robust standard errors later.
1""".. include:: ../../../docs/scores.md"""