Nous allons utiliser une bibliothèque d'apprentissage automatique disponible dans python dénommée scikit-learn. Cette bibliothèque contient de très nombreux algorithmes de classification supervisée et non supervisée.
À nouveau, nous allons utiliser les iris. Pour cela, nous écrirons :
from sklearn import linear_model, datasets iris = datasets.load_iris() X = iris.data[:, :] Y = iris.target
Remarque : ce sont exactement les mêmes données que dans le TP sur les k plus proches voisins. Seulement, elles sont fournies ici sous forme de matrice car scikit_learn attend des données stockées sous cette forme.
Effectuer la régression logistique est très simple. Il suffit d'écrire :
modele_regression_logistique = linear_model. LogisticRegression () modele_regression_logistique. fit (X, Y)
On peut maintenant utiliser le modèle pour prédire la classe d'une donnée ou obtenir la probabilité pour cette donnée d'appartenir à chacune des 3 classes.
Pour cela, en supposant que donneesApredire est un tableau contenant les attributs des données à prédire (tableau de la même forme que X), on écrit :
classesPredites = modele_regression_logistique. predict (donneesApredire)
qui met dans classesPredites la classe prédite pour chacune des données contenues dans donneesApredire.
Par exemple, si on applique le modèle sur l'ensemble d'entraînement, on obtient :
modele_regression_logistique. predict (X) [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
Quand vous le faites, le résultat que vous obtenez peut-être légérement différent. (Pourquoi d'après vous ?)
Pour obtenir les probablités d'appartenance à chacune des classes, on écrit :
probaClasses = modele_regression_logistique. predict_proba (donneesApredire)
probaClasses est alors un tableau dont chaque ligne correspond à une donnée de donneesApredire, chaque élément (colonne) correspondant à la probabilité d'appartenir à une classe.
Par exemple, si on applique le modèle sur l'ensemble d'entraînement, on obtient :
modele_regression_logistique. predict_proba (X) [[ 8.79681649e-01 1.20307538e-01 1.08131372e-05] [ 7.99706325e-01 2.00263292e-01 3.03825365e-05] [ 8.53796795e-01 1.46177302e-01 2.59031285e-05] ... [ 1.45811816e-03 2.98379693e-01 7.00162189e-01] [ 1.09779827e-03 1.31785617e-01 8.67116585e-01] [ 1.68397530e-03 2.81057800e-01 7.17258224e-01]]
Quand vous le faites, le résultat que vous obtenez peut-être légérement différent. (Pourquoi d'après vous ?)
Naturellement, pour chaque donnée, la classe prédite correspond à la colonne ayant la plus grande valeur (probabilité).
from sklearn import linear_model, datasets iris = datasets.load_iris() X = iris.data[:, :] Y = iris.target modele_regression_logistique = linear_model. LogisticRegression () modele_regression_logistique. fit (X, Y) classe_predite = modele_regression_logistique. predict (X)
# à la suite de ce qui précède from random import shuffle nb_erreur = 0 # découpe du jeu d'exemples en 80 % pour l'entraînement du modèle, le reste pour son test (voir le TP sur les k plus proches voisins) p = 0.8 # 80% listeDesIndices = [i for i in range (len (X))] shuffle (listeDesIndices) # la liste des indices des exemples utilisés pour l'entraînement indices_entrainement = listeDesIndices [0:int(p*len(X))] # la liste des indices des exemples utilisés pour le test indices_test = listeDesIndices [int(p*len(X)):len(X)] # on entraîne le modèle modele_regression_logistique. fit (X [indices_entrainement], Y [indices_entrainement]) # on prédit la classe des exemples du jeu de test classe_predite = modele_regression_logistique. predict (X [indices_test]) # on calcule le nombre d'erreurs de prédiction for i in range (len (indices_test)): if Y [indices_test [i]] != classe_predite [i]: nb_erreur += 1 # et on calcule le taux d'erreur demandé taux_erreur = nb_erreur / len (indices_test)
Pour la matrice de confusion :
matrice_confusion = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] for i in range (len (indices_test)): matrice_confusion [Y [indices_test [i]]] [classe_predite [i]] += 1
Comme on dit, « un dessin vaut mieux qu'un long discours ». Quand on cherche à extraire des informations de données, il est effectivement essentiel de faire des graphiques qui permettent de voir facilement des choses que des algorithmes ont du mal à trouver, pour comprendre des relations, ... Aussi, allons-nous apprendre à réaliser quelques graphiques simples pour poursuivre ce TP sur la régression logistique. Les notions vues ci-dessous sont très générales et s'appliquent bien entendu en dehors de la régression logistique.
Un scatter-plot représente un ensemble de points dans le plan. Python fournit tous les éléments pour que cela se fasse sans difficulté. On fait comme cela :
from random import randint x = [randint (0, 10) for i in range(10)] y = [randint (5, 20) for i in range(10)] import matplotlib.pyplot as plt plt.figure () plt.scatter (x, y) plt.show ()
On peut donner une taille à chacun des points comme cela :
taille = [i*10 for i in range (10)] plt.scatter (x, y, s = taille) plt.show ()
et une couleur :
from matplotlib.colors import ListedColormap palette = ListedColormap(['#FF0000', '#00FF00', '#0000FF']) couleur = [i % 3 for i in range (10)] plt.scatter (x, y, c = couleur, s = taille, cmap = palette) plt.show ()
Si on trouve que le cercle noir autour des points n'est pas joli, on ajoute edgecolors='none' en paramètre de la fonction plt.scatter() pour le retirer.
On peut aussi dessiner autre chose que des cercles/disques avec le paramètre marker. Celui-ci prend la valeur 'o' par défaut. Des tas d'autres valeurs sont possibles : voir cette page de documentation pour en avoir la liste.
Il faut toujours donner un titre à un graphique et indiquer ce que les axes représentent. Cela se fait à l'aide des fonctions :
On veut maintenant identifier les données mal prédites.
Refaites le même graphique en colorant les exemples en fonction de leur classe (comme précédemment). Cette fois-ci, vous indiquez les exemples mal classés en utilisant une forme particulière (à vous de choisir quelque chose de joli, qui se voit et qui se comprend au premier coup d'œil).
La regression logistique estime la probabilité d'appartenance d'une donnée à chacune des classes. Cette probabilité donne une information quant à l'incertitude de cette prédiction. Pour une donnée, si toutes les probabilités sont faibles sauf une qui est presqu'égale à 1, alors la classe est (presque) certaine. Au contraire, pour certaines données, des probabilités significativement différentes de 0 et de 1 sont estimées ; dans ce cas, la prédiction de la classe est incertaine.
Ici, on dit que si une probabilité est < 0,9 ou > 0,1, alors la classe prédite pour cette donnée est incertaine.
Refaites le même graphique que précédemment. Cette fois-ci vous indiquez les exemples dont la classe est incertaine par une couleur, une taille ou une forme particulière (à votre choix, du moment que l'on voit et comprend au premier coup d'œil).
Quand toutes les couleurs spécifiées sont la même, les points sont rouges. Si on veut spécifier une autre couleur, on peut utiliser son nom : voir ici la liste des couleurs disponibles.
La courbe ROC est un moyen très pratique pour estimer la qualité d'une procédure de classification. Nous allons la dessiner. Avant cela, il faut en calculer les points en suivant les indications données en cours, rappelées ci-dessous.
La courbe ROC est un graphique en deux dimensions représentant le taux de vrais positifs par rapport au taux de faux positifs.
Pour un problème de classification binaire, on procède comme suit :
from numpy import argsort toto = [6, 8, 2, 1, 4] titi = argsort (toto)titi contient un tableau dont les éléments sont [3, 2, 4, 0, 1]. Ce sont les indices des éléments du tableau qui ont été triés par argsort dans l'ordre croissant : le plus petit est celui d'indice 3, puis celui d'indice 2, ...
Reste à faire le graphique avec tfp en abscisses et tvp en ordonnées.
S'il y a k classes, on réalise k courbes ROC. Pour réaliser chacune de ces courbes, l'une des classes est considérée comme positive, toutes les autres comme négatives.
L'AUC est la surface en dessous de la courbe ROC. Elle se calcule très facilement comme une intégrale de Riemann, en faisant la somme des surfaces des rectangles situés sous la courbe ROC. Avec les valeurs de tvp calculées précédemment, ce calcul est immédiat.