Séance 5 — L’IA qui doute

Raisonner sous incertitude~: probabilités, Bayes, réseaux bayésiens

Dr. El Hadji Bassirou TOURÉ

Département de Mathématiques et Informatique, Faculté des Sciences et Techniques, Université Cheikh Anta Diop de Dakar

Objectifs de la séance

Ce que la séance construit

Raisonner quand le monde n’est pas connu avec certitude : remplacer le vrai et le faux par un degré de croyance, le mettre à jour par le théorème de Bayes à chaque observation, puis représenter un monde de nombreuses variables par un réseau bayésien et y calculer, sur le diagnostic de Fatou à Dakar.

  • Construire une distribution jointe, marginaliser, conditionner.
  • Appliquer le théorème de Bayes : prior, vraisemblance, évidence, posterior, en table.
  • Enchaîner les mises à jour, et lire l’effet d’une preuve contradictoire.
  • Construire un réseau bayésien, écrire sa factorisation, compter ses paramètres.
  • Décider d’une indépendance par la d-séparation, sans calcul.
  • Calculer une probabilité par énumération et par élimination de variables.
  • Relier Naive Bayes au diagnostic, et au cours de Machine Learning.

Le diagnostic de Fatou

Le cas de la séance

Août, saison des pluies. Fatou, 28 ans, consulte le Dr Ndoye au centre de santé de la Médina, à Dakar, pour une fièvre. Paludisme, grippe ou autre cause ? Le médecin dispose de trois observations : les frissons, la température et un test de diagnostic rapide (TDR).

La logique se heurte à l’ambiguïté

\(\text{fièvre}\land\text{frissons}\Rightarrow\text{paludisme}\) ? Les mêmes symptômes accompagnent la grippe ou la typhoïde : la même prémisse mènerait à des conclusions contradictoires.

La recherche suppose un monde certain

A* demande un état connu, des actions au résultat sûr et des coûts connus. Le médecin ne voit pas la maladie, et un test peut se tromper.

Lecture. Il faut un langage qui exprime « probablement le paludisme », et une règle pour réviser ce jugement quand une observation arrive.

Les trois sources d’incertitude

D’où vient l’incertitude d’un agent

  1. Observabilité partielle : l’agent voit les symptômes, pas la maladie ; le joueur de poker voit ses cartes, pas celles de l’adversaire.
  2. Non-déterminisme : deux patients atteints de la même maladie ne présentent pas les mêmes symptômes ; un test donne parfois un faux positif.
  3. Ignorance : certains facteurs sont inconnus ou trop nombreux pour être tous modélisés (terrain génétique, piqûres de la nuit précédente).

Lecture. Ce sont les environnements « partiellement observables » et « stochastiques » du tableau de la Séance 1, celui où le diagnostic médical avait été classé.

Du vrai et du faux au degré de croyance

logique (Séance 2) probabilités
valeurs vrai, faux \([0,1]\)
opérateurs \(\land,\lor,\neg,\Rightarrow\) \(P(\cdot)\), \(P(\cdot\mid\cdot)\)
raisonnement modus ponens, résolution théorème de Bayes
monde supposé certain, complet incertain, incomplet

Lecture. « Probablement le paludisme » devient \(P(\text{palu})=0{,}711\) ; avec 0 et 1 seulement, on retrouve la logique.

Variables aléatoires

Pour raisonner sur ce qu’il ne sait pas, l’agent commence par le nommer.

Variable aléatoire

Une variable aléatoire \(X\) prend ses valeurs dans un domaine \(\mathrm{Dom}(X)\) : booléen (frissons), discret (maladie), continu (température en degrés). Majuscule pour la variable, minuscule pour une valeur : \(M=\text{palu}\).

variable domaine rôle pour le Dr Ndoye
\(M\) (maladie) {palu, grippe, autre} cachée la cause, qu’il ne voit pas
\(Fr\) (frissons) {vrai, faux} observée examen clinique
\(T\) (température) {très haute, haute} observée thermomètre (\(>39{,}5\) °C)
\(TDR\) (test rapide) {\(+\), \(-\)} observée test sanguin du paludisme

Lecture. La maladie est l’état caché du monde ; frissons, température et test sont les capteurs. Diagnostiquer, c’est inférer la variable cachée à partir des observées.

Distribution et axiomes de Kolmogorov

Distribution de probabilité

Une fonction \(P:\mathrm{Dom}(X)\to[0,1]\) telle que \(\sum_x P(X=x)=1\) : on répartit un « budget de croyance » égal à 1 entre les valeurs.

Axiomes (Kolmogorov, 1933)

Un événement \(A\) est un sous-ensemble de l’ensemble \(\Omega\) des résultats possibles, par exemple \(\{M=\text{palu}\}\). \(P(A)\geq0\) ; \(P(\Omega)=1\) ; si \(A\cap B=\emptyset\), \(P(A\cup B)=P(A)+P(B)\). D’où \(P(\neg A)=1-P(A)\).

Le prior d’août

Registres du centre : sur 500 patients fiévreux en août, 200 paludismes, 175 grippes, 125 autres causes.

\(m\) cas \(P(M=m)\)
palu 200 \(0{,}40\)
grippe 175 \(0{,}35\)
autre 125 \(0{,}25\)
total 500 \(1{,}00\)

Lecture. \(P(M\neq\text{palu})=1-0{,}40=0{,}60\). Cette distribution, connue avant d’examiner Fatou, est le prior.

Deux lectures d’une probabilité

Lecture fréquentiste

\(P(\text{palu})=0{,}40\) : sur un grand nombre de patients fiévreux en août, 40 % ont le paludisme. Une propriété de la population, mesurée par une fréquence.

Lecture bayésienne

\(P(\text{palu})=0{,}40\) : le degré de croyance du Dr Ndoye, étant donné ce qu’il sait. Un état de connaissance, révisé à chaque observation.

La lecture retenue en IA

La lecture bayésienne modélise un agent qui apprend : chaque frisson, chaque mesure, chaque test met à jour sa croyance. En Machine Learning, l’apprentissage bayésien met à jour de la même façon une croyance sur les paramètres d’un modèle, les données jouant le rôle des observations.

Les données du diagnostic en Python

PRIOR = {"palu": 0.40, "grippe": 0.35, "autre": 0.25}    # fievre en aout a Dakar
FR = {"palu": 0.80, "grippe": 0.30, "autre": 0.10}       # P(Fr = vrai | M)
TE = {"palu": 0.70, "grippe": 0.20, "autre": 0.05}       # P(T = tres haute | M)
TDR = {"palu": 0.95, "grippe": 0.10, "autre": 0.10}      # P(TDR = + | M)
print(sum(PRIOR.values()))
print(1 - PRIOR["palu"])

Résultat \(\rightarrow\)

1.0
0.6

Lecture. Un dictionnaire par distribution : le prior d’août, puis, pour chaque maladie, la probabilité d’observer des frissons, une température très haute, un TDR positif. La somme du prior vaut 1.

La distribution jointe

Distribution jointe

\(P(X=x,Y=y)\) pour chaque couple de valeurs ; la somme de toutes les cases vaut 1. Elle contient toute l’information sur la relation entre \(X\) et \(Y\).

D’où vient une case

40 % des patients ont le paludisme, et 80 % d’entre eux ont des frissons : \(P(\text{palu},\text{oui})=0{,}40\times0{,}80=0{,}320\).

\(Fr=\) oui \(Fr=\) non total
palu \(0{,}320\) \(0{,}080\) \(0{,}40\)
grippe \(0{,}105\) \(0{,}245\) \(0{,}35\)
autre \(0{,}025\) \(0{,}225\) \(0{,}25\)
total \(0{,}450\) \(0{,}550\) \(1{,}00\)

Lecture. Six cases, de somme 1. Toute question sur la maladie et les frissons se lit dans ce tableau ; le pas à pas qui suit le construit.

La jointe, la marge, le zoom, pas à pas

Sortie \(\rightarrow\)

0.45
{'palu': 0.711, 'grippe': 0.233, 'autre': 0.056}

Lecture. Tour 1 : règle du produit : \(P(\text{palu},\text{oui})=0,400\times0,800=0,320\), \(P(\text{palu},\text{non})=0,400\times0,200=0,080\).

Lecture. Tour 2 : règle du produit : \(P(\text{grippe},\text{oui})=0,350\times0,300=0,105\), \(P(\text{grippe},\text{non})=0,350\times0,700=0,245\).

Lecture. Tour 3 : règle du produit : \(P(\text{autre},\text{oui})=0,250\times0,100=0,025\), \(P(\text{autre},\text{non})=0,250\times0,900=0,225\).

Lecture. Ligne 7 : marginalisation, on ajoute la case (palu, oui) ; somme partielle 0,320.

Lecture. Ligne 7 : marginalisation, on ajoute la case (grippe, oui) ; somme partielle 0,425.

Lecture. Ligne 7 : marginalisation, on ajoute la case (autre, oui) ; somme partielle 0,450.

Lecture. Ligne 10 : zoom sur Fr = oui : \(P(\text{palu}\mid\text{oui})=0,320/0,450=0,711\).

Lecture. Ligne 10 : zoom sur Fr = oui : \(P(\text{grippe}\mid\text{oui})=0,105/0,450=0,233\).

Lecture. Ligne 10 : zoom sur Fr = oui : \(P(\text{autre}\mid\text{oui})=0,025/0,450=0,056\).

Lecture. Ligne 11 : 45 % des patients fiévreux ont des frissons.

Lecture. Ligne 12 : la conditionnelle somme à 1 ; le paludisme passe de 0,40 à 0,711.

La marginalisation

Faire disparaître une variable

\[ P(X=x)=\sum_{y\in\mathrm{Dom}(Y)}P(X=x,Y=y) \]

On somme la ligne (ou la colonne) : le résultat s’écrit dans la marge du tableau, d’où le nom.

Sur le tableau des frissons

\(P(\text{palu})=0{,}320+0{,}080=0{,}40\) : on retrouve le prior. \(P(Fr=\text{oui})=0{,}320+0{,}105+0{,}025=0{,}45\) : 45 % des patients fiévreux ont des frissons, toutes causes confondues.

Lecture. Marginaliser, c’est répondre à une question qui ignore une variable ; c’est l’opération que l’inférence répétera dans les réseaux bayésiens.

La probabilité conditionnelle, un zoom

Probabilité conditionnelle

\[ P(X=x\mid Y=y)=\frac{P(X=x,Y=y)}{P(Y=y)} \]

défini si \(P(Y=y)>0\) ; « \(\mid\) » se lit « sachant ».

Observer \(Fr=\) oui, c’est ne garder que la colonne des frissons, puis la diviser par son total pour qu’elle somme à 1.

Lecture. \(P(\text{palu}\mid Fr)=0{,}320/0{,}450=32/45\approx0{,}711\), \(P(\text{grippe}\mid Fr)\approx0{,}233\), \(P(\text{autre}\mid Fr)\approx0{,}056\) : l’observation redistribue la croyance.

La règle du produit et l’indépendance

Règle du produit

\[ P(X,Y)=P(X\mid Y)\,P(Y)=P(Y\mid X)\,P(X) \]

C’est elle qui a rempli le tableau : \(P(\text{palu},\text{oui})=P(\text{oui}\mid\text{palu})\,P(\text{palu})=0{,}80\times0{,}40\).

Indépendance

\(X\perp Y\) si \(P(X,Y)=P(X)\,P(Y)\), autrement dit \(P(X\mid Y)=P(X)\) : observer \(Y\) ne change rien à la croyance sur \(X\).

Lecture. Ici \(P(\text{palu}\mid Fr)=0{,}711\neq0{,}40\) : maladie et frissons sont dépendants, et c’est pour cela que les frissons informent le diagnostic.

Exercice : la jointe des livraisons de Cheikh

Énoncé

Cheikh, coursier à vélo du Plateau, a noté la météo et la ponctualité de ses 200 dernières livraisons.

  1. La distribution jointe.
  2. Les marges \(P(\text{pluie})\), \(P(\text{retard})\).
  3. \(P(\text{retard}\mid\text{pluie})\), \(P(\text{retard}\mid\text{sec})\).
  4. Pluie et retard sont-ils indépendants ?
  5. \(P(\text{pluie}\mid\text{retard})\).

Correction

  1. Chaque effectif divisé par 200 : \(P(\text{pluie},\text{retard})=0,18\), …  ; somme 1.
  2. Marges : \(P(\text{pluie})=60/200=0,30\), \(P(\text{retard})=64/200=0,32\).
  3. Zoom sur chaque ligne : \(P(\text{retard}\mid\text{pluie})=36/60=0,6\), \(P(\text{retard}\mid\text{sec})=28/140=0,2\).
  4. \(P(\text{pluie})P(\text{retard})=0,096\neq0,18\) : dépendants.
  5. Zoom sur la colonne : \(P(\text{pluie}\mid\text{retard})=36/64=0,5625\), différent de \(P(\text{retard}\mid\text{pluie})=0,6\).

De l’effet à la cause

Le zoom a donné \(P(\text{palu}\mid Fr)\) à partir de la jointe ; le théorème de Bayes l’obtient à partir de ce que l’on connaît d’habitude.

Deux directions

Cause \(\to\) effet : \(P(Fr\mid\text{palu})=0{,}80\), mesurée en suivant des patients diagnostiqués.

Effet \(\to\) cause : \(P(\text{palu}\mid Fr)\), celle dont le médecin a besoin : remonter de l’observation à la cause cachée est un problème d’inférence.

Ne pas confondre \(P(A\mid B)\) et \(P(B\mid A)\)

« 80 % des paludéens ont des frissons » \(\neq\) « 80 % des patients qui ont des frissons sont paludéens » : ici, \(0{,}80\) contre \(0{,}711\). « 95 % des malades sont positifs » \(\neq\) « 95 % des positifs sont malades ». Cette confusion porte un nom, l’erreur du procureur.

Lecture. La population des patients qui frissonnent est plus large que celle des paludéens : les deux probabilités n’ont pas le même dénominateur.

Le théorème de Bayes

Dérivation

La règle du produit écrit la jointe de deux façons : \(P(H,E)=P(E\mid H)P(H)=P(H\mid E)P(E)\). On divise par \(P(E)\) :

\[ P(H\mid E)=\frac{P(E\mid H)\,P(H)}{P(E)} \]

avec \(P(E)=\sum_h P(E\mid h)P(h)\) (probabilités totales).

terme nom rôle
\(P(H)\) prior croyance avant l’observation
\(P(E\mid H)\) vraisemblance compatibilité de \(E\) avec \(H\)
\(P(E)\) évidence normalisation
\(P(H\mid E)\) posterior probabilité a posteriori

posterior \(\propto\) vraisemblance \(\times\) prior

Lecture. Le prior dit ce que l’on croyait, la vraisemblance ce que l’observation y change ; l’évidence ne dépend pas de l’hypothèse et ne sert qu’à normaliser.

Prior, vraisemblance, posterior en barres

Lecture. Le produit garde l’ordre palu, grippe, autre mais creuse les écarts : 0,320 contre 0,105 et 0,025. Divisé par la somme 0,45, il redevient une distribution : 0,711, 0,233, 0,056.

Bayes en table, pas à pas

Sortie \(\rightarrow\) 

{'palu': 0.711, 'grippe': 0.233, 'autre': 0.056}

Lecture. Tour 1 (ligne 4) : palu : prior \(\times\) vraisemblance \(=0,400\times0,800=0,320\).

Lecture. Tour 2 (ligne 4) : grippe : prior \(\times\) vraisemblance \(=0,350\times0,300=0,105\).

Lecture. Tour 3 (ligne 4) : autre : prior \(\times\) vraisemblance \(=0,250\times0,100=0,025\).

