Views
No views yet
X (N, D), it predicts the causal graph G (D, D) in a single forward pass.
model.predict(data) call.pip install cdfm-basetorch>=2.0, numpy>=1.20, safetensors, networkx, huggingface_hub.1from cdfm import CDFM
2from cdfm.utils import evaluate_graph, edge_auroc
3import numpy as np
4
5# Load from HuggingFace Hub
6model = CDFM.from_pretrained("DMIRLAB/CDFM")
7
8# Load a simple 4-variable nonlinear example (RFF mechanisms)
9data = np.loadtxt("tests/data/simple/data.csv", delimiter=",")
10gt = np.loadtxt("tests/data/simple/adjacency.csv", delimiter=",").astype(np.int32)
11
12# 1. Standard Prediction (Auto-calibrated threshold)
13result = model.predict(data)
14# 2. Manual Threshold Control
15result_manual = model.predict(data, threshold=0.5)
16
17print(result.adjacency) # (D, D) binary causal graph
18metrics = evaluate_graph(result.adjacency, gt)
19auc = edge_auroc(result.logits, gt)
20
21print(f"F1={metrics['f1']:.4f} SHD={metrics['shd']} AUC={auc:.4f}")
22# → F1=1.0000 SHD=0 AUC=1.0000model.imputation(data) to fill missing values automatically:1from cdfm import CDFM
2import numpy as np
3
4model = CDFM.from_pretrained("DMIRLAB/CDFM")
5
6# Load data and create missing values (seed for reproducibility)
7rng = np.random.default_rng(42)
8data = np.loadtxt("tests/data/simple/data.csv", delimiter=",")
9data_with_nan = data.copy()
10data_with_nan[rng.random(data.shape) < 0.2] = np.nan
11
12# CDFM imputation — auto-detects NaN
13imputed = model.imputation(data_with_nan)
14
15# Compare with mean imputation
16mean_imp = data_with_nan.copy()
17for j in range(data.shape[1]):
18 col = data_with_nan[~np.isnan(data_with_nan[:, j]), j]
19 mean_imp[np.isnan(mean_imp[:, j]), j] = col.mean()
20
21missing = np.isnan(data_with_nan)
22mae_cdfm = np.abs(imputed[missing] - data[missing]).mean()
23mae_mean = np.abs(mean_imp[missing] - data[missing]).mean()
24print(f"CDFM MAE: {mae_cdfm:.4f} | Mean MAE: {mae_mean:.4f}")
25# → CDFM MAE: 0.3719 | Mean MAE: 0.7817CDFM Class1class CDFM:
2 @classmethod
3 def from_pretrained(
4 cls,
5 pretrained_model_name_or_path: str = "DMIRLAB/CDFM", # HF Hub or local path
6 device: str = "auto", # auto / cpu / cuda:N
7 threshold: float | None = None, # None = auto-calibrate
8 ) -> "CDFM"
9
10 def predict(
11 self,
12 data: np.ndarray, # (N, D) float32
13 threshold: float | None = None, # Probability threshold
14 standardize: bool = True, # Apply z-score standardization
15 missing_mask: np.ndarray | None = None,
16 ) -> CDFMResultCDFMResult Object1@dataclass
2class CDFMResult:
3 logits: np.ndarray # (D, D) raw edge scores
4 probabilities: np.ndarray # (D, D) sigmoid(logits)
5 adjacency: np.ndarray | None # (D, D) binary graph
6 threshold: float | None # Threshold value used
7 runtime_sec: float # Wall-clock time1@article{qiao2026cdfm,
2 title = {{CDFM}: Towards a General-Purpose Causal Discovery Foundation Model},
3 author = {Jie Qiao and Ruichu Cai and Zijian Li and Weilin Chen and
4 Pengfei Hua and Boyan Xu and Zhengming Chen and Zhifeng Hao and
5 Peng Cui},
6 journal = {arXiv preprint arXiv:2607.11508},
7 year = {2026},
8}