Traitement de l’information incertaine¶
Réseaux Bayésiens¶
Exercice 1: Raisonnement probabiliste¶
Informellement, la probabilité que vous soyez malade est toujours proportionnelle à la probabilité de cette maladie. Ainsi, sur 10‘000 personnes, l’une d’entre elle sera effectivement malade et sera diagnostiquée comme telle par le test avec 99% de chance. Cependant, pour les 9‘999 personnes restantes, le test se trompera dans 1% des cas. Environ 100 personnes seront donc positives au test bien que n’étant pas malade. Globalement, vous avez donc seulement 1% de risque d’être effectivement malade si le test est positif.
Plus formellement, soit
la variable représentant le résultat du test, et
la variable représentant la maladie. Par définition des taux de faux négatifs et de faux positifs, on a
et
. Cependant,
puisque la maladie ne frappe qu’une personne sur 10‘000. La probabilité qui nous intéresse est
, puisque nous souhaitons déterminer le risque que vous soyez effectivement malade sachant que votre test a été positif. Or,

Comme ce chiffre demeure très faible, vous ne devez pas forcément vous inquiéter. Bien sûr, cette conclusion est due à la faible fréquence de la maladie dans la population.
Exercice 2: Causalité¶
Modélisation du problème¶
Question 2.1 :¶
Le réseau bayésien (figure 1) possède les noeuds :
= Route-Gelée
= Accident-Holmes
= Accident-Watson
= Professeur-Sauvé
et les arcs:
et
, car l’état des routes influence les accidents de Holmes et de Watson.
et
, car les accidents de Holmes et de Watson influencent la résolution de l’affaire.
Figure 1 Le réseau bayésien avec les noeuds: I=Route-Gelée, H=Accident-Holmes, W=Accident-Watson, S=Professeur-Sauvé
Question 2.2 (Inférence déductive) :¶
- Pour calculer
, il nous faut connaître
:

Il en va de même de la probabilité
, pour laquelle il faut connaître
:

- Pour calculer
, il nous faut en plus
:

Question 2.3 (Inférence abductive) :¶
La probabilité que nous cherchons est
. Pour la calculer, il nous faut
. Par la règle de Bayes, nous avons :

Question 2.4 (Déduction et abduction) :¶
- On cherche
. Il nous faut donc
et
:

- On cherche
. Il nous faut donc en plus
:

On détermine
de sorte que:

- On cherche
:

On détermine
de sorte que :

Calcul probabiliste¶
Question 2.5 :¶
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
0.9 | 0.1 | ![]() |
0.7 | 0.5 |
![]() |
0.1 | 0.9 | ![]() |
0.3 | 0.5 |
Question 2.6 :¶

Question 2.8 (Dépendance) :¶

On peut constater que la probabilité d’accident de Holmes a augmenté suite à la connaissance de l’accident de Watson, car cet accident laisse supposer que la route peut être gelée.
et
sont deux événements dépendants.
Question 2.9 (Indépendance conditionnelle) :¶
Si l’on sait que la route n’est pas gelée,
et l’accident de Watson n’a plus d’influence sur la probabilité d’accident de Holmes. En effet, l’accident de Watson n’a pas d’effet sur la probabilité que la route soit gelée puisque celle-ci est connue avec certitude. Ainsi, on a:
, sachant que
,
et
sont deux événements indépendants.
Question 2.10 :¶
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
0.1 | 0.2 | 0.8 | 1 |
![]() |
0.9 | 0.8 | 0.2 | 0 |
Question 2.11 (Causes multiples) :¶

Question 2.13 (Abduction avec plusieurs conséquences) :¶

Question 2.15 (Dépendance conditionnelle) :¶

Il faut que
, donc on trouve
et
et
. Donc, si en plus on sait que Watson a eu un accident, la probabilité que Holmes en ait eu un aussi redescend un peu. Ainsi,
et
sont des événements dépendants sachant que
et
.
Figure 2 Le nouveau réseau bayésien avec les noeuds: I=Route-Gelée, H=Accident-Holmes, W=Accident-Watson, S=Professeur-Sauvé, V=Vieux-Pneus-Watson
Question 2.16 :¶
On ajoute le noeud
= Vieux-Pneus-Watson et l’arc
(figure 2).
Inférence à chaînage avant avec facteurs de certitude¶
Module .../moteur_avec_variables_fc/facteurs_certitude.py :
""" Fonctions utilitaires pour gérer des facteurs de certitude. """
def fc_ou(fc1, fc2):
""" Calcule le facteur de certitude d'une disjonction de faits. """
if fc1 > 0.0 and fc2 > 0.0:
return fc1 + fc2 - (fc1 * fc2)
elif fc1 < 0.0 and fc2 < 0.0:
return fc1 + fc2 + (fc1 * fc2)
else:
return (fc1 + fc2) / (1.0 - min(abs(fc1), abs(fc2)))
def fc_et(fc1, fc2):
""" Calcule le facteur de certitude d'une conjonction de faits. """
return min(fc1, fc2)
Module .../moteur_avec_variables_fc/regle_avec_variables_fc.py :
from .facteurs_certitude import fc_et
class RegleAvecVariables_FC:
""" Représentation d'une règle d'inférence pour le chaînage avec variables. """
def __init__(self, conditions, conclusion, fc=1.0):
""" Construit une règle étant donné une liste de conditions,\
une conclusion et un facteur de certitude associé.
:param list conditions: une collection de propositions (pouvant\
contenir des variables) nécessaires à déclencher la règle.
:param conclusion: la proposition (pouvant contenir des variables)\
résultant du déclenchement de la règle.
:param fc: le facteur de certitude associé.
"""
self.conditions = conditions
self.conclusion = conclusion
self.fc = fc
def depend_de(self, fait, methode):
""" Vérifie qu'un fait fait partie, sous réserve de substitution,\
des conditions de la règle.
:param fait: un fait qui doit faire partie des conditions de\
déclenchement.
:param methode: ``Filtre`` ou ``Unificateur``, détermine le type\
de pattern match à appliquer.
:return: un dictionnaire qui attribue un environnement à chaque\
condition qui peut être satisfaite par le fait pasée en paramètre.\
``False`` si aucune condition n'est satisfaite par le fait.
"""
envs = {}
for condition in self.conditions:
# Si au moins une des conditions retourne un environnement,
# nous savons que la proposition satisfait une des conditions.
env = methode.pattern_match(fait, condition, {})
if env != methode.echec:
envs[condition] = env
return envs
def satisfaite_par(self, faits, cond, env, env_fc, methode):
""" Vérifie que des faits suffisent, sous réserve de substitution,\
à déclencher la règle.
:param list faits: une liste de faits.
:param cond: la condition qui a donné lieu à ``env`` par le\
pattern match.
:param dict env: un environnement de départ déjà établi par\
``depend_de``.
:param env_fc: le facteur de certitude associé à ``env``.
:param methode: ``Filtre`` ou ``Unificateur``, détermine le type\
de pattern match à appliquer.
:return: une liste d'environnements qui correspondent à toutes les\
substitutions possibles entre les conditions de la règle et les\
propositions. On retourne une liste vide si au moins une condition\
ne peut être satisfaite.
"""
envs_et_fcs = [(env, env_fc)]
conditions_a_tester = [cond1 for cond1 in self.conditions if cond1 != cond]
for cond1 in conditions_a_tester:
nouveaux_envs_et_fcs = []
for fait, fait_fc in faits:
for env1, env_fc1 in envs_et_fcs:
env1 = methode.pattern_match(fait, cond1, env1)
if env1 != methode.echec:
fc_mix = fc_et(env_fc1, fait_fc)
nouveaux_envs_et_fcs.append((env1, fc_mix))
if len(nouveaux_envs_et_fcs) == 0:
return []
envs_et_fcs = nouveaux_envs_et_fcs
return envs_et_fcs
def __repr__(self):
""" Représentation d'une règle sous forme de string. """
return '{} => {}, {}'.format(str(self.conditions),
str(self.conclusion),
str(self.fc))
Module .../moteur_avec_variables_fc/connaissance_fc.py :
from .facteurs_certitude import fc_ou
from moteur_avec_variables_fc.regle_avec_variables_fc import RegleAvecVariables_FC
class BaseConnaissances_FC:
""" Une base de connaissances destinée à contenir les faits et les règles\
d'un système de chaînage avec facteurs de certitude.
"""
def __init__(self):
""" Construit une base de connaissances. """
self.faits = {}
self.regles = []
def ajoute_un_fait(self, fait):
""" Ajoute un fait dans la base de connaissances.
Un fait est un tuple composé du fait proprement dit, c'est-à-dire\
une proposition sans variable, et optionnellement d'un scalaire\
représentant son facteur de certitude.
:param fait: un fait.
"""
if len(fait) == 2:
prop, fc = fait
elif len(fait) == 1:
prop, fc = fait[0], 1.0
else:
raise ValueError("Fait mal formé: " + str(fait))
fc_deja_present = self.faits.get(prop)
if fc_deja_present is not None:
nouveau_fc = fc_ou(fc, fc_deja_present)
self.faits[prop] = nouveau_fc
else:
self.faits[prop] = fc
def ajoute_faits(self, faits):
""" Ajoute une liste de faits dans la base de connaissances.
:param list faits: une liste de faits.
"""
for fait in faits:
self.ajoute_un_fait(fait)
def ajoute_une_regle(self, description):
""" Ajoute une règle dans la base de connaissances étant donné sa\
description.
Une règle est décrite par une liste (ou un tuple) de deux ou trois\
éléments: une liste de conditions, une conclusion et un facteur de\
certitude optionnel.
Les conditions et la conclusion doivent être des propositions.
:param description: une description de règle.
"""
if len(description) == 2:
regle = RegleAvecVariables_FC(description[0], description[1])
elif len(description) == 3:
regle = RegleAvecVariables_FC(description[0], description[1], description[2])
else:
raise ValueError("Une règle doit avoir deux ou trois éléments. Reçu " +
str(description))
self.regles.append(regle)
def ajoute_regles(self, descriptions):
""" Ajoute des règles dans la base de connaissance.
L'argument est une liste de descriptions, chacune composée d'une\
liste de conditions, d'une conséquence et optionnellement d'un\
facteur de certitude.
:param list descriptions: une liste de descriptions de règles.
"""
for description in descriptions:
self.ajoute_une_regle(description)
Module .../moteur_avec_variables_fc/chainage_avant_avec_variables_fc.py :
from moteur_sans_variables.chainage import Chainage
from moteur_avec_variables.filtre import Filtre
class ChainageAvantAvecVariables_FC(Chainage):
""" Un moteur d'inférence à chaînage avant avec variables. """
def __init__(self, connaissances, methode=None):
"""
:param methode: ``Filtre`` ou ``Unificateur``, détermine le type de\
pattern match à appliquer. ``Filtre`` par défaut.
"""
Chainage.__init__(self, connaissances)
if methode is None:
self.methode = Filtre()
else:
self.methode = methode
def instancie_conclusion(self, regle, envs_et_fcs):
""" Instancie la conclusion d'une règle pour tous les environnements.
:param regle: la règle dont la conclusion doit être instanciée.
:param list envs_et_fcs: une liste de paires d'environnements et de\
facteurs de certitude servant à instancier la conclusion de la règle.
:return: une liste de propositions correspondant aux différentes\
instanciations de la conclusion.
"""
nouveaux_faits = []
for env, env_fc in envs_et_fcs:
prop = self.methode.substitue(regle.conclusion, env)
nouveau_fait = (prop, max(0.0, env_fc) * regle.fc)
nouveaux_faits.append(nouveau_fait)
return nouveaux_faits
def chaine(self):
""" Effectue le chaînage avant sur les faits et les règles contenus\
dans la base de connaissances.
"""
queue = [p for p in self.connaissances.faits.items()]
self.reinitialise()
while len(queue) > 0:
fait, fait_fc = queue.pop(0)
if (fait, fait_fc) not in self.solutions:
self.trace.append((fait, fait_fc))
self.solutions.append((fait, fait_fc))
# Si le facteur de certitude du fait est supérieur à 0.0
if fait_fc > 0.0:
# on vérifie si des règles sont déclenchées par le nouveau fait.
for regle in self.connaissances.regles:
envs = regle.depend_de(fait, self.methode)
for cond, env in envs.items():
# On remplace l'environnement par ceux qui satisfont toutes les conditions de la règle
# et pas seulement la première condition.
envs1 = regle.satisfaite_par(self.solutions, cond, env, fait_fc, self.methode)
# On ajoute à la queue la conclusion de la règle instanciée selon chaque environnement possible.
if len(envs1) > 0:
queue.extend(self.instancie_conclusion(regle, envs1))
self.trace.append(regle)
return self.solutions






.\







, donc on trouve
,
et
.
, donc on trouve
et
et
.
. Il nous faut donc
:
de sorte que :