Cours

Cours.TME5 History

Hide minor edits - Show changes to output

October 23, 2017, at 11:04 AM EST by 132.227.203.245 -
Changed line 305 from:
import pydot       
to:
import pydotplus
October 22, 2017, at 03:09 PM EST by 132.227.207.128 -
Changed lines 350-352 from:
from pyAgrum.lib.pretty_print import pretty_cpt

to:

Changed line 376 from:
print bn
to:
print(bn)
Changed line 383 from:
pretty_cpt ( bn.cpt ( bn.idFromName ( 'bronchitis?' ) ) )
to:
gnb.showPotential( bn.cpt ( bn.idFromName ( 'bronchitis?' ) ) )
Changed lines 390-393 from:
proba = gnb.getPosterior ( bn, {}, 'bronchitis?' )

# affichage de la marginale
pretty_cpt ( proba
)
to:
proba = gum.getPosterior ( bn, {}, 'bronchitis?' )
Changed lines 396-397 from:
gnb.showPosterior ( bn, {}, 'bronchitis?' )
to:
# affichage de la marginale
gnb.showPotential( proba
)
Changed line 403 from:
gnb.showPosterior ( bn, {'smoking?': 'true', 'tuberculosis?' : 'false' }, 'bronchitis?' )
to:
gnb.showPotential(gum.getPosterior ( bn,{'smoking?': 'true', 'tuberculosis?' : 'false' }, 'bronchitis?' ))
October 04, 2017, at 09:22 AM EST by 132.227.207.127 -
Changed lines 349-350 from:
import gumLib.ipython as gnb
from gumLib.pretty_print import pretty_cpt
to:
import pyAgrum.lib.ipython as gnb
from pyAgrum.lib.pretty_print import pretty_cpt
October 04, 2017, at 09:20 AM EST by 132.227.207.127 -
Changed line 349 from:
import gumLib.notebook as gnb
to:
import gumLib.ipython as gnb
October 04, 2017, at 09:13 AM EST by 132.227.207.127 -
Changed line 91 from:
   data = np.loadtxt ( filename, delimiter=',', dtype='string' ).T
to:
   data = np.loadtxt ( filename, delimiter=',', dtype=np.str ).T
Changed lines 15-16 from:
|| asia || %target=_blank% [[http://www.cs.huji.ac.il/site/labs/compbio/Repository/networks.html | BN repository]] || 256 ||
|| alarm || %target=_blank% [[http://www.cs.huji.ac.il/site/labs/compbio/Repository/networks.html | BN repository]] || 10'^16^' ||
to:
|| asia || %target=_blank% [[http://www.bnlearn.com/bnrepository/ | BN repository]] || 256 ||
|| alarm || %target=_blank% [[http://www.bnlearn.com/bnrepository/ | BN repository]] || 10'^16^' ||
Changed line 216 from:
||sufficient_statistics ( data, dico, 2,3,[5])|| (130.0, 2) ||
to:
||sufficient_statistics ( data, dico, 2,3,[5])||(130.0, 2) ||
Changed lines 258-263 from:
||best_candidate ( data, dico, 1, [], 0.05 ) ||[] ||
||best_candidate ( data, dico, 4, [], 0.05 ) ||[1] ||
||best_candidate ( data, dico, 4, [1], 0.05 ) ||[] ||
||best_candidate ( data, dico, 5, [], 0.05 ) ||[3] ||
||best_candidate ( data, dico, 5, [6], 0.05 ) || [3] ||
||best_candidate ( data, dico, 5, [6,7], 0.05 ) ||[2] ||
to:
||best_candidate ( data, dico, 1, [], 0.05 ) || [] ||
||best_candidate ( data, dico, 4, [], 0.05 ) || [1] ||
||best_candidate ( data, dico, 4, [1], 0.05 ) || [] ||
||best_candidate ( data, dico, 5, [], 0.05 ) || [3] ||
||best_candidate ( data, dico, 5, [6], 0.05 )  || [3] ||
||best_candidate ( data, dico, 5, [6,7], 0.05 ) || [2] ||
Changed lines 3-4 from:
to:
%define=part apply=block bgcolor=#e6d8c0%
Added lines 6-7:

!! %part%Partie obligatoire%%
Changed lines 136-137 from:
-> En effet le paramètre @@[3]@@ indique que {$\mathbf{Z}$} est constitué uniquement de la quatrième variable de la base, autrement dit X_3. La dernière ligne du tableau @@data@@ indique les instanciations de X_3 et l'on peut observer que la valeur 0 apparaît 2 fois et  la valeur 1 apparaît une fois. On a donc {$N_{Z=0} = 2$} et {$N_{Z=1} = 1$}. On peut observer que les valeurs de {$N_{\mathbf{Z}}$} sont bien les premiers éléments des couples de @@resultat@@.
to:
-> En effet le paramètre @@[3]@@ indique que {$\mathbf{Z}$} est constitué uniquement de la quatrième variable de la base, autrement dit X_3. La dernière ligne du tableau @@data@@ indique les instanciations de X_3 et l'on peut observer que la valeur 0 apparaît 2 fois et  la valeur 1 apparaît une fois. On a donc {$N_{Z=0} = 2$} et {$N_{Z=1} = 1$}. On peut observer que les valeurs de {$N_{\mathbf{Z}}$} sont bien les premiers éléments des couples de @@resultat@@. Lorsque {$\mathbf{Z} = \emptyset$}, @@resultat@@ est un tableau avec un seul couple dont le premier élément correspond précisément à {$N$}, le nombre d'enregistrements de la base de données.
Changed lines 226-227 from:
Ecrivez une fonction '''indep_score'''( data, dico, x, y, z ) qui, étant donné les mêmes paramètres que ceux de la question précédente, vous renvoie un couple contenant la p-value correspondant à {$\chi^2_{X,Y|\mathbf{Z}}$} ainsi que le nombre de degrés de liberté de cette statistique. Vous testerez au préalable si len ( data[0] ), le nombre de lignes de votre CSV, est supérieur ou non à {$d_{min}$} ; si c'est inférieur, vous renverrez le couple (-1,1), qui représente une indépendance. Vous pourrez vous aider de la fonction scipy.stats.chi2.sf ( x, DoF ) qui renvoie la p-value (x) pour une loi à DoF degrés de liberté.
to:
Ecrivez une fonction '''indep_score''' @@: int np.2D-array x dico{string -> int} np.array x int x int x int list -> (float,int)@@ qui, étant donné les mêmes paramètres que ceux de la question précédente, vous renvoie un couple contenant la p-value correspondant à {$\chi^2_{X,Y|\mathbf{Z}}$} ainsi que le nombre de degrés de liberté de cette statistique. Vous testerez au préalable si len ( data[0] ), le nombre de lignes/enregistrements de votre CSV, est supérieur ou non à {$d_{min}$} ; si c'est inférieur, vous renverrez le couple (-1,1), qui représente une indépendance. Vous pourrez vous aider de la fonction scipy.stats.chi2.sf ( x, DoF ) qui renvoie la p-value (x) pour une loi à DoF degrés de liberté.
Changed lines 245-248 from:
to:
----
!! %part%Partie optionnelle%%
----

Changed lines 251-255 from:
Ecrivez une fonction '''best_candidate''' ( data, dico, x, z, alpha ) qui, étant donné une variable aléatoire {$X$} et un ensemble de variables aléatoires {$\mathbf{Z}$} détermine la variable {$Y$} (en fait, l'index de sa colonne dans le CSV), parmi toutes celles à gauche de {$X$} dans le fichier CSV, qui est la plus dépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, autrement dit, celle qui a la plus petite p-value. Si cette p-value est supérieure à alpha, cela veut dire que {$\chi^2_{X,Y|\mathbf{Z}}$} est inférieur à {$c_{\alpha}$} et donc que {$Y$} est jugée indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}. Votre fonction renverra une liste vide si {$Y$} est indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, sinon elle renverra une liste contenant {$Y$}. Vous pourrez tester votre fonction avec {$\alpha$} = 0.05.\\\


[[Cours.TME5ValidationCand  | Tests de validation du calcul des candidats parents
]]
to:
Ecrivez une fonction '''best_candidate''' @@: int np.2D-array x dico{string -> int} np.array x int x int list x float -> int list@@ qui, étant donné les tableaux @@data@@ et @@dico@@ calculés à la question 1, l'index d'une variable aléatoire {$X$}, la liste d'index d'un ensemble de variables aléatoires {$\mathbf{Z}$} et un risque {$\alpha$}, détermine la variable {$Y$} (en fait, l'index de sa colonne dans le CSV), parmi toutes celles à gauche de {$X$} dans le fichier CSV, qui est la plus dépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, autrement dit, celle qui a la plus petite p-value. Si cette p-value est supérieure à {$\alpha$}, cela veut dire que {$\chi^2_{X,Y|\mathbf{Z}}$} est inférieur à {$c_{\alpha}$} et donc que {$Y$} est jugée indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}. Votre fonction renverra une liste vide si {$Y$} est indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, sinon elle renverra une liste contenant {$Y$}. Vous pourrez tester votre fonction avec {$\alpha$} = 0.05:

|| border=1 align=center
||! appel de la fonction ||! résultat ||
||best_candidate ( data, dico, 1, [
], 0.05 ) ||[] ||
||best_candidate ( data, dico, 4, [], 0.05 ) ||[1] ||
||best_candidate ( data, dico, 4, [1], 0.05 ) ||[] ||
||best_candidate ( data, dico, 5, [], 0.05 ) ||[3] ||
||best_candidate ( data, dico, 5, [6], 0.05 ) || [3] ||
||best_candidate ( data, dico, 5, [6,7], 0.05 ) ||[2] ||

\\


Changed lines 273-274 from:
[[Cours.TME5ValidationParent  | Tests de validation de création des parents]]
to:
Vous pourrez tester la validité de votre fonction :

|| border=1 align=center
||! appel de la fonction ||! résultat ||
||create_
parents ( data, dico, 1, 0.05 ) ||[] ||
||create_parents ( data, dico, 4, 0.05 ) ||[1
] ||
||create_parents ( data, dico, 5, 0.05 ) ||[3, 2] ||
||create_parents ( data, dico, 6, 0.05 ) ||[4, 5] ||

\\


Changed lines 335-339 from:
to:
\\



Added lines 405-406:

\\
Deleted line 217:
Changed lines 233-244 from:
[[Cours.TME5ValidationIndep  | Tests de validation du calcul de l'indépendance]]
to:

Vous pourrez vérifier la validité de vos calculs: en utilisant la base de données "2015_tme5_asia.csv", vous devriez obtenir les résultats suivants:

|| border=1 align=center
||! appel de la fonction ||! résultat ||
||indep_score ( data, dico, 1,3,[
]) ||2.38520176938e-19 ||
||indep = indep_score ( data, dico, 1, 7, [
]) ||1.12562784979e-10 ||
||indep = indep_score ( data, dico, 0, 1,[2, 3]) ||0.000958828236575 ||
||indep = indep_score ( data, dico, 1, 2,[3, 4]) ||0.475266197894 ||

\\

Changed lines 146-148 from:
En utilisant la structure retournée par la fonction '''create_contingency_table''', écrivez une fonction '''sufficient_statistics'''@@: int np.2D-array x dico{string -> int} np.array x int x int x int list -> float@@ qui prend les mêmes arguments que la fonction '''create_contingency_table''' et qui renvoie la valeur de {$\chi^2_{X,Y|\mathbf{Z}}$}. Vous pourrez tirer profit du fait que {$N_{x\mathbf{z}} = \sum_{y} N_{xy\mathbf{z}}$} et {$N_{y\mathbf{z}} = \sum_{x} N_{xy\mathbf{z}}$}, ce qui revient à faire des sommes sur chaque ligne ou chaque colonne des {$N_{xy\mathbf{z}}$}. '''Attention :''' il peut arriver que certains {$N_{\mathbf{z}}$} soient égaux à 0. Dans ce cas, vous ne tiendrez pas compte des {$N_{xy\mathbf{z}}$}, {$N_{x\mathbf{z}}$} et {$N_{y\mathbf{z}}$} correspondants dans la formule de {$\chi^2_{X,Y|\mathbf{Z}}$} (car vous feriez des divisions par 0, ce qui est mal).

to:
En utilisant la structure retournée par la fonction '''create_contingency_table''', écrivez une fonction '''sufficient_statistics'''@@: int np.2D-array x dico{string -> int} np.array x int x int x int list -> float@@ qui prend les mêmes arguments que la fonction '''create_contingency_table''' et qui renvoie la valeur de {$\chi^2_{X,Y|\mathbf{Z}}$}. Vous pourrez tirer profit du fait que {$N_{x\mathbf{z}} = \sum_{y} N_{xy\mathbf{z}}$} et {$N_{y\mathbf{z}} = \sum_{x} N_{xy\mathbf{z}}$}, ce qui revient à faire des sommes sur chaque ligne ou chaque colonne des tableaux {$T_{X,Y,\mathbf{z}}$}. '''Attention :''' il peut arriver que certains {$N_{\mathbf{z}}$} soient égaux à 0. Dans ce cas, vous ne tiendrez pas compte des {$N_{xy\mathbf{z}}$}, {$N_{x\mathbf{z}}$} et {$N_{y\mathbf{z}}$} correspondants dans la formule de {$\chi^2_{X,Y|\mathbf{Z}}$} (car vous feriez des divisions par 0, ce qui est mal).

Changed lines 190-193 from:
||sufficient_statistics ( data, dico, 5,2,[1,3,6] ||1897.0 ||
||sufficient_statistics ( data, dico, 0,7,[4,5] ||3.2223237760949699 ||
||sufficient_statistics ( data, dico, 2,3,[5] ||130.0 ||
to:
||sufficient_statistics ( data, dico, 5,2,[1,3,6]) ||1897.0 ||
||sufficient_statistics ( data, dico, 0,7,[4,5]) ||3.2223237760949699 ||
||sufficient_statistics ( data, dico, 2,3,[5]) ||130.0 ||
Changed lines 202-204 from:
où {$|X|$} représente le nombre de valeurs possibles que peut prendre la variable {$X$}, autrement dit, c'est la taille de son dictionnaire. Le dernier terme de l'équation est simplement le nombre de {$N_{\mathbf{z}}$} différents de 0.\\\

[[Cours.TME5ValidationChi2  | Tests
de validation du calcul du chi2]]
to:
où {$|X|$} représente le nombre de valeurs possibles que peut prendre la variable {$X$}, autrement dit, c'est la taille de son dictionnaire. Le dernier terme de l'équation est simplement le nombre de {$N_{\mathbf{z}}$} différents de 0.

Vous pourrez vérifier la validité
de vos calculs: en utilisant la base de données "2015_tme5_asia.csv", vous devriez obtenir les résultats suivants:

|| border=1 align=center
||! appel de la fonction ||! résultat ||
||sufficient_statistics ( data, dico, 1,2,[3
]) ||(3.9466591186668296, 2) ||
||sufficient_statistics ( data, dico, 0,1,[2,3
]) ||(16.355207462350094, 3) ||
||sufficient_statistics ( data, dico, 1,3,[2]) ||(81.807449348140295, 2) ||
||sufficient_statistics ( data, dico, 5,2,[1,3,6]) ||(1897.0, 8) ||
||sufficient_statistics ( data, dico, 0,7,[4,5]) ||(3.2223237760949699, 4) ||
||sufficient_statistics ( data, dico, 2,3,[5])|| (130.0, 2) ||

\\

Changed lines 183-185 from:

[[Cours.TME5ValidationCont  | Tests
de validation de la contingence]] \\
[[Cours.TME5ValidationChi2  | Tests de validation du calcul du chi2
]]
to:
Vous pourrez vérifier la validité de vos calculs: en utilisant la base de données "2015_tme5_asia.csv", vous devriez obtenir les résultats suivants:

|| border=1 align=center
||! appel de la fonction ||! résultat ||
||sufficient_statistics ( data, dico, 1,2,[3
]) ||3.9466591186668296 ||
||sufficient_statistics ( data, dico, 0,1,[2,3
]) ||16.355207462350094 ||
||sufficient_statistics ( data, dico, 1,3,[2]) ||81.807449348140295 ||
||sufficient_statistics ( data, dico, 5,2,[1,3,6] ||1897.0 ||
||sufficient_statistics ( data, dico, 0,7,[4,5] ||3.2223237760949699 ||
||sufficient_statistics ( data, dico, 2,3,[5] ||130.0 ||

\\
Changed lines 146-172 from:
En utilisant la structure retournée par la fonction '''create_contingency_table''', écrivez une fonction '''sufficient_statistics'''@@: int np.2D-array x dico{string -> int} np.array x int x int x int list -> float@@ qui prend les mêmes arguments que la fonction ''create_contingency_table''' et qui renvoie la valeur de {$\chi^2_{X,Y|\mathbf{Z}}$}.




==========================================================


 ( data, dico, x, y, z ) qui, étant donné le tableau 2D des données et le dictionnaire obtenus à la question 1, ainsi que deux entiers x et y représentant deux variables aléatoires (les index de leurs colonnes dans le CSV, en commençant à l'index 0 pour la 1ère colonne) et une liste d'entiers z, potentiellement vide, représentant la liste des variables de {$\mathbf{Z}$} (index de colonnes dans le CSV), renvoie la valeur de {$\chi^2_{X,Y|\mathbf{Z}}$}. Ainsi, '''sufficient_statistics''' ( data, dico, 0, 1, [2,3] ) renverra la statistique pour {$X$} = la variable de la 1ère colonne du CSV, {$Y$} = la variable aléatoire de la 2ème colonne du CSV, et {$\mathbf{Z}$} = le couple des variables des 3ème et 4ème colonnes du CSV. Pour vous éviter de parser le tableau data afin de compter les nombres {$N_{xy\mathbf{z}}$}, {$N_{x\mathbf{z}}$}, {$N_{y\mathbf{z}}$} et {$N_{\mathbf{z}}$}, vous pourrez utiliser la fonction '''create_contingency_table''' ( data, dico, x, y, z ) ci-dessous qui, étant donné les mêmes arguments que votre fonction '''sufficient_statistics''', renvoie un tableau de couples ({$N_{\mathbf{z}}, T_{X,Y})$}, pour tous les {$\mathbf{z} \in\mathbf{Z}$}, où {$T_{X,Y}$} est un tableau 2D (première dimension en {$X$} et deuxième en {$Y$}) contenant les {$N_{x,y,\mathbf{z}}$}. Par exemple, '''create_contingency_table''' ( data, dico, 1, 2, [3] ) peut renvoyer le tableau suivant :

 array([(103, array([[  0.,  96.],
      [  0.,  7.]])),
      (1897, array([[ 887.,  18.],
      [ 983.,    9.]]))], dtype=object)

ce qui correspond précisément à :

{$$\begin{array}{l@{}l@{\ }l@{\ }l}
  \text{array([} & (N_{Z=0}\text{, array([} &
  [ N_{X=0,Y=0,\mathbf{Z}=0}, & N_{X=0,Y=1,\mathbf{Z}=0}],\\
  & & [ N_{X=1,Y=0,\mathbf{Z}=0}, & N_{X=1,Y=1,\mathbf{Z}=0}]])),\\
  & (N_{Z=1}\text{, array([} &
  [ N_{X=0,Y=0,\mathbf{Z}=1}, & N_{X=0,Y=1,\mathbf{Z}=1}],\\
  & & [ N_{X=1,Y=0,\mathbf{Z}=1}, & N_{X=1,Y=1,\mathbf{Z}=1}]]))])
\end{array}$$}

Pour un {$\mathbf{z}$} donné, calculer {$N_{x\mathbf{z}}$} revient donc à faire des sommes sur chaque ligne des {$N_{xy\mathbf{z}}$} et calculer les {$N_{y\mathbf{z}}$} revient à faire des sommes en colonne. '''Attention :''' il peut arriver que certains {$N_{\mathbf{z}}$} soient égaux à 0. Dans ce cas, vous ne tiendrez pas compte des {$N_{xy\mathbf{z}}$}, {$N_{x\mathbf{z}}$} et {$N_{y\mathbf{z}}$} correspondants dans la formule de {$\chi^2_{X,Y|\mathbf{Z}}$} (car vous feriez des divisions par 0, ce qui est mal).
to:
En utilisant la structure retournée par la fonction '''create_contingency_table''', écrivez une fonction '''sufficient_statistics'''@@: int np.2D-array x dico{string -> int} np.array x int x int x int list -> float@@ qui prend les mêmes arguments que la fonction '''create_contingency_table''' et qui renvoie la valeur de {$\chi^2_{X,Y|\mathbf{Z}}$}. Vous pourrez tirer profit du fait que {$N_{x\mathbf{z}} = \sum_{y} N_{xy\mathbf{z}}$} et {$N_{y\mathbf{z}} = \sum_{x} N_{xy\mathbf{z}}$}, ce qui revient à faire des sommes sur chaque ligne ou chaque colonne des {$N_{xy\mathbf{z}}$}. '''Attention :''' il peut arriver que certains {$N_{\mathbf{z}}$} soient égaux à 0. Dans ce cas, vous ne tiendrez pas compte des {$N_{xy\mathbf{z}}$}, {$N_{x\mathbf{z}}$} et {$N_{y\mathbf{z}}$} correspondants dans la formule de {$\chi^2_{X,Y|\mathbf{Z}}$} (car vous feriez des divisions par 0, ce qui est mal).
Changed lines 143-155 from:
-> Ce tableau nous indique que, lorsque {$X_3=0$}, les couples (X_0=0,X_2=0) et (X_0=1,X_2=2) apparaissent une seule fois et ce sont les seuls couples qui apparaissent dans la base de données. C'est précisément ce que représente le tableau en haut à droite de @@resultat@@.

==================================









Ecrivez une fonction
'''sufficient_statistics''' ( data, dico, x, y, z ) qui, étant donné le tableau 2D des données et le dictionnaire obtenus à la question 1, ainsi que deux entiers x et y représentant deux variables aléatoires (les index de leurs colonnes dans le CSV, en commençant à l'index 0 pour la 1ère colonne) et une liste d'entiers z, potentiellement vide, représentant la liste des variables de {$\mathbf{Z}$} (index de colonnes dans le CSV), renvoie la valeur de {$\chi^2_{X,Y|\mathbf{Z}}$}. Ainsi, '''sufficient_statistics''' ( data, dico, 0, 1, [2,3] ) renverra la statistique pour {$X$} = la variable de la 1ère colonne du CSV, {$Y$} = la variable aléatoire de la 2ème colonne du CSV, et {$\mathbf{Z}$} = le couple des variables des 3ème et 4ème colonnes du CSV. Pour vous éviter de parser le tableau data afin de compter les nombres {$N_{xy\mathbf{z}}$}, {$N_{x\mathbf{z}}$}, {$N_{y\mathbf{z}}$} et {$N_{\mathbf{z}}$}, vous pourrez utiliser la fonction '''create_contingency_table''' ( data, dico, x, y, z ) ci-dessous qui, étant donné les mêmes arguments que votre fonction '''sufficient_statistics''', renvoie un tableau de couples ({$N_{\mathbf{z}}, T_{X,Y})$}, pour tous les {$\mathbf{z} \in\mathbf{Z}$}, où {$T_{X,Y}$} est un tableau 2D (première dimension en {$X$} et deuxième en {$Y$}) contenant les {$N_{x,y,\mathbf{z}}$}. Par exemple, '''create_contingency_table''' ( data, dico, 1, 2, [3] ) peut renvoyer le tableau suivant :
to:
-> Ce tableau nous indique que, lorsque X_3=0, les couples (X_0=0,X_2=0) et (X_0=1,X_2=2) apparaissent une seule fois et ce sont les seuls couples qui apparaissent dans la base de données. C'est précisément ce que représente le tableau en haut à droite de @@resultat@@.


En utilisant la structure retournée par la fonction '''create_contingency_table''', écrivez une fonction '''sufficient_statistics'''@@: int np.2D-array x dico{string -> int} np.array x int x int x int list -> float@@ qui prend les mêmes arguments que la fonction ''create_contingency_table''' et qui renvoie la valeur de {$\chi^2_{X,Y|\mathbf{Z}}$}.




==========================================================


 ( data, dico, x, y, z ) qui, étant donné le tableau 2D des données et le dictionnaire obtenus à la question 1, ainsi que deux entiers x et y représentant deux variables aléatoires (les index de leurs colonnes dans le CSV, en commençant à l'index 0 pour la 1ère colonne) et une liste d'entiers z, potentiellement vide, représentant la liste des variables de {$\mathbf{Z}$} (index de colonnes dans le CSV), renvoie la valeur de {$\chi^2_{X,Y|\mathbf{Z}}$}. Ainsi, '''sufficient_statistics''' ( data, dico, 0, 1, [2,3] ) renverra la statistique pour {$X$} = la variable de la 1ère colonne du CSV, {$Y$} = la variable aléatoire de la 2ème colonne du CSV, et {$\mathbf{Z}$} = le couple des variables des 3ème et 4ème colonnes du CSV. Pour vous éviter de parser le tableau data afin de compter les nombres {$N_{xy\mathbf{z}}$}, {$N_{x\mathbf{z}}$}, {$N_{y\mathbf{z}}$} et {$N_{\mathbf{z}}$}, vous pourrez utiliser la fonction '''create_contingency_table''' ( data, dico, x, y, z ) ci-dessous qui, étant donné les mêmes arguments que votre fonction '''sufficient_statistics''', renvoie un tableau de couples ({$N_{\mathbf{z}}, T_{X,Y})$}, pour tous les {$\mathbf{z} \in\mathbf{Z}$}, où {$T_{X,Y}$} est un tableau 2D (première dimension en {$X$} et deuxième en {$Y$}) contenant les {$N_{x,y,\mathbf{z}}$}. Par exemple, '''create_contingency_table''' ( data, dico, 1, 2, [3] ) peut renvoyer le tableau suivant :
Changed line 138 from:
* {$T_{X,Y,\mathbf{z}}$} est un tableau 2D contenant le nombre d'occurrences des couples {$(X=x,Y=y)$} lorsque {$\mathbf{Z}=\mathbf{z}$}. La première dimension de ce tableau (les lignes) correspondent aux différentes valeurs de {$X$} et la deuxième (les colonnes) à celles de {$Y$}. Ainsi, le tableau en haut à droite de @@resultat@@ est obtenu de la manière suivante: ce tableau correspond à des occurrences de {$(X,Y)$} lorsque {$\mathbf{Z}=0$}. on commence donc par extraire de @@data@@ le sous-tableau correspondant à la première et à la troisième colonne (les colonnes où X_3=0) et on ne retient que les lignes correspondant à X_0 et X_2 (cf. les paramètres 0 et 2 passés en arguments de '''create_contingency_table'''). On obtient donc le sous-tableau:
to:
* {$T_{X,Y,\mathbf{z}}$} est un tableau 2D contenant le nombre d'occurrences {$N_{xy\mathbf{z}}$} des couples {$(X=x,Y=y)$} lorsque {$\mathbf{Z}=\mathbf{z}$}. La première dimension de ce tableau (les lignes) correspondent aux différentes valeurs de {$X$} et la deuxième (les colonnes) à celles de {$Y$}. Ainsi, le tableau en haut à droite de @@resultat@@ est obtenu de la manière suivante: ce tableau correspond à des occurrences de {$(X,Y)$} lorsque {$\mathbf{Z}=0$}. on commence donc par extraire de @@data@@ le sous-tableau correspondant à la première et à la troisième colonne (les colonnes où X_3=0) et on ne retient que les lignes correspondant à X_0 et X_2 (cf. les paramètres 0 et 2 passés en arguments de '''create_contingency_table'''). On obtient donc le sous-tableau:
Changed lines 129-130 from:
-> L'application de '''create_contingency_table''' @@( data, dico, 0, 2,[3] )@@ renverra le tableau:
to:
-> L'application de '''create_contingency_table''' @@( data, dico, 0, 2, [3] )@@ renverra le tableau:
Changed line 136 from:
-> En effet le paramètre @@[3]@@ indique que {$\mathbf{Z}$} est constitué uniquement de la quatrième variable de la base, autrement dit X_3. La dernière ligne du tableau @@data@@ indique les instanciations de X_3 et l'on peut observer que la valeur 0 apparaît 2 fois et  la valeur 1 apparaît une fois. On a donc {$N_{Z=0} = 2$} et {$N_{Z=1} = 1$}. On peut observer que les valeurs de {N_{\mathbf{Z}}$} sont bien les premiers éléments des couples.
to:
-> En effet le paramètre @@[3]@@ indique que {$\mathbf{Z}$} est constitué uniquement de la quatrième variable de la base, autrement dit X_3. La dernière ligne du tableau @@data@@ indique les instanciations de X_3 et l'on peut observer que la valeur 0 apparaît 2 fois et  la valeur 1 apparaît une fois. On a donc {$N_{Z=0} = 2$} et {$N_{Z=1} = 1$}. On peut observer que les valeurs de {$N_{\mathbf{Z}}$} sont bien les premiers éléments des couples de @@resultat@@.
Changed lines 57-58 from:
Téléchargez le fichier [[(Attach:)2015_tme5_asia.csv | 2015_tme5_asia.csv]] et lisez-le à l'aide de la fonction '''read_csv''' ci-dessous: la dernière instruction, @@names, data, dico = read_csv ( "2015_tme4_asia.csv" )@@, vous permettra de récupérer, séparément, les trois champs du triplet renvoyé par la fonction '''read_csv'''.
to:
Téléchargez le fichier [[(Attach:)2015_tme5_asia.csv | 2015_tme5_asia.csv]] et lisez-le à l'aide de la fonction '''read_csv''' ci-dessous: la dernière instruction, @@names, data, dico = read_csv ( "2015_tme5_asia.csv" )@@, vous permettra de récupérer, séparément, les trois champs du triplet renvoyé par la fonction '''read_csv'''.
Changed lines 103-104 from:
Soit deux variables aléatoires {$X$} et {$Y$}. Appelons {$N_{xy}$}, {$N_x$} et {$N_y$}, respectivement, le nombre d'occurrences du couple {$(X=x,Y=y)$} et des singletons {$X=x$} et {$Y=y$} dans la base de données. Alors, comme indiqué sur la planche 37 du cours 5, la statistique du {$\chi^2$} de {$X$} et {$Y$} est égale à :
to:
Soit deux variables aléatoires {$X$} et {$Y$}. Appelons {$N_{xy}$}, {$N_x$} et {$N_y$}, respectivement, le nombre d'occurrences du couple {$(X=x,Y=y)$} et des singletons {$X=x$} et {$Y=y$} dans la base de données. Alors, comme indiqué dans le cours 5, la statistique du {$\chi^2$} de {$X$} et {$Y$} est égale à :
Changed line 115 from:
* {N_{\mathbf{z}}$} représente le nombre d'occurences de {$Z=z$} dans la base de données. Par exemple, si la base de données est la suivante :
to:
* {$N_{\mathbf{z}}$} représente le nombre d'occurences de {$Z=z$} dans la base de données. Par exemple, si la base de données est la suivante :
Changed lines 41-45 from:
 np.array ( [ [0, 1, 1],
           [0, 1, 0],
             [0, 1, 2],
 
            [0, 1, 0]] )
to:
 np.array ( [ [0, 1, 1],    # instanciations de la variable X_0
             [0, 1, 0],    # instanciations de la variable X_1
             [0, 1, 2],    # instanciations de la variable X_2
              [0, 1, 0]]
)  # instanciations de la variable X_3
Changed lines 93-95 from:
to:
# names : tableau contenant les noms des variables aléatoires
# data  : tableau 2D contenant les instanciations des variables aléatoires
# dico  : tableau de dictionnaires contenant la correspondance (valeur de variable -> nombre)
Changed lines 113-117 from:
Afin de vous aider à calculer ces {$\chi^2$}, vous pourrez utiliser la fonction '''create_contingency_table''' @@: int np.2D-array x dico{string -> int} np.array x int x int x int list -> @@

 ( data, dico, x, y, z ) ci-dessous qui, étant donné les mêmes arguments que votre fonction '''sufficient_statistics''', renvoie un tableau de couples ({$N_{\mathbf{z}}, T_{X,Y})$}, pour tous les {$\mathbf{z} \in\mathbf{Z}$}, où {$T_{X,Y}$} est un tableau 2D (première dimension en {$X$} et deuxième en {$Y$}) contenant les {$N_{x,y,\mathbf{z}}$}. Par exemple, '''create_contingency_table''' ( data, dico, 1, 2, [3] ) peut renvoyer le tableau suivant :

to:
Afin de vous aider à calculer ces {$\chi^2$}, vous pourrez utiliser la fonction '''create_contingency_table''' @@: int np.2D-array x dico{string -> int} np.array x int x int x int list -> (int, np.2D-array) np.array@@ ci-dessous. Celle-ci prend en argument le tableau 2D numpy @@data@@ et le tableau de dictionnaires @@dico@@ retournés à la fin de la question 1, ainsi que l'index @@x@@ d'une variable aléatoire (0 = 1ère variable aléatoire (celle de la 1ère ligne de @@data@@), 1 = 2ème variable, ''etc.''), l'index @@y@@ d'une autre variable et une liste @@z@@ d'index d'autres variables aléatoires. Elle renvoie un tableau de couples ({$N_{\mathbf{z}}, T_{X,Y,\mathbf{z}})$}, pour tous les {$\mathbf{z} \in\mathbf{Z}$}, où:

* {N_{\mathbf{z}}$} représente le nombre d'occurences de {$Z=z$} dans la base de données. Par exemple, si la base de données est la suivante :

 X_0,X_1,X_2,X_3
 haut,gauche,petit,bas
 bas,droite,grand,gauche
 bas,gauche,moyen,bas

-> nous avons vu plus haut que le tableau @@data@@ est égal à :

 data = np.array ( [ [0, 1, 1],    # instanciations de la variable X_0
                    [0, 1, 0],    # instanciations de la variable X_1
                    [0, 1, 2],    # instanciations de la variable X_2
                    [0, 1, 0]] )  # instanciations de la variable X_3

-> L'application de '''create_contingency_table''' @@( data, dico, 0, 2,[3] )@@ renverra le tableau:

 resultat = array([ (2, array([[ 1.,  0.,  0.],        # Z = 0 => N_{Z=0} = 2
                              [ 0.,  0.,  1.]])),
                    (1, array([[ 0.,  0.,  0.],        # Z = 1 => N_{Z=1} = 1
                              [ 0.,  1.,  0.]])) ])

-> En effet le paramètre @@[3]@@ indique que {$\mathbf{Z}$} est constitué uniquement de la quatrième variable de la base, autrement dit X_3. La dernière ligne du tableau @@data@@ indique les instanciations de X_3 et l'on peut observer que la valeur 0 apparaît 2 fois et  la valeur 1 apparaît une fois. On a donc {$N_{Z=0} = 2$} et {$N_{Z=1} = 1$}. On peut observer que les valeurs de {N_{\mathbf{Z}}$} sont bien les premiers éléments des couples.

* {$T_{X,Y,\mathbf{z}}$} est un tableau 2D contenant le nombre d'occurrences des couples {$(X=x,Y=y)$} lorsque {$\mathbf{Z}=\mathbf{z}$}. La première dimension de ce tableau (les lignes) correspondent aux différentes valeurs de {$X$} et la deuxième (les colonnes) à celles de {$Y$}. Ainsi, le tableau en haut à droite de @@resultat@@ est obtenu de la manière suivante: ce tableau correspond à des occurrences de {$(X,Y)$} lorsque {$\mathbf{Z}=0$}. on commence donc par extraire de @@data@@ le sous-tableau correspondant à la première et à la troisième colonne (les colonnes où X_3=0) et on ne retient que les lignes correspondant à X_0 et X_2 (cf. les paramètres 0 et 2 passés en arguments de '''create_contingency_table'''). On obtient donc le sous-tableau:

 np.array ( [ [0, 1],    # instanciations de la variable X_0
              [0, 2]] )  # instanciations de la variable X_2
 
-> Ce tableau nous indique que, lorsque {$X_3=0$}, les couples (X_0=0,X_2=0) et (X_0=1,X_2=2) apparaissent une seule fois et ce sont les seuls couples qui apparaissent dans la base de données. C'est précisément ce que représente le tableau en haut à droite de @@resultat@@.

==================================
Changed lines 57-59 from:
Téléchargez le fichier [[(Attach:)2015_tme5_asia.csv | 2015_tme5_asia.csv]] et lisez-le à l'aide de la fonction '''read_csv'''.

to:
Téléchargez le fichier [[(Attach:)2015_tme5_asia.csv | 2015_tme5_asia.csv]] et lisez-le à l'aide de la fonction '''read_csv''' ci-dessous: la dernière instruction, @@names, data, dico = read_csv ( "2015_tme4_asia.csv" )@@, vous permettra de récupérer, séparément, les trois champs du triplet renvoyé par la fonction '''read_csv'''.
Added lines 92-94:


names, data, dico = read_csv ( "2015_tme5_asia.csv" )   
Changed lines 97-98 from:
to:
\\
Added lines 110-123:

Afin de vous aider à calculer ces {$\chi^2$}, vous pourrez utiliser la fonction '''create_contingency_table''' @@: int np.2D-array x dico{string -> int} np.array x int x int x int list -> @@

 ( data, dico, x, y, z ) ci-dessous qui, étant donné les mêmes arguments que votre fonction '''sufficient_statistics''', renvoie un tableau de couples ({$N_{\mathbf{z}}, T_{X,Y})$}, pour tous les {$\mathbf{z} \in\mathbf{Z}$}, où {$T_{X,Y}$} est un tableau 2D (première dimension en {$X$} et deuxième en {$Y$}) contenant les {$N_{x,y,\mathbf{z}}$}. Par exemple, '''create_contingency_table''' ( data, dico, 1, 2, [3] ) peut renvoyer le tableau suivant :









Changed lines 39-40 from:
* un tableau numpy 2D contenant les données du fichier CSV encodées sous forme numérique (les valeurs des variables aléatoires sont transformées en nombres entiers): chaque ligne de ce tableau correspond à une variable aléatoire et chaque colonne représente un enregistrement de la base de données, c'est-à-dire une instanciation/observation de toutes les variables aléatoires. Pour la base ci-dessus, nous obtiendrions (la signification des nombres est indiquée dans le dictionnaire précisé plus bas):
to:
* un tableau numpy 2D contenant les données du fichier CSV encodées sous forme numérique (les valeurs des variables aléatoires sont transformées en nombres entiers): chaque ligne de ce tableau représente les intanciations d'une variable aléatoire et chaque colonne représente un enregistrement de la base de données, c'est-à-dire une instanciation/observation de toutes les variables aléatoires. Pour la base ci-dessus, nous obtiendrions le tableau ci-dessous (la signification des nombres est indiquée dans le dictionnaire précisé plus bas):
Changed lines 46-47 from:
-> Ainsi, les valeurs observées de la première variable aléatoire {$X_0$} correspondent à la première ligne du tableau (0, 1 et 1). La première colonne correspond à une observation de toutes les variables {$(X_0=0,X_1=0,X_2=0,X_3=0)$}. C'est essentiellement sur ce tableau numpy que vous travaillerez dans ce TME.
to:
-> Ainsi, les valeurs observées de la première variable aléatoire X_0 correspondent à la première ligne du tableau (0, 1 et 1). La première colonne correspond à une observation de toutes les variables (X_0=0,X_1=0,X_2=0,X_3=0). C'est essentiellement sur ce tableau numpy que vous travaillerez dans ce TME.
Changed lines 50-55 from:
 np.array( [ {'haut': 0, 'bas': 1},
            {'droite': 1, 'gauche': 0},
            {'petit': 0, 'grand': 1, 'moyen': 2 },
            {'gauche': 1, 'bas': 0} ] )

-> On peut ainsi reconstituer le CSV d'origine. Par exemple
, la première colonne du tableau 2D ci-dessus, qui est égale à 0,0,0,0 correspond à haut,droite,petit,gauche: "haut" correspondant au 0 de la première variable aléatoire, "droite" correspondant au 0 de la 2ème variable, ''etc''.
to:
 np.array( [ {'haut': 0, 'bas': 1},                 # encodage variable X_0
             {'gauche': 0, 'droite': 1},            # encodage variable X_1
           {'petit': 0, 'grand': 1, 'moyen': 2 },  # encodage variable X_2
   
       {'bas': 0, 'gauche': 1} ] )            # encodage variable X_3

-> On peut ainsi reconstituer le CSV d'origine. Par exemple, la première colonne du tableau 2D ci-dessus, qui est égale à 0,0,0,0 correspond à haut,gauche,petit,bas: "haut" correspondant au 0 de la première variable aléatoire, "gauche
" correspondant au 0 de la 2ème variable, ''etc''.
Changed lines 31-33 from:
Dans cette base, nous avons 4 variables aléatoires nommées X_0, X_1, X_2, et X_3, et 2 enregistrements qui représentent des instanciations (observées) de ces 4 variables. Ainsi, X_0 a pour valeurs haut et bas, X_1 a pour valeurs gauche et droite, ''etc''.

La fonction '''read_csv''' prend en argument le nom d'un fichier CSV contenant une base de données et renvoie un triplet:
to:
Dans cette base, nous avons 4 variables aléatoires nommées X_0, X_1, X_2, et X_3, et 3 enregistrements qui représentent des instanciations (observées) de ces 4 variables. Ainsi, X_0 a pour valeurs haut, bas et bas, X_1 a pour valeurs gauche, droite, gauche, ''etc''.

La fonction '''read_csv''' prend en argument le nom d'un fichier CSV contenant une base de données et renvoie un triplet composé de :
Changed line 24 from:
Dans le code ci-dessous, la fonction '''read_csv''' @@: string -> (string np.array, int np.2D-array, dico{string -> int} np.array)@@ vous permettra de lire les données des bases sur lesquelles vous allez travailler, et de les organiser sous une forme adéquate. Par exemple, une base de données pourrait être un fichier de la forme:
to:
Dans le code ci-dessous, la fonction '''read_csv''' @@: string -> (string np.array, int np.2D-array, dico{string -> int} np.array)@@ vous permettra de lire les données des bases sur lesquelles vous allez travailler, et de les organiser sous une forme adéquate. Par exemple, une base de données est un fichier de la forme:
Changed lines 24-41 from:
Dans le code ci-dessous, la fonction '''read_csv''' @@: string -> (string np.array, int np.2D-array, dico(string -> int) np.array)@@ vous permettra de lire les données des bases sur lesquelles vous allez travailler, et de les organiser sous une forme adéquate. La fonction '''read_csv''' prend en argument le nom d'un fichier CSV et renvoie un triplet :

* 1 tableau numpy de strings contenant les noms des variables aléatoires
* un tableau numpy 2D contenant les données du fichier CSV encodées sous forme numérique (les valeurs des variables aléatoires sont transformées en nombres entiers): chaque ligne de ce tableau correspond à une variable aléatoire et chaque colonne représente
un enregistrement de la base de données, c'est-à-dire une instanciation/observation de toutes les variables aléatoires. Par exemple, si la base de données contient 2 enregistrements et que l'on a 4 variables aléatoires, le tableau 2D a la forme suivante:

 np.array ( [ [ 0, 2 ],
   
         [ 1, 0 ],
              [ 1, 1 ],
              [ 3
, 0 ] ] )

-> Ainsi, les valeurs observées de la première variable aléatoire {$X_0$} correspondent à la première ligne du tableau (0 et 2). La première colonne correspond à l'observation de toutes les variables {$(X_0=0
,X_1=1,X_2=1,X_3=3)$}. C'est essentiellement sur ce tableau numpy que vous travaillerez dans ce TME.

* un tableau numpy de dictionnaires faisant la correspondance, pour chaque variable aléatoire, entre l'encodage numérique du tableau 2D ci-dessus et les données du fichier CSV (le 1er dictionnaire correspond à la variable de
la 1ère colonne du CSV, le 2ème dictionnaire à celle de la 2ème colonne, ''etc''.). Ainsi:

 np.array ([
{'val1' : 0, 'val2': 1 },
            {'toto' : 0, 'titi': 1, 'tutu':2 } ] )

-> signifie que la valeur 0 de la première variable aléatoire dans le tableau 2D correspond à la chaîne de caractères 'val1' dans
la base de données.
to:
Dans le code ci-dessous, la fonction '''read_csv''' @@: string -> (string np.array, int np.2D-array, dico{string -> int} np.array)@@ vous permettra de lire les données des bases sur lesquelles vous allez travailler, et de les organiser sous une forme adéquate. Par exemple, une base de données pourrait être un fichier de la forme:

 X_0,X_1,X_2,X_3
 haut,gauche,petit,bas
 bas,droite,grand,gauche
 bas,gauche,moyen,bas

Dans cette base, nous avons 4 variables aléatoires nommées X_0, X_1, X_2, et X_3, et 2 enregistrements qui représentent des instanciations (observées) de ces 4 variables. Ainsi, X_0 a pour valeurs haut et bas, X_1 a pour valeurs gauche et droite, ''etc''.

La fonction '''read_csv''' prend en argument le nom d'
un fichier CSV contenant une base de données et renvoie un triplet:

* 1 tableau numpy de strings contenant les noms des variables aléatoires. Par exemple, pour la base ci-dessus, ce tableau correspond à:

 n.array (['X_0', 'X_1', 'X_2', 'X_3'])

* un tableau numpy 2D contenant les données du fichier CSV encodées sous forme numérique (les valeurs des variables aléatoires sont transformées en nombres entiers): chaque ligne de ce tableau correspond à une variable aléatoire et chaque colonne représente un enregistrement de la base de données, c'est-à-dire une instanciation/observation de toutes les variables aléatoires. Pour la base ci-dessus
, nous obtiendrions (la signification des nombres est indiquée dans le dictionnaire précisé plus bas):

 np.array ( [ [0, 1, 1],
 
             [0, 1, 0],
              [0, 1, 2],
              [0, 1, 0]] )

-> Ainsi, les valeurs observées de la première variable aléatoire {$X_0$} correspondent à
la première ligne du tableau (0, 1 et 1). La première colonne correspond à une observation de toutes les variables {$(X_0=0,X_1=0,X_2=0,X_3=0)$}. C'est essentiellement sur ce tableau numpy que vous travaillerez dans ce TME.

* un tableau numpy de dictionnaires faisant la correspondance, pour chaque variable aléatoire, entre l'encodage numérique du tableau 2D ci-dessus et les données du fichier CSV (le 1er dictionnaire correspond à
la variable de la 1ère colonne du CSV, le 2ème dictionnaire à celle de la 2ème colonne, ''etc''.). Ainsi, le dictionnaire est égal à :

 np.array( [ {'haut': 0, 'bas': 1},
            {'droite': 1, 'gauche': 0},
            {'petit': 0, 'grand': 1, 'moyen': 2 },
            {'gauche': 1, 'bas': 0} ] )

-> On peut ainsi reconstituer le CSV d'origine. Par exemple, la première colonne du tableau 2D ci-dessus, qui est égale à 0,0,0,0 correspond à haut,droite,petit,gauche: "haut" correspondant au 0 de la première variable aléatoire, "droite" correspondant au 0 de la 2ème variable, ''etc''
.
Changed lines 24-30 from:
Dans le code ci-dessous, la fonction '''read_csv''' vous permettra de lire les données des bases sur lesquelles vous allez travailler, et de les organiser sous une forme adéquate. La fonction '''read_csv''' prend en argument le nom d'un fichier CSV et renvoie un triplet :

* 1 tableau de strings contenant les noms des variables aléatoires
* un
tableau 2D contenant les données du fichier CSV encodées sous forme numérique (les valeurs des variables aléatoires sont transformées en nombres entiers)
* un tableau de dictionnaires faisant la correspondance, pour chaque variable aléatoire, entre l'encodage numérique et les données du fichier CSV (le 1er dictionnaire correspond à la variable
de la 1ère colonne du CSV, le 2ème dictionnaire à celle de la 2ème colonne, ''etc''.)

Téléchargez le fichier [[(Attach:)2014_tme5_asia.csv | asia dataset]]
et lisez-le à l'aide de la fonction '''read_csv'''.
to:
Dans le code ci-dessous, la fonction '''read_csv''' @@: string -> (string np.array, int np.2D-array, dico(string -> int) np.array)@@ vous permettra de lire les données des bases sur lesquelles vous allez travailler, et de les organiser sous une forme adéquate. La fonction '''read_csv''' prend en argument le nom d'un fichier CSV et renvoie un triplet :

* 1
tableau numpy de strings contenant les noms des variables aléatoires
* un tableau numpy 2D contenant les données du fichier CSV encodées sous forme numérique (les valeurs des variables aléatoires sont transformées en nombres entiers): chaque ligne de ce tableau correspond à une variable aléatoire et chaque colonne représente un enregistrement
de la base de données, c'est-à-dire une instanciation/observation de toutes les variables aléatoires. Par exemple, si la base de données contient 2 enregistrements et que l'on a 4 variables aléatoires, le tableau 2D a la forme suivante:

 np.array ( [ [ 0, 2 ],
              [ 1, 0 ],
              [ 1, 1 ],
              [ 3, 0 ] ] )

-> Ainsi, les valeurs observées de la première variable aléatoire {$X_0$} correspondent à la première ligne du tableau (0 et 2). La première colonne correspond à l'observation de toutes les variables {$(X_0=0,X_1=1,X_2=1,X_3=3)$}. C'est essentiellement sur ce tableau numpy que vous travaillerez dans ce TME.

* un tableau numpy de dictionnaires faisant la correspondance, pour chaque variable aléatoire, entre l'encodage numérique du tableau 2D ci-dessus et les données du fichier CSV (le 1er dictionnaire correspond à la variable de la 1ère colonne du CSV, le 2ème dictionnaire à celle de la 2ème colonne, ''etc''.). Ainsi:

 np.array ([ {'val1' : 0, 'val2': 1 },
            {'toto' : 0, 'titi': 1, 'tutu':2 } ] )

-> signifie que la valeur 0 de la première variable aléatoire dans le tableau 2D correspond à la chaîne de caractères 'val1' dans la base de données.

Téléchargez le fichier [[(Attach:)2015_tme5_asia.csv | 2015_tme5_asia.csv
]] et lisez-le à l'aide de la fonction '''read_csv'''.
Changed line 18 from:
Apprendre un réseau bayésien consiste à apprendre sa structure graphique ainsi que les paramètres de ses distributions de probabilité conditionnelles. Pour réaliser la deuxième tâche, il suffit d'estimer les paramètres de chaque distribution conditionnelle par maximum de vraisemblance, comme vous l'avez fait dans le TME 3. Ici, nous nous focaliserons donc plutôt sur l'apprentissage de structure. Celle-ci reflétant des indépendances conditionnelles entre variables aléatoires, vous devrez exploiter des tests d'indépendance du {$\chi^2$} afin d'obtenir des structures graphiques les moins denses possibles (en termes de nombres d'arcs). Ainsi, '''alarm''' représente une distribution jointe de plus de 10'^16^' événements élémentaires mais, quand cette distribution est décomposée grâce au graphe ci-dessous, elle peut être décrite (sans perte d'informations) à l'aide de seulement 752 paramètres. Comme nous l'avons vu en cours, cette représentation permet également d'effectuer très rapidement des calculs probabilistes.
to:
Apprendre un réseau bayésien consiste à apprendre sa structure graphique ainsi que les paramètres de ses distributions de probabilité conditionnelles. Pour réaliser la deuxième tâche, il suffit d'estimer les paramètres de chaque distribution conditionnelle par maximum de vraisemblance, comme vous l'avez fait dans le TME 3. Ici, nous nous focaliserons donc plutôt sur l'apprentissage de structure. Celle-ci reflétant des indépendances conditionnelles entre variables aléatoires, vous devrez exploiter des tests d'indépendance du {$\chi^2$} afin d'obtenir des structures graphiques les moins denses possibles (en termes de nombres d'arcs). Ainsi, '''alarm''' représente une distribution jointe de plus de 10'^16^' événements élémentaires mais, quand cette distribution est décomposée grâce au graphe ci-dessous (les noeuds représentant les variables aléatoires), elle peut être décrite (sans perte d'informations) à l'aide de seulement 752 paramètres. Comme nous l'avons vu en cours, cette représentation permet également d'effectuer très rapidement des calculs probabilistes.
October 22, 2014, at 01:47 PM EST by 132.227.206.222 -
Changed line 188 from:
 array( [[], [], [], [1, 0], [1], [3, 2], [4, 5], [5]] )
to:
 array( [ [], [], [], [1, 0], [1], [3, 2], [4, 5], [5] ] )
October 22, 2014, at 01:47 PM EST by 132.227.206.222 -
Changed line 188 from:
 array( [[] [] [] [1, 0] [1] [3, 2] [4, 5] [5]] )
to:
 array( [[], [], [], [1, 0], [1], [3, 2], [4, 5], [5]] )
October 22, 2014, at 01:46 PM EST by 132.227.206.222 -
Changed lines 188-189 from:
 array( [ [], [], [0], [1], [1], [2, 3], [4, 5], [3, 2] ] )
to:
 array( [[] [] [] [1, 0] [1] [3, 2] [4, 5] [5]] )
Deleted line 311:
October 22, 2014, at 01:34 PM EST by 132.227.206.222 -
Changed lines 165-166 from:
to:
[[Cours.TME5ValidationIndep  | Tests de validation du calcul de l'indépendance]]
Added lines 172-173:
[[Cours.TME5ValidationCand  | Tests de validation du calcul des candidats parents]]
Changed lines 182-183 from:
to:
[[Cours.TME5ValidationParent  | Tests de validation de création des parents]]
Deleted line 311:
October 22, 2014, at 01:26 PM EST by 132.227.206.222 -
Changed lines 137-138 from:
[[Cours.TME5ValidationCont  | Tests de validation de la contingence]]
to:
[[Cours.TME5ValidationCont  | Tests de validation de la contingence]] \\
[[Cours.TME5ValidationChi2  | Tests de validation du calcul du chi2
]]
Changed lines 148-149 from:
to:
[[Cours.TME5ValidationChi2  | Tests de validation du calcul du chi2]]
Deleted line 307:
October 22, 2014, at 01:20 PM EST by 132.227.206.222 -
Changed lines 83-87 from:
 array([(538,  array([[ 497.,    1.],
                    [  40.,    0.]])),
       (9462, array([[ 4476.,  54.],
                      [ 4863.,  69.]]))]
)
to:
 array([(103, array([[  0.,  96.],
      [  0.,  7.]])),
      (1897, array([[ 887.,  18.],
       [ 983.,    9.]]))], dtype=object)
Added lines 137-138:
[[Cours.TME5ValidationCont  | Tests de validation de la contingence]]
Deleted line 305:
October 21, 2014, at 08:08 AM EST by 132.227.206.153 -
Added lines 246-247:
   learner.useScoreLog2Likelihood ()
    learner.useAprioriSmoothing ()
October 20, 2014, at 03:50 PM EST by 132.227.206.153 -
Changed line 154 from:
Ecrivez une fonction '''indep_score'''( data, dico, x, y, z ) qui, étant donné les mêmes paramètres que ceux de la question précédente, vous renvoie la p-value correspondant à {$\chi^2_{X,Y|\mathbf{Z}}$}. Vous testerez au préalable si len ( data[0] ), le nombre de lignes de votre CSV, est supérieur ou non à {$d_{min}$} ; si c'est inférieur, vous renverrez le couple (-1,1), qui représente une indépendance. Vous pourrez vous aider de la fonction scipy.stats.chi2.sf ( x, DoF ) qui renvoie la p-value (x) pour une loi à DoF degrés de liberté.
to:
Ecrivez une fonction '''indep_score'''( data, dico, x, y, z ) qui, étant donné les mêmes paramètres que ceux de la question précédente, vous renvoie un couple contenant la p-value correspondant à {$\chi^2_{X,Y|\mathbf{Z}}$} ainsi que le nombre de degrés de liberté de cette statistique. Vous testerez au préalable si len ( data[0] ), le nombre de lignes de votre CSV, est supérieur ou non à {$d_{min}$} ; si c'est inférieur, vous renverrez le couple (-1,1), qui représente une indépendance. Vous pourrez vous aider de la fonction scipy.stats.chi2.sf ( x, DoF ) qui renvoie la p-value (x) pour une loi à DoF degrés de liberté.
October 20, 2014, at 03:29 PM EST by 132.227.206.153 -
Changed line 77 from:
{$$\chi^2_{X,Y|\mathbf{Z}} = \sum_x\sum_y\sum_{\mathbf{z}}\frac{\left(N_{xy\mathbf{z}} - \frac{N_{x\mathbf{z}} \times N_{y\mathbf{z}}}{N}\right)^2}{\frac{N_{x\mathbf{z}} \times N_{y\mathbf{z}}}{N_{\mathbf{z}}}}$$}
to:
{$$\chi^2_{X,Y|\mathbf{Z}} = \sum_x\sum_y\sum_{\mathbf{z}}\frac{\left(N_{xy\mathbf{z}} - \frac{N_{x\mathbf{z}} \times N_{y\mathbf{z}}}{N_{\mathbf{z}}}\right)^2}{\frac{N_{x\mathbf{z}} \times N_{y\mathbf{z}}}{N_{\mathbf{z}}}}$$}
Changed lines 152-154 from:
La p-value d'un nombre x est l'intégrale de la fonction de densité de la loi du {$\chi^2$} de x à {$+\infty$} (autrement dit, c'est la surface de la partie grisée sur votre table du {$\chi^2$} à partir de l'abscisse x. On a donc p-value{$(c_{\alpha}) = \alpha$}). En statistiques, on considère qu'elle n'a du sens que si les valeurs du tableau de contingence sont toutes supérieures ou égales à 5 (autrement dit, un test d'indépendance du {$\chi^2$} n'est "valide" que si toutes les valeurs du tableau de contingence sont supérieures ou égales à 5). En informatique, on allège souvent cette règle en considérant que le test est valide dès lors que la valeur moyenne des cases est supérieure ou égale à 5. Cet allègement permet de tester la validité du test sans réaliser celui-ci : si le nombre de lignes du CSV est supérieure ou égale à {$d_min = 5 \times |X| \times |Y| \times |\mathbf{z}|$}.

Ecrivez une fonction '''indep_score'''( data, dico, x, y, z ) qui
, étant donné les mêmes paramètres que ceux de la question précédente, vous renvoie la p-value correspondant à {$\chi^2_{X,Y|\mathbf{Z}}$}. Vous testerez au préalable si len ( data[0] ), le nombre de lignes de votre CSV, est supérieur ou non à {$d_min$} ; si c'est inférieur, vous renverrez le couple (-1,1), qui représente une indépendance. Vous pourrez vous aider de la fonction scipy.stats.chi2.sf ( x, DoF ) qui renvoie la p-value (x) pour une loi à DoF degrés de liberté.
to:
La p-value d'un nombre x est l'intégrale de la fonction de densité de la loi du {$\chi^2$} de x à {$+\infty$} (autrement dit, c'est la surface de la partie grisée sur votre table du {$\chi^2$} à partir de l'abscisse x. On a donc p-value{$(c_{\alpha}) = \alpha$}). En statistiques, on considère qu'elle n'a du sens que si les valeurs du tableau de contingence sont toutes supérieures ou égales à 5 (autrement dit, un test d'indépendance du {$\chi^2$} n'est "valide" que si toutes les valeurs du tableau de contingence sont supérieures ou égales à 5). En informatique, on allège souvent cette règle en considérant que le test est valide dès lors que la valeur moyenne des cases est supérieure ou égale à 5. Cet allègement permet de tester la validité du test sans réaliser celui-ci : si le nombre de lignes du CSV est supérieure ou égale à {$d_{min} = 5 \times |X| \times |Y| \times |\mathbf{Z}|$}, le test est considéré comme valide.

Ecrivez une fonction '''indep_score'''( data
, dico, x, y, z ) qui, étant donné les mêmes paramètres que ceux de la question précédente, vous renvoie la p-value correspondant à {$\chi^2_{X,Y|\mathbf{Z}}$}. Vous testerez au préalable si len ( data[0] ), le nombre de lignes de votre CSV, est supérieur ou non à {$d_{min}$} ; si c'est inférieur, vous renverrez le couple (-1,1), qui représente une indépendance. Vous pourrez vous aider de la fonction scipy.stats.chi2.sf ( x, DoF ) qui renvoie la p-value (x) pour une loi à DoF degrés de liberté.
Changed lines 152-155 from:
La p-value d'un nombre x est l'intégrale de la fonction de densité de la loi du {$\chi^2$} de x à {$+\infty$} (autrement dit, c'est la surface de la partie grisée sur votre table du {$\chi^2$} à partir de l'abscisse x. On a donc p-value{$(c_{\alpha}) = \alpha$}).

Ecrivez une fonction
'''indep_score'''( data, dico, x, y, z ) qui, étant donné les mêmes paramètres que ceux de la question précédente, vous renvoie la p-value correspondant à {$\chi^2_{X,Y|\mathbf{Z}}$}. Vous pourrez vous aider de la fonction scipy.stats.chi2.sf ( x, DoF ) qui renvoie la p-value (x) pour une loi à DoF degrés de liberté.
to:
La p-value d'un nombre x est l'intégrale de la fonction de densité de la loi du {$\chi^2$} de x à {$+\infty$} (autrement dit, c'est la surface de la partie grisée sur votre table du {$\chi^2$} à partir de l'abscisse x. On a donc p-value{$(c_{\alpha}) = \alpha$}). En statistiques, on considère qu'elle n'a du sens que si les valeurs du tableau de contingence sont toutes supérieures ou égales à 5 (autrement dit, un test d'indépendance du {$\chi^2$} n'est "valide" que si toutes les valeurs du tableau de contingence sont supérieures ou égales à 5). En informatique, on allège souvent cette règle en considérant que le test est valide dès lors que la valeur moyenne des cases est supérieure ou égale à 5. Cet allègement permet de tester la validité du test sans réaliser celui-ci : si le nombre de lignes du CSV est supérieure ou égale à {$d_min = 5 \times |X| \times |Y| \times |\mathbf{z}|$}.

Ecrivez une fonction '''indep_score'''( data, dico, x, y, z ) qui, étant donné les mêmes paramètres que ceux de la question précédente, vous renvoie la p-value correspondant à {$\chi^2_{X,Y|\mathbf{Z}}$}. Vous testerez au préalable si len ( data[0] ), le nombre de lignes de votre CSV, est supérieur ou non à {$d_min$} ; si c'est inférieur, vous renverrez le couple (-1,1), qui représente une indépendance
. Vous pourrez vous aider de la fonction scipy.stats.chi2.sf ( x, DoF ) qui renvoie la p-value (x) pour une loi à DoF degrés de liberté.
Changed line 291 from:
[+'''%quest%8. Autres bases de données%%'''+]
to:
[+'''%quest%8. (Bonus) Autres bases de données%%'''+]
Changed lines 228-229 from:
Comme précisé au début du TME, apprendre un réseau bayésien consiste à déterminer sa structure graphique et estimer ses paramètres. Vous avez réalisé la première partie. La deuxième, plus simple, peut se faire par maximum de vraisemblance, comme dans le TME 3. Utilisez la fonction '''learn_parameters''' ci-dessous pour effectuer cette tâche. Cette fonction prend en paramètres la structure graphique que vous avez apprise ainsi que le nom du fichier CSV que vous avez utilisé pour votre apprentissage. Elle renvoie un réseau bayésien à la %target=_blank% [[http://agrum.lip6.fr | aGrUM]]. Pour pouvoir utiliser aGrUM, reportez-vous à la %target=_blank% [[Cours.TME2#agrum | question 7 du TME 2]].
to:
Comme précisé au début du TME, apprendre un réseau bayésien consiste à déterminer sa structure graphique et estimer ses paramètres. Vous avez réalisé la première partie. La deuxième, plus simple, peut se faire par maximum de vraisemblance pour chaque table de probabilité des noeuds conditionnellement à leurs parents, comme dans le TME 3. Utilisez la fonction '''learn_parameters''' ci-dessous pour effectuer cette tâche. Cette fonction prend en paramètres la structure graphique que vous avez apprise ainsi que le nom du fichier CSV que vous avez utilisé pour votre apprentissage. Elle renvoie un réseau bayésien à la %target=_blank% [[http://agrum.lip6.fr | aGrUM]]. Pour pouvoir utiliser aGrUM, reportez-vous à la %target=_blank% [[Cours.TME2#agrum | question 7 du TME 2]].
Deleted line 297:
|| alarm || [[(Attach:)2014_tme5_alarm.csv | alarm dataset]] || 20000 || 10'^16^' ||
Changed line 301 from:
to:
|| alarm || [[(Attach:)2014_tme5_alarm.csv | alarm dataset]] || 20000 || 10'^16^' ||
Changed lines 171-173 from:
L'algorithme qui consiste à appliquer pour chaque noeud/variable aléatoire votre fonction '''create_parents''' correspond, en grande partie, à l'article suivant :

Gregory F. Cooper and Edward Herskovits (1992) "A Bayesian method for the induction of probabilistic networks from data", ''Machine Learning'', Vol. 9, n°4, pp. 309--347.\\\
to:
L'algorithme qui consiste à appliquer, pour chaque noeud/variable aléatoire, votre fonction '''create_parents''' correspond, en grande partie, à l'article suivant :

Gregory F. Cooper and Edward Herskovits (1992) "A Bayesian method for the induction of probabilistic networks from data", ''Machine Learning'', Vol. 9, n°4, pp. 309-347.\\\
Changed line 96 from:
  & & [ N_{X=1,Y=0,\mathbf{Z}=0}, & N_{X=1,Y=1,\mathbf{Z}=0}]]))])
to:
  & & [ N_{X=1,Y=0,\mathbf{Z}=1}, & N_{X=1,Y=1,\mathbf{Z}=1}]]))])
Changed lines 164-166 from:
Ecrivez une fonction '''best_candidate''' ( data, dico, x, z, alpha ) qui, étant donné une variable aléatoire {$X$} et un ensemble de variables aléatoires {$\mathbf{Z}$} détermine la variable {$Y$} (en fait, l'index de sa colonne dans le CSV), parmi toutes celles à gauche de {$X$} dans le fichier CSV, qui est la plus dépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, autrement dit, celle qui a la plus petite p-value. Si cette p-value est supérieure à alpha, cela veut dire que {$\chi^2_{X,Y|\mathbf{Z}}$} est inférieur à {$c_{\alpha}$} et donc que {$Y$} est jugée indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}. Votre fonction renverra une liste vide si {$Y$} est indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, sinon elle renverra une liste contenant {$Y$}.\\\

to:
Ecrivez une fonction '''best_candidate''' ( data, dico, x, z, alpha ) qui, étant donné une variable aléatoire {$X$} et un ensemble de variables aléatoires {$\mathbf{Z}$} détermine la variable {$Y$} (en fait, l'index de sa colonne dans le CSV), parmi toutes celles à gauche de {$X$} dans le fichier CSV, qui est la plus dépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, autrement dit, celle qui a la plus petite p-value. Si cette p-value est supérieure à alpha, cela veut dire que {$\chi^2_{X,Y|\mathbf{Z}}$} est inférieur à {$c_{\alpha}$} et donc que {$Y$} est jugée indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}. Votre fonction renverra une liste vide si {$Y$} est indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, sinon elle renverra une liste contenant {$Y$}. Vous pourrez tester votre fonction avec {$\alpha$} = 0.05.\\\

Changed lines 169-170 from:
Ecrivez une fonction '''create_parents''' ( data, dico, x, alpha ) qui, étant donné une variable aléatoire x et un niveau de risque alpha retourne la liste z de ses parents dans le réseau bayésien. L'algorithme est le suivant :  partez de z = l'ensemble vide, puis tant que '''best_candidate''' ( x, z, alpha ) vous renvoie une liste non vide [y], rajouter y à z. Lorsque vous sortirez de cette boucle, toutes les autres variables seront indépendantes de x conditionnellement à z.\\\
to:
Ecrivez une fonction '''create_parents''' ( data, dico, x, alpha ) qui, étant donné une variable aléatoire x et un niveau de risque alpha, retourne la liste z de ses parents dans le réseau bayésien. L'algorithme est le suivant :  partez de z = l'ensemble vide, puis tant que '''best_candidate''' ( x, z, alpha ) vous renvoie une liste non vide [y], rajoutez y à z. Lorsque vous sortirez de cette boucle, toutes les autres variables seront indépendantes de x conditionnellement à z.

L'algorithme qui consiste à appliquer pour chaque noeud/variable aléatoire votre fonction '''create_parents''' correspond, en grande partie, à l'article suivant :

Gregory F. Cooper and Edward Herskovits (1992) "A Bayesian method for the induction of probabilistic networks from data", ''Machine Learning'', Vol. 9, n°4, pp. 309--347.
\\\
Changed lines 18-19 from:
Apprendre un réseau bayésien consiste à apprendre sa structure graphique ainsi que les paramètres de ses distributions de probabilité conditionnelles. Pour réaliser la deuxième tâche, il suffit d'estimer ces paramètres par maximum de vraisemblance, comme vous l'avez fait dans le TME 3. Ici, nous nous focaliserons donc plutôt sur l'apprentissage de structure. Celle-ci reflétant des indépendances conditionnelles entre variables aléatoires, vous devrez exploiter des tests d'indépendance du {$\chi^2$} afin d'obtenir des structures graphiques les moins denses possibles (en termes de nombres d'arcs). Ainsi, '''alarm''' représente une distribution jointe de plus de 10'^16^' événements élémentaires mais, quand cette distribution est décomposée grâce au graphe ci-dessous, elle peut être décrite (sans perte d'informations) à l'aide de seulement 752 paramètres. Comme nous l'avons vu en cours, cette représentation permet également d'effectuer très rapidement des calculs probabilistes.
to:
Apprendre un réseau bayésien consiste à apprendre sa structure graphique ainsi que les paramètres de ses distributions de probabilité conditionnelles. Pour réaliser la deuxième tâche, il suffit d'estimer les paramètres de chaque distribution conditionnelle par maximum de vraisemblance, comme vous l'avez fait dans le TME 3. Ici, nous nous focaliserons donc plutôt sur l'apprentissage de structure. Celle-ci reflétant des indépendances conditionnelles entre variables aléatoires, vous devrez exploiter des tests d'indépendance du {$\chi^2$} afin d'obtenir des structures graphiques les moins denses possibles (en termes de nombres d'arcs). Ainsi, '''alarm''' représente une distribution jointe de plus de 10'^16^' événements élémentaires mais, quand cette distribution est décomposée grâce au graphe ci-dessous, elle peut être décrite (sans perte d'informations) à l'aide de seulement 752 paramètres. Comme nous l'avons vu en cours, cette représentation permet également d'effectuer très rapidement des calculs probabilistes.
Changed lines 27-28 from:
* un tableau 2D contenant les données du fichier CSV encodées sous forme numérique (le valeurs des variables aléatoires sont transformées en nombres entiers)
* un tableau de dictionnaires faisant la correspondance entre l'encodage numérique et les données du fichier CSV (il y a un dictionnaire par variable, le 1er dictionnaire correspondant à la 1ère colonne du CSV, ''etc''.)
to:
* un tableau 2D contenant les données du fichier CSV encodées sous forme numérique (les valeurs des variables aléatoires sont transformées en nombres entiers)
* un tableau de dictionnaires faisant la correspondance, pour chaque variable aléatoire, entre l'encodage numérique et les données du fichier CSV (le 1er dictionnaire correspond à la variable de la 1ère colonne du CSV, le 2ème dictionnaire à celle de la 2ème colonne, ''etc''.)
Changed line 294 from:
|| alarm || [[(Attach:)2014_tme5_alarm.csv | alarm dataset]] || 10000 || 10'^16^' ||
to:
|| alarm || [[(Attach:)2014_tme5_alarm.csv | alarm dataset]] || 20000 || 10'^16^' ||
Changed lines 20-21 from:
%block text-align=center% %width=500px%  Attach:2014_tme4_alarm.png
to:
%block text-align=center% %width=500px%  Attach:2014_tme5_alarm.png
Changed lines 30-32 from:
Téléchargez le fichier [[(Attach:)2014_tme4_asia.csv | asia dataset]] et lisez-le à l'aide de la fonction '''read_csv'''.

to:
Téléchargez le fichier [[(Attach:)2014_tme5_asia.csv | asia dataset]] et lisez-le à l'aide de la fonction '''read_csv'''.

Changed lines 219-221 from:
%block text-align=center% %width=400px%  Attach:2014_tme4_asia.png\\\

to:
%block text-align=center% %width=400px%  Attach:2014_tme5_asia.png\\\

Changed lines 293-297 from:
|| asia  || [[(Attach:)2014_tme4_asia3.csv | asia  dataset]] || 30000 || 256 ||
|| alarm || [[(Attach:)2014_tme4_alarm.csv | alarm dataset]] || 10000 || 10'^16^' ||
|| adult || [[(Attach:)2014_tme4_adult.csv | adult dataset]] || 30162 || 10'^12^' ||
|| car  || [[(Attach:)2014_tme4_car.csv  | car  dataset]] || 1728  || 6912 ||
|| agaricus-lepiota || [[(Attach:)2014_tme4_agaricus_lepiota.csv | agaricus-lepiota dataset]] || 8124 || 10'^16^' ||
to:
|| asia  || [[(Attach:)2014_tme5_asia3.csv | asia  dataset]] || 30000 || 256 ||
|| alarm || [[(Attach:)2014_tme5_alarm.csv | alarm dataset]] || 10000 || 10'^16^' ||
|| adult || [[(Attach:)2014_tme5_adult.csv | adult dataset]] || 30162 || 10'^12^' ||
|| car  || [[(Attach:)2014_tme5_car.csv  | car  dataset]] || 1728  || 6912 ||
|| agaricus-lepiota || [[(Attach:)2014_tme5_agaricus_lepiota.csv | agaricus-lepiota dataset]] || 8124 || 10'^16^' ||
Changed lines 247-248 from:
# affichage de la taille du réseau bayésien
to:
* affichage de la taille du réseau bayésien
Changed lines 257-258 from:
# affichage de la table de probabilité conditionnelle d'un noeud du réseau déterminé par son nom (1ère ligne du CSV):
to:
* affichage de la table de probabilité conditionnelle d'un noeud du réseau déterminé par son nom (1ère ligne du CSV):
Changed lines 264-265 from:
# calcul de la probabilité marginale d'un noeud : P('bronchitis?'):
to:
* calcul de la probabilité marginale d'un noeud : P('bronchitis?'):
Changed lines 274-275 from:
# affichage graphique d'une distribution de probabilité marginale
to:
* affichage graphique d'une distribution de probabilité marginale
Changed lines 280-281 from:
# calcul d'une distribution marginale a posteriori : P(bronchitis? | smoking? = true, turberculosis? = false )
to:
* calcul d'une distribution marginale a posteriori : P(bronchitis? | smoking? = true, turberculosis? = false )
Changed lines 219-221 from:
%block text-align=center% %width=400px%  Attach:2014_tme4_asia.png

to:
%block text-align=center% %width=400px%  Attach:2014_tme4_asia.png\\\

Changed lines 247-248 from:
# affichage de la table de probabilité conditionnelle d'un noeud du réseau déterminé par son nom (1ère ligne du CSV):
to:
# affichage de la taille du réseau bayésien
Changed lines 253-254 from:
# affichage de la table de probabilité
pretty_cpt ( bn.cpt ( bn.idFromName ( 'bronchitis?' ) ) )
to:
# affichage de sa taille
print bn
Changed lines 257-258 from:
# calcul de la probabilité marginale d'un noeud : P('bronchitis?'):
to:
# affichage de la table de probabilité conditionnelle d'un noeud du réseau déterminé par son nom (1ère ligne du CSV):
Added lines 260-265:
# récupération de la ''conditional probability table'' (CPT) et affichage de cette table
pretty_cpt ( bn.cpt ( bn.idFromName ( 'bronchitis?' ) ) )
(:sourceend:)

# calcul de la probabilité marginale d'un noeud : P('bronchitis?'):
(:source lang=python:)
Changed lines 284-294 from:
to:
[+'''%quest%8. Autres bases de données%%'''+]

Vous pouvez appliquer vos algorithmes sur des bases un peu plus conséquentes qu'asia:

|| border=1 align=center
||! nom de la base ||! dataset ||! nb de lignes de la base ||! événements élémentaires ||
|| asia  || [[(Attach:)2014_tme4_asia3.csv | asia  dataset]] || 30000 || 256 ||
|| alarm || [[(Attach:)2014_tme4_alarm.csv | alarm dataset]] || 10000 || 10'^16^' ||
|| adult || [[(Attach:)2014_tme4_adult.csv | adult dataset]] || 30162 || 10'^12^' ||
|| car  || [[(Attach:)2014_tme4_car.csv  | car  dataset]] || 1728  || 6912 ||
|| agaricus-lepiota || [[(Attach:)2014_tme4_agaricus_lepiota.csv | agaricus-lepiota dataset]] || 8124 || 10'^16^' ||
Changed lines 224-226 from:
Comme précisé au début du TME, apprendre un réseau bayésien consiste à déterminer sa structure graphique et estimer ses paramètres. Vous avez réalisé la première partie. La deuxième, plus simple, peut se faire par maximum de vraisemblance, comme dans le TME 3. Utilisez la fonction '''learn_parameters''' ci-dessous pour effectuer cette tâche. Cette fonction prend en paramètres la structure graphique que vous avez apprise ainsi que le nom du fichier CSV que vous avez utilisé pour votre apprentissage. Elle renvoie un réseau bayésien à la [[http://agrum.lip6.fr | aGrUM]].

to:
Comme précisé au début du TME, apprendre un réseau bayésien consiste à déterminer sa structure graphique et estimer ses paramètres. Vous avez réalisé la première partie. La deuxième, plus simple, peut se faire par maximum de vraisemblance, comme dans le TME 3. Utilisez la fonction '''learn_parameters''' ci-dessous pour effectuer cette tâche. Cette fonction prend en paramètres la structure graphique que vous avez apprise ainsi que le nom du fichier CSV que vous avez utilisé pour votre apprentissage. Elle renvoie un réseau bayésien à la %target=_blank% [[http://agrum.lip6.fr | aGrUM]]. Pour pouvoir utiliser aGrUM, reportez-vous à la %target=_blank% [[Cours.TME2#agrum | question 7 du TME 2]].
Added lines 244-282:

Vous pouvez maintenant réaliser des calculs probabilistes :

# affichage de la table de probabilité conditionnelle d'un noeud du réseau déterminé par son nom (1ère ligne du CSV):

(:source lang=python:)
# création du réseau bayésien à la aGrUM
bn = learn_parameters ( bn_struct, ficname )

# affichage de la table de probabilité
pretty_cpt ( bn.cpt ( bn.idFromName ( 'bronchitis?' ) ) )
(:sourceend:)

# calcul de la probabilité marginale d'un noeud : P('bronchitis?'):
(:source lang=python:)
# calcul de la marginale
proba = gnb.getPosterior ( bn, {}, 'bronchitis?' )

# affichage de la marginale
pretty_cpt ( proba )
(:sourceend:)

# affichage graphique d'une distribution de probabilité marginale
(:source lang=python:)
gnb.showPosterior ( bn, {}, 'bronchitis?' )
(:sourceend:)

# calcul d'une distribution marginale a posteriori : P(bronchitis? | smoking? = true, turberculosis? = false )
(:source lang=python:)
gnb.showPosterior ( bn, {'smoking?': 'true', 'tuberculosis?' : 'false' }, 'bronchitis?' )
(:sourceend:)







Changed lines 224-226 from:
Comme précisé au début du TME, apprendre un réseau bayésien consiste à déterminer sa structure graphique et estimer ses paramètres. Vous avez réalisé la première partie. La deuxième, plus simple, peut se faire par maximum de vraisemblance, comme dans le TME 3. Utilisez la fonction '''learn_parameters''' ci-dessous pour effectuer cette tâche.

to:
Comme précisé au début du TME, apprendre un réseau bayésien consiste à déterminer sa structure graphique et estimer ses paramètres. Vous avez réalisé la première partie. La deuxième, plus simple, peut se faire par maximum de vraisemblance, comme dans le TME 3. Utilisez la fonction '''learn_parameters''' ci-dessous pour effectuer cette tâche. Cette fonction prend en paramètres la structure graphique que vous avez apprise ainsi que le nom du fichier CSV que vous avez utilisé pour votre apprentissage. Elle renvoie un réseau bayésien à la [[http://agrum.lip6.fr | aGrUM]].

Changed line 233 from:
def learn_parameters ( data, dico, node_names, bn_struct, ficname ):
to:
def learn_parameters ( bn_struct, ficname ):
Deleted lines 242-243:
   learner.useScoreLog2Likelihood ()
    learner.useAprioriSmoothing ()
Changed lines 219-220 from:
%block text-align=center% %width=200px%  Attach:2014_tme4_asia3.png
to:
%block text-align=center% %width=400px%  Attach:2014_tme4_asia.png

Changed lines 224-225 from:

to:
Comme précisé au début du TME, apprendre un réseau bayésien consiste à déterminer sa structure graphique et estimer ses paramètres. Vous avez réalisé la première partie. La deuxième, plus simple, peut se faire par maximum de vraisemblance, comme dans le TME 3. Utilisez la fonction '''learn_parameters''' ci-dessous pour effectuer cette tâche.


(:source lang=python:)
import pyAgrum as gum
import gumLib.notebook as gnb
from gumLib.pretty_print import pretty_cpt


def learn_parameters ( data, dico, node_names, bn_struct, ficname ):
    # création du dag correspondant au bn_struct
    graphe = gum.DAG ()
    nodes = [ graphe.addNode () for i in range ( bn_struct.shape[0] ) ]
    for i in range ( bn_struct.shape[0] ):
        for parent in bn_struct[i]:
            graphe.addArc ( nodes[parent], nodes[i] )
   
    # appel au BNLearner pour apprendre les paramètres
    learner = gum.BNLearner ( ficname )
    learner.useScoreLog2Likelihood ()
    learner.useAprioriSmoothing ()
    return learner.learnParameters ( graphe )
(:sourceend:)
Added lines 173-223:

Ecrivez une fonction '''learn_BN_structure''' ( data, dico, alpha ) qui renvoie un tableau contenant, pour chaque noeud, la liste de ses parents. Ainsi, si votre fonction vous renvoie le tableau ci-dessous,

 array( [ [], [], [0], [1], [1], [2, 3], [4, 5], [3, 2] ] )

les noeud correspondant aux 2 premières colonnes du CSV n'ont pas de parents, le noeud de la 3ème colonne a pour parent celui de la 1ère colonne, etc.

Pour visualiser plus aisément votre structure, utilisez la fonction '''display_BN''' ci-dessous. Celle-ci prend en paramètres :

# le tableau des noms des variables aléatoires déterminé à la question 1
# la structure que vous avez calculée avec votre fonction '''learn_BN_structure'''
# un nom que vous voulez donner à votre réseau
# un style pour afficher les noeuds

(:source lang=python:)
import pydot       
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

style = { "bgcolor" : "#6b85d1", "fgcolor" : "#FFFFFF" }

def display_BN ( node_names, bn_struct, bn_name, style ):
    graph = pydot.Dot( bn_name, graph_type='digraph')

    # création des noeuds du réseau
    for name in node_names:
        new_node = pydot.Node( name,
                              style="filled",
                              fillcolor=style["bgcolor"],
                              fontcolor=style["fgcolor"] )
        graph.add_node( new_node )
       
    # création des arcs
    for node in range ( len ( node_names ) ):
        parents = bn_struct[node]
        for par in parents:
            new_edge = pydot.Edge ( node_names[par], node_names[node] )
            graph.add_edge ( new_edge )
   
    # sauvegarde et affaichage
    outfile = bn_name + '.png'
    graph.write_png( outfile )
    img = mpimg.imread ( outfile )
    plt.imshow( img )
(:sourceend:)

%block text-align=center% %width=200px%  Attach:2014_tme4_asia3.png

[+'''%quest%7. Fin de l'apprentissage et calcul probabiliste%%'''+]

Changed lines 164-172 from:
Ecrivez une fonction '''best_candidate''' ( data, dico, x, z, alpha ) qui, étant donné une variable aléatoire {$X$} et un ensemble de variables aléatoires {$\mathbf{Z}$} détermine la variable {$Y$} (en fait, l'index de sa colonne dans le CSV), parmi toutes celles à gauche de {$X$} dans le fichier CSV, qui est la plus dépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, autrement dit, celle qui a la plus petite p-value. Si cette p-value est supérieure à alpha, cela veut dire que {$\chi^2_{X,Y|\mathbf{Z}}$} est inférieur à {$c_{alpha}$} et donc que {$Y$} est jugée indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}. Votre fonction renverra une liste vide si {$Y$} est indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, sinon elle renverra une liste contenant {$Y$}.
to:
Ecrivez une fonction '''best_candidate''' ( data, dico, x, z, alpha ) qui, étant donné une variable aléatoire {$X$} et un ensemble de variables aléatoires {$\mathbf{Z}$} détermine la variable {$Y$} (en fait, l'index de sa colonne dans le CSV), parmi toutes celles à gauche de {$X$} dans le fichier CSV, qui est la plus dépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, autrement dit, celle qui a la plus petite p-value. Si cette p-value est supérieure à alpha, cela veut dire que {$\chi^2_{X,Y|\mathbf{Z}}$} est inférieur à {$c_{\alpha}$} et donc que {$Y$} est jugée indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}. Votre fonction renverra une liste vide si {$Y$} est indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, sinon elle renverra une liste contenant {$Y$}.\\\


[+'''%quest%6. Création des parents d'un noeud%%'''+]

Ecrivez une fonction '''create_parents''' ( data, dico, x, alpha ) qui, étant donné une variable aléatoire x et un niveau de risque alpha retourne la liste z de ses parents dans le réseau bayésien. L'algorithme est le suivant :  partez de z = l'ensemble vide, puis tant que '''best_candidate''' ( x, z, alpha ) vous renvoie une liste non vide [y], rajouter y à z. Lorsque vous sortirez de cette boucle, toutes les autres variables seront indépendantes de x conditionnellement à z.\\\


[+'''%quest%7. Apprentissage de la structure d'un réseau bayésien%%'''+]
Changed lines 143-144 from:
où {$|X|$} représente le nombre de valeurs possibles que peut prendre la variable {$X$}, autrement dit, c'est la taille de son dictionnaire. Le dernier terme de l'équation est simplement le nombre de {$N_{\mathbf{z}}$} différents de 0.
 
to:
où {$|X|$} représente le nombre de valeurs possibles que peut prendre la variable {$X$}, autrement dit, c'est la taille de son dictionnaire. Le dernier terme de l'équation est simplement le nombre de {$N_{\mathbf{z}}$} différents de 0.\\\


[+'''%quest%4. Test d'indépendance%%'''+]

En cours, nous avons vu que, pour un risque {$\alpha$} donné, si la statistique {$\chi^2_{X,Y|\mathbf{Z}}$} est inférieure au seuil critique {$c_{\alpha}$} de la loi du {$\chi^2$} à DoF degrés de liberté, alors {$X$} et {$Y$} sont considérés comme indépendants conditionnellement à {$\mathbf{Z}$} ({$X \perp\hspace{-1.7mm}\perp Y | \mathbf{Z}$}). On peut reformuler cette propriété de la manière suivante :

{$$\text{p-value}(\chi^2_{X,Y|\mathbf{Z}}) \geq \alpha \Longleftrightarrow X \perp\hspace{-1.7mm}\perp Y | \mathbf{Z}$$}

La p-value d'un nombre x est l'intégrale de la fonction de densité de la loi du {$\chi^2$} de x à {$+\infty$} (autrement dit, c'est la surface de la partie grisée sur votre table du {$\chi^2$} à partir de l'abscisse x. On a donc p-value{$(c_{\alpha}) = \alpha$}).

Ecrivez une fonction '''indep_score'''( data, dico, x, y, z ) qui, étant donné les mêmes paramètres que ceux de la question précédente, vous renvoie la p-value correspondant à {$\chi^2_{X,Y|\mathbf{Z}}$}. Vous pourrez vous aider de la fonction scipy.stats.chi2.sf ( x, DoF ) qui renvoie la p-value (x) pour une loi à DoF degrés de liberté.

(:source lang=python:)
import scipy.stats as stats
stats.chi2.sf ( x, DoF )
(:sourceend:)


[+'''%quest%5. Meilleur candidat pour être un parent%%'''+]

Ecrivez une fonction '''best_candidate''' ( data, dico, x, z, alpha ) qui, étant donné une variable aléatoire {$X$} et un ensemble de variables aléatoires {$\mathbf{Z}$} détermine la variable {$Y$} (en fait, l'index de sa colonne dans le CSV), parmi toutes celles à gauche de {$X$} dans le fichier CSV, qui est la plus dépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, autrement dit, celle qui a la plus petite p-value. Si cette p-value est supérieure à alpha, cela veut dire que {$\chi^2_{X,Y|\mathbf{Z}}$} est inférieur à {$c_{alpha}$} et donc que {$Y$} est jugée indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}. Votre fonction renverra une liste vide si {$Y$} est indépendante de {$X$} conditionnellement à {$\mathbf{Z}$}, sinon elle renverra une liste contenant {$Y$}.

Changed lines 15-16 from:
|| car || %target=_blank% [[https://archive.ics.uci.edu/ml/datasets/Adult | UCI machine learning repository]] || 6912 ||
|| agaricus-lepiota || [[https://archive.ics.uci.edu/ml/datasets/Adult | UCI machine learning repository]] || 10'^16^' ||
to:
|| car || %target=_blank% [[https://archive.ics.uci.edu/ml/datasets/Car+Evaluation | UCI machine learning repository]] || 6912 ||
|| agaricus-lepiota || [[https://archive.ics.uci.edu/ml/datasets/Mushroom | UCI machine learning repository]] || 10'^16^' ||
Changed lines 12-15 from:
|| asia || [[http://www.cs.huji.ac.il/site/labs/compbio/Repository/networks.html | BN repository]] || 256 ||
|| alarm || [[http://www.cs.huji.ac.il/site/labs/compbio/Repository/networks.html | BN repository]] || 10'^16^' ||
|| adult || [[https://archive.ics.uci.edu/ml/datasets/Adult | UCI machine learning repository]] || 10'^12^' ||
|| car || [[https://archive.ics.uci.edu/ml/datasets/Adult | UCI machine learning repository]] || 6912 ||
to:
|| asia || %target=_blank% [[http://www.cs.huji.ac.il/site/labs/compbio/Repository/networks.html | BN repository]] || 256 ||
|| alarm || %target=_blank% [[http://www.cs.huji.ac.il/site/labs/compbio/Repository/networks.html | BN repository]] || 10'^16^' ||
|| adult || %target=_blank% [[https://archive.ics.uci.edu/ml/datasets/Adult | UCI machine learning repository]] || 10'^12^' ||
|| car || %target=_blank% [[https://archive.ics.uci.edu/ml/datasets/Adult | UCI machine learning repository]] || 6912 ||
Added lines 135-145:


[+'''%quest%3. Statistique du {$\chi^2$} et degré de liberté%%'''+]

Modifiez votre fonction '''sufficient_statistics''' afin qu'elle ne renvoie plus seulement {$\chi^2_{X,Y|\mathbf{Z}}$} mais plutôt un couple ({$\chi^2_{X,Y|\mathbf{Z}}$},DoF), où DoF est le nombre de degrés de liberté de votre statistique. Celui-ci est égal à :

{$$(|X|-1) \times (|Y|-1) \times |\{\mathbf{z} : N_{\mathbf{z}} \neq 0\}| $$}

où {$|X|$} représente le nombre de valeurs possibles que peut prendre la variable {$X$}, autrement dit, c'est la taille de son dictionnaire. Le dernier terme de l'équation est simplement le nombre de {$N_{\mathbf{z}}$} différents de 0.
 

Deleted lines 115-116:
   res_type = 'float, (' + \
        str ( len ( dico[x] ) ) + ',' + str ( len ( dico[y] ) ) + ')float'
Deleted line 124:
           #print indices
Deleted line 129:
       #res[0][0] = data.shape[1]   
Changed lines 81-84 from:
Ecrivez une fonction '''sufficient_statistics''' ( data, dico, x, y, z ) qui, étant donné le tableau 2D des données et le dictionnaire obtenus à la question 1, ainsi que deux entiers x et y représentant deux variables aléatoires (les index de leur colonne dans le CSV, en commençant à l'index 0 pour la 1ère colonne) et une liste d'entiers z, potentiellement vide, représentant la liste des variables de {$\mathbf{Z}$} (index de colonnes dans le CSV), renvoie la valeur de {$\chi^2_{X,Y|\mathbf{Z}}$}. Ainsi, '''sufficient_statistics''' ( data, dico, 0, 1, [2,3] ) renverra la statistique pour {$X$} = la variable de la 1ère colonne du CSV, {$Y$} = la variable aléatoire de la 2ème colonne du CSV, et {$\mathbf{Z}$} = le couple des variables des 3ème et 4ème colonnes du CSV.


to:
Ecrivez une fonction '''sufficient_statistics''' ( data, dico, x, y, z ) qui, étant donné le tableau 2D des données et le dictionnaire obtenus à la question 1, ainsi que deux entiers x et y représentant deux variables aléatoires (les index de leurs colonnes dans le CSV, en commençant à l'index 0 pour la 1ère colonne) et une liste d'entiers z, potentiellement vide, représentant la liste des variables de {$\mathbf{Z}$} (index de colonnes dans le CSV), renvoie la valeur de {$\chi^2_{X,Y|\mathbf{Z}}$}. Ainsi, '''sufficient_statistics''' ( data, dico, 0, 1, [2,3] ) renverra la statistique pour {$X$} = la variable de la 1ère colonne du CSV, {$Y$} = la variable aléatoire de la 2ème colonne du CSV, et {$\mathbf{Z}$} = le couple des variables des 3ème et 4ème colonnes du CSV. Pour vous éviter de parser le tableau data afin de compter les nombres {$N_{xy\mathbf{z}}$}, {$N_{x\mathbf{z}}$}, {$N_{y\mathbf{z}}$} et {$N_{\mathbf{z}}$}, vous pourrez utiliser la fonction '''create_contingency_table''' ( data, dico, x, y, z ) ci-dessous qui, étant donné les mêmes arguments que votre fonction '''sufficient_statistics''', renvoie un tableau de couples ({$N_{\mathbf{z}}, T_{X,Y})$}, pour tous les {$\mathbf{z} \in\mathbf{Z}$}, où {$T_{X,Y}$} est un tableau 2D (première dimension en {$X$} et deuxième en {$Y$}) contenant les {$N_{x,y,\mathbf{z}}$}. Par exemple, '''create_contingency_table''' ( data, dico, 1, 2, [3] ) peut renvoyer le tableau suivant :

 array([(538,  array([[ 497.,    1.],
                      [  40.,    0.]])),
        (9462, array([[ 4476.,  54.],
                      [ 4863.,  69.]]))])

ce qui correspond précisément à :

{$$\begin{array}{l@{}l@{\ }l@{\ }l}
  \text{array([} & (N_{Z=0}\text{, array([} &
  [ N_{X=0,Y=0,\mathbf{Z}=0}, & N_{X=0,Y=1,\mathbf{Z}=0}],\\
  & & [ N_{X=1,Y=0,\mathbf{Z}=0}, & N_{X=1,Y=1,\mathbf{Z}=0}]])),\\
  & (N_{Z=1}\text{, array([} &
  [ N_{X=0,Y=0,\mathbf{Z}=1}, & N_{X=0,Y=1,\mathbf{Z}=1}],\\
  & & [ N_{X=1,Y=0,\mathbf{Z}=0}, & N_{X=1,Y=1,\mathbf{Z}=0}]]))])
\end{array}$$}

Pour un {$\mathbf{z}$} donné, calculer {$N_{x\mathbf{z}}$} revient donc à faire des sommes sur chaque ligne des {$N_{xy\mathbf{z}}$} et calculer les {$N_{y\mathbf{z}}$} revient à faire des sommes en colonne. '''Attention :''' il peut arriver que certains {$N_{\mathbf{z}}$} soient égaux à 0. Dans ce cas, vous ne tiendrez pas compte des {$N_{xy\mathbf{z}}$}, {$N_{x\mathbf{z}}$} et {$N_{y\mathbf{z}}$} correspondants dans la formule de {$\chi^2_{X,Y|\mathbf{Z}}$} (car vous feriez des divisions par 0, ce qui est mal).


(:source lang=python:)
# etant donné une BD data et son dictionnaire, cette fonction crée le
# tableau de contingence de (x,y) | z
def create_contingency_table ( data, dico, x, y, z ):
    # détermination de la taille de z
    size_z = 1
    offset_z = np.zeros ( len ( z ) )
    j = 0
    for i in z:
        offset_z[j] = size_z     
        size_z *= len ( dico[i] )
        j += 1

    # création du tableau de contingence
    res_type = 'float, (' + \
        str ( len ( dico[x] ) ) + ',' + str ( len ( dico[y] ) ) + ')float'
    res = np.zeros ( size_z, dtype = object )
   
    # remplissage du tableau de contingence
    if size_z != 1:
        z_values = np.apply_along_axis ( lambda val_z : val_z.dot ( offset_z ),
                                        1, data[z,:].T )
        i = 0
        while i < size_z:
            indices, = np.where ( z_values == i )
            #print indices
            a,b,c = np.histogram2d ( data[x,indices], data[y,indices],
                                    bins = [ len ( dico[x] ), len (dico[y] ) ] )
            res[i] = ( indices.size, a )
            i += 1
    else:
        #res[0][0] = data.shape[1]   
        a,b,c = np.histogram2d ( data[x,:], data[y,:],
                                bins = [ len ( dico[x] ), len (dico[y] ) ] )
        res[0] = ( data.shape[1], a )
    return res
(:sourceend:)
Changed lines 24-27 from:



to:
Dans le code ci-dessous, la fonction '''read_csv''' vous permettra de lire les données des bases sur lesquelles vous allez travailler, et de les organiser sous une forme adéquate. La fonction '''read_csv''' prend en argument le nom d'un fichier CSV et renvoie un triplet :

* 1 tableau de strings contenant les noms des variables aléatoires
* un tableau 2D contenant les données du fichier CSV encodées sous forme numérique (le valeurs des variables aléatoires sont transformées en nombres entiers)
* un tableau de dictionnaires faisant la correspondance entre l'encodage numérique et les données du fichier CSV (il y a un dictionnaire par variable, le 1er dictionnaire correspondant à la 1ère colonne du CSV, ''etc''.)

Téléchargez le fichier [[(Attach:)2014_tme4_asia.csv | asia dataset]] et lisez-le à l'aide de la fonction '''read_csv'''.


Changed lines 69-81 from:
to:
[+'''%quest%2. Statistique du {$\chi^2$} conditionnel%%'''+]

Soit deux variables aléatoires {$X$} et {$Y$}. Appelons {$N_{xy}$}, {$N_x$} et {$N_y$}, respectivement, le nombre d'occurrences du couple {$(X=x,Y=y)$} et des singletons {$X=x$} et {$Y=y$} dans la base de données. Alors, comme indiqué sur la planche 37 du cours 5, la statistique du {$\chi^2$} de {$X$} et {$Y$} est égale à :

{$$\chi^2_{X,Y} = \sum_x\sum_y\frac{\left(N_{xy} - \frac{N_x \times N_y}{N}\right)^2}{\frac{N_x \times N_y}{N}}$$}

où {$N$} représente le nombre de lignes de la base de données. Cette formule permet de tester l'indépendance entre les deux variables {$X$} et {$Y$}. On peut aisément généraliser celle-ci pour tester des indépendances conditionnellement à un ensemble de variables {$\mathbf{Z}$}:

{$$\chi^2_{X,Y|\mathbf{Z}} = \sum_x\sum_y\sum_{\mathbf{z}}\frac{\left(N_{xy\mathbf{z}} - \frac{N_{x\mathbf{z}} \times N_{y\mathbf{z}}}{N}\right)^2}{\frac{N_{x\mathbf{z}} \times N_{y\mathbf{z}}}{N_{\mathbf{z}}}}$$}

où {$N_{xy\mathbf{z}}$}, {$N_{x\mathbf{z}}$}, {$N_{y\mathbf{z}}$} et {$N_{\mathbf{z}}$} représentent, respectivement, le nombre d'occurrences du triplet {$(X=x,Y=y,\mathbf{Z} = \mathbf{z})$}, des couples {$(X=x,\mathbf{Z} = \mathbf{z})$} et {$(Y=y,\mathbf{Z} = \mathbf{z})$}, et du singleton {$\mathbf{Z} = \mathbf{z}$}. Ainsi, si {$\mathbf{Z}$} est un ensemble de 3 variables aléatoires {$(A,B,C)$}, les valeurs {$\mathbf{z}$} seront des triplets {$(a,b,c)$}.

Ecrivez une fonction '''sufficient_statistics''' ( data, dico, x, y, z ) qui, étant donné le tableau 2D des données et le dictionnaire obtenus à la question 1, ainsi que deux entiers x et y représentant deux variables aléatoires (les index de leur colonne dans le CSV, en commençant à l'index 0 pour la 1ère colonne) et une liste d'entiers z, potentiellement vide, représentant la liste des variables de {$\mathbf{Z}$} (index de colonnes dans le CSV), renvoie la valeur de {$\chi^2_{X,Y|\mathbf{Z}}$}. Ainsi, '''sufficient_statistics''' ( data, dico, 0, 1, [2,3] ) renverra la statistique pour {$X$} = la variable de la 1ère colonne du CSV, {$Y$} = la variable aléatoire de la 2ème colonne du CSV, et {$\mathbf{Z}$} = le couple des variables des 3ème et 4ème colonnes du CSV.
Changed lines 18-20 from:
Apprendre un réseau bayésien consiste à apprendre sa structure graphique ainsi que les paramètres de ses distributions de probabilité conditionnelles. Pour réaliser la deuxième tâche, il suffit d'estimer ces paramètres par maximum de vraisemblance, comme vous l'avez fait dans le TME 3. Ici, nous nous focaliserons donc plutôt sur l'apprentissage de structure. Celle-ci reflétant des indépendances conditionnelles entre variables aléatoires, vous devrez exploiter des tests d'indépendance du {$\chi^2$} afin d'obtenir des structures graphiques les moins denses possibles (en termes de nombres d'arcs). Ainsi, '''alarm''' représente une distribution jointe de plus de 10'^16^' événements élémentaires mais, quand cette distribution est décomposée grâce au graphe ci-dessous, elle peut être décrite (sans perte d'informations) à l'aide de seulement 752 paramètres.

%block text-align=center% %width=300px%  Attach:2014_tme4_alarm.png
to:
Apprendre un réseau bayésien consiste à apprendre sa structure graphique ainsi que les paramètres de ses distributions de probabilité conditionnelles. Pour réaliser la deuxième tâche, il suffit d'estimer ces paramètres par maximum de vraisemblance, comme vous l'avez fait dans le TME 3. Ici, nous nous focaliserons donc plutôt sur l'apprentissage de structure. Celle-ci reflétant des indépendances conditionnelles entre variables aléatoires, vous devrez exploiter des tests d'indépendance du {$\chi^2$} afin d'obtenir des structures graphiques les moins denses possibles (en termes de nombres d'arcs). Ainsi, '''alarm''' représente une distribution jointe de plus de 10'^16^' événements élémentaires mais, quand cette distribution est décomposée grâce au graphe ci-dessous, elle peut être décrite (sans perte d'informations) à l'aide de seulement 752 paramètres. Comme nous l'avons vu en cours, cette représentation permet également d'effectuer très rapidement des calculs probabilistes.

%block text-align=center% %width=500px%  Attach:2014_tme4_alarm.png

[+'''%quest%1. Lecture des données%%'''+]





(:source lang=python:)
# -*- coding: utf-8 -*-

import numpy as np

# fonction pour transformer les données brutes en nombres de 0 à n-1
def translate_data ( data ):
    # création des structures de données à retourner
    nb_variables = data.shape[0]
    nb_observations = data.shape[1] - 1 # - nom variable
    res_data = np.zeros ( (nb_variables, nb_observations ), int )
    res_dico = np.empty ( nb_variables, dtype=object )
   
    # pour chaque variable, faire la traduction
    for i in range ( nb_variables ):
        res_dico[i] = {}
        index = 0
        for j in range ( 1, nb_observations + 1 ):
            # si l'observation n'existe pas dans le dictionnaire, la rajouter
            if data[i,j] not in res_dico[i]:
                res_dico[i].update ( { data[i,j] : index } )
                index += 1
            # rajouter la traduction dans le tableau de données à retourner
            res_data[i,j-1] = res_dico[i][data[i,j]]
    return ( res_data, res_dico )


# fonction pour lire les données de la base d'apprentissage
def read_csv ( filename ):
    data = np.loadtxt ( filename, delimiter=',', dtype='string' ).T
    names = data[:,0].copy ()
    data, dico = translate_data ( data )
    return names, data, dico
(:sourceend:)



Changed line 20 from:
%block text-align=center% %width=300px%  Attach:2014_tme4_alarm.jpg
to:
%block text-align=center% %width=300px%  Attach:2014_tme4_alarm.png
Added lines 1-22:
%define=exo color=red%
%define=quest color=blue%

! Indépendances conditionnelles et réseaux bayésiens

----

Dans ce TME, l'objectif est d'apprendre des réseaux bayésiens à partir de bases de données. Hormis la base '''asia''', un exemple jouet relativement petit qui vous permettra de mettre au point les différents algorithmes du TME, et '''car''', les autres bases correspondront à des distributions de probabilité de tailles raisonnables :

|| border=1 align=center
||! nom de la base ||! provenance ||! nombre d'événements élémentaires ||
|| asia || [[http://www.cs.huji.ac.il/site/labs/compbio/Repository/networks.html | BN repository]] || 256 ||
|| alarm || [[http://www.cs.huji.ac.il/site/labs/compbio/Repository/networks.html | BN repository]] || 10'^16^' ||
|| adult || [[https://archive.ics.uci.edu/ml/datasets/Adult | UCI machine learning repository]] || 10'^12^' ||
|| car || [[https://archive.ics.uci.edu/ml/datasets/Adult | UCI machine learning repository]] || 6912 ||
|| agaricus-lepiota || [[https://archive.ics.uci.edu/ml/datasets/Adult | UCI machine learning repository]] || 10'^16^' ||

Apprendre un réseau bayésien consiste à apprendre sa structure graphique ainsi que les paramètres de ses distributions de probabilité conditionnelles. Pour réaliser la deuxième tâche, il suffit d'estimer ces paramètres par maximum de vraisemblance, comme vous l'avez fait dans le TME 3. Ici, nous nous focaliserons donc plutôt sur l'apprentissage de structure. Celle-ci reflétant des indépendances conditionnelles entre variables aléatoires, vous devrez exploiter des tests d'indépendance du {$\chi^2$} afin d'obtenir des structures graphiques les moins denses possibles (en termes de nombres d'arcs). Ainsi, '''alarm''' représente une distribution jointe de plus de 10'^16^' événements élémentaires mais, quand cette distribution est décomposée grâce au graphe ci-dessous, elle peut être décrite (sans perte d'informations) à l'aide de seulement 752 paramètres.

%block text-align=center% %width=300px%  Attach:2014_tme4_alarm.jpg