Residual-correlation causal screening with iterative peeling, localized modeling, and drift early-warning
Project description
causalscreen
Residual-correlation causal screening with iterative peeling, causal-factor partitioning with inference-time local models, and a missing-causal-power drift alarm.
Companion code for: R. K. Mandal, "Residual-Correlation Causal Screening with
Localized Supervised Modeling: A Practical Framework for Confounder
Identification, Error Reduction, and Drift Early-Warning" (working paper,
2026; research 2022–present). Paper PDF in /paper · Preprint: https://papers.ssrn.com/sol3/papers.cfm?abstract_id=7135078
What it does
Supervised models fail in deployment because they lean on confounded
proxies — features whose correlation with the target is inherited from other
variables. causalscreen:
- Screens every candidate feature via the two-regression residual
construction (Frisch–Waugh–Lovell partial correlation): regress
yon the other features, regressx_jon the other features, correlate the residuals. High residual correlation = genuine independent effect. - Peels iteratively: each discovered factor's contribution is stripped out of the response before the next round, so its influence cannot re-enter the screen through the variables it confounds.
- Ranks features by causal power and reports the missing causal power — the share of response variance the discovered factors cannot explain — a deployable early-warning statistic for data/model drift.
- Exploits the ranking:
PartitionedRegressorpartitions data on top causal factors and trains one small local model per query at inference time (interpolation), falling back to the global model out of support (extrapolation) — so the error reduction of local modeling never costs out-of-sample generalization.
Quick result (synthetic ground truth, examples/demo.py)
| feature | naive |corr| with y | causal screen verdict |
|---|---|---|
| x1 (true cause) | 0.92 | ranked (power 0.78) |
| x2 (confounded proxy of x1) | 0.87 | rejected |
| x3 (noise) | 0.01 | rejected |
| x4 (true cause, weak) | 0.33 | ranked (power 0.83) |
Missing causal power: 5.1% — the exact noise floor of the generating process. Partitioned local modeling: 99.0% out-of-sample MSE reduction vs. a global model on regime-structured data.
Install & use
pip install -e .
python examples/demo.py
pytest tests/
from causalscreen import CausalScreen, PartitionedRegressor
res = CausalScreen(alpha=0.05).fit(X, y, feature_names)
res.ranking # features in decreasing causal power
res.causal_power # partial correlation at selection round
res.missing_causal_power # drift-alarm statistic
pr = PartitionedRegressor(partition_features=res.ranking[:2], min_cell=50)
pr.fit(X, y, feature_names)
pr.predict(X_new) # local model in-support, global model out-of-support
Assumptions (stated plainly)
Stationary cross-sectional data · causal sufficiency (all relevant variables observed) · no reverse causation · features measured before the response. The screen addresses the confounding component of causal analysis; it does not prove causality in full generality. See paper §3, §7.
Deployed results
Layered over Random Forest, OLS and Prophet models in commercial deployments (credit risk, segmentation, forecasting), the framework reduced out-of-sample error by 65–85%. Client data is not releasable; this repo's synthetic benchmarks are the reproducible counterpart. DoWhy/EconML comparison suite: in progress.
Performance (v0.2.0)
Screening uses a single precision-matrix inversion per round (FWL-equivalent,
with an exact residual-regression fallback for ill-conditioned designs) —
~77x faster than the reference implementation at n=5000, p=40. Partitioned
prediction indexes cells at fit time and caches local models — ~409x faster
on batch prediction (20k train / 5k queries). Equivalence to the reference
implementation is enforced in the test suite to ~1e-8 (38 tests; reference
implementation vendored in tests/).
License
MIT
Pipeline
flowchart LR
A[Training data] --> B["CausalScreen<br/>residual-correlation test<br/>+ iterative peeling"]
B -->|"ranked causal factors<br/>(decreasing causal power)"| C["Partition data on<br/>top causal factors<br/>(strength x significance rule)"]
C --> G1[(Subgroup 1)]
C --> G2[(Subgroup 2)]
C --> Gn[(Subgroup n)]
Q[Query point] --> R{inside a<br/>subgroup?}
R -->|"yes (interpolation)"| L["Train ONE local model<br/>in that subgroup only<br/>(Optimisation 2)"]
R -->|"no (extrapolation)"| F["Global model fallback<br/>(retains significance &<br/>generalization)"]
G1 -.-> L
G2 -.-> L
Gn -.-> L
B --> M["Missing causal power<br/>= drift early-warning alarm"]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file causalscreen-0.2.0.tar.gz.
File metadata
- Download URL: causalscreen-0.2.0.tar.gz
- Upload date:
- Size: 13.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f4bc39a449031aa2348b028e16c8d2c05ad53aa4d96cdd26b4d16d8bbcfff73
|
|
| MD5 |
8966b64b8e438612c5d48d9be28a2e3a
|
|
| BLAKE2b-256 |
c20a07d44aa54985aae986838d80e699670477c40a440ee5e0f1add44a872f71
|
File details
Details for the file causalscreen-0.2.0-py3-none-any.whl.
File metadata
- Download URL: causalscreen-0.2.0-py3-none-any.whl
- Upload date:
- Size: 9.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93a16b280731e4536cbb317334d72fec3e554574ca345b0d1cae4909020c1a39
|
|
| MD5 |
016a1b3201f5cc5bee2463693e34fc57
|
|
| BLAKE2b-256 |
b29f121c34e07ff7f8f327980fe6d8f2df5c2cd38b88a2ff3259385aa07010e6
|