Du graphe causal au do-calculus — le pont entre les quatre séries causales
Notebook-pont de la constellation causale du dépôt (règle F : dowhy installé et exécuté réellement, SOTA-OK). Il ne remplace pas les notebooks dédiés de chaque moteur : il donne l’armature formelle unifiée (échelle de Pearl + trois règles du do-calculus) et la fait tourner sur l’outil de référencedowhy, avant de renvoyer à chaque série pour l’instanciation par moteur.
La causalité est traitée à quatre endroits du dépôt, chacun avec son moteur et son angle :
Ce que ce pont ajoute, que les quatre notebooks ne font pas chacun séparément : (1) la théorie unifiée du do-calculus présentée une bonne fois ; (2) une exécution sur l’outil SOTAdowhy qui identifie l’estimande (backdoor/front-door/IV), estime puis réfute ; (3) la mise en regard des deux grands paradigmes — l’interventionnisme de Pearl et l’émergence causale de Hoel. (4) l’ouverture sur la cinquième modalité — le raisonnement causal d’un LLM à partir des seules métadonnées et connaissances (§9).
Objectifs d’apprentissage
À l’issue de ce notebook vous saurez :
Situer chaque série causale du dépôt sur l’échelle de Pearl (observation / intervention / contrefactuel).
Énoncer les trois règles du do-calculus et les lire comme des chirurgies du graphe causal.
Reconnaître les critères backdoor et front-door, et les exécuter avec dowhy sur des données simulées à effet connu.
Distinguer la causalité interventionniste (Pearl) de l’émergence causale (Hoel / information effective) — deux réponses différentes à la question « quelle échelle cause ? ».
Classer les quatre tâches prototypiques du data-fusion (confondage observationnel, régiment expérimental, biais de sélection, transportabilité) et corriger sélection et transport par pondération inverse.
Démontrer la cécité de la couche L1 : deux SCM gaussiens à loi jointe identique et conclusions interventionnelles opposées — le Causal Hierarchy Theorem rendu machine.
Relier le do-calculus aux attributions de Shapley : choisir une baseline d’attribution, c’est choisir un estimand causal (voir/intervenir).
Prérequis : probabilités conditionnelles, graphes orientés acycliques (DAG), notions d’inférence bayésienne. Une lecture préalable de l’un des quatre notebooks ci-dessus rend le pont plus concret.
1. L’échelle de Pearl — trois niveaux de causalité
Judea Pearl structure la causalité en trois échelons croissants, chacun subsumant le précédent :
Niveau
Question type
Symbole
Opération
1. Association
Que vois-je ?
\(P(y \mid x)\)
observer
2. Intervention
Que se passe-t-il si je fais \(x\) ?
\(P(y \mid do(x))\)
agir
3. Contrefactuel
Que se serait-il passé si j’avais fait \(x'\) ?
\(P(y_x \mid x', y')\)
imaginer
Le saut du niveau 1 au niveau 2 est le cœur du do-calculus : \(P(y \mid x)\) (ce qu’on observe dans les données) diffère en général de \(P(y \mid do(x))\) (l’effet d’une intervention), précisément à cause des chemins confondants que le do-calculus permet de neutraliser. Les quatre notebooks de la constellation couvrent les trois niveaux depuis l’angle de leur moteur ; nous récapitulons ici le formalisme partagé.
2. Les trois règles du do-calculus
Soit \(G\) un graphe causal, \(G_{\overline{Z}}\) (resp. \(G_{\underline{Z}}\)) le graphe où l’on coupe les arêtes entrant dans (resp. sortant de) \(Z\). Les trois règles de Pearl permettent de transformer toute expression avec \(do(\cdot)\) en expression sans \(do(\cdot)\) lorsque c’est possible :
Règle 1 (insertion/suppression d’observations).\(P(y \mid do(x), z, w) = P(y \mid do(x), w)\) si \((Y \perp\!\!\!\perp Z \mid X, W)_{G_{\overline{X}}}\).
Règle 3 (insertion/suppression d’actions).\(P(y \mid do(x), do(z), w) = P(y \mid do(x), w)\) si \((Y \perp\!\!\!\perp Z \mid X, W)_{G_{\overline{X}\overline{Z(W)}}}\).
Intuition unifiée : chaque règle est une chirurgie du graphe suivie d’un test de \(d\)-séparation. Si deux variables sont indépendantes conditionnellement dans le graphe mutilé approprié, on peut réécrire la probabilité. Le critère backdoor (§4) et le critère front-door (§5) sont les cas spéciaux les plus utiles qui en découlent directement.
3. Configuration — l’outil de référence dowhy
Nous utilisons dowhy (écosystème PyWhy), la librairie de référence pour l’inférence causale. Elle poursuit le pipeline en quatre étapes qui structurent toute analyse causale sérieuse :
Modèle — on fournit les données et le graphe causal (hypothèses expertes) ;
Identification — dowhy lit le graphe et détermine quel estimande est calculable (backdoor, front-door, variable instrumentale) ;
Estimation — on choisit un estimateur (régression, appariement, pondération inverse) ;
Réfutation — on stress-teste l’estimation (placebo, sous-échantillon, proxy) pour vérifier sa robustesse.
C’est précisément la rigueur (identification avant estimation) qui distingue une analyse causale d’une simple régression corrélationnelle.
import warnings# dowhy emet un advisory de modelisation causale ("N variables are assumed") qui fuit le chemin# absolu du fichier source. C'est une information utile (identification causale) -> on la GARDE# visible, mais on retire le prefixe de chemin (anti path-leak #3436).def _warn_no_path(message, category, filename, lineno, file=None, line=None):"""Affiche le warning SANS le chemin absolu du fichier source (anti path-leak #3436)."""returnf"{category.__name__}: {message}\n"warnings.formatwarning = _warn_no_pathimport numpy as npimport pandas as pdimport networkx as nxfrom dowhy import CausalModelimport dowhyprint("dowhy", dowhy.__version__, "| networkx", nx.__version__, "| pandas", pd.__version__)
dowhy 0.14 | networkx 3.6.1 | pandas 3.0.5
4. Le critère backdoor — neutraliser le confondeur observable
Énoncé (Pearl). Un ensemble \(Z\) satisfait le critère backdoor relativement à \((X, Y)\) si :
aucun nœud de \(Z\) n’est un descendant de \(X\) ;
\(Z\)bloque tous les chemins backdoor (chemins entrant dans \(X\) par une arête pointée vers \(X\)) entre \(X\) et \(Y\).
Quand un tel \(Z\) existe et est observable, alors
ce qui ramène l’intervention à un ajustement — règle 2 du do-calculus.
Exemple : aptitude → {études, salaire}
Le facteur d’aptitude\(U\) cause à la fois la décision de faire des études (\(T\)) et le salaire\(Y\). L’effet vrai de \(T\) sur \(Y\) est \(2{,}0\). La simple comparaison des salaires moyens est biaisée car \(U\) ouvre un chemin backdoor \(T \leftarrow U \rightarrow Y\).
Le biais est net : l’effet naïf (~3,49) surévalue largement l’effet vrai (2,0) — l’aptitude ouvre un chemin backdoor\(T \leftarrow U \rightarrow Y\). Pour corriger, il faut indiquer à dowhy la structure causale du problème. Le graphe ci-dessous déclare nos connaissances (\(U \to T\), \(T \to Y\), \(U \to Y\)) ; à partir de lui, dowhy va identifier lui-même l’ensemble des variables à ajuster. C’est l’étape identify, distincte de l’estimation : on ne dit pas comment ajuster, on dit ce que l’on sait du mécanisme, et le moteur en déduit la stratégie d’identification.
Estimand type: EstimandType.NONPARAMETRIC_ATE
### Estimand : 1
Estimand name: backdoor
Estimand expression:
d
──────────(E[earnings|aptitude])
d[college]
Estimand assumption 1, Unconfoundedness: If U→{college} and U→earnings then P(earnings|college,aptitude,U) = P(earnings|college,aptitude)
### Estimand : 2
Estimand name: iv
No such variable(s) found!
### Estimand : 3
Estimand name: frontdoor
No such variable(s) found!
### Estimand : 4
Estimand name: general_adjustment
Estimand expression:
d
──────────(E[earnings|aptitude])
d[college]
Estimand assumption 1, Unconfoundedness: If U→{college} and U→earnings then P(earnings|college,aptitude,U) = P(earnings|college,aptitude)
dowhy a lu le graphe et produit l’estimande : la seule stratégie viable est backdoor en ajustant sur aptitude (les variables instrumentales et la voie front-door sont rejetées — il n’y en a pas dans ce graphe). La forme de l’estimande, \(\frac{d}{d[\text{college}]} E[\text{earnings} \mid \text{aptitude}]\), est la règle 2 du do-calculus matérialisée : l’intervention \(do(\text{college})\) se ramène à un ajustement conditionnel. On estime maintenant l’effet en appliquant cet ajustement (régression linéaire), puis on le soumet à deux réfutations : un placebo (le vrai effet doit disparaître) et un sous-échantillon (l’effet doit rester stable).
estimate_bd = model_bd.estimate_effect(estimand_bd, method_name="backdoor.linear_regression")print(f"Effet estime (dowhy, ajustement backdoor) : {estimate_bd.value:.3f}")print(f"Effet vrai : 2.000")# Réfutation : l'effet résiste-t-il à un placebo et à un sous-échantillon ?refute_placebo = model_bd.refute_estimate(estimand_bd, estimate_bd, method_name="placebo_treatment_refuter")refute_subset = model_bd.refute_estimate(estimand_bd, estimate_bd, method_name="data_subset_refuter")print("\nPlacebo (effet attendu ~0) :", round(refute_placebo.new_effect, 3))print("Sous-echantillon :", round(refute_subset.new_effect, 3))
L’effet naïf (~3,49) surévalue l’effet des études : les diplômés gagnent plus en partie parce qu’ils étaient plus aptes au départ (chemin backdoor).
Une fois ajusté sur l’aptitude (l’ensemble backdoor \(\{U\}\)), dowhy recouvre ~1,98 ≈ effet vrai 2,0 : la chirurgie graphique a neutralisé le confondeur.
Les réfutations confirment la robustesse : l’effet tombe vers 0 sous placebo (un faux traitement ne donne rien) et reste stable sur un sous-échantillon.
5. Le critère front-door — quand le confondeur est inobservable
Que faire si le confondeur est inobservable (génétique, préférences latentes) ? Si l’on dispose d’un médiateur\(M\) captant tout l’effet de \(X\) sur \(Y\), le critère front-door sauve la situation :
\(M\)intercepte tous les chemins dirigés de \(X\) vers \(Y\) ;
il n’existe pas de chemin backdoor de \(X\) vers \(M\) ;
tous les chemins backdoor de \(M\) vers \(Y\) sont bloqués par \(X\).
Exemple : génotype (latent) → tabagisme → goudron → cancer
Un génotype\(U\) (non observé) pousse à la fois au tabagisme\(X\) et au cancer\(Y\). Impossible d’ajuster sur \(U\) : on n’a pas la donnée. Mais le tabagisme n’affecte le cancer qu’à travers le goudron\(M\), qu’on mesure. dowhy doit alors échouer à trouver une backdoor et basculer sur la front-door via le médiateur.
np.random.seed(7)N =20_000genotype = np.random.normal(0, 1, N) # CONFOUNDEUR LATENT (non observé)smoking = (1.0* genotype + np.random.normal(0, 1, N) >0).astype(int)tar =0.9* smoking + np.random.normal(0, 0.5, N)cancer =1.0* tar +0.8* genotype + np.random.normal(0, 1, N)# On n'observe QUE smoking, tar, cancer (le génotype reste caché)df_frontdoor = pd.DataFrame({"smoking": smoking, "tar": tar, "cancer": cancer})
Le génotype\(U\) est latent : il a généré les données mais n’apparaît pas dans le DataFrame. On déclare néanmoins le graphe à dowhyen incluant \(U\) comme nœud — c’est décisif. Sans aucune variable observable pour bloquer le chemin backdoor \(X \leftarrow U \rightarrow Y\), dowhy doit échouer à trouver une backdoor et basculer sur la voie front-door à travers le médiateur tar, que l’on mesure. C’est toute la situation qui motive le critère front-door : un confondeur inobservable, un médiateur mesurable.
Estimand type: EstimandType.NONPARAMETRIC_ATE
### Estimand : 1
Estimand name: backdoor
No such variable(s) found!
### Estimand : 2
Estimand name: iv
No such variable(s) found!
### Estimand : 3
Estimand name: frontdoor
Estimand expression:
⎡ d d ⎤
E⎢──────(cancer)⋅──────────([tar])⎥
⎣d[tar] d[smoking] ⎦
Estimand assumption 1, Full-mediation: tar intercepts (blocks) all directed paths from smoking to c,a,n,c,e,r.
Estimand assumption 2, First-stage-unconfoundedness: If U→{smoking} and U→{tar} then P(tar|smoking,U) = P(tar|smoking)
Estimand assumption 3, Second-stage-unconfoundedness: If U→{tar} and U→cancer then P(cancer|tar, smoking, U) = P(cancer|tar, smoking)
### Estimand : 4
Estimand name: general_adjustment
No such variable(s) found!
Comme prévu, dowhy rejette la backdoor (« No such variable(s) found! » — \(U\) est inobservable) et identifie la front-door via tar. Trois hypothèses sont posées : (1) tarmédie entièrement l’effet smoking \(\to\) cancer ; (2) aucun chemin backdoor de smoking vers tar ; (3) tout chemin backdoor de tar vers cancer est bloqué par smoking. L’estimande devient alors \(E\!\left[\frac{\partial\,\text{cancer}}{\partial\,\text{tar}} \cdot
\frac{\partial\,\text{tar}}{\partial\,\text{smoking}}\right]\). On l’estime par la régression en deux étapes — sans jamais avoir observé le génotype.
estimate_fd = model_fd.estimate_effect(estimand_fd, method_name="frontdoor.two_stage_regression")print(f"Effet estime (front-door, deux etapes) : {estimate_fd.value:.3f}")print(f"Effet vrai via le mediateur : ~0.900 (0.9 * 1.0)")
Effet estime (front-door, deux etapes) : 0.934
Effet vrai via le mediateur : ~0.900 (0.9 * 1.0)
Interprétation
dowhy confirme le raisonnement :
backdoor : « No such variable(s) found! » — \(U\) est latent, aucun ajustement direct possible ;
front-door : l’estimande identifiée passe par le médiateur tar (\(E[\frac{\partial\, cancer}{\partial\, tar} \cdot \frac{\partial\, tar}{\partial\, smoking}]\)) ;
l’estimation (~0,93) recouvre l’effet vrai (~0,9) sans jamais observer le génotype. C’est toute la puissance du front-door : neutraliser un confondeur latent via un médiateur mesurable.
6. Les quatre tâches prototypiques du data-fusion
Le do-calculus ne sert pas seulement à passer de l’observationnel à l’interventionnel sur un jeu de données : Bareinboim & Pearl (Causal inference and the data-fusion problem, PNAS 2016, Fig. 1) encodent chaque design de collecte comme un triplet — population, régime (observationnel vs expérimental), méthode d’échantillonnage — et demandent quelles requêtes causales chaque design permet de répondre. Quatre tâches archétypales :
#
Design
Information disponible
Biais à dompter
1
Observationnel, même population
\(P(v)\)
confondage — neutralisé par backdoor (§4)
2
Expérimental sur \(Z\) (plus accessible que \(X\))
\(P(v \mid do(z))\)
extrapolation d’intervention — le cas instrumental (§5 de CausalBridges-06)
3
Essai randomisé, échantillon non représentatif
\(P(v \mid do(x), S{=}1)\)
sélection — l’essai dit vrai… de son échantillon
4
Source expérimentale ≠ population cible
\(P(v \mid do(x))\) + \(P(v \mid S{=}s)\)
transportabilité — généraliser l’effet à la cible
Les tâches 1-2 sont couvertes par les critères des sections précédentes. Les tâches 3-4 partagent un même mécanisme profond — un tiers variable (\(S\) ou le site) filtre la distribution des modificateurs d’effet — et un même remède : repondérer par la distribution de la population visée.
# Tache 3 : essai randomise sur echantillon non representatif# Monde : Y depend de X (effet heterogene) et de Z ; l'essai randomise X, mais# l'inclusion dans l'essai (S=1) depend de Z -- les forts Z s'enrolent plus.import numpy as nprng6 = np.random.default_rng(7)N6 =400_000sig =lambda z: 1.0/ (1.0+ np.exp(-z))Z6 = rng6.normal(0, 1, N6)X6 = (rng6.uniform(0, 1, N6) <0.5).astype(float) # RCT : X randomiseY6 = (0.8+0.4* Z6) * X6 + rng6.normal(0, 1, N6) # TE(Z) = 0.8 + 0.4 ZS6 = (rng6.uniform(0, 1, N6) < sig(1.8* Z6)).astype(int) # selection sur Zobs6 = S6 ==1te_population =0.8# = 0.8 + 0.4 * E[Z], E[Z] = 0naif6 = Y6[obs6 & (X6 ==1)].mean() - Y6[obs6 & (X6 ==0)].mean()# Correction IPW : reponderer l'echantillon selectionne par 1/P(S=1|Z)w6 =1.0/ sig(1.8* Z6[obs6])Xo, Yo = X6[obs6], Y6[obs6]n1, d1 = (w6 * Yo * (Xo ==1)).sum(), (w6 * (Xo ==1)).sum()n0, d0 = (w6 * Yo * (Xo ==0)).sum(), (w6 * (Xo ==0)).sum()ipw6 = n1 / d1 - n0 / d0print(f"TE population = {te_population:.3f}")print(f"Naif (essai, S=1) = {naif6:+.3f} <- l'essai randomise est BIAS pour la population")print(f"IPW (1/P(S|Z)) = {ipw6:+.3f} <- selection corrigee")print(f"E[Z | S=1] = {Z6[obs6].mean():+.3f} vs E[Z] = {Z6.mean():+.3f} : l'echantillon sur-represente les forts Z")
TE population = 0.800
Naif (essai, S=1) = +1.029 <- l'essai randomise est BIAS pour la population
IPW (1/P(S|Z)) = +0.808 <- selection corrigee
E[Z | S=1] = +0.578 vs E[Z] = +0.001 : l'echantillon sur-represente les forts Z
Lecture — pourquoi un essai randomisé peut être biaisé
Le contraste \(E[Y \mid X{=}1, S{=}1] - E[Y \mid X{=}0, S{=}1]\) est un ATE non biaisé pour l’échantillon (X y est randomisé), mais l’échantillon n’est pas la population : il sur-représente les forts \(Z\) (\(E[Z \mid S{=}1] = +0.58\)), et comme l’effet varie avec Z (\(TE(Z) = 0.8 + 0.4Z\)), l’effet mesuré est l’effet des volontaires, pas celui de la population. C’est le résultat des essais cliniques à recrutement sélectif. La pondération inverse \(1/P(S{=}1 \mid Z)\) reconstitue la population — à condition de connaître (ou d’estimer) la probabilité d’inclusion : en pratique, un modèle de participation.
La sélection ne mord que parce qu’elle corrige un modificateur d’effet. Sans hétérogénéité (\(0.4 \to 0\)), le contraste RCT serait resté 0.8 malgré l’échantillon bancal — retenez la condition, pas seulement la recette.
# Tache 4 : transportabilite -- generaliser un effet source vers une population cibledef site(mu_z, seed, n=400_000): r = np.random.default_rng(seed) Zs = r.normal(mu_z, 1, n) Xs = (r.uniform(0, 1, n) <0.5).astype(float) # RCT local Ys = (0.4+0.3* Zs) * Xs + r.normal(0, 1, n) # TE(Z) = 0.4 + 0.3 Zreturn Zs, Xs, YsZs, Xs, Ys = site(0.0, seed=1) # site source : Z ~ N(0, 1)Zt, Xt, Yt = site(1.2, seed=2) # population cible : Z ~ N(1.2, 1) (verite, non observable en RCT)te_cible_exact =0.4+0.3*1.2# = 0.76te_source = Ys[Xs ==1].mean() - Ys[Xs ==0].mean() # ce que le RCT source rapporte# Transport : TE estime PAR STRATES de Z sur la source, repondere par la# distribution de Z dans la cible (elle, observationnelle : un recensement suffit)K =20bords = np.quantile(np.concatenate([Zs, Zt]), np.linspace(0, 1, K +1))str_s = np.clip(np.digitize(Zs, bords[1:-1]), 0, K -1)str_t = np.clip(np.digitize(Zt, bords[1:-1]), 0, K -1)tes_strates = np.array([Ys[(str_s == k) & (Xs ==1)].mean()- Ys[(str_s == k) & (Xs ==0)].mean() for k inrange(K)])poids_cible = np.array([(str_t == k).mean() for k inrange(K)])te_transporte =float((tes_strates * poids_cible).sum())print(f"TE source (RCT) = {te_source:+.3f} <- vrai pour la source, faux pour la cible")print(f"TE cible (verite) = {te_cible_exact:.3f}")print(f"Transport K=20 = {te_transporte:+.3f} <- RCT source + distribution de Z dans la cible")
TE source (RCT) = +0.396 <- vrai pour la source, faux pour la cible
TE cible (verite) = 0.760
Transport K=20 = +0.750 <- RCT source + distribution de Z dans la cible
Lecture — le RCT local n’est pas un effet universel
Transplanter naïvement le chiffre de la source (+0.396) vers la cible livre la moitié de l’effet réel (0.760) : l’effet dépend de Z et la cible a \(E[Z] = 1.2\). La formule de transport est une moyenne de l’effet stratifié, repondérée par la distribution du modificateur dans la cible — une donnée observationnelle bon marché (recensement, cohortes). Tâche 3 et tâche 4 sont la même pièce vue des deux côtés :
tâche 3 : l’échantillon n’est pas la population → repondérer vers la population ;
tâche 4 : l’essai n’est pas mené dans la population → repondérer vers la cible.
Dans les deux cas, le do-calculus certifie quand la repondération suffit (quels ensembles ajuster pour que l’identification tienne) — l’identification précède l’estimation, même en terrain expérimental.
7. Le Causal Hierarchy Theorem — pourquoi L1 ne devient pas L2 tout seul
L’échelle de Pearl (§1) n’est pas une convention pédagogique : elle est théoriquement étanche. Le Causal Hierarchy Theorem (Bareinboim et al., Causal Artificial Intelligence, 2026, Thm 2.3.1) formalise le fait que la hiérarchie « presque jamais ne s’effondre » : pour presque tout SCM \(\mathcal{M}^*\), il existe un SCM \(\mathcal{M}\) qui génère exactement les mêmes distributions L1 (et même L2) mais contredit \(\mathcal{M}^*\) sur des questions contrefactuelles — et symétriquement, des paires indistinguables en L1 qui divergent dès la première intervention.
La démonstration la plus épurée tient en deux lois gaussiennes. Construisez deux SCM sur \((X, Y)\) :
Les deux produisent la même loi jointe gaussienne (marginales standard, covariance 0.8) — donc le même tableau de données, la même regression, le même \(R^2\) — mais la flèche causale est inversée.
# CHT rendu machine : deux SCM, meme L1, verdicts interventionnels opposesrng7 = np.random.default_rng(42)n7 =400_000XA = rng7.normal(0, 1, n7); YA =0.8* XA + rng7.normal(0, 0.6, n7) # X cause YYB = rng7.normal(0, 1, n7); XB =0.8* YB + rng7.normal(0, 0.6, n7) # Y cause Xprint("Ce que voit un observateur L1 (meme tableau de données, au bruit Monte-Carlo pres) :")print(f" SCM-A : std(X) = {XA.std():.3f}, std(Y) = {YA.std():.3f}, cov(X,Y) = {np.cov(XA, YA)[0,1]:+.3f}")print(f" SCM-B : std(X) = {XB.std():.3f}, std(Y) = {YB.std():.3f}, cov(X,Y) = {np.cov(XB, YB)[0,1]:+.3f}")print(f" regresseur E[Y|X~1] : SCM-A {YA[(XA >0.99) & (XA <1.01)].mean():+.3f} vs SCM-B {YB[(XB >0.99) & (XB <1.01)].mean():+.3f}")print("\nCe que dit do(X=1) (invisible en L1, oppose entre les deux mondes) :")print(f" SCM-A : E[Y | do(X=1)] = {0.8*1.0:+.3f} (X cause Y : l'intervention deplace Y)")print(f" SCM-B : E[Y | do(X=1)] = {YB.mean():+.3f} (X n'a aucun effet sur Y)")# Verification par intervention SIMULEE (pas par theorie) : re-simuler sous do(X=1)eps_do = rng7.normal(0, 1, n7) # bruit de Y, independant de X dans les deux mondesprint(f" re-simulation do(X=1) : SCM-A {np.mean(0.8*1.0+ rng7.normal(0, 0.6, n7)):+.3f}"f" | SCM-B {eps_do.mean():+.3f}")
Ce que voit un observateur L1 (meme tableau de données, au bruit Monte-Carlo pres) :
SCM-A : std(X) = 1.001, std(Y) = 1.002, cov(X,Y) = +0.803
SCM-B : std(X) = 0.999, std(Y) = 0.999, cov(X,Y) = +0.798
regresseur E[Y|X~1] : SCM-A +0.819 vs SCM-B +0.786
Ce que dit do(X=1) (invisible en L1, oppose entre les deux mondes) :
SCM-A : E[Y | do(X=1)] = +0.800 (X cause Y : l'intervention deplace Y)
SCM-B : E[Y | do(X=1)] = +0.002 (X n'a aucun effet sur Y)
re-simulation do(X=1) : SCM-A +0.800 | SCM-B +0.000
Lecture — l’information qui manque n’est pas dans les données
Même covariance, mêmes marginales : aucun algorithme entraîné sur le tableau L1 ne peut départager les deux mondes — l’information n’y est pas, ce n’est pas une question de taille d’échantillon ou de puissance de modèle. C’est la teneur du CHT : monter de L1 à L2 exige une hypothèse causale externe aux données (le graphe, l’ordre causal, une variable instrumentale, un essai). C’est pourquoi :
« laisser les données parler » ne peut pas, en principe, produire une conclusion interventionnelle ;
les régularités apprises en L1 (tout l’apprentissage statistique supervisé) restent aveugles aux régimes — elles prédisent \(P(y \mid x)\), pas \(P(y \mid do(x))\) ;
le do-calculus n’est pas un outillage optionnel au-dessus du machine learning : il est la seule porte entre ce que les données contiennent et ce qu’on demande à un système causal.
Le pont pratique avec le §3 : dowhy exige un graphe en entrée — ce n’est pas un défaut d’ergonomie, c’est le CHT payé d’avance.
8. La jonction XAI ↔︎ Pearl — choisir une baseline d’attribution, c’est choisir un estimand
Les valeurs de Shapley (SHAP) décomposent \(f(x) - \text{baseline}\) en sommant des contributions marginales. Pour un modèle à features corrélées, deux conventions s’affrontent, et le choix est exactement le choix voir vs intervenir :
attribution interventionnelle : la feature est forcée (\(do\)), indépendamment des autres — la baseline est une marginale ; l’attribution de \(A\) mesure son effet causal dans le modèle (c’est l’esprit « interventional SHAP » de Janzing et al. 2020 / Aas et al. 2021, et le mode par défaut de TreeSHAP) ;
attribution conditionnelle : la feature est observée à sa valeur, les autres suivent leur distribution conditionnelle — l’attribution de \(A\) absorbe aussi les corrélations de \(A\) avec le reste : elle mesure une association, pas un effet.
Et ce ne sont que les deux premiers étages de l’échelle d’attribution — la section 8bis monte au troisième (L3 SV contre-factuelles, Def/Thm 6.2.6 de Bareinboim 2026).
Sur un monde linéaire avec confondeur, l’écart entre les deux se calcule au cordeau — et c’est exactement l’écart TV/TE de l’analyse d’équité causale (notebook Causal-Fairness, Epic #16620) :
# La meme quantite sous les deux baselines : effondrement de la jonction sur un monde lineaire# Monde d'embauche minimal : Z (SES) -> A (protege) -> W -> Y ; Z -> W ; Z -> Yrng8 = np.random.default_rng(42)n8 =200_000Z8 = rng8.normal(0, 1, n8)A8 = (rng8.uniform(0, 1, n8) <1.0/ (1.0+ np.exp(-0.9* Z8))).astype(float)W8 =0.5* A8 +0.6* Z8 + rng8.normal(0, 1, n8)Y8 =0.3* A8 +0.4* W8 +0.2* Z8 + rng8.normal(0, 1, n8)# Baseline interventionnelle : A force, bruit ET confondeur ne suivent pas -> effet causalY_do1 =0.3*1.0+0.4* (0.5*1.0+0.6* Z8) +0.2* Z8 + rng8.normal(0, 1, n8)Y_do0 =0.3*0.0+0.4* (0.5*0.0+0.6* Z8) +0.2* Z8 + rng8.normal(0, 1, n8)attr_do =float(Y_do1.mean() - Y_do0.mean())# Baseline conditionnelle : A observe -> le contraste observationnel absorbe la selectionattr_see =float(Y8[A8 ==1].mean() - Y8[A8 ==0].mean())print(f"Attribution interventionnelle (baseline do) : {attr_do:+.4f} = effet causal total (TE)")print(f"Attribution conditionnelle (baseline voir) : {attr_see:+.4f} = variation totale (TV)")print(f"Ecart = {attr_see - attr_do:+.4f} : le chemin spurieux Z -> A, facture a la feature A")print("\nL'attribution 'voir' accuse la feature de corriger le monde ; l'attribution 'do'")print("lui fait porter seulement ce que le modele fait d'elle.")
Attribution interventionnelle (baseline do) : +0.5006 = effet causal total (TE)
Attribution conditionnelle (baseline voir) : +0.8438 = variation totale (TV)
Ecart = +0.3432 : le chemin spurieux Z -> A, facture a la feature A
L'attribution 'voir' accuse la feature de corriger le monde ; l'attribution 'do'
lui fait porter seulement ce que le modele fait d'elle.
Lecture — le grain d’asymétrie d’attribution
L’écart mesuré (≈ +0.34 ici) n’est ni un bug ni un détail d’implémentation : c’est la part d’association que la baseline voir impute à la feature via ses corrélations — le chemin \(Z \to A\) que ni le modèle ni la feature ne « possèdent ». Choisir une convention d’attribution, c’est donc répondre à une question causale :
« combien la prédiction changerait-elle si on forçait cette feature ? » → baseline do (interventionnelle) ;
« combien la prédiction est-elle associée à cette feature, monde corrélé compris ? » → baseline voir (conditionnelle).
SHAP n’est pas la causalité — mais le choix de sa baseline est un estimand causal déguisé. C’est la jonction formelle entre la série XAI (attribution par instance : 2.14-Explicabilite, PR ouverte) et ce pont : les deux disciplines résolvent le même problème d’allocation de responsabilité (à des features ou à des chemins), avec les mêmes pièges de corrélations, et le do-calculus fournit le langage pour dire précisément quoi on alloue. L’Epic #16620 déplie cette jonction : décomposition d’équité (famille TV, notebook Causal-Fairness), attribution par instance (ML-4 Tree SHAP), et le présent pont.
8bis. L’attribution ne s’arrête pas à L2 — les valeurs de Shapley contre-factuelles (L3 SV)
La jonction XAI ↔︎ Pearl de la section 8 s’arrête au niveau interventionnel : la baseline do attribue à \(A\) son effet causal moyen (+0.50 ci-dessus) — le même chiffre pour chaque individu. Bareinboim pousse l’échelle un étage plus haut (Causal Artificial Intelligence, 2026, § 6.2) :
GDE (Def 6.2.5, p. 494) : la contribution marginale de \(X\) quand le sous-ensemble \(Z\) varie naturellement entre unités — \(GDE_Z(X,Y \mid v) = NTE(\{X\} \cup Z, Y \mid v) - NTE(Z, Y \mid v)\), où le NTE contre-factuel fixe l’unité \(u\) et laisse les variables de \(Z\) suivre leur marginale naturelle ;
Théorème 6.2.1 (p. 496) : pour tout ordre \(\pi\), le NTE se décompose exactement en \(\sum_i GDE_{\pi_{<i}}(X_i, Y \mid v)\) — le \(Z\)-set résout la dépendance à l’ordre exactement comme les coalitions de Shapley ;
L3 SV (Def 6.2.6, p. 496) : \(\phi^{L3}_X(v) = \mathbb{E}_{\pi}[GDE_{\pi_{<X}}(X, Y \mid v)]\) — la moyenne sur les ordres, propre à l’unité \(v\) (abduction–action–prédiction : le bruit de CETTE unité est conservé) ;
Théorème 6.2.6 (p. 502) : les L3 SV satisfont simultanément causal admissibility, causal explanatory power et causal normality — aucun des attributors concurrents (LIME, SHAP classique, effets totaux, actual causation) ne les satisfait tous (Table 6.3).
C’est la réponse à la question laissée ouverte en section 8 : l’attribution interventionnelle est un moyen, la L3 SV est une explication individuelle — elle dit ce que CETTE unité doit à \(A\), en gardant son contexte \(Z^*\) et ses bruits. On la calcule au cordeau sur le même monde linéaire (abduction triviale : contre-factuel = même bruit, équations modifiées).
# L3 Shapley values (Def 6.2.6) : GDE sur permutations, contre-factuel propre a l'unite# Memes equations que la section 8 : Z -> A -> W -> Y ; Z -> W ; Z -> Y.from itertools import permutationsrng8b = np.random.default_rng(7)def draw_unit(rng): Z = rng.normal(0, 1) A =float(rng.uniform(0, 1) <1.0/ (1.0+ np.exp(-0.9* Z))) eW = rng.normal(0, 1) W =0.5* A +0.6* Z + eW eY = rng.normal(0, 1) Y =0.3* A +0.4* W +0.2* Z + eYreturndict(Z=Z, A=A, W=W, Y=Y, eW=eW, eY=eY)def Y_cf(u, do=None):# Action-prediction : variables de `do` forcees, exogenes de u conserves (abduction lineaire) Z, A = u["Z"], u["A"]if do and"Z"in do: Z = do["Z"]if do and"A"in do: A = do["A"] W =0.5* A +0.6* Z + u["eW"]if do and"W"in do: W = do["W"]return0.3* A +0.4* W +0.2* Z + u["eY"]def NTE(u, S, rng, m=400_000):# NTE(S,Y|v) = Y(u) - E_{s~P(S)}[Y_s(u)] : s tire de la marginale naturelle JOINTEifnot S:return0.0 Zs = rng.normal(0, 1, m) As = (rng.uniform(0, 1, m) <1.0/ (1.0+ np.exp(-0.9* Zs))).astype(float) Ws =0.5* As +0.6* Zs + rng.normal(0, 1, m) vals = {"Z": Zs, "A": As, "W": Ws}return u["Y"] -float(np.mean(Y_cf(u, {k: vals[k] for k in S})))def GDE(u, X, Zset, rng):return NTE(u, set(Zset) | {X}, rng) - NTE(u, set(Zset), rng)def l3_sv(u, feats=("Z", "A", "W"), rng=None, check=True): phis =dict.fromkeys(feats, 0.0) perms =list(permutations(feats))for pi in perms:for i, X inenumerate(pi): phis[X] += GDE(u, X, set(pi[:i]), rng) phis = {f: v /len(perms) for f, v in phis.items()}if check: # Thm 6.2.1 : NTE(Z,Y|v) = somme des GDE pour TOUT ordre nte_full = NTE(u, set(feats), rng)assertall(abs(sum(GDE(u, X, set(pi[:pi.index(X)]), rng) for X in pi) - nte_full) <5e-3for pi in perms), "decomposition 6.2.1 rompue"return phisrng_u = np.random.default_rng(11)units = [draw_unit(rng_u) for _ inrange(200)]u_A1 =next(u for u in units if u["A"] ==1.0and u["Z"] >0.5) # embauche, SES eleveu_A0 =next(u for u in units if u["A"] ==0.0and u["Z"] <-0.5) # refusee, SES faiblefor u in (u_A1, u_A0): phis = l3_sv(u, rng=np.random.default_rng(13)) total =sum(phis.values()) nte_full = NTE(u, {"Z", "A", "W"}, np.random.default_rng(17))print(f"Unite A={u['A']:.0f} Z*={u['Z']:+.3f} W*={u['W']:+.3f} Y*={u['Y']:+.3f}")for f, v in phis.items():print(f" phi_L3({f}) = {v:+.4f}")print(f" Somme = {total:+.4f} | NTE(Z,A,W | v) = {nte_full:+.4f} (efficacite, Thm 6.2.1)")print(f" phi_L3(A) seul = {phis['A']:+.4f} vs TE moyen (section 8, do) = +0.5006 constant")print()
Unite A=1 Z*=+0.747 W*=+2.515 Y*=+1.359
phi_L3(Z) = +0.2388
phi_L3(A) = +0.2000
phi_L3(W) = +0.7665
Somme = +1.2052 | NTE(Z,A,W | v) = +1.2043 (efficacite, Thm 6.2.1)
phi_L3(A) seul = +0.2000 vs TE moyen (section 8, do) = +0.5006 constant
Unite A=0 Z*=-1.920 W*=-1.620 Y*=-2.225
phi_L3(Z) = -0.6147
phi_L3(A) = -0.2000
phi_L3(W) = -0.4672
Somme = -1.2820 | NTE(Z,A,W | v) = -1.2830 (efficacite, Thm 6.2.1)
phi_L3(A) seul = -0.2000 vs TE moyen (section 8, do) = +0.5006 constant
Lecture — l’attribution L3 est propre à l’unité, l’attribution L2 est une moyenne
Les deux unités reçoivent le même effet interventionnel moyen (+0.50 : c’est une propriété du modèle, pas de l’individu) mais des L3 SV différentes : l’unité à SES élevé et l’unité à SES faible ne doivent pas la même chose à \(A\) — leur contexte \(Z^*\) et leurs bruits \(\varepsilon_W, \varepsilon_Y\), conservés par l’abduction, pèsent dans la décomposition. C’est exactement la hiérarchie de Pearl rendue visible dans l’attribution : L2 ne peut pas dire ça (le do moyen efface l’unité), L1 non plus (le conditionnement mélange association et effet — écart +0.34 de la section 8).
La vérification imprimée (somme des \(\phi^{L3}\) = \(NTE(Z,A,W \mid v)\) à la précision Monte-Carlo) est le Théorème 6.2.1 en action : la décomposition en GDE est exacte pour chaque ordre, la moyenne sur les ordres hérite de l’exactitude — la propriété d’efficacité de Shapley, obtenue causalement.
Limite honnête : l’abduction est triviale ici (SCM linéaire gaussien : bruit = résidu). Sur un modèle profond, l’étape d’abduction (inférer le \(u\) compatible avec l’observation) devient le coût dominant — c’est le prix de l’étage L3, et la raison pour laquelle les attributions SHAP déployées restent presque toutes L2. Le Théorème 6.2.6 reste la référence : admissibilité causale + pouvoir explicatif causal + normalité causale, les trois ensemble, uniquement au niveau 3.
9. Comment chaque moteur instancie le do-calculus
Les quatre séries implantent le même formalisme (§1-2) avec des outils différents. Partout, \(do(X=x)\) se traduit par une mutilation du graphe : on supprime les arêtes entrant dans \(X\) (déconnexion du mécanisme générant \(X\)) puis on fige \(X=x\).
Le présent notebook est complémentaire : là où Infer-5 et PyMC-5 instrumentent le do à la main sur leur moteur, dowhyautomatise l’identification (lit le graphe, choisit backdoor/front-door/IV) puis estime et réfute — le pipeline qu’on utiliserait en pratique pour une vraie étude causale.
10. Deux paradigmes : Pearl (intervention) vs Hoel (émergence causale)
Les notebooks ICT-5 et ICT-6 défendent une thèse différente et complémentaire : la causalité émergente d’Erik Hoel. Là où Pearl demande « quel est l’effet d’une intervention sur \(X\) ? » au sein d’un graphe fixé, Hoel demande « quelle échelle de description du système porte le plus de causalité ? ».
Le formalisme de Hoel repose sur l’information effective (EI), mesurée sur la matrice de transition d’un système :
Un coarse-graining (regroupement de micro-états en macro-état) peut augmenter l’EI : la macro-échelle est alors plus causale que la micro. ICT-5 le démontre sur le réseau canonique de PyPhi (EI passe de ~0,11 à ~0,60).
Pearl (do-calculus)
Hoel (émergence causale)
Question
Effet d’une intervention ?
Quelle échelle cause le plus ?
Objet
un graphe causal fixé
l’échelle de description optimale
Outil
dowhy, Infer.NET, PyMC
PyPhi (CE 2.0)
Causalité vue comme
chirurgie du graphe (\(do\))
information effective (EI)
Pont conceptuel : les deux cadres répondent à « où est la causalité ? » — Pearl la localise dans les flèches qu’on coupe, Hoel dans l’échelle qui maximise l’information sur le futur. Un système peut admettre une description causale riche au sens de Hoel (forte EI macro) tout en se prêtant au do-calculus de Pearl au niveau micro : ce sont deux loupes différentes, non concurrentes.
Du simple coarse-graining au multiscale : l’émergence causale 2.0 (Jansma & Hoel, 2025)
La formulation originelle de Hoel (2017) compare deux échelles — le micro et un macro — et constate que le macro peut porter davantage d’information effective (EI). Jansma & Hoel (Engineering Emergence, 2025) généralisent le cadre à une hiérarchie complète d’échelles : c’est l’émergence causale 2.0, mise en œuvre numériquement dans ICT-5 et ICT-6.
Extension CE 2.0
Ce qu’elle change par rapport à Hoel 2017
Hiérarchie multiescale
La causalité n’est plus comparée entre deux niveaux seulement, mais à travers toute la hiérarchie de description (ex. matériel → code machine → système d’exploitation). Le « bon » niveau n’est plus nécessairement le macro absolu : c’est celui qui maximise l’EI dans la hiérarchie.
Taxonomie top-heavy / bottom-heavy
Selon l’endroit où se concentrent les contributions causales, un système est dit top-heavy (la causalité domine aux grandes échelles) ou bottom-heavy (elle domine au micro). Ce vocabulaire classifie les systèmes, au-delà du verdict binaire « émerge / n’émerge pas » de la version 1.0.
Scale-freeness causale
Une mesure de complexité fondée sur une notion littérale de sans-échelle : la causation est répartie également à travers les échelles. Les auteurs la relient à la scale-freeness des réseaux (distribution de degré en loi de puissance).
Ce que cela change pour le pont. Le do-calculus de Pearl opère à une échelle fixée — on intervient sur un graphe donné, quelle que soit l’échelle de description. L’émergence causale 2.0 demande, elle, à quelle échelle se concentre la causalité, et admet qu’un même système soit top-heavy (description macro privilégiée) tout en restant entièrement soumis au do-calculus au niveau micro. Les deux cadres restent complémentaires : Pearl localise la causalité dans les flèches qu’on coupe ; Jansma–Hoel dans l’échelle qui maximise l’information sur le futur. La mise en œuvre chiffrée (recherche exhaustive de l’échelle émergente via pyphi.macro, démonstration que l’émergence n’est pas automatique) est dans ICT-5.
11. Causal primitives communes : Pearl, Hoel, et les mesures classiques se ramènent au même vocabulaire
Comolatti & Hoel (2022, Causal emergence is widespread across measures of causation, arXiv:2202.01854) montrent que toutes les mesures majeures de la causalité se décomposent dans un petit jeu de primitives causales communes — et que ces mêmes primitives sont déjà au cœur du couple Pearl/Hoel présenté en §7. C’est le pont formel manquant entre les deux paradigmes.
8.1 Les deux primitives (axes orthogonaux)
Pour une cause candidate \(c\) et un effet candidat \(e\) dans un ensemble de causes \(C\) et d’effets \(E\) :
Primitive
Symbole
Lecture
Sufficiency
\(\mathrm{suff}(e; c) = P(e \mid c)\)
Quand \(c\) se produit, \(e\) suit-il ?
Necessity
\(\mathrm{nec}(e; c) = P(C_{\neg c} \mid e)\)
Les autres causes peuvent-elles aussi produire \(e\) ?
Les deux sont orthogonales (Comolatti & Hoel §2.1) : \(c\) peut être suffisant et non-nécessaire (d’autres causes produisent aussi \(e\)) ; ou nécessaire et non-suffisant (à lui seul \(c\) ne déclenche pas \(e\) à coup sûr).
8.2 Extension information-théorique : déterminisme et dégénérescence
Hoel utilise les versions entropiques (qui moyennent sur l’ensemble des effets ou des causes) :
Déterminisme = certitude des effets d’une cause \(c\) (faible entropie sur \(e \mid c\)). Différent de la simple sufficiency : 4 effets équiprobables depuis \(c\) donnent \(\mathrm{suff}=1/4\) chacune mais \(\det=0\).
Dégénérescence = généralisation information-théorique de la necessity : plusieurs causes convergent vers le même effet.
Information effective (EI) = det − deg : c’est exactement la formule Hoel de §7. Les deux paradigmes Pearl (intervention) et Hoel (émergence) ne sont donc pas des vocabulaires distincts : ce sont deux fenêtres différentes sur le même couple (sufficiency, necessity) — Pearl en intervention, Hoel en entropie.
8.3 Toutes les mesures classiques se décomposent en (suff, nec)
Le résultat de consilience (Comolatti & Hoel §3) : des mesures développées indépendamment dans philo, statistique, psycho, génétique — toutes — sont fonctions du même couple de primitives. Ce n’est pas une coïncidence, c’est la signature d’un fait général sur les relations causales.
8.4 Pont avec le notebook
ICT-06-SortingToTPM-CausalEmergence-Python.ipynb calcule déjà \(\det\) et \(\deg\) sur la matrice de transition d’un système de votes (S4 de la constellation ICT). En passant au do-calculus :
Le set d’ajustement backdoor vise à rendre les conditionnements sur \(c\) aussi proches que possible de \(P(e \mid do(c))\) — c’est neutraliser la dégénérescence non-contrôlée (mêmes effets par d’autres causes latentes).
Le médiateur front-door découple le chemin \(c \to e\) en deux segments où la sufficiency reste valable localement.
En ce sens, les trois stratégies du do-calculus sont des différents contrôles sur le couple (suff, nec) : ajuster les causes dégénérées, garantir une médiation suffisante, séparer observation et intervention.
8.5 Limite honnête
Le cadre des primitives suppose qu’on peut définir une distribution \(P(C)\) sur l’ensemble des causes (ce qu’on appelle “intervention distribution” dans le papier). Sous distribution observationnelle pure, la sufficiency et la necessity ne sont pas identifiées séparément — elles se confondent en leur combinaison visible \(P(e \mid c)\). Les interventions max-ent de Hoel (et d’ICT-6) résolvent ce décalage, mais au prix d’une plausibilité limitée si le système réel n’a pas une distribution uniforme sur les causes.
C’est pourquoi le verdict “émergence causale” dépend du système et de l’intervention choisie : deux systèmes équivalents observationnellement peuvent diverger sous intervention. La leçon vaut autant pour Pearl (l’estimande identifié dépend des variables observables) que pour Hoel (l’EI dépend de la TPM impliquée).
12. Cinquième modalité : le raisonnement causal par connaissance (LLM)
Les quatre séries de la constellation — et dowhy dans ce pont — estiment toutes la causalité à partir des valeurs de données : covariances, distributions conditionnelles, matrices de transition. Kıcıman et al. (2023) explorent la modalité complémentaire : un LLM qui raisonne à partir des métadonnées et des connaissances — noms de variables, contexte de domaine, sémantique des relations — sans voir une seule valeur de donnée. Les erreurs de cette modalité diffèrent de celles des méthodes fondées sur la covariance, ce qui motive un usage hybride plutôt qu’un remplacement.
Source canonique archivée : G:\Mon Drive\MyIA\IA\Bibliographie IA\Probabilistic\2023 - Kiciman et al - Causal Reasoning and Large Language Models.pdf — E. Kıcıman, R. O. Ness, A. Sharma, C. Tan, Causal Reasoning and Large Language Models: Opening a New Frontier for Causality, arXiv:2305.00050v3 (2023). Chaque nombre ci-dessous est attribué à son modèle, dataset et protocole d’origine.
9.1 Trois résultats du papier, chaque nombre attribué
Tâche (dataset)
Modèle et protocole
Résultat mesuré
Réf.
Découverte causale par paires — Tübingen cause-effect pairs (Mooij et al. 2016 : 108 paires issues de 37 jeux de données)
gpt-4, prompt unique « step-by-step » ; précision pondérée (pondération recommandée par Mooij et al. contre le surcomptage de paires similaires)
92,4 % contre 83,9 % pour text-davinci-003 (meilleur score rapporté par les auteurs du benchmark) ; annotateurs humains 98,2 %
Table 9
Nuance obligatoire : sur la tâche la plus difficile (graphe complet), les auteurs concluent que les LLM atteignent une précision similaire aux méthodes récentes d’apprentissage profond — pas supérieure. L’avantage net du tableau n’existe qu’en régime métadonnées-seules ; dès qu’il s’agit d’estimer l’amplitude d’un effet ou de l’identifier depuis des données, le do-calculus (§2) et ses critères (§4-5) restent l’arbitre.
9.2 Deux contre-mesures d’honnêteté
Sensibilité au prompt. Chaque performance ci-dessus est une propriété du couple (modèle, prompt), pas du modèle seul : sur le graphe de douleur, changer seulement le prompt fait passer F1 de 0,21 à 0,68 (même modèle) ; sur Tübingen, la persona « agent of causal reasoning » gagne environ 5 points à gpt-3.5-turbo (86,9 % pondéré). Un chiffre LLM cité sans son prompt n’est pas reproductible.
Échecs imprévisibles. Les auteurs documentent des modes d’échec imprévisibles : un LLM énonce une arête fausse avec la même assurance qu’une arête correcte — sans borne de confiance ni diagnostic d’erreur. Une vérification anti-mémorisation (datasets publiés après la date de coupure d’entraînement des modèles) atteste néanmoins que la capacité ne se réduit pas à de la mémorisation : les scores tiennent sur des données nouvelles.
9.3 Conclusion pédagogique : l’hybride, pas le remplacement
Les erreurs des deux familles ne se recouvrent pas : le LLM se trompe là où la connaissance du domaine manque ou induit en erreur, l’algorithme là où les valeurs seules laissent la direction ambiguë (classe d’équivalence de Markov). La leçon pour la constellation : utiliser le LLM comme oracle de connaissances — proposer des arêtes candidates, écarter les directions absurdes du domaine — puis laisser l’estimation causale sur données (backdoor/front-door de §4-5, Infer.NET, PyMC) identifier et estimer ce que les données soutiennent. La cinquième modalité ne remplace pas les quatre : elle répond à « que dit notre connaissance de la structure plausible ? » là où les §1-5 demandent « qu’est-ce que les données identifient ? »
Un benchmark local (Qwen) de cette modalité sur nos propres paires appartient à un futur sous-grain de l’EPIC ; aucune mesure locale n’est présentée ici comme réplication des scores GPT-4.
13. Exercices
Les exercices suivent la convention du dépôt (stub à compléter). Aucun ne lève d’erreur : remplacez None par votre code.
Exercice 1 — Ajouter un second confondeur à la backdoor
Ajoutez un confondeur observablemotivation (qui cause collegeetearnings) au modèle backdoor, puis demandez à dowhy d’identifier l’estimande. L’ensemble backdoor doit maintenant contenir {aptitude, motivation}.
Exercice 2 — Rompre le critère front-door
Modifiez le graphe front-door en ajoutant un chemin directsmoking -> cancer (contournant le médiateur tar). Vérifiez que le critère front-door échoue à identifier l’effet — l’hypothèse de médiation complète est rompue.
Exercice 3 — Comparer effet naïf et effet ajusté sur un nouveau jeu
Générez un nouveau jeu backdoor avec un effet vrai de 5,0 et un confondeur plus fort (coefficient 2,5 sur l’aptitude). Calculez l’effet naïf puis l’effet ajusté, et commentez l’écart relatif.
# Exercice 1 — ajoutez un 2e confondeur observable au modèle backdoor.# Objectif : dowhy doit identifier l'ensemble backdoor {aptitude, motivation}.# Indice : motivation -> college ET motivation -> earnings (mêmes flèches que aptitude).# TODO etudiant : construisez df_ex1, le graphe gml_ex1, puis identifiez l'estimande.df_ex1 =None# TODO etudiantgml_ex1 =None# TODO etudiantestimand_ex1 =None# TODO etudiantprint("Exercice 1 a completer")
Exercice 1 a completer
# Exercice 2 — ajoutez un chemin direct smoking -> cancer (médiation rompue).# Objectif : montrer que l'identification front-door échoue.# Indice : ajoutez 'edge [ source 1 target 3 ]' au graphe gml_frontdoor.# TODO etudiant : définissez gml_ex2 avec ce chemin direct, identifiez l'effet.gml_ex2 =None# TODO etudiantprint("Exercice 2 a completer")
Exercice 2 a completer
# Exercice 3 — nouvel effet vrai = 5.0, confondeur plus fort (2.5*aptitude).# Objectif : comparer effet naïf vs ajusté, commenter l'écart relatif.# TODO etudiant : générez les données, calculez naive puis estimate_bd, affichez l'écart.print("Exercice 3 a completer")
Exercice 3 a completer
Exercice 4 — Le compromis biais-variance du transport stratifié
Reprenez le transport de la tâche 4 avec \(K \in \{3, 20, 100\}\) strates : comment l’estimé évolue-t-il ? Prédisez d’abord (strates grossières = biais résiduel de modification intra-strate ; strates fines = variance Monte-Carlo par strate), puis mesurez.
# Exercice 4 : transport stratifie a K = 3, 20, 100 strates# Etapes :# 1. Re-utiliser le monde de la tache 4 (site() ci-dessus, memes seeds)# 2. Boucler sur K, recalculer te_transporte pour chaque valeur# 3. Comparer a te_cible_exact = 0.76 : biais a petit K, variance a grand K ?resultat_ex4 =None# TODO etudiant : dict {K: te_transporte} + une phrase de lecture
14. Synthèse
Vous avez parcouru l’armature formelle partagée par les quatre séries causales du dépôt :
Échelle de Pearl (§1) : observation < intervention < contrefactuel — le do-calculus opère le saut \(P(y\mid x) \to P(y\mid do(x))\).
Trois règles (§2) : chacune est une chirurgie du graphe + un test de \(d\)-séparation.
Backdoor (§4) : ajustement sur les confondeurs observables — exécuté par dowhy, recouvre l’effet vrai.
Front-door (§5) : sauvetage par médiateur quand le confondeur est latent.
Data-fusion (§6) : les quatre designs archétypaux — sélection et transportabilité corrigées par repondération du modificateur d’effet.
CHT (§7) : deux SCM à loi jointe identique et interventions opposées — L1 ne devient pas L2 sans hypothèse causale externe.
Jonction XAI (§8) : baseline d’attribution do vs voir — l’écart mesure le chemin spurieux facturé à la feature.
Pearl vs Hoel (§10) : intervention sur un graphe fixé vs échelle de description optimale (information effective).
Connaissance/LLM (§9) : cinquième modalité — raisonnement causal sur les seules métadonnées (Kıcıman et al. 2023) ; prompt-sensible, échecs imprévisibles, à hybrider avec l’estimation sur données.
Pont suivant (après merge de ce notebook) : câbler les quatre notebooks en aller-retour vers ce pont, pour que chaque série renvoie ici pour le formalisme unifié.
9. Comment chaque moteur instancie le do-calculus
Les quatre séries implantent le même formalisme (§1-2) avec des outils différents. Partout, \(do(X=x)\) se traduit par une mutilation du graphe : on supprime les arêtes entrant dans \(X\) (déconnexion du mécanisme générant \(X\)) puis on fige \(X=x\).
do(X)opérationnellementdonatifdowhyLe présent notebook est complémentaire : là où Infer-5 et PyMC-5 instrumentent le
doà la main sur leur moteur,dowhyautomatise l’identification (lit le graphe, choisit backdoor/front-door/IV) puis estime et réfute — le pipeline qu’on utiliserait en pratique pour une vraie étude causale.