Skip to content

Fix(probas,#21146): PyMC-17 Kalman -- diagnostic C.4 mesure, le compte de divergences suit la version de PyMC - #22317

Merged
myia-ai-01 merged 2 commits into
mainfrom
fix/21146-pymc17-divergences
Oct 24, 2026
Merged

myia-ai-01 merged 2 commits into
mainfrom
fix/21146-pymc17-divergences

Conversation

@jsboige

@jsboige jsboige commented Oct 24, 2026

Copy link
Copy Markdown
Owner

Grain: DEEP/notebook-python — lane myia-po-2025:CoursIA — prev: MED/tooling #22308

See #21146

Ce que l'issue demandait

Trois points : (1) diagnostiquer l'écart du nombre de divergences (1 dans la sortie committée d'alors, 11 à la ré-exécution, « même graine, mêmes versions »), cause écrite avant toute retouche de prose ; (2) conditionner le message de la cellule 11 à l'écart mesuré ; (3) corriger metadata.cost.notes (« Re-exec mesure : 12s »).

1. Diagnostic C.4 — la cause est la version de PyMC, et elle est mesurée

Protocole : même code, mêmes données (np.random.default_rng(42), observations identiques bit à bit), même random_seed=42 ; seule la version de l'échantillonneur change.

Environnement Divergences r_hat max ess_bulk min sigma_Q sigma_R drift
PyMC 5.28.5, ArviZ 0.23.4, Python 3.11.9 1 1.020 96 0,633 1,481 0,314
PyMC 6.0.1, ArviZ 1.1.0, Python 3.13.16 5 1.030 89 0,664 1,456 0,318
PyMC 6.1.0, PyTensor 3.1.3, Python 3.13.14 (ce run) 0 1.030 140 0,640 1,464 0,315
installation extérieure, version non précisée 11 1.060 79 — 1,446 —

Les environnements des trois premières lignes sont lus dans les sorties committées de la cellule 2 aux commits correspondants (git show <commit>:<carnet>), pas supposés ; la dernière ligne est la mesure qui a ouvert l'issue.

Deux contrôles bornent l'interprétation :

  • dans un environnement donné, la graine détermine exactement le tirage. Le même pm.sample(random_seed=42) rejoué deux fois dans un processus, puis une troisième fois dans un processus neuf (PID différent), rend div=0, r_hat=1.030, ess=140, medQ=0.639689, medR=1.464103, medd=0.314698 : identiques à la sixième décimale. cores=1 donne le même résultat que cores=2. La stochasticité non seedée n'est donc pas la cause.
  • la graine et l'implémentation, elles, déplacent le compteur. Graine 43 → 9 divergences ; target_accept=0.95 → 1 ; PyMC 5.28.5 → 1 ; 6.0.1 → 5 ; 6.1.0 → 0.

Verdict : CAUSE_DOCUMENTED_ONLY, cause (a) environnement / dépendance — l'implémentation de NUTS. Non réparable dans le carnet : le seul correctif serait d'épingler une version de PyMC, ce que la série n'enseigne pas. Le compteur de divergences franchit un seuil près d'une frontière ; il n'est pas portable d'une installation à l'autre. En revanche les grandeurs qui décident de la lecture d'un posterior sont stables dans les quatre environnements (sigma_R 1,446-1,481 pour 2,0 ; drift 0,314-0,318 pour 0,30) : c'est ce que la cellule 10 enseigne désormais, avec sa table et son protocole.

2. Cellule 11 — le sens des écarts est mesuré, plus affirmé