Lecture. Ligne 5 : l’évidence \(P(Fr)=z=0,450\), somme des trois produits (probabilités totales).

Lecture. Ligne 8 : posterior de palu : \(0,320/0,450=0,711\).

Lecture. Ligne 8 : posterior de grippe : \(0,105/0,450=0,233\).

Lecture. Ligne 8 : posterior de autre : \(0,025/0,450=0,056\).

Lecture. Ligne 11 : le posterior somme à 1 ; le paludisme passe de 0,40 à 0,711, « autre » de 0,25 à 0,056.

Le rapport de vraisemblance

Deux raisons qui se multiplient

Un prior déjà favorable (\(0{,}40>0{,}35>0{,}25\)), et une vraisemblance élevée : les frissons sont bien plus fréquents avec le paludisme (0,80) qu’avec la grippe (0,30) ou une autre cause (0,10).

Rapport de vraisemblance

\[ \mathrm{LR}(\text{palu}/\text{grippe})=\frac{P(Fr\mid\text{palu})}{P(Fr\mid\text{grippe})}=\frac{0{,}80}{0{,}30}=\frac83\approx2{,}67 \]

La force de la preuve : les frissons sont 2,67 fois plus probables sous l’hypothèse du paludisme que sous celle de la grippe.

Lecture. Le rapport des posteriors est le rapport des priors multiplié par LR : \(\frac{0{,}711}{0{,}233}=\frac{0{,}40}{0{,}35}\times\frac83\).

Même preuve, autre contexte : Paris en janvier

PARIS = {"palu": 0.001, "grippe": 0.700, "autre": 0.299}
post = bayes(PARIS, FR)
print({h: round(p, 3) for h, p in post.items()})

Résultat \(\rightarrow\)

{'palu': 0.003, 'grippe': 0.872, 'autre': 0.124}

Lecture. Les vraisemblances sont les mêmes qu’à Dakar ; seul le prior change, \(P(\text{palu})=0{,}001\). L’évidence vaut \(P(Fr)=0{,}2407\) et le paludisme tombe à 0,003.

Le prior est le contexte

Lieu, saison, population : le prior encode l’environnement de l’agent. La même observation n’a pas le même sens à Dakar en août et à Paris en janvier.

Bayes sous forme de cotes

Cote

\(O(H)=P(H)/P(\neg H)\) : \(O(\text{palu})=0{,}40/0{,}60=2/3\), « 2 contre 3 ».

Cote après \(=\) rapport de vraisemblance \(\times\) cote avant

\[ \frac{P(H\mid E)}{P(\neg H\mid E)}=\frac{P(E\mid H)}{P(E\mid\neg H)}\times\frac{P(H)}{P(\neg H)} \]

Ici \(P(Fr\mid\neg\text{palu})=0{,}13/0{,}60=13/60\), d’où \(\mathrm{LR}=0{,}80/(13/60)=48/13\approx3{,}69\) et une cote après observation de \(\frac23\times\frac{48}{13}=\frac{32}{13}\approx2{,}46\), soit \(P=32/45\).

Lecture. Un LR supérieur à 1 renforce l’hypothèse, inférieur à 1 l’affaiblit, égal à 1 ne dit rien ; c’est la forme employée en médecine.

Quoi, pourquoi, quand ça échoue : le théorème de Bayes

Quoi

Multiplier le prior de chaque hypothèse par la vraisemblance de l’observation, puis normaliser par l’évidence.

Pourquoi c’est exact

C’est la règle du produit lue dans les deux sens : aucune approximation, dès que le prior et les vraisemblances sont justes.

Quand ça échoue

Un prior faux fausse tout (un paludisme jugé impossible, \(P=0\), le reste après n’importe quelle preuve) ; des vraisemblances estimées sur une autre population aussi. Avec \(n\) hypothèses et des observations nombreuses et liées entre elles, la jointe devient impossible à écrire : il faudra les réseaux bayésiens.

La mise à jour séquentielle

Le posterior d’hier est le prior d’aujourd’hui : après les frissons, le Dr Ndoye mesure la température, puis demande un TDR.

Mise à jour séquentielle

  1. Partir du prior \(P(H)\).
  2. Observer \(E_1\) : Bayes donne \(P(H\mid E_1)\).
  3. Le prendre comme prior, observer \(E_2\) : \(P(H\mid E_1,E_2)\), et ainsi de suite.

Indépendance conditionnelle

Utiliser \(P(E_2\mid H)\) seul suppose \(P(E_1,E_2\mid H)=P(E_1\mid H)\,P(E_2\mid H)\) : la maladie connue, les frissons n’apprennent rien sur la température. Hypothèse forte, au cœur de Naive Bayes.

\(h\) \(P(Fr\mid h)\) \(P(T=\text{très haute}\mid h)\) \(P(TDR^+\mid h)\)
palu 0,80 0,70 0,95
grippe 0,30 0,20 0,10
autre 0,10 0,05 0,10

La mise à jour séquentielle, pas à pas

Sortie \(\rightarrow\)

frissons [0.711, 0.233, 0.056]
temperature [0.91, 0.085, 0.005]
TDR+ [0.99, 0.01, 0.001]

Lecture. Initialisation (lignes 1–3) : la croyance de départ est le prior d’août.

Lecture. Tour 1, frissons : le paludisme passe de 0,400 à 0,711 ; ce posterior devient le prior.

Lecture. Tour 2, temperature : le paludisme passe de 0,711 à 0,910 ; ce posterior devient le prior.

Lecture. Tour 3, TDR+ : le paludisme passe de 0,910 à 0,990 ; ce posterior devient le prior.

La preuve contradictoire

NEG = {h: 1 - p for h, p in TDR.items()}   # P(TDR = - | M)
avant = bayes(bayes(PRIOR, FR), TE)
apres = bayes(avant, NEG)
print(round(avant["palu"], 3), round(apres["palu"], 3))
autre_ordre = bayes(bayes(bayes(PRIOR, TDR), TE), FR)
print(round(autre_ordre["palu"], 3))

Résultat \(\rightarrow\)

0.91 0.359
0.99

Lecture. Après frissons et température, 0,910 ; un TDR négatif la fait tomber à 0,359, sans l’annuler. Dans l’ordre TDR, température, frissons : 0,990.

Le raisonnement est symétrique

Une preuve peut renforcer ou affaiblir : tenir compte des seules preuves favorables n’est pas un raisonnement bayésien.

Retour au Monde de Bouki

CASES = [(i, j) for i in range(1, 5) for j in range(1, 5)]
def adjacentes(c):
    i, j = c
    return {(i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)}
P = {c: 1 / 15 for c in CASES if c != (1, 1)}   # Bouki n'est pas au depart
print(len(P), round(P[(2, 2)], 3))
print(sorted(adjacentes((2, 1)) & set(P)))

Résultat \(\rightarrow\)

15 0.067
[(2, 2), (3, 1)]

Ce que disait la logique (Séance 2)

Odeur en \((2,1)\) : \(B_{2,2}\lor B_{3,1}\). Avec un seul Bouki et un odorat infaillible, l’odeur en \((1,2)\) désignerait \((2,2)\). Mais un capteur qui se trompe parfois ne permet plus aucune déduction certaine.

Le modèle probabiliste

Prior uniforme sur les 15 cases autres que le départ ; capteur bruité : \(P(\text{odeur}\mid\text{Bouki voisin})=0{,}9\), \(P(\text{odeur}\mid\text{non voisin})=0{,}05\). Ousmane vivant dans une case : vraisemblance 0 que Bouki y soit.

Le Monde de Bouki probabiliste, pas à pas

Sortie \(\rightarrow\) 

(1, 1) [0.076, 0.076]  (2, 1) [0.382, 0.382]  (1, 2) [0.876, 0.049]

Lecture. Initialisation : Bouki n’est pas au départ ; prior uniforme \(1/15\approx0,067\) sur les 15 autres cases.

