Un reseau bayesien represente des relations probabilistes entre variables :
[Maladie] ----> [Symptome]
\--------> [Test]
Extension : Reseaux de Decision (Influence Diagrams)
Un reseau de decision ajoute :
Noeuds de decision : choix de l’agent
Noeuds d’utilite : consequences des choix
Arcs informationnels : ce que l’agent sait au moment de decider
[Maladie] ----> [Test Result]
| |
v v
<Traitement> ----> ((Utilite))
Configuration de l’environnement
Avant de modeliser des reseaux de decision, nous chargeons la bibliotheque Infer.NET. Cette cellule est necessaire pour toutes les demonstrations de ce notebook.
The below script needs to be able to find the current output cell; this is an easy method to get it.
Installed Packages
Microsoft.ML.Probabilistic, 0.4.2504.701
Microsoft.ML.Probabilistic.Compiler, 0.4.2504.701
Infer.NET charge !
Chargement du helper de visualisation des graphes de facteurs.
// Chargement du helper pour visualiser les factor graphs inline#load "../../Infer/FactorGraphHelper.cs"// Verification de la disponibilite de Graphvizif(FactorGraphHelper.IsGraphvizAvailable()) Console.WriteLine("Graphviz disponible - les factor graphs seront affiches en SVG inline");else Console.WriteLine("Graphviz non installe - les factor graphs seront disponibles en fichiers .gv");
Graphviz disponible - les factor graphs seront affiches en SVG inline
2. Types de Noeuds
Les reseaux de decision utilisent une notation graphique standardisee (Howard, 1984) qui distingue clairement les différents types de noeuds. Cette convention visuelle permet de lire immediatement la structure du problème decisionnel.
Convention graphique
Type
Forme
Symbole
Description
Exemple
Chance
Ovale/Cercle
[X]
Variable aleatoire non controlee
Maladie, Marche, Meteo
Decision
Rectangle
Choix contrôle par l’agent
Traiter, Investir, Acheter
Utilite
Losange/Hexagone
((U))
Fonction de valeur/payoff
Profit, Sante, Satisfaction
Arcs et leur signification
Chaque type d’arc encode une relation spécifique dans le problème :
Type d’arc
Signification
Interpretation
Chance → Chance
Dépendance probabiliste
P(B|A) - A influence B
Chance → Decision
Arc informationnel
L’agent observe A avant de choisir D
Chance → Utilite
La variable affecte l’utilite
U depend de la valeur de A
Decision → Chance
La decision influence le résultat
L’action D modifie P(B)
Decision → Utilite
Cout/benefice direct de la decision
U inclut le cout de D
Ordre temporel implicite
Dans un reseau de decision bien forme : 1. Les noeuds de decision sont totalement ordonnes (D1 avant D2 avant D3…) 2. Un arc informationnel vers Di signifie que la variable est connue avant Di 3. Pas de cycles impliquant des noeuds de decision
La cellule suivante définit une structure de données simple pour representer les noeuds d’un reseau de decision et illustre la notation graphique sur un exemple medical.
// Representation d'un reseau de decision simplepublicenum NodeType { Chance, Decision, Utility }publicclass DecisionNode{publicstring Name {get;set;}public NodeType Type {get;set;}public List<string> Parents {get;set;}=new List<string>();publicstringToSymbol(){return Type switch{ NodeType.Chance=> $"[{Name}]", NodeType.Decision=> $"<{Name}>", NodeType.Utility=> $"(({Name}))", _ => Name};}}// Exemple : Decision medicalevar network =new List<DecisionNode>{new DecisionNode { Name ="Maladie", Type = NodeType.Chance},new DecisionNode { Name ="Test", Type = NodeType.Chance, Parents ={"Maladie"}},new DecisionNode { Name ="Traiter", Type = NodeType.Decision, Parents ={"Test"}},new DecisionNode { Name ="Sante", Type = NodeType.Chance, Parents ={"Maladie","Traiter"}},new DecisionNode { Name ="Utilite", Type = NodeType.Utility, Parents ={"Sante","Traiter"}},};Console.WriteLine("Reseau de decision : Diagnostic Medical\n");foreach(var node in network){string parents = node.Parents.Any()? $" <- {string.Join(",", node.Parents)}":""; Console.WriteLine($" {node.ToSymbol()}{parents}");}
Reseau de decision : Diagnostic Medical
[Maladie]
[Test] <- Maladie
<Traiter> <- Test
[Sante] <- Maladie, Traiter
((Utilite)) <- Sante, Traiter
Interpretation de la structure
Le reseau ci-dessus represente un problème de diagnostic medical classique :
Noeud
Type
Rôle
[Maladie]
Chance
Etat du patient (inconnu)
[Test]
Chance
Résultat observable, depend de Maladie
<Traiter>
Decision
Choix du medecin, base sur le résultat du test
[Sante]
Chance
Etat futur, depend de Maladie ET de la decision
((Utilite))
Utilite
Valeur finale, depend de Sante et du cout du traitement
Point cle : L’arc Test -> Traiter est un arc informationnel. Il indique que le medecin connait le résultat du test avant de decider. Sans cet arc, le medecin devrait decider “en aveugle”.
3. Arcs Informationnels
Les arcs informationnels sont fondamentaux pour modeliser ce que l’agent sait au moment de prendre une decision. Ils capturent l’asymetrie d’information qui rend les problemes de decision interessants.
Concept cle
Un arc informationnel vers un noeud de decision indique ce que l’agent sait au moment de prendre cette decision. C’est la différence entre agir en aveugle et agir en connaissance de cause.
Exemple
[Résultat Test] ----> <Traitement>
Signifie : L’agent connait le résultat du test avant de decider du traitement.
Absence d’arc = L’agent ne connait pas la valeur de la variable.
Impact sur la politique
Situation
Politique
Complexite
Aucune information
Action unique
1 decision
Test observe
Action conditionnelle au test
2^k decisions (k = bits d’information)
Information parfaite
Action conditionnelle a l’etat
Action optimale par etat
No-forgetting assumption
Dans les decisions séquentielles, on suppose généralement que l’agent n’oublie pas : - Toutes les observations passees restent accessibles - Toutes les decisions passees sont connues
Cette hypothese simplifie l’analyse mais n’est pas toujours realiste (memoire limitee, cout de stockage).
Valeur de l’information
L’ajout d’un arc informationnel peut augmenter l’utilite esperee. La différence est la valeur de l’information que nous etudierons dans le notebook suivant (DecInfer-06).
La cellule suivante illustre concretement l’impact des arcs informationnels en comparant deux scénarios : decision sans information (a priori) et decision avec information (après observation du test).
// Impact des arcs informationnelsConsole.WriteLine("Scenarios d'information :\n");// Prior sur la maladiedouble pMaladie =0.1;double sensibilite =0.95;// P(test+|malade)double specificite =0.90;// P(test-|sain)// Utilitesdouble U_traiter_malade =90;// Guerisondouble U_traiter_sain =70;// Effets secondaires inutilesdouble U_pasTraiter_malade =10;// Maladie non traiteedouble U_pasTraiter_sain =100;// Parfait// Scenario 1 : Pas d'information (decision a priori)double EU_traiter_apriori = pMaladie * U_traiter_malade +(1- pMaladie)* U_traiter_sain;double EU_pasTraiter_apriori = pMaladie * U_pasTraiter_malade +(1- pMaladie)* U_pasTraiter_sain;Console.WriteLine("Scenario 1 : Decision SANS information (pas de test)");Console.WriteLine($" P(malade) = {pMaladie:P0}");Console.WriteLine($" E[U(traiter)] = {EU_traiter_apriori:F1}");Console.WriteLine($" E[U(pas traiter)] = {EU_pasTraiter_apriori:F1}");Console.WriteLine($" => Decision : {(EU_traiter_apriori > EU_pasTraiter_apriori ? "TRAITER" : "PAS TRAITER")}\n");// Scenario 2 : Decision AVEC information (apres test)// Calculer P(malade|test+) et P(malade|test-) par Bayesdouble pTestPositif = pMaladie * sensibilite +(1- pMaladie)*(1- specificite);double pMaladeSachantTestPositif =(pMaladie * sensibilite)/ pTestPositif;double pMaladeSachantTestNegatif =(pMaladie *(1- sensibilite))/(1- pTestPositif);Console.WriteLine("Scenario 2 : Decision AVEC information (apres test)");Console.WriteLine($" P(test+) = {pTestPositif:P1}");Console.WriteLine($" P(malade|test+) = {pMaladeSachantTestPositif:P1}");Console.WriteLine($" P(malade|test-) = {pMaladeSachantTestNegatif:P1}");// Decision si test positifdouble EU_traiter_testPos = pMaladeSachantTestPositif * U_traiter_malade +(1- pMaladeSachantTestPositif)* U_traiter_sain;double EU_pasTraiter_testPos = pMaladeSachantTestPositif * U_pasTraiter_malade +(1- pMaladeSachantTestPositif)* U_pasTraiter_sain;Console.WriteLine($" Si test+ : traiter={EU_traiter_testPos:F1}, pas traiter={EU_pasTraiter_testPos:F1} => {(EU_traiter_testPos > EU_pasTraiter_testPos ? "TRAITER" : "PAS TRAITER")}");// Decision si test negatifdouble EU_traiter_testNeg = pMaladeSachantTestNegatif * U_traiter_malade +(1- pMaladeSachantTestNegatif)* U_traiter_sain;double EU_pasTraiter_testNeg = pMaladeSachantTestNegatif * U_pasTraiter_malade +(1- pMaladeSachantTestNegatif)* U_pasTraiter_sain;Console.WriteLine($" Si test- : traiter={EU_traiter_testNeg:F1}, pas traiter={EU_pasTraiter_testNeg:F1} => {(EU_traiter_testNeg > EU_pasTraiter_testNeg ? "TRAITER" : "PAS TRAITER")}");
Scenarios d'information :
Scenario 1 : Decision SANS information (pas de test)
P(malade) = 10 %
E[U(traiter)] = 72,0
E[U(pas traiter)] = 91,0
=> Decision : PAS TRAITER
Scenario 2 : Decision AVEC information (apres test)
P(test+) = 18,5 %
P(malade|test+) = 51,4 %
P(malade|test-) = 0,6 %
Si test+ : traiter=80,3, pas traiter=53,8 => TRAITER
Si test- : traiter=70,1, pas traiter=99,4 => PAS TRAITER
Analyse des résultats : Impact de l’information
Les résultats ci-dessus illustrent le theoreme fondamental de la valeur de l’information :
Scénario
Decision
E[U]
Commentaire
Sans test
Pas traiter
91.0
Prior faible (10%), risque acceptable
Avec test+
Traiter
80.3
Posterior eleve (51.4%), traitement justifie
Avec test-
Pas traiter
99.4
Posterior très faible (0.6%), rassurant
Pourquoi la decision change-t-elle ?
A priori : P(malade) = 10% est faible. Le cout des effets secondaires (U=70 vs 100) domine.
Test positif : Le theoreme de Bayes “concentre” la probabilite : \[P(\text{malade}|\text{test}+) = \frac{0.10 \times 0.95}{0.185} = 51.4\%\] Le risque devient majoritaire, justifiant le traitement.
Test negatif : La probabilite residuelle (0.6%) est negligeable.
Lecon : L’information ne change pas toujours la decision (si le prior etait de 50%, on traiterait dans tous les cas). La valeur de l’information depend de la distance entre le prior et les seuils de decision.
4. Calcul de la Politique Optimale
Algorithme Backward Induction
L’algorithme standard pour resoudre un reseau de decision est la backward induction (ou programmation dynamique). L’idee est de resoudre le problème de la fin vers le debut.
Algorithme pas a pas
Étape 0 : Preparation - Ordonner les noeuds de decision temporellement : D1 → D2 → … → Dn - Identifier les parents informationnels de chaque decision
Étape 1 : Dernière decision (Dn) - Pour chaque configuration possible des parents informationnels de Dn : - Calculer E[U | parents, action] pour chaque action possible - Sélectionner l’action qui maximise E[U] - Stocker cette action optimale et sa valeur
Étape 2 : Remonter (Dn-1, Dn-2, …) - Pour chaque decision précédente : - Utiliser les valeurs optimales des decisions suivantes - Repeter le processus de maximisation
Étape 3 : Première decision (D1) - La dernière itération donne la decision optimale initiale - La politique complete est l’ensemble des decisions conditionnelles
Complexite
Nombre de decisions
Complexite
Commentaire
1
O(|A| × |S|)
A = actions, S = etats
n séquentielles
O(|A|^n × |S|^n)
Exponentielle en n
Avec info parfaite
O(|S| × |A|)
Lineaire car decision par etat
Pourquoi “backward” ?
On commence par la fin car l’utilite finale depend des decisions futures. En resolvant d’abord les decisions futures, on connait leur contribution a l’utilite esperee, ce qui permet de resoudre les decisions anterieures.
La cellule suivante implemente une classe SimpleDecisionNetwork qui resout le problème de diagnostic medical par backward induction. Elle calcule la politique optimale (quelle action prendre pour chaque observation) et l’utilite esperee globale.
Remarque technique : Cette utilite (95.90) est superieure a celle sans test (91.0). La différence (4.90) represente la valeur de l’information apportee par le test - un concept que nous approfondirons dans le notebook suivant.
5. Exemple : Investissement avec Test de Marche
Scénario
Un investisseur considere un projet. Le marche peut etre favorable ou non. Il peut commander une étude de marche avant de decider.
La cellule suivante applique les mêmes principes a un problème d’investissement. L’investisseur peut commander une étude de marche (couteuse) avant de decider s’il investit. Le code compare les deux stratégies : decision directe vs decision informee.
Les résultats revelent plusieurs phenomenes interessants :
Comparaison des stratégies
Stratégie
Decision
E[Profit]
Commentaire
Sans étude
Investir directement
80 000 EUR
Prior P(favorable)=40% suffit
Avec étude
Conditionnel au résultat
104 000 EUR
Evite les grosses pertes
Decomposition de la valeur de l’étude
La valeur de l’étude (24 000 EUR) se decompose ainsi :
Gain brut d’information : L’étude permet d’eviter d’investir quand le signal est negatif
Sans étude : on investit toujours (EU = 80 000 EUR)
Avec E- (50% des cas) : on n’investit pas, evitant une perte esperee
Cout de l’étude : -20 000 EUR
Valeur nette : 24 000 EUR
Point cle : L’étude est rentable car elle permet de changer de decision dans certains cas. Si P(favorable) etait de 80%, on investirait dans tous les cas (E+ ou E-), et l’étude n’aurait aucune valeur decisionnelle.
Conditions pour que l’information ait de la valeur
L’information a de la valeur si et seulement si elle peut changer la decision optimale. Dans cet exemple : - E+ confirme l’investissement (64% favorable) - E- dissuade l’investissement (16% favorable)
La qualite de l’étude (sensibilite/specificite) determine a quel point les posteriors divergent du prior.
Exercice 1 : Reseau de decision pour un lancement de produit
Une startup envisage de lancer un nouveau produit. Le marche peut etre porteur ou sature. Avant de decider, elle peut commander une étude de marché couteuse.
Paramètres : - P(marche porteur) = 0.35 - Étude : sensibilite = 0.75, specificite = 0.70 - Profits : lancer sur marche porteur = 300 000 EUR, lancer sur marche sature = -150 000 EUR, ne pas lancer = 0 EUR - Cout de l’étude = 25 000 EUR
Étapes : 1. Calculez les posteriors P(porteur|étude+) et P(porteur|étude-) par theoreme de Bayes 2. Pour chaque résultat d’étude, determinez s’il faut lancer ou non (comparez E[U] de chaque action) 3. Calculez l’utilite esperee de la stratégie “commander l’étude” 4. Calculez l’utilite esperee de la stratégie “decider sans étude” 5. (Indice) : A quel seuil de P(marche porteur) l’étude perd-elle toute valeur decisionnelle ?
Cet exercice reprend le schema de la section 5 avec des paramètres différents. Il vous permet de pratiquer la backward induction sur un problème de type “option reelle”.
// Exercice : Reseau de decision pour un lancement de produit// Parametresdouble pPorteur =0.35;// P(marche porteur)double sensEtude =0.75;// P(etude+|porteur)double specEtude =0.70;// P(etude-|sature)double profit_lancer_porteur =300000;double profit_lancer_sature =-150000;double profit_pasLancer =0;double coutEtude =25000;// TODO 1 : Calculez les posteriors P(porteur|etude+) et P(porteur|etude-)// Indice : P(etude+) = pPorteur * sensEtude + (1 - pPorteur) * (1 - specEtude)// Puis P(porteur|etude+) = (pPorteur * sensEtude) / P(etude+)// TODO 2 : Pour chaque resultat d'etude, determinez s'il faut lancer// Calculez E[Profit(lancer)] et E[Profit(pas lancer)] pour chaque cas// Indice : E[Profit(lancer|obs)] = P(porteur|obs) * profit_lancer_porteur + (1 - P(porteur|obs)) * profit_lancer_sature// TODO 3 : Calculez l'utilite esperee de la strategie "commander l'etude"// E[Profit avec etude] = P(etude+) * bestProfit(etude+) + P(etude-) * bestProfit(etude-) - coutEtude// TODO 4 : Calculez l'utilite esperee de la strategie "decider sans etude"// E[Profit sans etude] = max(E[Profit(lancer)], E[Profit(pas lancer)]) avec prior// TODO 5 : (Bonus) Trouvez le seuil de P(porteur) ou l'etude n'a plus de valeur// Indice : a quel prior l'agent prendrait-il la meme decision quel que soit le resultat de l'etude ?Console.WriteLine("Exercice a completer");
Exercice a completer
L’exemple précédent illustrait une situation avec une seule decision après observation. Dans de nombreux problemes reels, nous devons prendre plusieurs decisions dans le temps, chacune pouvant reveler de l’information utile pour les suivantes.
6. Decisions Séquentielles
Ordre des decisions
Quand il y a plusieurs noeuds de decision, leur ordre temporel doit etre specifie.
Deux decisions séquentielles : 1. D’abord : Faire le test ou non ? 2. Ensuite : Traiter ou non ? (en connaissant le résultat si test fait)
La cellule suivante implemente une decision séquentielle a deux étapes : d’abord decider si on fait le test, puis decider si on traite. L’algorithme de backward induction resout d’abord la deuxieme decision, puis remonte a la première.
// Decision sequentielle : Faire test puis traiter// Parametresdouble pMaladie_seq =0.2;double sensibilite_seq =0.90;double specificite_seq =0.85;double cout_test =50;// Utilites (sans cout test)double U_traiterMalade =100;double U_traiterSain =60;double U_pasTraiterMalade =20;double U_pasTraiterSain =100;// Resolution par backward inductionConsole.WriteLine("=== Decision Sequentielle : Test puis Traitement ===\n");// D'abord : calculer politique optimale pour D2 (traiter) sachant test faitdouble pTpos_seq = pMaladie_seq * sensibilite_seq +(1- pMaladie_seq)*(1- specificite_seq);double pM_Tpos =(pMaladie_seq * sensibilite_seq)/ pTpos_seq;double EU_traiter_Tpos = pM_Tpos * U_traiterMalade +(1- pM_Tpos)* U_traiterSain;double EU_pasTraiter_Tpos = pM_Tpos * U_pasTraiterMalade +(1- pM_Tpos)* U_pasTraiterSain;double bestU_Tpos = Math.Max(EU_traiter_Tpos, EU_pasTraiter_Tpos)- cout_test;double pM_Tneg =(pMaladie_seq *(1- sensibilite_seq))/(1- pTpos_seq);double EU_traiter_Tneg = pM_Tneg * U_traiterMalade +(1- pM_Tneg)* U_traiterSain;double EU_pasTraiter_Tneg = pM_Tneg * U_pasTraiterMalade +(1- pM_Tneg)* U_pasTraiterSain;double bestU_Tneg = Math.Max(EU_traiter_Tneg, EU_pasTraiter_Tneg)- cout_test;double EU_faireTest = pTpos_seq * bestU_Tpos +(1- pTpos_seq)* bestU_Tneg;// Si pas de test : decision a prioridouble EU_traiter_apriori = pMaladie_seq * U_traiterMalade +(1- pMaladie_seq)* U_traiterSain;double EU_pasTraiter_apriori = pMaladie_seq * U_pasTraiterMalade +(1- pMaladie_seq)* U_pasTraiterSain;double EU_pasTest = Math.Max(EU_traiter_apriori, EU_pasTraiter_apriori);Console.WriteLine("Etape 2 : Politique de traitement si test fait");Console.WriteLine($" Si T+ : P(M|T+)={pM_Tpos:P1} => {(EU_traiter_Tpos > EU_pasTraiter_Tpos ? "Traiter" : "Pas traiter")}");Console.WriteLine($" Si T- : P(M|T-)={pM_Tneg:P1} => {(EU_traiter_Tneg > EU_pasTraiter_Tneg ? "Traiter" : "Pas traiter")}\n");Console.WriteLine("Etape 1 : Decision de faire le test");Console.WriteLine($" E[U | faire test] = {EU_faireTest:F1}");Console.WriteLine($" E[U | pas test] = {EU_pasTest:F1} ({(EU_traiter_apriori > EU_pasTraiter_apriori ? "traiter" : "pas traiter")})\n");Console.WriteLine("=== Politique Optimale Globale ===");Console.WriteLine($"D1 : {(EU_faireTest > EU_pasTest ? "FAIRE LE TEST" : "NE PAS FAIRE LE TEST")}");if(EU_faireTest > EU_pasTest){ Console.WriteLine($"D2 : Si T+ => {(EU_traiter_Tpos > EU_pasTraiter_Tpos ? "TRAITER" : "PAS TRAITER")}"); Console.WriteLine($" Si T- => {(EU_traiter_Tneg > EU_pasTraiter_Tneg ? "TRAITER" : "PAS TRAITER")}");}else{ Console.WriteLine($"D2 : {(EU_traiter_apriori > EU_pasTraiter_apriori ? "TRAITER" : "PAS TRAITER")} (sans test)");}
=== Decision Sequentielle : Test puis Traitement ===
Etape 2 : Politique de traitement si test fait
Si T+ : P(M|T+)=60,0 % => Traiter
Si T- : P(M|T-)=2,9 % => Pas traiter
Etape 1 : Decision de faire le test
E[U | faire test] = 43,6
E[U | pas test] = 84,0 (pas traiter)
=== Politique Optimale Globale ===
D1 : NE PAS FAIRE LE TEST
D2 : PAS TRAITER (sans test)
Analyse de la decision séquentielle
Ce résultat est contre-intuitif : malgre un test informatif (sensibilite 90%, specificite 85%), la politique optimale est de ne pas faire le test.
Pourquoi ne pas faire le test ?
Facteur
Valeur
Impact
Prior P(maladie)
20%
Relativement faible
Cout du test
50 points
Penalise chaque branche
Utilite “pas traiter sain”
100
Très attractive
Decision a priori optimale
Pas traiter
EU = 84.0
Decision avec test
Conditionnelle
EU = 43.6 (après cout)
Le cout du test (50 points) est applique dans les deux branches (T+ et T-), ce qui reduit significativement l’utilite esperee.
Le cout fixe de 50 points fait basculer la decision vers “ne pas tester”.
Lecon importante : Dans les decisions séquentielles, le timing des couts est crucial. Un cout fixe en amont peut rendre toute la branche sous-optimale, même si l’information obtenue est de haute qualite.
Quand le test deviendrait-il rentable ?
Le test serait rentable si : - Son cout etait inferieur a environ 10 points, OU - Le prior P(maladie) etait plus eleve (ex: 40%), OU
- L’ecart d’utilite “traiter malade vs pas traiter malade” etait plus grand
Exercice 2 : Decision séquentielle - Maintenance preventive d’une machine
Dans cette usine, une machine critique peut etre en bon etat ou defaillant. Le responsable maintenance doit prendre deux decisions séquentielles :
D1 : Faire ou non une inspection (cout = 30 points d’utilite)
D2 : Effectuer ou non la maintenance preventive (cout = 100 points si effectuee)
Paramètres : - P(machine defaillante) = 0.25 - Inspection : sensibilite = 0.85, specificite = 0.80 - Utilites (hors couts) : maintenance sur machine defaillante = 150, maintenance sur machine saine = 50, pas de maintenance sur machine defaillante = -200 (arret de production), pas de maintenance sur machine saine = 120
Étapes : 1. Calculez la politique optimale de D2 (maintenance) conditionnellement au résultat de l’inspection 2. Calculez l’utilite esperee de la branche “faire inspection” en integrant le cout 3. Calculez l’utilite esperee de la branche “pas d’inspection” (decision a priori) 4. Determinez la politique optimale globale (D1 + D2) 5. (Indice) : Quel seuil de cout d’inspection rend l’inspection non rentable ? Testez avec cout_inspection
// Exercice : Decision sequentielle - Maintenance preventive d'une machine// Parametresdouble pDefaillant =0.25;// P(machine defaillante)double sensibilite_insp =0.85;// P(inspection+|defaillant)double specificite_insp =0.80;// P(inspection-|saine)double cout_inspection =30;double cout_maintenance =100;// Utilites (hors couts inspection et maintenance)double U_maint_defaillant =150;// Maintenance sur machine defaillantedouble U_maint_sain =50;// Maintenance sur machine sainedouble U_pasMaint_defaillant =-200;// Pas de maintenance sur defaillantdouble U_pasMaint_sain =120;// Pas de maintenance sur machine saine// TODO 1 : Backward induction - Etape 2 (D2 : maintenance)// Calculez P(defaillant|inspection+) et P(defaillant|inspection-)// Puis calculez E[U(maintenance)] et E[U(pas maintenance)] pour chaque cas// Indice : utilisez le theoreme de Bayes comme dans l'exemple precedent// TODO 2 : Calculez E[U de la branche "faire inspection"]// E[U|faire insp] = P(insp+) * bestU(insp+) + P(insp-) * bestU(insp-) - cout_inspection// N'oubliez pas de soustraire le cout de l'inspection ET le cout de la maintenance si effectuee// TODO 3 : Calculez E[U de la branche "pas d'inspection"]// Decision a priori : maintenance ou pas ? (sans information)// Indice : comparez E[U(maintenir)] et E[U(pas maintenir)] avec le prior P(defaillant)// TODO 4 : Affichez la politique optimale globale (D1 et D2)// D1 : faire inspection ou pas ?// D2 : quelle action conditionnellement au resultat de l'inspection ?// TODO 5 : (Bonus) Trouvez le cout d'inspection seuil// Au-delaà de quel cout l'inspection n'est plus rentable ?// Indice : resolvez E[U|faire insp] = E[U|pas insp] pour cout_inspectionConsole.WriteLine("Exercice a completer");
Exercice a completer
Approche pratique avec Infer.NET
Dans la cellule suivante, nous allons implementer un reseau de decision complet en utilisant Infer.NET pour l’inference bayesienne :
Modelisation : Variables maladie et testPositif avec leurs dependances
Enumeration : Pour chaque valeur possible du test (positif/negatif)
Inference : Calcul de P(maladie|test) via engine.Infer<Bernoulli>()
Decision : Sélection de l’action maximisant E[U]
Point technique : Infer.NET n’a pas de noeuds de decision natifs. Nous simulons la resolution en enumerant manuellement les observations possibles et en calculant l’utilite esperee pour chaque action.
7. Implementation avec Infer.NET
Infer.NET n’a pas de support natif pour les noeuds de decision, mais nous pouvons :
Modeliser les variables de chance
Enumerer les decisions
Calculer E[U] pour chaque configuration
// Reseau de decision avec Infer.NET// Probleme : Diagnostic et traitement// Variables de chanceVariable<bool> maladie = Variable.Bernoulli(0.15).Named("maladie");// Test (conditionnel a la maladie)Variable<bool> testPositif = Variable.New<bool>().Named("test");using(Variable.If(maladie)) testPositif.SetTo(Variable.Bernoulli(0.92));// Sensibiliteusing(Variable.IfNot(maladie)) testPositif.SetTo(Variable.Bernoulli(0.12));// 1-Specificite// InferenceInferenceEngine engine =newInferenceEngine();engine.Compiler.CompilerChoice= Microsoft.ML.Probabilistic.Compiler.CompilerChoice.Roslyn;// Enumerer les observations possibles et calculer E[U] pour chaque decisionvar utilites =new Dictionary<string,double>{{"traiter_malade",85},{"traiter_sain",65},{"pasTraiter_malade",15},{"pasTraiter_sain",100}};Console.WriteLine("=== Reseau de Decision avec Infer.NET ===\n");foreach(bool obsTest innew[]{true,false}){// Observer le test testPositif.ObservedValue= obsTest;// Inferrer P(maladie|test) Bernoulli posteriorMaladie = engine.Infer<Bernoulli>(maladie);double pM = posteriorMaladie.GetProbTrue();// Calculer E[U] pour chaque decisiondouble EU_traiter = pM * utilites["traiter_malade"]+(1- pM)* utilites["traiter_sain"];double EU_pasTraiter = pM * utilites["pasTraiter_malade"]+(1- pM)* utilites["pasTraiter_sain"];string decision = EU_traiter > EU_pasTraiter ?"TRAITER":"PAS TRAITER"; Console.WriteLine($"Observation : test = {(obsTest ? "POSITIF" : "NEGATIF")}"); Console.WriteLine($" P(maladie|test) = {pM:P1}"); Console.WriteLine($" E[U(traiter)] = {EU_traiter:F1}"); Console.WriteLine($" E[U(pas traiter)] = {EU_pasTraiter:F1}"); Console.WriteLine($" => Decision optimale : {decision}\n");// Nettoyer l'observation pour la prochaine iteration testPositif.ClearObservedValue();}
L’implementation ci-dessus montre comment utiliser Infer.NET pour les reseaux de decision :
Stratégie d’implementation
Modeliser les variables de chance avec Infer.NET (ici : maladie, testPositif)
Observer chaque configuration possible des parents informationnels
Inferer les posteriors avec engine.Infer<Bernoulli>()
Calculer E[U] pour chaque action et sélectionner la meilleure
Résultats obtenus
Test observe
P(maladie|test)
E[U(traiter)]
E[U(pas traiter)]
Decision
POSITIF
57.5%
76.5
51.1
TRAITER
NEGATIF
1.6%
65.3
98.7
PAS TRAITER
Note technique : Le message “Compiling model…done.” apparait car Infer.NET compile le modèle en code C# optimise lors de la première inference. Les inferences suivantes reutilisent ce code compile.
Avantages de l’approche Infer.NET
Avantage
Description
Inference exacte
Pas d’approximation pour les modèles discrets
Modèles complexes
Supporte des structures arbitrairement complexes
Observations partielles
Gere naturellement les données manquantes
Apprentissage
Peut apprendre les paramètres a partir de données
Limitations
Infer.NET ne fournit pas de support natif pour les noeuds de decision. L’enumeration des decisions doit etre faite manuellement, ce qui peut devenir couteux pour de nombreuses decisions.
Visualisation du Factor Graph : Reseau de Diagnostic
Le modèle Infer.NET ci-dessus peut etre visualise sous forme de factor graph. Cette representation montre :
La cellule suivante genere et affiche le factor graph si Graphviz est disponible.
// Generation et affichage du factor graph pour le reseau de diagnostic// Le modele Maladie -> Test est un exemple classique de reseau bayesien a deux noeudsVariable<bool> maladieDN = Variable.Bernoulli(0.15).Named("Maladie");Variable<bool> testDN = Variable.New<bool>().Named("TestResult");using(Variable.If(maladieDN)) testDN.SetTo(Variable.Bernoulli(0.92));// P(test+|malade) = sensibiliteusing(Variable.IfNot(maladieDN)) testDN.SetTo(Variable.Bernoulli(0.12));// P(test+|sain) = 1 - specificite// Configurer le moteur pour generer le factor graphInferenceEngine engineDN =newInferenceEngine();engineDN.Compiler.CompilerChoice= Microsoft.ML.Probabilistic.Compiler.CompilerChoice.Roslyn;engineDN.ShowFactorGraph=true;// Executer l'inference (genere le fichier .gv)var postDN = engineDN.Infer<Bernoulli>(maladieDN);Console.WriteLine($"Prior : P(Maladie) = {postDN.GetProbTrue():P1}");Console.WriteLine();// Afficher le factor graph inline si disponibleFactorGraphHelper.GetLatestFactorGraphHtml(700).DisplayAs("text/html");
Note : Sans observation du test, le posterior est identique au prior. Le factor graph montre les connexions entre variables, pas les valeurs. L’inference calcule les marginales en propageant les messages le long de ces connexions.
Maintenant que nous avons vu comment calculer des politiques optimales avec Infer.NET, examinons comment visualiser la structure interne du modèle. Cette visualisation est particulierement utile pour :
Verifier que le modèle correspond bien a notre intention
Identifier les dependances implicites
Comprendre pourquoi l’inference peut etre lente sur certains modèles
7.1 Visualisation du Factor Graph
Infer.NET peut generer le graphe de facteurs du modèle. C’est utile pour : - Verifier la structure du modèle - Comprendre les dependances - Debugger les erreurs d’inference
// Visualisation du graphe de facteurs du modele de diagnostic// Recreer le modele (nouvelle instance pour generation du graphe)Variable<bool> maladieFG = Variable.Bernoulli(0.15).Named("Maladie");Variable<bool> testFG = Variable.New<bool>().Named("TestResult");using(Variable.If(maladieFG)) testFG.SetTo(Variable.Bernoulli(0.92));using(Variable.IfNot(maladieFG)) testFG.SetTo(Variable.Bernoulli(0.12));// Activer la generation du graphe de facteursInferenceEngine engineFG =newInferenceEngine();engineFG.Compiler.CompilerChoice= Microsoft.ML.Probabilistic.Compiler.CompilerChoice.Roslyn;engineFG.ShowFactorGraph=true;// Active la generation du grapheConsole.WriteLine("=== Generation du Factor Graph ===\n");Console.WriteLine("Le graphe de facteurs sera genere lors de l'inference.");Console.WriteLine("Sur un environnement avec Graphviz installe, un fichier .dgml sera cree.\n");// Effectuer l'inference (declenche la generation du graphe)try{var posterior = engineFG.Infer<Bernoulli>(maladieFG); Console.WriteLine($"Inference reussie : P(Maladie) = {posterior}"); Console.WriteLine(); Console.WriteLine("Structure du modele :"); Console.WriteLine(" [Maladie] -----> [TestResult]"); Console.WriteLine(" | |"); Console.WriteLine(" v v"); Console.WriteLine(" (Bernoulli) (Conditionnel)"); Console.WriteLine(); Console.WriteLine("Dans le factor graph :"); Console.WriteLine(" - Noeuds ronds = Variables (Maladie, TestResult)"); Console.WriteLine(" - Noeuds carres = Facteurs (Prior, Likelihood)"); Console.WriteLine(" - Aretes = Connexions facteur-variable");}catch(Exception ex){ Console.WriteLine($"Note : {ex.Message}"); Console.WriteLine("La visualisation graphique necessite Graphviz.");}
=== Generation du Factor Graph ===
Le graphe de facteurs sera genere lors de l'inference.
Sur un environnement avec Graphviz installe, un fichier .dgml sera cree.
Compiling model...done.
Inference reussie : P(Maladie) = Bernoulli(0,15)
Structure du modele :
[Maladie] -----> [TestResult]
| |
v v
(Bernoulli) (Conditionnel)
Dans le factor graph :
- Noeuds ronds = Variables (Maladie, TestResult)
- Noeuds carres = Facteurs (Prior, Likelihood)
- Aretes = Connexions facteur-variable
Affichage du Factor Graph
Le code suivant affiche le factor graph genere par Infer.NET. Ce graphe montre :
Les variables aleatoires (cercles) : les noeuds du reseau de decision
Les facteurs (rectangles) : les distributions conditionnelles et contraintes
Les aretes : les dependances entre variables
Cette visualisation aide a comprendre la structure du modèle probabiliste.
// Affichage du factor graph genere par la cellule precedente// Le graphe montre la structure : Maladie (prior) -> TestResult (likelihood)FactorGraphHelper.GetLatestFactorGraphHtml(700).DisplayAs("text/html");
Model_09_23_26_09_16_10_55.svg
Comprendre les Factor Graphs
Le graphe de facteurs (factor graph) est la representation interne utilisee par Infer.NET pour l’inference. Comprendre cette structure aide a debugger et optimiser les modèles.
Pourquoi c’est important : La structure du factor graph determine la complexite de l’inference. Un graphe avec des cycles necessites des itérations, tandis qu’un arbre permet une inference exacte en un seul passage.
Visualisation avec Graphviz
Sur un système avec Graphviz installe, ShowFactorGraph = true genere un fichier .dgml visualisable dans Visual Studio ou converti en image PNG/SVG.
8. Exercice : Reseau de Decision Personnalise
Enonce
Modelisez le reseau de decision suivant :
Un etudiant doit decider s’il revise ou pas pour un examen. - Variable aleatoire : Difficulte de l’examen (Facile/Difficile) - Decision : Reviser (cout en temps) ou pas - Utilite : Note obtenue moins cout de revision
Indications
Cet exercice demande de calculer l’utilite esperee pour deux actions (reviser / ne pas reviser) etant donne l’incertitude sur la difficulte de l’examen.
Rappel de la formule :
\[E[U(a)] = \sum_{s} P(s) \times U(a, s)\]
ou \(s \in \{\text{facile}, \text{difficile}\}\) et \(a \in \{\text{reviser}, \text{pas reviser}\}\).
// Exercice : Reseau de decision Etudiant// Parametresdouble pDifficile =0.4;// P(examen difficile)// Notes espereesdouble note_revise_facile =18;double note_revise_difficile =14;double note_pasRevise_facile =14;double note_pasRevise_difficile =8;// Cout de revision (en points d'utilite)double coutRevision =2;// TODO 1 : Calculer l'utilite esperee de "reviser"// Formule : E[U(reviser)] = P(facile) * (note_revise_facile - coutRevision) + P(difficile) * (note_revise_difficile - coutRevision)// TODO 2 : Calculer l'utilite esperee de "ne pas reviser"// Formule : E[U(pas reviser)] = P(facile) * note_pasRevise_facile + P(difficile) * note_pasRevise_difficile// TODO 3 : Comparer et afficher la decision optimale// Indice : utilisez un if/else sur les deux utilites esperees// TODO 4 : Calculer le cout seuil (cout de revision au-dela duquel il ne faut plus reviser)// Indice : resolvez E[U(reviser)] = E[U(pas reviser)] pour coutRevisionConsole.WriteLine("Exercice a completer");
Exercice a completer
Analyse de vos résultats
Après avoir implemente le code, verifiez :
Quelle action a la plus grande utilite esperee ?
Le cout seuil est-il coherent avec les paramètres du problème ?
Que se passe-t-il si P(difficile) augmente a 0.7 ?
8bis. Application MAUT : Choix de Site d’Aeroport
Contexte
Un comite doit choisir l’emplacement d’un nouvel aeroport parmi 3 sites candidats. Les critères d’evaluation sont incertains car bases sur des études preliminaires :
Critere
Description
Incertitude
Couts
Construction, infrastructure
Depend du terrain, geologie
Securite
Trafic aerien, conditions meteo
Études locales necessaires
Nuisances
Bruit pour riverains, pollution
Impact environnemental
Cet exemple illustre comment combiner Decision Networks et MAUT avec des attributs incertains.
Visualisation du Factor Graph : Modèle MAUT Multi-Attribut
Le modèle MAUT ci-dessus utilise des variables independantes pour chaque attribut de chaque site. La cellule suivante genere le factor graph montrant la structure de ce modèle a variables multiples.
// Reseau de Decision Multi-Attribut : Site d'Aeroport// 3 sites candidats, 3 attributs incertains modelises avec Infer.NETint nSites =3;string[] sites ={"Site A (cotier)","Site B (rural)","Site C (periurbain)"};// Priors sur les attributs basés sur études préliminaires// Couts (millions EUR) - incertitude sur conditions de terraindouble[] coutMean ={500,300,400};double[] coutVar ={10000,5000,8000};// Securite (score 0-1) - incertitude sur conditions localesdouble[] secAlpha ={8,5,6};double[] secBeta ={2,5,4};// Nuisances (score 1-10) - incertitude sur impact reeldouble[] nuisMean ={3,1,5};double[] nuisVar ={1,0.5,2};// Poids MAUT (determines par les parties prenantes)double w_cout =0.35, w_securite =0.40, w_nuisances =0.25;Console.WriteLine("=== Decision Multi-Attribut avec Infer.NET : Site d'Aeroport ===\n");Console.WriteLine($"Poids : Cout={w_cout:P0}, Securite={w_securite:P0}, Nuisances={w_nuisances:P0}\n");// Creer le modele Infer.NET pour chaque sitevar engineAeroport =newInferenceEngine();engineAeroport.Compiler.CompilerChoice= Microsoft.ML.Probabilistic.Compiler.CompilerChoice.Roslyn;Console.WriteLine("Distributions des attributs par site :\n");Console.WriteLine("Site | Cout (MEUR) | Securite | Nuisances");Console.WriteLine("----------------------|------------------|------------------|------------------");var distributionsCout =new Gaussian[nSites];var distributionsSec =new Beta[nSites];var distributionsNuis =new Gaussian[nSites];for(int s =0; s < nSites; s++){// Creer les variables pour ce site Variable<double> cout_s = Variable.GaussianFromMeanAndVariance(coutMean[s], coutVar[s]).Named($"cout_{s}"); Variable<double> sec_s = Variable.Beta(secAlpha[s], secBeta[s]).Named($"sec_{s}"); Variable<double> nuis_s = Variable.GaussianFromMeanAndVariance(nuisMean[s], nuisVar[s]).Named($"nuis_{s}");// Inferer les distributions distributionsCout[s]= engineAeroport.Infer<Gaussian>(cout_s); distributionsSec[s]= engineAeroport.Infer<Beta>(sec_s); distributionsNuis[s]= engineAeroport.Infer<Gaussian>(nuis_s); Console.WriteLine($"{sites[s],-21} | {distributionsCout[s].GetMean():F0} +/- {Math.Sqrt(distributionsCout[s].GetVariance()):F0} | {distributionsSec[s].GetMean():P0} +/- {Math.Sqrt(distributionsSec[s].GetVariance()):P0} | {distributionsNuis[s].GetMean():F1} +/- {Math.Sqrt(distributionsNuis[s].GetVariance()):F1}");}Console.WriteLine("\n=== Calcul de l'Utilite Esperee par Site ===\n");// Normalisation et calcul EUdouble[] EU =newdouble[nSites];for(int s =0; s < nSites; s++){// Normaliser les attributs (0-1)double normCout =1-(distributionsCout[s].GetMean()-300)/200;// 300-500 MEUR → 1-0double normSec = distributionsSec[s].GetMean();// Deja 0-1double normNuis =1-(distributionsNuis[s].GetMean()-1)/9;// 1-10 → 1-0 EU[s]= w_cout * normCout + w_securite * normSec + w_nuisances * normNuis; Console.WriteLine($"{sites[s],-21} :"); Console.WriteLine($" v_cout={normCout:F3}, v_sec={normSec:F3}, v_nuis={normNuis:F3}"); Console.WriteLine($" => EU = {EU[s]:F3}");}// Decision optimaleint bestSite = EU.Select((v, i)=>(v, i)).OrderByDescending(x => x.v).First().i;Console.WriteLine($"\n=== Decision Optimale : {sites[bestSite]} (EU = {EU[bestSite]:F3}) ===");
=== Decision Multi-Attribut avec Infer.NET : Site d'Aeroport ===
Poids : Cout=35 %, Securite=40 %, Nuisances=25 %
Distributions des attributs par site :
Site | Cout (MEUR) | Securite | Nuisances
----------------------|------------------|------------------|------------------
Compiling model...done.
Compiling model...done.
Compiling model...done.
Site A (cotier) | 500 +/- 100 | 80 % +/- 12 % | 3,0 +/- 1,0
Compiling model...done.
Compiling model...done.
Compiling model...done.
Site B (rural) | 300 +/- 71 | 50 % +/- 15 % | 1,0 +/- 0,7
Compiling model...done.
Compiling model...done.
Compiling model...done.
Site C (periurbain) | 400 +/- 89 | 60 % +/- 15 % | 5,0 +/- 1,4
=== Calcul de l'Utilite Esperee par Site ===
Site A (cotier) :
v_cout=0,000, v_sec=0,800, v_nuis=0,778
=> EU = 0,514
Site B (rural) :
v_cout=1,000, v_sec=0,500, v_nuis=1,000
=> EU = 0,800
Site C (periurbain) :
v_cout=0,500, v_sec=0,600, v_nuis=0,556
=> EU = 0,554
=== Decision Optimale : Site B (rural) (EU = 0,800) ===
Interpretation de l’analyse multi-attribut
Cet exemple combine Decision Networks et MAUT (Multi-Attribute Utility Theory) pour un problème realiste de choix de site.
Résultats attendus de l’analyse
L’exécution du code ci-dessus produit :
Site
Cout (normalise)
Securite (normalise)
Nuisances (normalise)
EU
A (cotier)
0.0 (500M = max)
0.80
0.78
~0.55
B (rural)
1.0 (300M = min)
0.50
1.00
~0.78
C (periurbain)
0.5
0.60
0.56
~0.55
Note : Les valeurs exactes dependent de l’exécution et des distributions inferees.
Rôle de l’incertitude
Contrairement a MAUT déterministe, ici chaque attribut est incertain : - Les couts suivent une distribution gaussienne (incertitude geologique) - La securite suit une distribution Beta (incertitude sur les conditions) - Les nuisances suivent une gaussienne (incertitude environnementale)
Infer.NET calcule les esperances de ces distributions pour le scoring MAUT.
Extensions possibles
Extension
Description
Analyse de sensibilite
Varier les poids pour voir si la decision change
Dominance stochastique
Comparer les distributions completes, pas seulement les moyennes
Information supplementaire
Modeliser une étude de terrain comme source d’information
// Generation du factor graph pour le modele MAUT d'un site (Site B comme exemple)// Ce modele montre 3 variables independantes : Cout, Securite, NuisancesVariable<double> coutMAUT = Variable.GaussianFromMeanAndVariance(300,5000).Named("Cout_SiteB");Variable<double> secMAUT = Variable.Beta(5,5).Named("Securite_SiteB");Variable<double> nuisMAUT = Variable.GaussianFromMeanAndVariance(1,0.5).Named("Nuisances_SiteB");var engineMAUT =newInferenceEngine();engineMAUT.Compiler.CompilerChoice= Microsoft.ML.Probabilistic.Compiler.CompilerChoice.Roslyn;engineMAUT.ShowFactorGraph=true;// Inferer pour generer le graphevar postCout = engineMAUT.Infer<Gaussian>(coutMAUT);var postSec = engineMAUT.Infer<Beta>(secMAUT);var postNuis = engineMAUT.Infer<Gaussian>(nuisMAUT);Console.WriteLine("Factor Graph du modele MAUT pour Site B :");Console.WriteLine($" Cout ~ Gaussian({postCout.GetMean():F0}, {Math.Sqrt(postCout.GetVariance()):F0})");Console.WriteLine($" Securite ~ Beta(5,5) = {postSec.GetMean():P0}");Console.WriteLine($" Nuisances ~ Gaussian({postNuis.GetMean():F1}, {Math.Sqrt(postNuis.GetVariance()):F1})");Console.WriteLine();// Afficher le factor graphFactorGraphHelper.GetLatestFactorGraphHtml(700).DisplayAs("text/html");
Compiling model...done.
Compiling model...done.
Compiling model...done.
Factor Graph du modele MAUT pour Site B :
Cout ~ Gaussian(300, 71)
Securite ~ Beta(5,5) = 50 %
Nuisances ~ Gaussian(1,0, 0,7)
Model_09_23_26_09_16_15_21.svg
Exercice 3 : Reseau de decision avec Infer.NET - Assurance qualite
Une usine fabrique des composants electroniques. Chaque lot peut contenir des pieces defectueuses (variable de chance inobservable directement). L’agent de qualite peut :
Action A : Expedier le lot tel quel (pas de cout, mais risque de reclamations)
Action B : Tester une piece echantillon, puis decider d’expedier ou de trier le lot
Paramètres : - P(lot defectueux) = 0.20 (20% des lots ont un taux de defaut eleve) - Test echantillon : sensibilite = 0.88, specificite = 0.75 - Couts : expedier un lot defectueux = -500 EUR (reclamations), expedier un lot sain = +200 EUR, trier le lot (quel que soit l’etat) = -50 EUR (cout fixe de tri)
Étapes : 1. Modelisez les variables de chance avec Infer.NET (Variable.Bernoulli pour le defaut, Variable.If/Variable.IfNot pour le test conditionnel) 2. Pour chaque observation du test (positif/negatif), utilisez engine.Infer<Bernoulli>() pour calculer P(defaut|test) 3. Calculez E[U] de chaque action (expedier vs trier) conditionnellement a chaque résultat de test 4. Determinez la politique optimale : que faire si test positif ? si test negatif ? 5. (Bonus) : Pour quel seuil de P(defaut) la politique change-t-elle (seuil de decision) ?
Indices : - Reutilisez le pattern de la section 7 : boucle foreach (bool obsTest in new[] { true, false }) avec testPositif.ObservedValue = obsTest - N’oubliez pas testPositif.ClearObservedValue() entre les itérations - Le cout de tri (-50 EUR) est identique que le lot soit defectueux ou sain
// Exercice : Reseau de decision avec Infer.NET - Assurance qualite// Parametresdouble pDefaut =0.20;// P(lot defectueux)double sensibiliteQA =0.88;// P(test+|defaut)double specificiteQA =0.75;// P(test-|sain)double cout_expedier_defaut =-500;// Reclamationsdouble cout_expedier_sain =200;// Profit normaldouble cout_trier =-50;// Cout fixe de tri// TODO 1 : Modelisez les variables de chance avec Infer.NET// Indice : Variable<bool> defaut = Variable.Bernoulli(pDefaut).Named("defaut");// Variable<bool> testPos = Variable.New<bool>().Named("testQA");// using (Variable.If(defaut)) testPos.SetTo(Variable.Bernoulli(sensibiliteQA));// using (Variable.IfNot(defaut)) testPos.SetTo(Variable.Bernoulli(1 - specificiteQA));// TODO 2 : Creez le moteur d'inference et bouclez sur les observations// InferenceEngine engineQA = new InferenceEngine();// engineQA.Compiler.CompilerChoice = CompilerChoice.Roslyn;// foreach (bool obs in new[] { true, false }) { testPos.ObservedValue = obs; ... }// TODO 3 : Pour chaque observation, calculez P(defaut|test) puis E[U] de chaque action// double pD = engineQA.Infer<Bernoulli>(defaut).GetProbTrue();// E[U(expedir)] = pD * cout_expedier_defaut + (1 - pD) * cout_expedier_sain// E[U(trier)] = cout_trier (fixe, independant de l'etat)// TODO 4 : Affichez la politique optimale conditionnelle// Si test positif : expedier ou trier ?// Si test negatif : expedier ou trier ?// TODO 5 : (Bonus) Trouvez le seuil de P(defaut) ou la politique change// Indice : resolvez pD * cout_expedier_defaut + (1 - pD) * cout_expedier_sain = cout_trier pour pDConsole.WriteLine("Exercice a completer");
Exercice a completer
Recapitulatif des concepts Infer.NET utilises
Distributions utilisees
Distribution
Usage dans ce notebook
Exemple
Bernoulli
Variables binaires (maladie, test)
Variable.Bernoulli(0.15)
Gaussian
Attributs continus incertains (couts)
Variable.GaussianFromMeanAndVariance(500, 10000)
Beta
Scores bornes [0,1] (securite)
Variable.Beta(8, 2)
Patterns Infer.NET
Pattern
Description
Section
Modèle conditionnel
using (Variable.If(...)) pour CPT
7
Observation
variable.ObservedValue = ...
7
Enumeration
Boucle sur les observations possibles
7
Factor Graph
ShowFactorGraph = true
7.1
Concepts de decision illustres
Concept
Description
Section
Arcs informationnels
Ce que l’agent sait avant de decider
3
Backward induction
Resolution de la fin vers le debut
4
Valeur de l’information
Gain d’utilite grace a l’observation
5
Decisions séquentielles
Plusieurs decisions dans le temps
6
MAUT probabiliste
Multi-attributs avec incertitude
8bis
9. Resume
Concept
Description
Reseau de decision
Extension des reseaux bayesiens avec decisions et utilites
Noeuds de decision
Choix contrôles par l’agent
Noeuds d’utilite
Consequences des choix
Arcs informationnels
Ce que l’agent sait au moment de decider
Politique
Fonction observations → decisions
Backward induction
Resolution du dernier au premier noeud de decision