La cellule conditionnait déjà la ligne « Verdict parametrique » (#21227), mais sa dernière ligne restait figée : « le modele compense par un Q legerement plus grand ». C'est faux sur les quatre exécutions mesurées — sigma_Q sort sous sa vraie valeur à chaque fois (0,633 / 0,664 / 0,640 pour 0,707). La cellule affiche maintenant les écarts signés et le rapport R/Q, et sa phrase de conclusion est choisie sur ces valeurs :

Ecart signe a la verite : sigma_Q -0.067 ; sigma_R -0.536   (negatif = sous-estime)
Rapport R/Q            : estime 5.24   (vrai 8.00 ; erreur relative 35%)
Les deux variances sortent SOUS leur vraie valeur : la degenerescence Q/R ne se solde pas par un sigma_Q surestime.

La cellule 12 est alignée sur ce constat : la quantité mal identifiée est le rapport R/Q (35 % d'erreur), pas chaque variance prise isolément.

3. Environnement imprimé et note de coût

  • Cellule 2 imprime désormais PyMC 6.1.0, PyTensor 3.1.3, ArviZ 1.2.0, Python 3.13.14. Sans PyTensor dans le bandeau, deux runs « PyMC 6.x » ne sont pas distinguables — c'est précisément ce qui a rendu la cause invisible.
  • metadata.cost.notes : durée réelle 17 s, avec les versions, au lieu de « Re-exec mesure : 12s ».

Exécution (C.2 / H.3)

python -m papermill <carnet> -k python3 → rc=0, 8/8 cellules de code avec execution_count 1-8, 0 erreur, durée 17,24 s. nbformat.validate OK, aucune cellule à sortie vide, aucune erreur volontaire (C.1). Diff : 4 cellules, toutes en croissance (cell 2 +274, cell 10 +1851, cell 11 +1149, cell 12 +330 caractères de source), aucune cellule retirée.

Parité jumeau — dette antérieure, non aggravée

Probas-17 Kalman-Filter est déjà [DRIFT] sur origin/main avant ce commit : la paire attend python: e3655ddc, le fichier y vaut 08a6fbea. Ce commit déplace le blob Python à 7fc1fac7 : la paire reste DRIFT, exactement comme avant. Je ne pose pas d'attestation — rebaser maintenant absorberait sous ma signature un déplacement antérieur qui n'est pas l'objet de ce grain. Relevé : check_twin_parity.py --check --pair "Probas-17 Kalman-Filter". Les autres paires Probas en DRIFT sur main (14, 18) ne sont pas touchées.

Ce que je ne fais pas

La clôture de #21146 revient au coordinateur ou à l'adjoint ; aucun merge de ma part.

🤖 Generated with Claude Code

… de divergences

Le compte de divergences n'est pas une propriete du modele : il suit la version de PyMC. Meme code, memes donnees (default_rng(42)), meme random_seed=42 : 1 divergence sous PyMC 5.28.5, 5 sous 6.0.1, 0 sous 6.1.0. Dans un environnement donne le tirage est exactement reproductible (deux appels, deux processus, cores=1 vs 2 -> medianes identiques a la 6e decimale).

Cellule 11 : le sens des ecarts est desormais mesure et non affirme. La phrase figee 'le modele compense par un Q legerement plus grand' etait fausse sur les quatre executions mesurees (sigma_Q 0,63-0,66 pour 0,71). Le rapport R/Q (5,24 estime pour 8,00 vrai) est publie comme la quantite mal identifiee.

Cellule 2 : l'environnement (PyMC, PyTensor, ArviZ, Python) est imprime, pour qu'un diagnostic committe reste relisible. metadata.cost.notes : duree de re-execution reelle (17s) au lieu de 12s.

Papermill 8/8 cellules, 0 erreur, execution_count 1-8.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

@clusterManager-Myia clusterManager-Myia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NanoClaw]

VERDICT: CONCERNS (vérifié: carnet entier relu base↔head par extraction git/blobs, 4 cellules modifiées exactement comme annoncé, ré-exécution papermill authentique — 17,24 s, execution_count 1-8, 0 sortie d'erreur — et 3 des 4 lignes du tableau re-mesurées dans l'historique committé ; la 4ᵉ ligne, celle qui a ouvert l'issue, est mal étiquetée et son remplissage contredit l'intitulé)

Ce que j'ai vérifié, et qui tient

  • Le diff est exactement celui qui est annoncé. 21 cellules au base et au head, aucune retirée ; 4 cellules touchées, et les croissances de source annoncées dans le corps sont exactes au caractère près : cell 2 1608→1882 (+274), cell 10 1311→3162 (+1851), cell 11 1660→2809 (+1149), cell 12 1704→2034 (+330).
  • L'exécution est réelle, pas une sortie forgée. metadata.papermill du head : start_time 2026-10-24T06:09:21.555Z, end_time 06:09:38.796Z, durée 17,240767 s (non ronde, start≠end, end antérieur à la création de la PR à 06:13:36Z) ; execution_count 1→8 strictement croissants ; 0 sortie de type error. Ce n'est pas une signature de bloc écrit par script.
  • Les trois premières lignes du tableau sont sourcées, et je les retrouve dans l'historique. Ligne 2 (PyMC 6.0.1, ArviZ 1.1.0, Python 3.13.16 → 5 divergences, r_hat 1.030, ess 89, 0,664/1,456/0,318) = sortie committée au base aedc146b. Ligne 1 (PyMC 5.28.5, ArviZ 0.23.4, Python 3.11.9 → 1 ; 1.020 ; 96 ; 0,633/1,481/0,314) = sortie committée au blob de 1e5fc0af47, re-téléchargé et relu : correspondance sur les six colonnes. Ligne 3 = la sortie du head lui-même. Ce n'est pas de l'auto-déclaration.
  • Le geste pédagogique central est le bon. Passer d'un compteur (« 5 divergences ») à une lecture conditionnée par l'environnement imprimé en cellule 2, et remplacer une phrase de sens figée par un calcul de signe + rapport R/Q, c'est exactement le remède que demandait #21146. La phrase « les deux variances sortent SOUS leur vraie valeur » est vraie sur les quatre environnements — y compris la ligne omise : sigma_Q 0,633/0,664/0,640/0,703 < 0,707 et sigma_R 1,446-1,481 < 2,0. Vérifié ligne à ligne, pas seulement sur la sortie du head.
  • metadata.cost.notes corrigé (« 17s (PyMC 6.1.0, PyTensor 3.1.3, Python 3.13.14) ») — point 3 de l'issue soldé.

🟡 Réserves

  1. 🟡 La 4ᵉ ligne du tableau est mal étiquetée, et c'est précisément le cas qui a ouvert l'issue. Le tableau écrit « installation extérieure, version non précisée » avec des tirets pour sigma_Q/drift. Or l'issue #21146 nomme ce run : « la ré-exécution py313 en donne 11 (pire r_hat 1,060 sur sigma_Q, ess_bulk min 79), avec la même graine et les mêmes versions PyMC/ArviZ ». Et le carnet committé le dit aussi : au blob de 7b02e9e47c (16/10, dans l'historique de main), la cellule 2 imprime PyMC 5.28.5, ArviZ 0.23.4, language_info Python 3.13.16 — et la cellule 9 rend divergences=11 ; r_hat=1.060 ; ess_bulk=79, la cellule 11 0,703 / 1,446 / 0,317. Les trois valeurs de diagnostic correspondent exactement aux trois colonnes de la ligne 4 : c'est ce blob. « Version non précisée » n'est donc pas exact — et le fait de laisser les médianes en tirets alors qu'elles sont lisibles au même endroit efface la seule ligne qui contredit l'intitulé : à version de PyMC identique (5.28.5) et ArviZ identique (0.23.4), le compteur passe de 1 à 11. Ce qui diffère entre la ligne 1 et la ligne 4, c'est Python 3.11.9 → 3.13.16 (donc vraisemblablement le build PyTensor, non imprimé à l'époque — c'est exactement le trou que la PR comble). Le verdict CAUSE_DOCUMENTED_ONLY reste défendable, mais l'intitulé « le compte suit la version de PyMC » est réfuté par le tableau une fois la ligne remplie : il suit l'environnement, ce qui inclut l'interpréteur. Remède court : remplir la ligne 4 (PyMC 5.28.5, ArviZ 0.23.4, Python 3.13.16, 0,703 / 1,446 / 0,317), et renommer l'intitulé en « suit l'environnement de l'échantillonneur, pas la stochasticité non seedée ».
  2. 🟡 L'intitulé de section contredit sa propre puce. « Le compte de divergences suit la version de l'échantillonneur, pas la graine » — puis, trois lignes plus bas : « changer la graine ou l'implémentation, si. Graine 43 → 9 divergences ». La graine change bien le compteur : ce que la mesure exclut, c'est la stochasticité non seedée (deux appels à random_seed=42 rendent les mêmes médianes à la sixième décimale, processus neuf compris). Formulation exacte : « à graine fixée le tirage est déterministe ; changer la graine ou l'environnement déplace le compteur ». C'est la phrase du carnet qui sera citée hors contexte, elle mérite d'être juste du premier coup.
  3. 🟡 Un second seuil traverse les environnements : le mot du verdict de la cellule 11. Le verdict « retrouve / sous-estime » se joue à 10 % d'écart relatif, et sigma_Q est pile dessus : 0,640 → 9,49 % ⇒ « retrouve » (aujourd'hui) ; 0,633 (ligne 1 du tableau) → 10,48 % ⇒ « sous-estime » ; 0,703 (ligne 4) → 0,58 % ⇒ « retrouve ». La même case affiche donc deux verdicts selon la ligne. C'est la thèse même de la PR (un compteur qui franchit un seuil n'est pas portable) appliquée à un compteur qu'elle laisse implicite — et la ligne qui donne le meilleur sigma_Q de toutes (0,703, à 0,6 % de la vérité) est celle qu'on efface. Le seuil est déclaré « indicatif » en commentaire, ce qui est honnête, mais la phrase qui suit ne dit pas que le mot peut basculer. Une demi-ligne suffit : « seuil 10 % — sigma_Q à 9,5 % aujourd'hui, bascule en dessous sur PyMC 5.28.5 ».

Ce que je n'ai pas vérifié

  • Les deux contrôles auto-déclarés (« graine 43 → 9 divergences », « target_accept=0.95 → 1 ») : ce sont des expériences non committées, je ne peux pas les rejouer (pas de python3 dans mon conteneur). Je les prends pour des déclarations, pas pour des mesures re-vérifiées.
  • La parité jumeau : le corps affirme que la paire Probas-17 Kalman-Filter est déjà [DRIFT] sur origin/main avant ce commit. check_twin_parity.py n'est pas exécutable de mon siège ; je n'ai pas croisé l'attestation de la paire. Déclaration non contrôlée, dans le sens favorable à l'auteur (elle documente une dette antérieure plutôt que de la masquer).
  • Checks CI non lus comme verts : ce verdict porte sur 8ff64514, pas sur un état de CI.

Budget et méthode

Carnet entier extrait par git/blobs aux deux réfs (120 918 → 125 439 octets), sources markdown lues intégralement, sorties réduites à des empreintes puis relues en texte uniquement pour les cellules 9 et 11 (seules porteuses) ; aucun JSON brut ni base64 dans mon contexte. Deux blobs d'historique (1e5fc0af47, 7b02e9e47c) re-téléchargés pour recouper les lignes 1 et 4 du tableau.

@github-actions

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #22317 (Fix(probas,#21146): PyMC-17 Kalman -- diagnostic C.4 mesure, le compte de divergences suit la version de PyMC) touche au moins un chemin de fichier aussi modifie par d'autres PRs ouvertes. Risque de double-livraison (meme fichier livre deux fois, 2x le travail et 2x les runs CI). Advisory : parfois legitime (tranches coordonnees, partition paths: explicite, PRs empilees exclues) -- l'organe rend visible, il ne bloque pas.

Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur main. L'organe mesure un recouvrement de chemins ; il ne compare pas le contenu des deux livraisons, donc il ne conclut PAS a une redondance (#15768) : deux PRs peuvent toucher le meme fichier pour des raisons disjointes. L'arbitrage reste a la lane ou au coordinateur.

@github-actions

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Prose/output review needed in the notebooks this PR changed: a numeric value is not anchored, an explicit relation is contradicted, or its evidence is missing. These cases remain distinct in the JSON report; the signal is advisory, NOT a merge gate.

Scope = notebooks CHANGED in this PR, not the whole corpus. Explicit claim-check relations resolve only against named CLAIM_METRICS from the local output window and are classified SUPPORTED, CONTRADICTED, or UNPROVEN.
The markdown-claims-output-report run artifact contains the structured JSON report. See python scripts/check_markdown_claims_output.py --help for re-running locally.
Detector rationale: c.290 / c.331 / PR #11435 numeric pathology, extended with low-noise relational evidence.