Lecture. Tour 1 (lignes 2–10) : en (1,1), rien : \(\times0{,}1\) pour (1,2) et (2,1), \(\times0{,}95\) ailleurs ; \(z=0,837\).

Lecture. Normalisation (lignes 11–12, puis 18) : (1,2) et (2,1) tombent à 0,008, les 13 autres cases montent à 0,076.

Lecture. Tour 2 (lignes 2–10) : Ousmane est vivant en (2, 1) (vraisemblance 0) ; odeur : \(\times0{,}9\) pour ses voisines, \(\times0{,}05\) ailleurs ; \(z=0,1783\).

Lecture. Lignes 11–12, puis 18 : (2,2) et (3,1), voisines de (2,1), montent ensemble à 0,382 : la symétrie n’est pas encore brisée.

Lecture. Tour 3 (lignes 2–10) : Ousmane est vivant en (1, 2) (vraisemblance 0) ; odeur : \(\times0{,}9\) pour ses voisines, \(\times0{,}05\) ailleurs ; \(z=0,3927\).

Lecture. Lignes 11–12, puis 18 : (2,2), voisine de (1,2), monte à 0,876 ; (3,1), qui ne l’est pas, tombe à 0,049.

L’apport des probabilités

La brisure de symétrie

Après \((2,1)\), \((2,2)\) et \((3,1)\) ont la même croyance, 0,382. L’odeur en \((1,2)\) est \(0{,}9/0{,}05=18\) fois plus probable si Bouki est en \((2,2)\), voisine de \((1,2)\), qu’en \((3,1)\) : ce rapport de vraisemblance porte \((2,2)\) à 0,876.

logique (Séance 2) probabilités
conclusion « \((2,2)\) » si l’odorat est infaillible ; aucune déduction s’il se trompe « \((2,2)\) avec 0,876 »
capteur bruité hors du langage modélisé par la vraisemblance
case visitée \(\neg B_{i,j}\) vraisemblance 0, la même élimination
décision explorer \((1,3)\) ou \((3,1)\), sûres éviter \((2,2)\), risque chiffré

Lecture. La logique est le cas limite des vraisemblances 0 et 1. Choisir la case suivante à partir de ces croyances est un problème de décision : la Séance 6.

Exercice : le vélo de Cheikh

Énoncé

Un bruit sur le vélo de Cheikh : chaîne sèche, frein usé ou rayon desserré ? \(E_1\) : bruit au pédalage ; \(E_2\) : bruit au freinage.

  1. Les posteriors après \(E_1\).
  2. Puis après \(E_2\).
  3. Dans l’ordre \(E_2\), \(E_1\).
  4. Le rapport de vraisemblance de \(E_2\), chaîne contre frein.

Correction

  1. Produits 0,40, 0,03, 0,08 ; \(z=0,51\) ; posteriors 0,784, 0,059, 0,157.
  2. Prior \(=\) (a) ; produits 0,0784, 0,0529, 0,0471 ; \(z=0,1784\) ; posteriors 0,440, 0,297, 0,264.
  3. Même résultat (\(40/91\), \(27/91\), \(24/91\)) : le produit des vraisemblances ne dépend pas de l’ordre.
  4. \(P(E_2\mid\text{chaîne})/P(E_2\mid\text{frein})=0{,}1/0{,}9=1/9\) : \(E_2\) divise par 9 la cote de la chaîne contre le frein ; la chaîne reste en tête (0,440), sans certitude.

L’explosion combinatoire de la jointe

Jusqu’ici, deux ou trois variables ; un diagnostic réel en compte des dizaines.

\(n\) variables booléennes paramètres \(2^n-1\)
5 31
10 1 023
20 \(\approx1{,}05\times10^{6}\)
30 \(\approx1{,}07\times10^{9}\)
100 \(\approx1{,}27\times10^{30}\)

Le même mur qu’en Séance 3

Un arbre de recherche de facteur \(b\) a \(b^d\) nœuds au niveau \(d\) ; la jointe de \(n\) variables a \(2^n\) cases. Là-bas, l’heuristique évitait d’explorer tout l’arbre ; ici, les indépendances conditionnelles évitent d’écrire toute la jointe.

Lecture. À 30 variables, un milliard de nombres à estimer et à stocker : impossible à fournir par un expert, et même à apprendre par des données.

L’indépendance conditionnelle

Indépendance conditionnelle

\[ X\perp Y\mid Z\iff P(X,Y\mid Z)=P(X\mid Z)\,P(Y\mid Z) \]

Une fois \(Z\) connu, apprendre \(X\) n’apporte rien sur \(Y\) : toute la dépendance entre \(X\) et \(Y\) passe par \(Z\).

Frissons et TDR

Sans connaître la maladie, un TDR positif rend les frissons plus probables : les deux pointent vers le paludisme. Sachant que Fatou a le paludisme, le TDR n’apprend plus rien sur ses frissons : \(Fr\perp TDR\mid M\).

Lecture. La plupart des variables d’un domaine ne s’influencent pas directement : c’est cette rareté des liens directs que le réseau bayésien exploite.

Réseau bayésien : définition

Réseau bayésien \((\mathcal G,\Theta)\)

\(\mathcal G\) est un graphe orienté acyclique : un nœud par variable, un arc \(X\to Y\) quand \(X\) influence directement \(Y\) (\(X\) est un parent de \(Y\)). \(\Theta\) donne, pour chaque nœud, sa table de probabilités conditionnelles : \(P(X_i\mid\mathrm{Parents}(X_i))\).

Factorisation de la jointe

\[ P(X_1,\dots,X_n)=\prod_{i=1}^n P\big(X_i\mid\mathrm{Parents}(X_i)\big) \]

Exacte quand le graphe décrit les indépendances du domaine.

Lecture. Construire : ordonner les variables des causes vers les effets, donner à chacune pour parents les variables déjà placées qui l’influencent directement, puis sa table.

Le réseau de Fatou

Table illustrative. \(P(S=\text{pluies})=P(Mq=\text{oui})=0{,}5\) ; \(P(Fr\mid M)\), \(P(T\mid M)\), \(P(TDR\mid M)\) : les tables du diagnostic.

Lecture. La moustiquaire divise le paludisme par 4 en saison des pluies, par 9 en saison sèche ; la moyenne sur \(Mq\) redonne le prior d’août, 0,40, 0,35, 0,25.

Le réseau en Python

P_S = {"pluies": 0.5, "seche": 0.5}
P_MQ = {"oui": 0.5, "non": 0.5}                  # dort sous moustiquaire
P_M = {("pluies", "oui"): {"palu": 0.16, "grippe": 0.49, "autre": 0.35},
       ("pluies", "non"): {"palu": 0.64, "grippe": 0.21, "autre": 0.15},
       ("seche", "oui"): {"palu": 0.02, "grippe": 0.49, "autre": 0.49},
       ("seche", "non"): {"palu": 0.18, "grippe": 0.41, "autre": 0.41}}
DOM = {"S": ["pluies", "seche"], "Mq": ["oui", "non"],
       "M": ["palu", "grippe", "autre"], "Fr": [True, False],
       "T": [True, False], "TDR": [True, False]}
print({m: (P_M["pluies", "oui"][m] + P_M["pluies", "non"][m]) / 2
       for m in PRIOR})

Résultat \(\rightarrow\)

{'palu': 0.4, 'grippe': 0.35, 'autre': 0.25}

Lecture. Une table par nœud ; P_M a une ligne par combinaison des parents, et chaque ligne somme à 1. La dernière ligne vérifie le prior d’août.

La jointe factorisée

def p_oui(table, m, x):                          # P(X = x | M = m), X booleen
    return table[m] if x else 1 - table[m]
def jointe_reseau(s, q, m, fr, te, tdr):
    return (P_S[s] * P_MQ[q] * P_M[s, q][m]
            * p_oui(FR, m, fr) * p_oui(TE, m, te) * p_oui(TDR, m, tdr))
total = 0
for x in itertools.product(*DOM.values()):
    total = total + jointe_reseau(*x)
