try:
from sklearn.datasets import make_classification
from sklearn.ensemble import GradientBoostingClassifier
except ImportError:
print("sklearn and numpy are required: pip install scikit-learn numpy")
raise SystemExit(1)
from causasv import ASVExplainer, CausalDAG
X, y = make_classification(n_samples=500, n_features=3, n_informative=3,
n_redundant=0, random_state=0)
feature_names = ["education", "income", "risk_score"]
model = GradientBoostingClassifier(n_estimators=50, random_state=0)
model.fit(X, y)
x_instance = X[0]
background_means = X.mean(axis=0)
dag = CausalDAG.from_edges([("education", "income"), ("income", "risk_score")])
def make_value_fn(model, x, background, names):
name_to_idx = {n: i for i, n in enumerate(names)}
def value_fn(coalition: list[str]) -> float:
row = background.copy()
for name in coalition:
row[name_to_idx[name]] = x[name_to_idx[name]]
return float(model.predict_proba(row.reshape(1, -1))[0, 1])
return value_fn
value_fn = make_value_fn(model, x_instance, background_means, feature_names)
explainer = ASVExplainer(dag)
info = explainer.explain_with_diagnostics(
value_fn=value_fn,
method="exact",
n_samples=0,
)
print("=== ASV attributions (education -> income -> risk_score) ===")
for name, val in sorted(info["values"].items()):
print(f" {name:<15} {val:+.4f}")
print(f"\nv(all) - v(empty) = {value_fn(feature_names) - value_fn([]):.4f}")
print(f"Sum of ASV = {sum(info['values'].values()):.4f} (efficiency axiom)")
print(f"Exact: {info['is_exact']}")