Skip to content

baksho/DAGnostics

Repository files navigation

When Do Continuous-Optimization DAG Learners Actually Work?

An audit of NOTEARS and DAGMA through the lens of varsortability, plus a directed↔undirected (Bayesian-network ↔ Markov-network) bridge on real protein- signaling data.

About

Continuous-optimization structure learners such as NOTEARS (Zheng et al., 2018) and DAGMA (Bello et al., 2022) post strong numbers on simulated DAG benchmarks. Reisach et al. (2021) showed that much of that success can be an artifact called varsortability: in generically parameterized structural equation models, marginal variance grows along the causal order, so the order leaks through the variances and a trivial variance-sorting baseline can match the sophisticated methods.

This project reproduces that effect in a clean, uniform harness, pushes past the usual "just standardize the data" takeaway using the scale-invariant R²-sortability, and then turns the same machinery on the real Sachs protein-signaling benchmark — where it also compares a directed model against an undirected Gaussian Markov network learned on the identical data. The reimplementation of prior methods is deliberately not the contribution; the audit harness, the residual-structure analysis, and the directed↔undirected bridge are. See docs/design.md for the full rationale and limitations.

Key results

All numbers come from the scripts in src/dag_audit/experiments/ on the committed configuration. Seed counts are small for fast reproduction, so treat these as illustrative and expect run-to-run variation.

1. Learner "skill" tracks varsortability. Across data spanning varsortability 0.12 → 1.00, the trivial sortnregress baseline's F1 correlates with varsortability at Pearson r ≈ 0.96 — it is essentially a varsortability meter — and at high varsortability it is competitive with, and often ahead of, NOTEARS and DAGMA. High benchmark scores alone do not demonstrate discovery ability.

Varsortability sweep

2. Standardization removes the signal. On high-varsortability data (≈0.92), standardizing every variable to unit variance drives varsortability to ≈0.50 and collapses every method's F1 — the trivial baseline most of all.

Standardization collapse

3. But "just standardize" is too glib. Standardization removes varsortability (→0.50) but not the scale-invariant R²-sortability (stays ≈0.68), and the learners keep an above-baseline edge on standardized data. The honest lesson is to report scale-invariant structure, not to assume standardization makes a benchmark safe.

What survives standardization

4. Real biology behaves as the thesis predicts. On Sachs, varsortability is only ≈0.36 — the synthetic crutch is absent — and the learners recover the 17-edge consensus network poorly, matching the published literature:

Method SHD F1 Precision Recall
NOTEARS 21 0.21 0.27 0.18
DAGMA 18 0.28 0.33 0.24
sortnregress 39 0.25 0.17 0.47

5. Directed vs. undirected on the same data. Moralizing the learned NOTEARS DAG yields ≈10 undirected edges, while a graphical-lasso Markov network fit to the same data has ≈35, overlapping only modestly (Jaccard ≈0.25). The undirected model asserts many conditional dependencies the sparse DAG does not — a concrete view of the Bayesian-network ↔ Markov-network representation gap on correlated biological data.

Getting Started

Prerequisites

  • Python >= 3.10

Installation

git clone https://github.com/baksho/dag-discovery-audit.git
cd dag-discovery-audit
pip install -e .

This installs the dag_audit package and its dependencies (numpy, scipy, scikit-learn, networkx, matplotlib, and the official dagma package).

Reproduce the synthetic experiments

No external data is required for experiments 1–3:

python scripts/run_all.py

Results (JSON) are written to results/ and figures to results/figures/.

Reproduce the Sachs experiment

Experiment 4 needs the Sachs dataset. Fetch the CC BY 4.0 mirror on first use:

SACHS_DOWNLOAD=1 python -m dag_audit.experiments.exp4_sachs_bn_mn

The canonical origin of the data is the bnlearn distribution (https://www.bnlearn.com/research/sachs05/); see src/dag_audit/data/sachs.py for provenance, the consensus-graph choice, and the observational-subset caveat.

Usage

Everything is a plain function. A minimal end-to-end example:

from dag_audit.data import simulate_linear_sem, standardize
from dag_audit.methods import default_learners
from dag_audit.metrics import varsortability, structural_scores

ds = simulate_linear_sem(d=15, noise_scale_strategy="increasing", seed=0)
print("varsortability:", varsortability(ds.X, ds.W_true))

learn = default_learners()["NOTEARS"]
W_est = learn(ds.X)
print("F1 vs truth:", structural_scores(W_est, ds.B_true).f1)

The directed↔undirected bridge:

from dag_audit.methods import graphical_lasso_graph, moralize, compare_moral_vs_ggm

W_dag = default_learners()["NOTEARS"](ds.X)
A_ggm = graphical_lasso_graph(ds.X)
print(compare_moral_vs_ggm(W_dag, A_ggm).as_dict())

Project Structure

src/dag_audit/
  data/        synthetic linear SEMs, the Sachs loader, and the optional GRN simulator
  methods/     from-scratch NOTEARS, a DAGMA wrapper, baselines, and the undirected/bridge tools
  metrics/     varsortability, R2-sortability, and structure-recovery metrics
  experiments/ the four runnable experiments described above
scripts/       run_all.py
tests/         pytest suite for the metrics, NOTEARS, and moralization
docs/          design.md — rationale, results, and limitations

Testing

pip install -e ".[dev]"
pytest

The suite checks varsortability on hand-built and generated cases, that the from-scratch NOTEARS returns an acyclic graph and recovers a known chain, SHD behavior on reversed/perfect graphs, and that moralization marries parents of a v-structure.

Scope and honesty

  • The varsortability effect and its reference code (Reisach et al., 2021) predate this work and are reproduced, not claimed as novel. The audit harness, the R²-sortability analysis, and the directed↔undirected bridge are the contributions.
  • Hyperparameters are fixed, not tuned per instance; read the varsortability dependence, not the exact F1 gaps, as the finding.
  • The committed Sachs run pools all experimental conditions; the observational subset is the principled choice and a one-line change.
  • The Sachs consensus graph is a contested proxy, and its edge count is reported inconsistently (17/18/20) in the literature. This repo fixes the 17-edge version and documents it.

Full detail in docs/design.md.

References

  • Zheng, X., Aragam, B., Ravikumar, P., & Xing, E. P. (2018). DAGs with NO TEARS. NeurIPS. arXiv:1803.01422.
  • Bello, K., Aragam, B., & Ravikumar, P. (2022). DAGMA. NeurIPS. arXiv:2209.08037.
  • Reisach, A. G., Seiler, C., & Weichwald, S. (2021). Beware of the Simulated DAG! NeurIPS. arXiv:2102.13647.
  • Reisach, A. G., Tami, M., Seiler, C., Chambaz, A., & Weichwald, S. (2023). A Scale-Invariant Sorting Criterion. NeurIPS. arXiv:2303.18211.
  • Sachs, K., Perez, O., Pe'er, D., Lauffenburger, D. A., & Nolan, G. P. (2005). Science, 308(5721), 523–529.

License

MIT — see LICENSE.

About

Auditing continuous-optimization DAG learners (NOTEARS, DAGMA): when high benchmark scores are really varsortability, what survives standardization, and a directed↔undirected bridge on real protein-signaling data.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages