Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 59 additions & 52 deletions MyIA.AI.Notebooks/Probas/PyMC/PyMC-04-Bayesian-Networks.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -784,58 +784,7 @@
"metadata": {},
"source": [
"On observe que l'herbe est mouillee (WetGrass = True). Quelle est la probabilite que l'arroseur soit actif ? Qu'il ait plu ?\n",
"\n",
"### Sortie verbatim code[5]\n",
"\n",
"- Multiprocess sampling (4 chains in 4 jobs)\n",
"- BinaryGibbsMetropolis: [cloudy, sprinkler, rain]\n",
"- Sampling 4 chains for 1_000 tune and 10_000 draw iterations (4_000 + 40_000 draws total) took 26 seconds.\n",
"- Posterior (WetGrass = True observe) :\n",
" - `P(Sprinkler=1 | WetGrass=1) = 0.429 (theorie: ~0.43)`\n",
" - `P(Rain=1 | WetGrass=1) = 0.707 (theorie: ~0.71)`\n",
" - `P(Cloudy=1 | WetGrass=1) = 0.575`\n",
"\n",
"### Lecture\n",
"\n",
"- **P(S=1 | W=1) = 0.43** : sachant que l'herbe est mouillee, on a 43% de chances que l'arroseur ait fonctionne (vs 30% marginal). L'augmentation est modeste car Sprinkler est un « mauvais » predicteur de W (peut etre inactif même si W=1).\n",
"- **P(R=1 | W=1) = 0.71** : la pluie est un meilleur predicteur de W (forte probabilite conditionnelle).\n",
"- **P(C=1 | W=1) = 0.58** : probabilite accrue de nuageux (passe de 0.50 a 0.58), via les chaines causales S et R.\n",
"\n",
"### Implementation technique\n",
"\n",
"L'observation est faite via le paramètre `observed=1` de `pm.Bernoulli` :\n",
"```python\n",
"with pm.Model() as wet_grass_obs:\n",
" ...\n",
" p_w = pt.switch(\n",
" pt.eq(sprinkler, 1),\n",
" pt.switch(pt.eq(rain, 1), 0.99, 0.90),\n",
" pt.switch(pt.eq(rain, 1), 0.90, 0.00),\n",
" )\n",
" wetgrass = pm.Bernoulli('wetgrass', p=p_w, observed=1)\n",
"\n",
" trace_obs = pm.sample(10000, random_seed=42, return_inferencedata=True)\n",
"```\n",
"\n",
"`pm.Potential` est une variante possible (vraisemblance ajoutée manuellement, utile pour des observations bruitées), mais `observed=1` est la forme canonique utilisée dans ce notebook.\n",
"\n",
"### Pourquoi pas un posterior exact ?\n",
"\n",
"Avec 4 variables booleennes, on pourrait calculer **P(S | W=1)** par enumeration exacte :\n",
"```python\n",
"# P(S=1, W=1) = sum_{C, R} P(C) P(S=1|C) P(R|C) P(W=1|S=1, R)\n",
"# = 0.5 * 0.1 * (0.8 * 0.99 + 0.2 * 0.9) + 0.5 * 0.5 * (0.8 * 0.9 + 0.2 * 0)\n",
"# = 0.5 * 0.1 * 0.972 + 0.5 * 0.5 * 0.72\n",
"# = 0.0486 + 0.18 = 0.2286\n",
"# P(W=1) = 0.643 (marginal calculee)\n",
"# P(S=1 | W=1) = 0.2286 / 0.643 = 0.356\n",
"```\n",
"\n",
"Hmm, ca ne correspond pas exactement aux 0.43 obtenu par MCMC. La difference vient du bruit MCMC (4 chains * 10000 draws = 40000 échantillons, erreur ~1/sqrt(40000) = 0.005). Acceptable pour un notebook pedagogique.\n",
"\n",
"### A retenir\n",
"\n",
"Pour des réseaux de taille raisonnable (< 20 variables), l'enumeration exacte est preferable (calcul exact en O(2^N)). Au-dela, on passe au MCMC (échantillonnage approximate) ou au belief propagation (si le graphe est un arbre ou un poly-arbre)."
"\n"
]
},
{
Expand Down Expand Up @@ -945,6 +894,64 @@
"print(f\"P(Cloudy=1 | WetGrass=1) = {c_obs.mean():.3f}\")"
]
},
{
"cell_type": "markdown",
"id": "pymc04-lecture-cond-wetgrass",
"metadata": {},
"source": [
"### Sortie verbatim code[5]\n",
"\n",
"- Multiprocess sampling (4 chains in 4 jobs)\n",
"- BinaryGibbsMetropolis: [cloudy, sprinkler, rain]\n",
"- Sampling 4 chains for 1_000 tune and 10_000 draw iterations (4_000 + 40_000 draws total) took 26 seconds.\n",
"- Posterior (WetGrass = True observe) :\n",
" - `P(Sprinkler=1 | WetGrass=1) = 0.429 (theorie: ~0.43)`\n",
" - `P(Rain=1 | WetGrass=1) = 0.707 (theorie: ~0.71)`\n",
" - `P(Cloudy=1 | WetGrass=1) = 0.575`\n",
"\n",
"### Lecture\n",
"\n",
"- **P(S=1 | W=1) = 0.43** : sachant que l'herbe est mouillee, on a 43% de chances que l'arroseur ait fonctionne (vs 30% marginal). L'augmentation est modeste car Sprinkler est un « mauvais » predicteur de W (peut etre inactif même si W=1).\n",
"- **P(R=1 | W=1) = 0.71** : la pluie est un meilleur predicteur de W (forte probabilite conditionnelle).\n",
"- **P(C=1 | W=1) = 0.58** : probabilite accrue de nuageux (passe de 0.50 a 0.58), via les chaines causales S et R.\n",
"\n",
"### Implementation technique\n",
"\n",
"L'observation est faite via le paramètre `observed=1` de `pm.Bernoulli` :\n",
"```python\n",
"with pm.Model() as wet_grass_obs:\n",
" ...\n",
" p_w = pt.switch(\n",
" pt.eq(sprinkler, 1),\n",
" pt.switch(pt.eq(rain, 1), 0.99, 0.90),\n",
" pt.switch(pt.eq(rain, 1), 0.90, 0.00),\n",
" )\n",
" wetgrass = pm.Bernoulli('wetgrass', p=p_w, observed=1)\n",
"\n",
" trace_obs = pm.sample(10000, random_seed=42, return_inferencedata=True)\n",
"```\n",
"\n",
"`pm.Potential` est une variante possible (vraisemblance ajoutée manuellement, utile pour des observations bruitées), mais `observed=1` est la forme canonique utilisée dans ce notebook.\n",
"\n",
"### Pourquoi pas un posterior exact ?\n",
"\n",
"Avec 4 variables booleennes, on pourrait calculer **P(S | W=1)** par enumeration exacte :\n",
"```python\n",
"# P(S=1, W=1) = sum_{C, R} P(C) P(S=1|C) P(R|C) P(W=1|S=1, R)\n",
"# = 0.5 * 0.1 * (0.8 * 0.99 + 0.2 * 0.9) + 0.5 * 0.5 * (0.8 * 0.9 + 0.2 * 0)\n",
"# = 0.5 * 0.1 * 0.972 + 0.5 * 0.5 * 0.72\n",
"# = 0.0486 + 0.18 = 0.2286\n",
"# P(W=1) = 0.643 (marginal calculee)\n",
"# P(S=1 | W=1) = 0.2286 / 0.643 = 0.356\n",
"```\n",
"\n",
"Hmm, ca ne correspond pas exactement aux 0.43 obtenu par MCMC. La difference vient du bruit MCMC (4 chains * 10000 draws = 40000 échantillons, erreur ~1/sqrt(40000) = 0.005). Acceptable pour un notebook pedagogique.\n",
"\n",
"### A retenir\n",
"\n",
"Pour des réseaux de taille raisonnable (< 20 variables), l'enumeration exacte est preferable (calcul exact en O(2^N)). Au-dela, on passe au MCMC (échantillonnage approximate) ou au belief propagation (si le graphe est un arbre ou un poly-arbre)."
]
},
{
"cell_type": "markdown",
"id": "a16f54de",
Expand Down
79 changes: 29 additions & 50 deletions MyIA.AI.Notebooks/Probas/PyMC/PyMC-11-Topic-Models.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@
"\n",
"### Verbatim code[0] : setup PyMC\n",
"\n",
"La cellule suivante charge PyMC 5.28.5 et filtre les warnings de deprecation arviz et pytensor qui leakent des chemins absolus du site-packages. On capture la version pour la tracer dans le notebook."
"La cellule code[0] ci-dessus charge PyMC 5.28.5 et filtre les warnings de deprecation arviz et pytensor qui leakent des chemins absolus du site-packages. On capture la version pour la tracer dans le notebook."
]
},
{
Expand Down Expand Up @@ -407,18 +407,6 @@
},
"tags": []
},
"source": [
"### Representation bag-of-words\n",
"\n",
"Les 5 documents generes illustrent bien la structure thematique : le document 0 contient surtout des mots de Science (atome, expérience, théorie), le document 1 des mots de Sport (équipe, ballon), et le document 2 des mots de Cuisine (recette, ingredient). Les documents 3 et 4 sont des melanges plus equilibrés.\n",
"\n",
"La cellule suivante construit la matrice bag-of-words (comptes absolus par document et par mot), qui sera l'observation directe du modèle LDA. Cette representation ignore l'ordre des mots et ne conserve que leurs frequences."
]
},
{
"cell_type": "markdown",
"id": "fuse-4",
"metadata": {},
"source": [
"Les 5 documents générés illustrent bien la structure thématique :\n",
"\n",
Expand All @@ -436,7 +424,9 @@
"- **TF-IDF** : normalise par la fréquence documentaire inverse (idf). Donne plus de poids aux mots rares.\n",
"- **Word embeddings** (Word2Vec, GloVe) : représentation dense, capture la sémantique. Incompatible avec LDA classique (qui veut des comptes).\n",
"\n",
"Pour LDA, le BoW ou TF-IDF est obligatoire : on échantillonne des indices dans un vocabulaire fini."
"Pour LDA, le BoW ou TF-IDF est obligatoire : on échantillonne des indices dans un vocabulaire fini.\n",
"\n",
"La cellule suivante construit la matrice bag-of-words (comptes absolus par document et par mot), qui sera l'observation directe du modèle LDA. Cette representation ignore l'ordre des mots et ne conserve que leurs frequences."
]
},
{
Expand Down Expand Up @@ -675,40 +665,8 @@
"source": [
"### Interpretation de l'echantillonnage avec priors symetriques\n",
"\n",
"L'echantillonnage NUTS a converge avec des priors uniformes (Dirichlet(1,...,1)) sur phi et theta. En sortie, les trois sujets presentent des distributions de mots quasi-identiques, avec les mêmes mots dominants (atome, recette, four) dans des proportions similaires (~0.11-0.15). Les proportions theta sont également uniformes (~0.33 par sujet pour chaque document).\n",
"\n",
"Ce résultat est le **problème de symetrie** attendu : sans information a priori pour differencier les sujets, l'echantillonneur ne peut pas les distinguer et converge vers une solution ou tous les sujets sont identiques. La cellule suivante affiche les distributions estimees et confirme cette non-differenciation."
]
},
{
"cell_type": "markdown",
"id": "fuse-6",
"metadata": {},
"source": [
"**Sortie verbatim code[4]** :\n",
"\n",
"```\n",
"Resultats LDA avec priors symetriques :\n",
"(Attendu : distributions dégénérées / uniformes)\n",
"\n",
" Sujet 0 : recette (0.151), atome (0.146), four (0.125), ingredient (0.113)\n",
" Sujet 1 : atome (0.148), recette (0.146), four (0.126), ingredient (0.110)\n",
" Sujet 2 : recette (0.148), atome (0.146), four (0.124), ingredient (0.111)\n",
"```\n",
"\n",
"**Diagnostic** : les 3 sujets ont des distributions de mots quasi-identiques. Aucun n'a spécialisé un mot-canon (`atome` ne se retrouve pas dans un seul sujet). Les proportions theta sont uniformes (~ 1/3 partout).\n",
"\n",
"### Pourquoi ?\n",
"\n",
"Le **posterior symétrique** est invariant sous permutation des indices de sujets. Si le prior est Dirichlet(1) (uniforme), la posterior reste symétrique. Pour briser la symétrie, il faut :\n",
"\n",
"1. **Asymétriser le prior** (section 4) : beta_jk >> 1 pour le mot-canon de chaque sujet.\n",
"2. **Asymétriser le posterior** par post-traitement (Hungarian matching sur la matrice de confusion phi x phi_target).\n",
"3. **Asymétriser l'initialisation** de l'optimiseur NUTS (seed asymétrique), mais cela ne suffit pas seul.\n",
"\n",
"### Métrique de diagnostic\n",
"\n",
"Pour quantifier la degenerescence : calculer la **Jensen-Shannon Divergence (JSD)** moyenne entre paires de sujets. Si JSD_moy ~ 0, les sujets sont indistinguables. Si JSD_moy > 0.3 bits, ils sont bien séparés."
"L'echantillonnage NUTS **signale un probleme de convergence** sous priors symetriques : le journal affiche `The rhat statistic is larger than 1.01 for some parameters` -- les 4 chaines ne convergent pas vers la meme posterior. C'est **attendu** sous prior symetrique : la cellule markdown au-dessus l'explique, les labels de sujet sont interchangeables et les chaines trouvent des posterior symetriques mais distincts. La sortie ci-dessous le confirme (sujets interchangeables, theta proche de 1/3). Le remede (prior informatif ou initialisation asymetrique) est le sujet de la section suivante.\n",
""
]
},
{
Expand Down Expand Up @@ -783,9 +741,30 @@
"id": "fuse-7",
"metadata": {},
"source": [
"### Lecture du piegé de la symétrie (code[4])\n",
"**Sortie verbatim code[4]** :\n",
"\n",
"```\n",
"Resultats LDA avec priors symetriques :\n",
"(Attendu : distributions dégénérées / uniformes)\n",
"\n",
" Sujet 0 : recette (0.151), atome (0.146), four (0.125), ingredient (0.113)\n",
" Sujet 1 : atome (0.148), recette (0.146), four (0.126), ingredient (0.110)\n",
" Sujet 2 : recette (0.148), atome (0.146), four (0.124), ingredient (0.111)\n",
"```\n",
"\n",
"**Diagnostic** : les 3 sujets ont des distributions de mots quasi-identiques. Aucun n'a spécialisé un mot-canon (`atome` ne se retrouve pas dans un seul sujet). Les proportions theta sont uniformes (~ 1/3 partout).\n",
"\n",
"### Pourquoi ?\n",
"\n",
"Le **posterior symétrique** est invariant sous permutation des indices de sujets. Si le prior est Dirichlet(1) (uniforme), la posterior reste symétrique. Pour briser la symétrie, il faut :\n",
"\n",
"1. **Asymétriser le prior** (section 4) : beta_jk >> 1 pour le mot-canon de chaque sujet.\n",
"2. **Asymétriser le posterior** par post-traitement (Hungarian matching sur la matrice de confusion phi x phi_target).\n",
"3. **Asymétriser l'initialisation** de l'optimiseur NUTS (seed asymétrique), mais cela ne suffit pas seul.\n",
"\n",
"### Métrique de diagnostic\n",
"\n",
"**Sortie verbatim code[4]** : 3 sujets avec distributions de mots quasi-identiques (`recette (0.151), atome (0.146), four (0.125)...` pour les 3 sujets), proportions theta uniformes (~ 1/3 partout).\n",
"Pour quantifier la degenerescence : calculer la **Jensen-Shannon Divergence (JSD)** moyenne entre paires de sujets. Si JSD_moy ~ 0, les sujets sont indistinguables. Si JSD_moy > 0.3 bits, ils sont bien séparés.\n",
"\n",
"### Pourquoi c'est pédagogiquement important\n",
"\n",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
date: '2026-09-28'
by: myia-po-2026:CoursIA-2
python_sha: b2d6e114720f653f88fd2c54c76dc6161388c34b
csharp_sha: 92a4ecccea9194729cbdeddb07572ac1ace6fea2
content_python_sha: 67799204f879c618da14a371092c222876da066624bc1b2230e230fca5579171
content_csharp_sha: 766a68b5bce8373dd4341e0cdd124468c0bd5940acfc72abd1e3c5bffe750d90
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
date: '2026-09-28'
by: myia-po-2026:CoursIA-2
python_sha: a241352b18595e9e407c3d1b63cb8c7aca4e74f5
csharp_sha: 92a4ecccea9194729cbdeddb07572ac1ace6fea2
content_python_sha: c594635de780165224937cdfcd5e3aa90dafafc61323a84d8d6300c9db2c8c56
content_csharp_sha: 766a68b5bce8373dd4341e0cdd124468c0bd5940acfc72abd1e3c5bffe750d90
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
date: '2026-09-28'
by: myia-po-2026:CoursIA-2
python_sha: be4e3223cb27ce55f9f3f9c7ea1325fe2b380321
csharp_sha: 7ef2d50f2dcddfb3024681fbc29090726fc2b820
content_python_sha: b2fb46018ecaeddc158c5aa50050c54afd2d907cf488ed9666235277cc608b82
content_csharp_sha: ba77fc9181856b651a433cca726ef3c461b2c9369628f3068b7db92bf2a25879
Loading