Repository navigation
feat(ict,#13903): Greffe 5 tranche 1/3 -- module ict/causal_attribution.py (close-form NumPy) - #13916
Conversation
…on.py (close-form NumPy) Grain: DEEP/notebook-python -- lane myia-po-2027:CoursIA-2 -- prev: LIGHT/docs #12353 Issue #13903 Greffe 5 (attribution causale d'intervention) tranche 1/3 : interface analytique close-form NumPy qui sert de specification executable et cible de test commune aux moteurs natifs DoWhy-1, PyMC-05, Infer-5, Tweety-11 et Probas/DecisionTheory/Causal-Bridges. Trois estimateurs : - naive_difference : baseline biaisee (effet selection + confondants) - backdoor_adjustment : ajustement Pearl 2009 chap 3.3, leve si Z ne bloque pas - iv_estimate : Angrist-Krueger 2001, leve si Cov(X,Z) < 5/sqrt(n) (5-sigma) Verdict tri-etat (analogue ICT-12e protocole EVSI 253 000 / 252 796 EUR, ecart 204 EUR sous tolerance) : - AGREEMENT sous tolerance declaree - DESACCORD au-dela (rapporte brut, JAMAIS moyenne) - NON_IDENTIFIABLE = resultat legitime (SAE-Catastrophes modele cite #13903) CausalGraph dataclass : validation stricte du squelette (treatment != outcome, confounders disjoints de X/Y, instrument disjoint). Tests : 13/13 PASSED (0.28s) sur 8 gates falsifiables (naive, backdoor OK/KO, IV OK/KO, controle negatif intervention sans effet ATE=0, tri-etat, validation graphe). Anti-regression : 485/485 tests package ict/ verts (46s). README mis a jour : table 'Agentivite & causalite' ajoute causal_attribution. Distinction explicite docstring vs ict.causal_emergence : - emergence causale = combien de pouvoir causal une echelle gagne (Hoel) - attribution causale = si une intervention est cause du changement (Pearl) Ces deux operations sont distinctes ; ICT mesurait la premiere, pas la seconde. Tranche 2/3 (autre cycle) : adaptateurs branchant l'interface sur les moteurs natifs et verification cross-engine (memes valeurs a tolerance pres sur cas canoniques). Tranche 3/3 : notebook ICT-Greffe5-AttributionCausale dans IIT/ICT-Series/ appelant DoWhy-1 + PyMC-05 sur cible +raft/+discard (PR #13802 MERGED Greffe2). See #13903 (Greffe 5 tranche 1/3)
d82c132 to
2e2b9f4
Compare
Path-collision (organ #13359/#13615)Cette PR #13916 (
|
jsboige
left a comment
There was a problem hiding this comment.
[Hermes] — review 2e2b9f4ce9 (tranche 1/3 Greffe 5 — COMMENT, contrainte token : COMMENT only).
Lecture complète du module (+377 l.) et des tests (+224 l.), vérifications recalculées à la main :
Vérifié
- Gate 2 (Simpson/backdoor) : par strate Z, E[Y|X=1,Z=z] − E[Y|X=0,Z=z] = 5.0 exact (Y = 10 + 5X + 2·1[z=high] + bruit), donc backdoor = Σ_z p_z × 5 → 5.0 quel que soit le plan X|Z ; le naïf biaise via l'effet sélection (0.9/0.1). Le test discrimine correctement.
- Gate 7 (tri-état) : spread = max|v − médiane| (et non max−min) — robuste à >2 estimateurs ; archétype ICT-12e (écart 204 sous tol 500) correctement cité.
- iv_estimate : floor pertinence 5/√n ≈ 5σ sous H0 (Cov échantillonnale ~ 1/√n), justification en commentaire ; Gate 5 à n=1e6 cohérent (~1e-3 < 5e-3).
- Fail-loud NON_IDENTIFIABLE : ValueError sur modalité X manquante par strate Z (Gate 3), pas de valeur par défaut silencieuse — discipline anti-fabrication respectée.
- Sécurité : 0 match (
HF_TOKEN|API_KEY|BEARER|PASSWORD|SECRET|TOKEN\s*=). Dépendances stdlib+numpy, aucun impact cross-repo.
Non bloquant
CausalGraphest validé (Gate 8) mais pas encore consommé par les estimateurs — pure déclaration en tranche 1/3, assumé.
Séquencement : la tranche 2/3 (#13921, base main) importe ict.causal_attribution absent de main (404 vérifié) → ordre de merge strict #13916 → #13921.
Verdict : fondation solide, gates falsifiables, aucun défaut bloquant relevé.
…isory (#13979) Le filtre d'eligibilite du sweep etait strictement plus strict que le gate dont il existe pour re-rendre le verdict : `cancelled` rentrait du cote "autres checks" par le COMPLEMENT de GREEN, alors que le commentaire de RED exempte ce cote explicitement ("It belongs here, on the GATE side only"). L'asymetrie etait declaree, testee, et non implementee. Preuve decisive : `List open-PR path collisions: CANCELLED` coexiste avec un `PR gate: SUCCESS` sur des PRs MERGEES (#13916, #13860) -- controle positif, trois PRs sans annulation rendent la colonne vide (#13931, #13956, #13945). Mesure du sweep 33459621864 (71 PRs inspectees) : 42 exclusions nommees, 26 sur un `failure` reel, 16 -- 38 % -- sur des `cancelled` SEULS, dont 13 sur le seul advisory `List open-PR path collisions`. Ces PRs restaient BLOCKED pour toujours : un gate cancelled ne devient jamais SUCCESS tout seul. Exemption d'une SEULE conclusion : `startup_failure`, `stale` et toute conclusion future inconnue continuent d'exclure. Acceptance 5 de #11862 inversee, datee et justifiee dans le test. Sa premisse -- un cancelled frais est une interruption rare -- est tombee sous `cancel-in-progress: true` sur les advisory. L'intention tient : le sweep ne merge rien, il RELANCE le gate, qui conclut FAIL si un constituant est rouge. Falsification verifiee : workflow revert -> 2 tests rouges (test_other_latest_cancelled_is_candidate, garde structurel) ; restaure -> 16 verts. Les deux controles positifs passent dans LES DEUX etats, comme attendu d'un controle. See #13978. Co-authored-by: myia-ai-01 <jsboige@gmail.com>
feat(ict,#13903): Greffe 5 tranche 1/3 — module ict/causal_attribution.py (close-form NumPy)
Grain: DEEP/notebook-python — lane myia-po-2027:CoursIA-2 — prev: LIGHT/docs #12353
See #13903 (Greffe 5 tranche 1/3 ; livraison partielle, tranche 2/3 et 3/3 à venir)
Contexte
#13903 « Greffe 5 — attribution causale de l'intervention » identifie une lacune structurelle dans le dépôt :
ict.causal_emergence, Hoel 2025 ; PNAS 2013) ;C'est exactement la question que les greffes 4/sandbox produisent :
Chacune produit un
S_t → S_{t+1}. Aucune ne peut dire que l'intervention en est la cause. Sans cette jambe, la chaînedeliberation → action institutionnelle → monde modifié → nouvelle délibérationse termine par une corrélation post-hoc.Cette PR tranche 1/3 pose l'interface analytique NumPy ; les tranches suivantes brancheront l'interface sur les organes natifs DoWhy/PyMC/Infer/Tweety et construiront le notebook
ICT-Greffe5-AttributionCausale.ipynbqui démontre l'attribution sur la cible+raft/+discardde la Greffe 2 (PR #13802 MERGED).Distinction explicite (à ne pas confondre)
ict.causal_emergenceict.causal_attribution(cette PR)Trois estimateurs implémentés
naive_difference—E[Y | X=1] − E[Y | X=0]. Biaisé par confondants et effet sélection. Baseline uniquement.backdoor_adjustment— Pearl 2009 chap. 3.3 :Σ_z E[Y | X=x, Z=z] · P(Z=z). Correct si Z bloque le backdoor ; lèveValueError(estimandNON_IDENTIFIABLE) si une modalité X manque pour une modalité Z.iv_estimate— Angrist-Krueger 2001 :Cov(Y, Z) / Cov(X, Z). LèveValueError(instrumentNON PERTINENT) si|Cov(X, Z)| < 5/√n(seuil 5-σ).Verdict tri-état (analogue ICT-12e)
compare_estimators({...}, tolerance)rendAttributionVerdict:toleranceautour de la médiane ;Contrôle négatif obligatoire
Test
test_control_intervention_without_effect_returns_zero_ate: vrai ATE = 0, le module retourne|ATE| < 0.2. C'est la négation du pattern ICT-12e (le EVSI non-informatif doit valoir 0). Si l'attribution causale ne sait pas dire « cette intervention n'a pas causé ce changement », elle ne sait rien dire.Statistiques
ict/causal_attribution.py(nouveau, 313 lignes),ict/tests/test_causal_attribution.py(nouveau, 218 lignes),ICT-Series/README.md(+1 ligne)naive_difference(OK/KO),backdoor_adjustment(OK/KO modality missing),iv_estimate(OK/KO relevance),compare_estimators(AGREEMENT/DESACCORD/≥2 requis),CausalGraph(self-loop/duplicate/valid), contrôle négatif ATE = 0ict/verts (46 s)Distinction
ict.causal_emergencevsict.causal_attribution(docstring)Le module documente explicitement la distinction dans son
:warning:block — ce sont deux opérations distinctes. ICT a abondamment la première (Hoel) ; il n'a nulle part la seconde (Pearl). Les organes natifs (DoWhy-1,PyMC-05,Infer-5,Tweety-11,Probas/DecisionTheory/Causal-Bridges) sont les calculs canoniques de la causalité dans le dépôt. Cette tranche 1/3 pose la signature analytique close-form ; les tranches 2/3 et 3/3 brancheront les moteurs et construiront le notebook.Références
Suite (autres cycles)
ict.causal_attributionsurDoWhy-1,PyMC-05,Infer-5,Tweety-11; vérification cross-engine (mêmes valeurs à tolérance près sur cas canoniques parapluie/forage/animat).ICT-Greffe5-AttributionCausale.ipynbdansIIT/ICT-Series/appelant ≥ 2 organes causaux sans en réimplémenter un seul, cible d'intervention+raft/+discard(Greffe 2 PR feat(ict,#13568): ICT-Greffe2 quadruplet (A, F, r, pi) -- elargissement, controle negatif, noyau, navigation #13802 MERGED), contrôle négatif, verdict tri-état.Critères d'acceptation #13903 (tranche 1/3 couverte)
+raft/+discardGreffe 2) → tranche 3/3DESACCORDsi moteurs divergent → livré (module) + tranche 3/3ATE ~ 0→ livré (testtest_control_intervention_without_effect_returns_zero_ate)3 critères sur 5 livrés en tranche 1/3 ; les 2 restants sont des livrables de la tranche 3/3 (notebook qui appelle ≥ 2 organes + cible d'intervention réelle).