print(round(total, 12))
print(round(jointe_reseau("pluies", "non", "palu", True, True, True), 5))

Résultat \(\rightarrow\)

1.0
0.08512

Lecture. Six facteurs, un par nœud. La somme sur les \(2\times2\times3\times2\times2\times2=96\) configurations vaut 1 ; une configuration : \(0{,}5\times0{,}5\times0{,}64\times0{,}80\times0{,}70\times0{,}95=0{,}08512\).

Compter les paramètres

table paramètres libres
\(P(S)\), \(P(Mq)\) \(1+1\)
\(P(M\mid S,Mq)\) \(4\times2=8\)
\(P(Fr\mid M)\), \(P(T\mid M)\), \(P(TDR\mid M)\) \(3\times3=9\)
réseau 19
jointe brute \(2\cdot2\cdot3\cdot2\cdot2\cdot2-1\) 95

Une colonne, une contrainte

Pour chaque combinaison des parents, les probabilités d’un nœud somment à 1 : une valeur se déduit des autres. Un nœud à \(k\) valeurs et \(q\) combinaisons de parents a \(q(k-1)\) paramètres libres.

Le gain grandit avec le domaine

Une maladie à 3 valeurs et 30 symptômes booléens : \(3\times2^{30}-1\approx3{,}2\times10^9\) paramètres pour la jointe, \(2+30\times3=92\) pour le réseau où chaque symptôme ne dépend que de la maladie.

Exercice : le réseau du retard de Cheikh

Énoncé

Pluie \(P\), embouteillage \(E\), crevaison \(C\), retard \(R\), plainte \(Q\). \(P(P)=0{,}3\) ; \(P(E\mid P)=0{,}7\) ou \(0{,}2\) ; \(P(C)=0{,}1\) ; \(P(R\mid E,C)=0{,}9\), \(0{,}6\), \(0{,}7\), \(0{,}1\) (les deux, \(E\) seul, \(C\) seul, aucun) ; \(P(Q\mid R)=0{,}5\) ou \(0{,}05\).

  1. La factorisation.
  2. Les paramètres, contre la jointe.
  3. \(P(P,E,\neg C,R,Q)\).
  4. \(P(E)\) et \(P(R)\).

Correction

  1. \(P(P,E,C,R,Q)=P(P)\,P(E\mid P)\,P(C)\,P(R\mid E,C)\,P(Q\mid R)\).
  2. \(1+2+1+4+2=10\) paramètres, contre \(2^5-1=31\) pour la jointe.
  3. \(0{,}3\times0{,}7\times(1-0{,}1)\times0{,}6\times0{,}5=0,0567\).
  4. \(P(E)=0{,}3\times0{,}7+0{,}7\times0{,}2=0,35\) ; \(P(R)=0,3245\) (somme sur \(E\) et \(C\)).

Interroger le réseau en sommant la jointe

Toute probabilité conditionnelle se calcule en sommant la jointe factorisée, comme les cases du tableau des frissons.

def prob(requete, obs):
    num = 0
    den = 0
    for x in itertools.product(*DOM.values()):
        a = dict(zip(DOM, x))
        if all(a[v] == obs[v] for v in obs):
            p = jointe_reseau(*x)
            den = den + p
            if all(a[v] == requete[v] for v in requete):
                num = num + p
    return num / den
print(round(prob({"Fr": True}, {"S": "pluies"}), 3))
print(round(prob({"Fr": True}, {"S": "seche"}), 3))

Résultat \(\rightarrow\)

0.45
0.26

Lecture. \(P(Fr\mid\text{pluies})=0{,}45\) et \(P(Fr\mid\text{sèche})=0{,}26\) : sans rien savoir de la maladie, la saison renseigne sur les frissons.

La chaîne et la cause commune

print(round(prob({"Fr": True}, {"S": "seche", "M": "palu"}), 3))
print(round(prob({"TDR": True}, {}), 4))
print(round(prob({"TDR": True}, {"Fr": True}), 4))
print(round(prob({"TDR": True}, {"Fr": True, "M": "palu"}), 3))

Résultat \(\rightarrow\)

0.8
0.3125
0.5789
0.95

Chaîne \(S\to M\to Fr\)

Sans \(M\), \(S\) et \(Fr\) dépendent l’un de l’autre (0,45 contre 0,26). Sachant \(M=\) palu, \(P(Fr)=0{,}8\) en saison sèche comme en saison des pluies : \(S\perp Fr\mid M\). Le nœud du milieu, observé, bloque le passage.

Cause commune \(Fr\leftarrow M\to TDR\)

\(P(TDR^+)=0{,}3125\) monte à \(0{,}5789\) sachant \(Fr\) ; sachant aussi \(M=\) palu, il vaut \(0{,}95\) quoi qu’il en soit des frissons : \(Fr\perp TDR\mid M\).

La v-structure et l’explication concurrente

q = {"Mq": "oui"}
print(round(prob(q, {}), 3), round(prob(q, {"S": "seche"}), 3))
print(round(prob(q, {"M": "palu"}), 3))
print(round(prob(q, {"M": "palu", "S": "seche"}), 3))

Résultat \(\rightarrow\)

0.5 0.5
0.18
0.1

V-structure \(S\to M\leftarrow Mq\)

\(P(Mq)=0{,}5\), en saison sèche aussi : indépendantes. Sachant le paludisme, \(P(Mq)=0{,}18\) ; sachant de plus la saison sèche, 0,1.

Observer l’effet commun ouvre le passage

En saison sèche, le paludisme demande une autre explication : l’absence de moustiquaire. C’est l’explication concurrente {(explaining away)}.

Lecture. Sachant le paludisme, \(P(\text{pluies})=0{,}8\) ; \(8/9\approx0{,}889\) avec moustiquaire, \(32/41\approx0{,}780\) sans.

Les trois motifs

motif sans observer le nœud central en l’observant
chaîne \(A\to B\to C\) \(A\), \(C\) dépendants \(A\perp C\mid B\) : bloque
cause commune \(A\leftarrow B\to C\) \(A\), \(C\) dépendants \(A\perp C\mid B\) : bloque
v-structure \(A\to B\leftarrow C\) \(A\perp C\) \(A\), \(C\) dépendants : ouvre

Le descendant d’une v-structure

Observer un descendant de \(B\) ouvre aussi la v-structure : observer les frissons renseigne sur la maladie, donc \(S\) et \(Mq\) deviennent dépendants sachant \(Fr\).

Le critère de d-séparation

d-séparation (Pearl)

\(X\) et \(Y\) sont d-séparés par \(Z\) si tout chemin non orienté entre \(X\) et \(Y\) est bloqué, un chemin étant bloqué dès qu’il contient :

  • une chaîne ou une cause commune dont le nœud central est dans \(Z\), ou
  • une v-structure dont ni le nœud central ni aucun de ses descendants n’est dans \(Z\).

Théorème

Si \(X\) et \(Y\) sont d-séparés par \(Z\), alors \(X\perp Y\mid Z\) pour toutes les tables compatibles avec le graphe. Un seul chemin actif laisse en général la dépendance.

Lecture. Le critère lit les indépendances dans le graphe, sans un seul calcul ; sur le réseau de Fatou, les 240 requêtes possibles donnent le même verdict que le calcul.

Les chemins du graphe

PARENTS = {"S": [], "Mq": [], "M": ["S", "Mq"], "Fr": ["M"], "T": ["M"], "TDR": ["M"]}
VOISINS = {v: set(PARENTS[v]) for v in PARENTS}
for v in PARENTS:
    for p in PARENTS[v]:
        VOISINS[p].add(v)
def descendants(v):
    d = set()
    for w in PARENTS:
        if v in PARENTS[w]:
            d = d | {w} | descendants(w)
    return d
def chemins(x, y, vus):
    if x == y:
        return [[y]]
    res = []
    for v in sorted(VOISINS[x] - set(vus)):
        for c in chemins(v, y, vus + [v]):
            res.append([x] + c)
    return res

Lecture. Les voisins ignorent le sens des arcs ; chemins énumère les chemins sans nœud répété, descendants suit les arcs vers le bas.

La d-séparation, pas à pas

Sortie \(\rightarrow\)

S Fr [] FalseFr TDR ['M'] TrueS Mq ['M'] False
S Fr ['M'] TrueS Mq [] TrueS Mq ['Fr'] False

Lecture. Initialisation (lignes 1–17) : les deux fonctions et les six requêtes.

Lecture. Tour 1, \(Z=\emptyset\) : S–M–Fr, chaîne, M non observé : actif ; d-séparés : non.

Lecture. Tour 2, \(Z=\{M\}\) : S–M–Fr, chaîne, M observé : bloqué ; d-séparés : oui.

Lecture. Tour 3, \(Z=\{M\}\) : Fr–M–TDR, cause commune, M observé : bloqué ; d-séparés : oui.

Lecture. Tour 4, \(Z=\emptyset\) : S–M–Mq, v-structure, rien d’observé : bloqué ; d-séparés : oui.

Lecture. Tour 5, \(Z=\{M\}\) : S–M–Mq, v-structure, M observé : ouvert ; d-séparés : non.

Lecture. Tour 6, \(Z=\{Fr\}\) : S–M–Mq, v-structure, descendant Fr observé : ouvert ; d-séparés : non.

La d-séparation à deux chemins

Une bonne pluie fait la récolte et baisse le prix du marché ; récolte et prix font le revenu, qui fait la santé du ménage.

Récolte, Prix, sans observation : dépendants
par Pluie actif
par Revenu bloqué en Revenu (v-structure)
Récolte, Prix, sachant Pluie : d-séparés
par Pluie bloqué en Pluie (cause commune)
par Revenu bloqué en Revenu (v-structure)
Récolte, Prix, sachant Pluie et Santé : dépendants
par Pluie bloqué en Pluie (cause commune)
par Revenu actif
Pluie, Santé, sachant Revenu : d-séparés
par Prix, Revenu bloqué en Revenu (chaîne)
par Récolte, Revenu bloqué en Revenu (chaîne)

Lecture. Bloqué si tous les chemins sont bloqués : sachant la pluie, récolte et prix sont d-séparés ; observer aussi la santé rouvre le chemin par le revenu.

La couverture de Markov

Couverture de Markov

Les parents, les enfants et les autres parents de ses enfants : sachant sa couverture, un nœud est indépendant de tous les autres.

Lecture. La couverture de \(S\) contient \(Mq\), l’autre parent de \(M\).

Quoi, pourquoi, quand ça échoue : la d-séparation

Quoi

Examiner chaque chemin entre \(X\) et \(Y\), et chaque triplet de ce chemin, pour dire s’il est bloqué par les observations \(Z\).

Pourquoi on peut s’y fier

Une indépendance lue dans le graphe vaut pour toutes les tables : elle découle de la factorisation, non des nombres.

Quand ça échoue

Le critère ne voit que le graphe : deux variables non d-séparées peuvent être indépendantes par un hasard des nombres, et un graphe faux (un arc oublié) donne des indépendances fausses. Énumérer les chemins coûte un temps exponentiel dans le pire cas ; un parcours du graphe de type Bayes-Ball décide la d-séparation en temps linéaire.

Exercice : d-séparation sur le réseau de Cheikh

Énoncé

Le réseau de l’exercice précédent. d-séparés ?

  1. \(P\) et \(C\).
  2. \(P\) et \(C\) sachant \(R\).
  3. \(P\) et \(C\) sachant \(Q\).
  4. \(P\) et \(R\) sachant \(E\).
  5. \(E\) et \(Q\) sachant \(R\).
  6. \(P\) et \(Q\).
  7. \(P(C\mid R)\), puis \(P(C\mid R,E)\).

Correction

  1. chemin P–E–R–C, \(R\) v-structure non observée, \(Q\) non plus : bloqué ; oui.
  2. \(R\) observé : la v-structure s’ouvre ; non.
  3. \(Q\), descendant de \(R\), observé : ouvert ; non.
  4. chaîne P–E–R, \(E\) observé : bloquée ; oui.
  5. chaîne E–R–Q, \(R\) observé : bloquée ; oui.
  6. chaîne P–E–R–Q, rien d’observé : active ; non.
  7. \(P(C\mid R)=0,237\) tombe à \(P(C\mid R,E)=1/7\approx0,143\) : l’embouteillage explique le retard.

Le problème d’inférence

Le réseau construit, il reste à l’interroger : sachant des observations, que croire des variables cachées ?

Requête, observations, variables cachées

Une requête \(X\), des observations \(\mathbf e\), et les autres variables, cachées, \(\mathbf h\). Exemple : \(P(M\mid Fr=\text{vrai},TDR=+)\), avec \(S\), \(Mq\) et \(T\) cachées.

Inférence par énumération

\[ P(X\mid\mathbf e)=\alpha\sum_{\mathbf h}\prod_i P\big(X_i\mid\mathrm{Parents}(X_i)\big) \]

Pour chaque valeur de \(X\) : fixer les observations, sommer le produit des tables sur toutes les valeurs des variables cachées ; puis normaliser (\(\alpha\)).

Lecture. C’est la marginalisation et le zoom de la section 2, appliqués à la jointe factorisée.

L’énumération en Python

def enumeration(var, obs):
    caches = [v for v in DOM if v != var and v not in obs]
    scores = {}
    termes = 0
    for val in DOM[var]:
        scores[val] = 0
        for h in itertools.product(*(DOM[v] for v in caches)):
            a = dict(zip(caches, h))
            a.update(obs)
            a[var] = val
            scores[val] = scores[val] + jointe_reseau(*(a[v] for v in DOM))
            termes = termes + 1
    z = sum(scores.values())
    return {v: round(p / z, 3) for v, p in scores.items()}, termes
print(enumeration("M", {"Fr": True, "TDR": True}))
print(enumeration("M", {"Fr": True, "TDR": True, "S": "pluies"}))

Résultat \(\rightarrow\)

({'palu': 0.925, 'grippe': 0.058, 'autre': 0.017}, 24)
({'palu': 0.959, 'grippe': 0.033, 'autre': 0.008}, 12)

Lecture. Sans la saison : 24 termes (3 valeurs de \(M\), 8 configurations de \(S\), \(Mq\), \(T\)), \(P(\text{palu}\mid Fr,TDR^+)\approx0{,}925\). Saison des pluies connue : 12 termes, 0,959.

Le coût de l’énumération

\(m\) \(\tau(m)\) \(\times P(Fr\mid m)P(TDR^+\mid m)\) \(=\)
palu 0,25 \(0{,}80\times0{,}95\) 0,19
grippe 0,40 \(0{,}30\times0{,}10\) 0,012
autre 0,35 \(0{,}10\times0{,}10\) 0,0035
somme \(=P(Fr,TDR^+)\) 0,2055

\(\tau(m)=\sum_{s,q}P(s)P(q)P(m\mid s,q)\) : la répartition sur l’année, plus « tiède » que le prior d’août.

Un coût exponentiel

L’énumération calcule chaque terme en entier : 24 termes de 6 facteurs, soit 120 multiplications, et \(d^{\,n}\) termes en général. Elle recalcule les mêmes sous-produits : la somme sur \(T\) vaut 1, et la somme sur \(S\), \(Mq\) ne dépend pas des observations.

Lecture. \(0{,}19/0{,}2055\approx0{,}925\) ; avec le prior d’août au lieu de \(\tau\), \(0{,}304/0{,}317\approx0{,}959\) : le contexte précisé donne un diagnostic plus net.

L’élimination de variables

Factoriser avant de développer

Comme \(ab+ac=a(b+c)\), on sort de chaque somme les facteurs qui ne dépendent pas de la variable sommée :

\[ \sum_{s,q,t}P(s)P(q)P(m\mid s,q)P(t\mid m)=\Big(\sum_s P(s)\sum_q P(q)P(m\mid s,q)\Big)\Big(\sum_t P(t\mid m)\Big) \]

Deux opérations sur les facteurs

Un facteur est une table sur quelques variables. Le produit de deux facteurs porte sur l’union de leurs variables ; la somme sur une variable la fait disparaître (marginalisation). Éliminer \(Z\) : multiplier les facteurs qui contiennent \(Z\), sommer sur \(Z\), remettre le résultat dans la liste.

Lecture. Le coût dépend de la taille du plus grand facteur créé, donc de l’ordre d’élimination et de la structure du graphe.

Les facteurs en Python

def facteur(vs, f):                              # table de f sur ses variables
    return vs, {x: f(*x) for x in itertools.product(*(DOM[v] for v in vs))}
def produit(f, g):
    (vf, tf), (vg, tg) = f, g
    vs = vf + tuple(v for v in vg if v not in vf)
    t = {}
    for x in itertools.product(*(DOM[v] for v in vs)):
        a = dict(zip(vs, x))
        t[x] = tf[tuple(a[v] for v in vf)] * tg[tuple(a[v] for v in vg)]
    return vs, t
def sommer(f, var):                              # marginaliser var
    vs, t = f
    i = vs.index(var)
    s = {}
    for x, p in t.items():
        s[x[:i] + x[i + 1:]] = s.get(x[:i] + x[i + 1:], 0) + p
    return vs[:i] + vs[i + 1:], s
print(sommer(facteur(("T", "M"), lambda t, m: p_oui(TE, m, t)), "T"))

Résultat \(\rightarrow\)

(('M',), {('palu',): 1.0, ('grippe',): 1.0, ('autre',): 1.0})

Lecture. Sommer \(P(T\mid M)\) sur \(T\) donne 1 : \(T\) disparaît sans calcul.

Les facteurs du réseau de Fatou

F = [facteur(("S",), lambda s: P_S[s]),
     facteur(("Mq",), lambda q: P_MQ[q]),
     facteur(("M", "S", "Mq"), lambda m, s, q: P_M[s, q][m]),
     facteur(("M",), lambda m: FR[m]),           # Fr = vrai, observe
     facteur(("T", "M"), lambda t, m: p_oui(TE, m, t)),
     facteur(("M",), lambda m: TDR[m])]          # TDR = +, observe
print([vs for vs, t in F], sum(len(t) for vs, t in F))

Résultat \(\rightarrow\)

[('S',), ('Mq',), ('M', 'S', 'Mq'), ('M',), ('T', 'M'), ('M',)] 28

Lecture. Les observations sont fixées avant l’élimination : \(P(Fr\mid M)\) est restreint à \(Fr=\) vrai, \(P(TDR\mid M)\) à \(TDR=+\). Six facteurs, 28 cases en tout.

L’élimination de variables, pas à pas

Sortie \(\rightarrow\) 

{'palu': 0.925, 'grippe': 0.058, 'autre': 0.017}

Lecture. Initialisation (lignes 1, 15) : six facteurs ; les observations \(Fr=\) vrai et \(TDR=+\) sont déjà fixées dans leurs tables.

Lecture. Tour 1, \(T\) (lignes 3–8) : seul \(P(T\mid M)\) contient \(T\) ; sa somme sur \(T\), \(\tau_1(M)\), vaut 1 : aucun calcul utile.

Lecture. Tour 2, \(Mq\) : produit de \(P(Mq)\) et \(P(M\mid S,Mq)\) (12 cases), somme sur \(Mq\) : \(\tau_2(M,S)=P(M\mid S)\).

Lecture. Tour 3, \(S\) : produit de \(P(S)\) et \(\tau_2\), somme sur \(S\) : \(\tau_3(M)\) vaut 0,250, 0,400, 0,350.

Lecture. Lignes 9–11 : produit des quatre facteurs restants, tous sur \(M\) : 0,190, 0,0120, 0,004.

Lecture. Lignes 12–15 : normalisation par \(z=0,2055\) : \(P(\text{palu}\mid Fr,TDR^+)=0,925\).

Énumération contre élimination

énumération élimination
principe tout développer factoriser
multiplications ici 120 27
coût en général \(O(d^{\,n})\) \(O(n\,d^{\,w+1})\)
réseau en arbre exponentiel linéaire
résultat exact exact

27 \(=\) 12 (produit pour \(Mq\)) \(+\) 6 (pour \(S\)) \(+\) 9 (produit final).

La largeur d’arbre

\(w\) est la taille du plus grand facteur créé, moins un, pour le meilleur ordre : elle mesure la densité structurelle du réseau.

Aucun algorithme exact ne passe partout

L’inférence exacte dans un réseau quelconque est NP-difficile (Cooper, 1990).

Lecture. Le même gain qu’A* face à BFS en Séance 3 : exploiter la structure du problème plutôt que la force brute.

L’inférence approchée par échantillonnage

def tirer(rng, dist):
    return rng.choices(list(dist), weights=list(dist.values()))[0]
def rejet(n, rng):
    gardes = 0
    palu = 0
    for _ in range(n):
        s = tirer(rng, P_S)
        q = tirer(rng, P_MQ)
        m = tirer(rng, P_M[s, q])
        fr = rng.random() < FR[m]
        tdr = rng.random() < TDR[m]
        if fr and tdr:
            gardes = gardes + 1
            palu = palu + (m == "palu")
    return gardes, round(palu / gardes, 3)
for n in (100, 1000000):
    print(n, rejet(n, random.Random(221)))

Résultat \(\rightarrow\)

100 (25, 0.96)
1000000 (206483, 0.926)

Lecture. 100 tirages : 25 gardés, 0,96 ; un million : 206 483 gardés (21 %), 0,926 pour 0,925 exact.

Quoi, pourquoi, quand ça échoue : l’élimination

Quoi

Pour chaque variable cachée, dans un ordre choisi : multiplier les facteurs qui la contiennent, la sommer, remettre le facteur obtenu ; multiplier ce qui reste, normaliser.

Pourquoi elle est exacte et plus rapide

Elle calcule la même somme que l’énumération, mais chaque sous-produit une seule fois, grâce à la distributivité.

Quand ça échoue

Un mauvais ordre crée des facteurs énormes ; trouver le meilleur ordre est lui-même difficile. Sur un réseau dense, la largeur d’arbre reste grande et il faut l’échantillonnage.

Exercice : élimination sur le réseau de Cheikh

Énoncé

Le client de Cheikh se plaint (\(Q=1\)) : quelle probabilité de crevaison ? Éliminer \(P\), puis \(E\), puis \(R\).

  1. Le facteur \(\tau_1(E)\) (élimination de \(P\)).
  2. Le facteur \(\tau_2(R,C)\) (de \(E\)).
  3. Le facteur \(\tau_3(C)\) (de \(R\)).
  4. \(P(C\mid Q=1)\), et le nombre de multiplications.

Correction

  1. \(\tau_1(E)=\sum_P P(P)P(E\mid P)\) : 0,35 et 0,65 (4 multiplications).
  2. \(\tau_2(R,C)=\sum_E\tau_1(E)P(R\mid E,C)\) : \(P(R{=}1\mid C{=}1)=0,77\), \(P(R{=}1\mid C{=}0)=0,275\) (8).
  3. \(\tau_3(C)=\sum_R\tau_2(R,C)P(Q{=}1\mid R)\) : 0,3965 et 0,17375 (4).
  4. \(\times P(C)\) : 0,03965 et 0,156375 ; \(z=P(Q{=}1)=0,196025\) ; \(P(C{=}1\mid Q{=}1)\approx0,202\), en 18 multiplications contre 64 par énumération.

Le classifieur Naive Bayes

Le diagnostic de Fatou était déjà un classifieur : il reste à lui donner son nom.

Naive Bayes

\[ P(c\mid x_1,\dots,x_k)\propto P(c)\prod_{i=1}^k P(x_i\mid c) \]

La classe \(c\) est l’unique parent de chaque attribut \(x_i\) : les attributs sont supposés indépendants sachant la classe. On prédit la classe de plus grand posterior.

Le diagnostic, relu

Classe \(M\), attributs \(Fr\), \(T\), \(TDR\) : le produit \(0{,}40\times0{,}80\times0{,}70\times0{,}95\), normalisé, redonne 0,990, comme les trois mises à jour successives.

Lecture. « Naïf » désigne l’hypothèse d’indépendance conditionnelle, rarement exacte ; le classifieur reste un des plus utilisés pour le texte.

Naive Bayes pour le filtrage du spam

P_SPAM = {"spam": 0.30, "legitime": 0.70}
MOTS = {"gratuit": {"spam": 0.80, "legitime": 0.05},
        "offre": {"spam": 0.60, "legitime": 0.10},
        "cliquez": {"spam": 0.70, "legitime": 0.08}}
def naive_bayes(mots):
    score = dict(P_SPAM)
    for w in mots:
        for c in score:
            score[c] = score[c] * MOTS[w][c]
    z = sum(score.values())
    return {c: round(s / z, 4) for c, s in score.items()}
print(naive_bayes(["gratuit", "offre", "cliquez"]))
print(naive_bayes(["offre"]))

Résultat \(\rightarrow\)

{'spam': 0.9972, 'legitime': 0.0028}
{'spam': 0.72, 'legitime': 0.28}

Le calcul

spam : \(0{,}30\times0{,}80\times0{,}60\times0{,}70=0{,}1008\)

légitime : \(0{,}70\times0{,}05\times0{,}10\times0{,}08=0{,}00028\)

posterior : \(0{,}1008/0{,}10108\approx0{,}9972\)

Lecture. Les trois mots ensemble : spam à 99,72 %. Le mot « offre » seul : \(0{,}18/(0{,}18+0{,}07)=0{,}72\). Chaque mot multiplie la cote par son rapport de vraisemblance (16, 6 et 8,75).

Du modèle donné au modèle appris

cette séance cours de Machine Learning
modèle donné par l’expert appris sur des données
prior fixé : 40 % de paludisme en août estimé : fréquence de la classe
vraisemblances connues : 80 % de frissons estimées par comptage, ou par optimisation
inférence calculer \(P(H\mid E)\) prédire la classe d’un nouvel exemple

Compter sur DataSANTÉ-221

Sur les 10 000 patients du jeu de données du cours de ML, 1 176 ont le paludisme : \(P(\text{palu})\approx0{,}118\) ; parmi eux, 894 ont consulté en saison des pluies : \(P(\text{pluies}\mid\text{palu})\approx0{,}760\). Ce sont un prior et une vraisemblance, estimés par comptage.

Lecture. La régression logistique, les réseaux de neurones et les modèles génératifs reprendront la vraisemblance et le posterior ; seule change l’origine des nombres.

L’espérance, vers la décision

Espérance

\[ \mathbb E[X]=\sum_x x\,P(X=x) \]

La moyenne des valeurs de \(X\), pondérée par leurs probabilités : la valeur attendue « en moyenne ». Sachant une observation \(B\), \(\mathbb E[X\mid B]=\sum_x x\,P(X=x\mid B)\).

La durée de traitement

Paludisme 7 jours, grippe 4, autre cause 2. Avec le prior d’août : \(\mathbb E[\text{durée}]=0{,}40\times7+0{,}35\times4+0{,}25\times2=2{,}8+1{,}4+0{,}5=4{,}7\) jours. Sachant les frissons : \(\frac{32}{45}\times7+\frac{7}{30}\times4+\frac1{18}\times2=\frac{271}{45}\approx6{,}02\) jours.

Lecture. La Séance 6 pondère de la même façon les conséquences d’une action par leurs probabilités : c’est l’utilité espérée, puis la valeur d’un état.

Les méthodes de la séance, côte à côte

méthode ce qu’elle calcule coût cas de Fatou
jointe + zoom \(P(X\mid y)\) par le tableau taille de la jointe 0,711
Bayes posterior un terme par hypothèse 0,711 ; Paris 0,003
séquentiel posterior après \(k\) preuves \(k\) fois Bayes 0,711, 0,910, 0,990
d-séparation une indépendance chemins du graphe \(S\perp Fr\mid M\)
énumération \(P(X\mid\mathbf e)\) exacte \(O(d^{\,n})\) 0,925 ; 120 mult.
élimination \(P(X\mid\mathbf e)\) exacte \(O(n\,d^{\,w+1})\) 0,925 ; 27 mult.
échantillonnage une estimation nombre de tirages 0,926 (un million)
Naive Bayes la classe la plus probable linéaire en attributs 0,990 ; spam 0,9972

Lecture. Toutes reposent sur deux règles, la règle du produit et la marginalisation ; elles diffèrent par ce qu’elles supposent du domaine et par ce qu’elles évitent de calculer.

Le choix d’une méthode d’inférence

Quelle méthode choisir ?

  1. Une hypothèse, quelques observations indépendantes sachant elle ? Bayes, en table, puis la mise à jour séquentielle.
  2. Beaucoup de variables liées ? Un réseau bayésien ; la d-séparation dit d’abord quelles variables comptent.
  3. Petit réseau ? L’énumération, pour vérifier.
  4. Réseau de faible largeur d’arbre ? L’élimination de variables, en éliminant d’abord les variables cachées sans descendant observé.
  5. Réseau dense ou très grand ? L’échantillonnage, en connaissant son erreur.

Lecture. Dans tous les cas, la qualité de la réponse est celle du prior et des tables : un calcul exact sur un modèle faux reste faux.

À retenir

À retenir

  • Une probabilité est un degré de croyance ; la jointe contient tout, la marginalisation somme, le conditionnement zoome.
  • \(P(A\mid B)\neq P(B\mid A)\) ; posterior \(\propto\) vraisemblance \(\times\) prior, normalisé par l’évidence.
  • Le prior est le contexte : frissons à Dakar en août, 0,711 ; à Paris en janvier, 0,003.
  • Le posterior d’hier est le prior d’aujourd’hui, sous l’indépendance conditionnelle des preuves ; une preuve contraire affaiblit (0,910 \(\to\) 0,359).
  • Un réseau bayésien factorise la jointe par les parents : 19 paramètres au lieu de 95.
  • Chaîne et cause commune : observer le centre bloque ; v-structure : observer le centre, ou un descendant, ouvre.
  • L’élimination de variables calcule la même réponse que l’énumération, en factorisant : 27 multiplications au lieu de 120.
  • Naive Bayes est Bayes séquentiel ; le Machine Learning apprend ses probabilités sur des données.

Prochaine séance

Séance 6 — L’IA qui apprend

Fatou a le paludisme avec une probabilité de 0,990 : faut-il traiter tout de suite, ou attendre un examen de plus ? Une croyance ne dit pas encore quoi faire. La Séance 6 passe de la croyance à la décision : utilité espérée, processus de décision markoviens, équation de Bellman, puis apprentissage par renforcement (Q-learning), avec le Monde de Bouki revisité et un gridworld de Dakar.

Références

  • Russell, Norvig — Artificial Intelligence: A Modern Approach, 4e éd., Pearson, 2020 (chap. 12 « Quantifying Uncertainty », chap. 13 « Probabilistic Reasoning »).
  • Pearl — Probabilistic Reasoning in Intelligent Systems, Morgan Kaufmann, 1988.
  • Koller, Friedman — Probabilistic Graphical Models, MIT Press, 2009.
  • Poole, Mackworth — Artificial Intelligence: Foundations of Computational Agents, 3e éd., Cambridge University Press, 2023.
  • Murphy — Probabilistic Machine Learning: An Introduction, MIT Press, 2022.
  • Bayes — « An Essay towards Solving a Problem in the Doctrine of Chances », Philosophical Transactions of the Royal Society, 1763.
  • Cooper — « The Computational Complexity of Probabilistic Inference Using Bayesian Belief Networks », Artificial Intelligence, 1990.