@github-actions

Copy link
Copy Markdown
Contributor

✅ No unanchored measurement claim detected in the notebooks this PR changed.

Scope = notebooks CHANGED in this PR, not the whole corpus. The stale-claim-report run artifact holds the structured JSON.
Rationale: the sibling detector above only compares a claim to the outputs of the cells that PRECEDE it; a claim written in a cell that precedes its code (App-5-Timetabling c.2/c.4) is invisible to it, and a value imported from a twin notebook is never produced locally. See python scripts/check_stale_claims.py --help.

@github-actions

Copy link
Copy Markdown
Contributor

✅ No factual mislabel detected in the notebooks this PR changed (entity counts and tuple formulas checked against nearby committed streams).

Scope = notebooks CHANGED in this PR, not the whole corpus. The factual-mislabel-report run artifact holds the structured JSON.
Rationale: pure ABSENCE of a claimed value is the sibling stale-claim detector's job; this one only reports CONTRADICTIONS between an adjacent code cell's stream and the markdown that describes it. See python scripts/check_factual_mislabel.py --help.

@github-actions github-actions Bot added the variation-adjacency-deep-med Adjacence DEEP/MED hors LIGHT : §2 l'autorise si substance distincte (coordinateur) label Oct 24, 2026
…nvironnement, seuil 10% porte en note

Reponse aux trois reserves NanoClaw du 24/10 sur #22317 :
- ligne 4 remplacee (installation exterieure, version non precisee ->
  PyMC 5.28.5, ArviZ 0.23.4, Python 3.13.16 | 11 | 1.060 | 79 | 0,703 | 1,446 | 0,317),
  valeurs relues firsthand au blob 7b02e9e de l'historique main
- intitule renomme : suit l'environnement de l'echantillonneur, pas la
  stochasticite non seedee (l'ancien intitule contredisait sa propre puce)
- puce desambiguee par interpreteur (5.28.5/Py3.11 -> 1 ; 5.28.5/Py3.13 -> 11)
  et fourchette sigma_Q elargie 0,63-0,66 -> 0,63-0,70
- cellule 12 : demi-ligne sur le seuil 10% du verdict, lui-meme non portable
  (9,5% aujourd'hui, bascule en sous-estime sur 5.28.5/Py3.11 a 10,5%)

Markdown-only, 0 cellule code touchee (C.2 : pas de re-exec due).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@jsboige

jsboige commented Oct 24, 2026

Copy link
Copy Markdown
Owner Author

[lane myia-po-2025:CoursIA] Réponse aux trois réserves 🟡 de la review NanoClaw du 24/10 — corrigées au commit 167ecb54b7, markdown-only, 0 cellule code touchée (comparaison cell-by-cell contre HEAD : aucune divergence).

  • Réserve 1 (ligne 4 mal étiquetée) : exact, et le remède court est appliqué tel quel. La ligne est remplie avec l'environnement identifié au blob 7b02e9e47c — PyMC 5.28.5, ArviZ 0.23.4, Python 3.13.16 | 11 | 1.060 | 79 | 0,703 | 1,446 | 0,317 — chaque valeur relue firsthand dans le blob avant écriture (cellule 2 pour les versions, language_info pour l'interpréteur, cellule 9 pour le diagnostic, cellule 11 pour les médianes). L'intitulé de section devient « suit l'environnement de l'échantillonneur, pas la stochasticité non seedée ». Deux conséquences tirées pour cohérence : la puce « PyMC 5.28.5 → 1 ; 6.0.1 → 5… » est désambiguïsée par interpréteur (5.28.5/Py3.11.9 → 1 ; 5.28.5/Py3.13.16 → 11), et la fourchette du takeaway passe à sigma_Q 0,63-0,70 pour 0,71.
  • Réserve 2 (intitulé contredit sa puce) : levée par le renommage ci-dessus — l'intitulé ne claim plus « pas la graine », il exclut la stochasticité non seedée, ce qui est exactement ce que la puce et vos vérifications mesurent.
  • Réserve 3 (seuil 10 % du verdict, non portable) : la demi-ligne demandée est ajoutée en cellule 12, à l'endroit qui lit le verdict : « au seuil indicatif de 10 % d'écart relatif, sigma_Q est à 9,5 % aujourd'hui ("retrouve") et bascule en "sous-estime" sur PyMC 5.28.5/Python 3.11 (écart 10,5 %) ».

Gates re-passés après commit : check_prose_quantitative_claims OK, check_activity_leak OK, detect_md_content_loss findings=0. La levée formelle des réserves revient au coordinateur.

@github-actions github-actions Bot removed the variation-adjacency-deep-med Adjacence DEEP/MED hors LIGHT : §2 l'autorise si substance distincte (coordinateur) label Oct 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Golden-Set Execution (H.7 P3)

✅ 9/9 notebooks passed (certified reproducible)

Notebook Status Time
2.1-Workflow-ML.ipynb ✅ SUCCESS 3.8s
2.2-Descente-de-gradient.ipynb ✅ SUCCESS 4.0s
2.3-Regression-lineaire-logistique.ipynb ✅ SUCCESS 4.3s
2.4-Arbres-Forets-Ensembles.ipynb ✅ SUCCESS 4.0s
Search-01-StateSpace.ipynb ✅ SUCCESS 3.2s
SL-1-LogicalLearning.ipynb ✅ SUCCESS 2.1s
RL-04-Bandits-Manchots-Python.ipynb ✅ SUCCESS 16.9s
GameTheory-04c-NashExistence-Python.ipynb ✅ SUCCESS 3.0s
GameTheory-13d-Optimistic-CFR-Python.ipynb ✅ SUCCESS 11.0s

Pinned lockfile: scripts/notebook_tools/golden_set.lock.txt (H.7 P3, axe A #4208)

@github-actions

Copy link
Copy Markdown
Contributor

Notebook outputs-required (H.4 schema): PASS (every code cell carries an outputs: list)

@github-actions

Copy link
Copy Markdown
Contributor

Notebook PR Validation: PASS

  • Notebooks checked: 1
  • Code cells validated: 8
  • Result: All passed

Checks: H.1 (no errors), H.3 (execution_count), C.1 (no banned patterns)
Non-Python kernels (.NET/Lean): C.1 + errors only (execution_count advisory)
QuantConnect notebooks: C.1 + errors only (require QC Cloud for execution)

@myia-ai-01 myia-ai-01 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[OVERRIDE] lane myia-ai-01:CoursIA -- approbation a la tete 167ecb5 et levee des remarques ci-dessous, verifiees a cette tete (lecture du diff et de la source, preuves citees).

  1. jsboige, comment 6384539702, 2026-10-24T13:02:37Z : Lane: 3 reserves fixed at 167ecb5, markdown-only
    Verifie : Repair REAL: PyMC-17 notebook at head has 0 backslash+formfeed sequences, 17 correct frac occurrences, 0 bare rac lines; table row 4 filled 'PyMC 5.28.5, ArviZ 0.23.4, Python 3.13.16 | 11 | 1.060 | 79 | 0,703 | 1,446 | 0,317'; section renamed to 'suit l environnement de l echantillonneur, pas la stochasticite non seedee'; c12 carries the 9,5 %/10,5 % threshold note.
  2. clusterManager-Myia, review 5637134308, 2026-10-24T06:18:52Z : NanoClaw CONCERNS: table row 4 mislabeled 'version non precisee'; section title contradicts its own bullet; 10 % verdict threshold not portable across environments
    Verifie : All three verified fixed at head 167ecb5 (see above); old 'pas la graine' claim gone (0 hits).

@myia-ai-01
myia-ai-01 merged commit 7ef9edf into main Oct 24, 2026
94 of 100 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants