0% ont trouvé ce document utile (0 vote)
55 vues12 pages

TD2 KNN Classification

Le document présente l'algorithme KNN (k plus proches voisins) en utilisant la bibliothèque sklearn sur la base de données MNIST, qui contient des images de chiffres manuscrits. Il décrit les étapes d'importation des données, de séparation en ensembles d'entraînement et de test, ainsi que l'entraînement du modèle et l'évaluation de sa performance à l'aide de la matrice de confusion. Enfin, il aborde l'importance de la normalisation des données pour améliorer la qualité des prédictions.

Transféré par

abderrahim najim
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
55 vues12 pages

TD2 KNN Classification

Le document présente l'algorithme KNN (k plus proches voisins) en utilisant la bibliothèque sklearn sur la base de données MNIST, qui contient des images de chiffres manuscrits. Il décrit les étapes d'importation des données, de séparation en ensembles d'entraînement et de test, ainsi que l'entraînement du modèle et l'évaluation de sa performance à l'aide de la matrice de confusion. Enfin, il aborde l'importance de la normalisation des données pour améliorer la qualité des prédictions.

Transféré par

abderrahim najim
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Cours2- TD2

KNN (classification & régression) :


Bibliothèque « sklearn »
A) Algorithme KNN en utilisant la bibliothèque « sklearn » :
application sur la base MNIST
La base de données MNIST pour Modified ou Mixed National Institute of Standards and
Technology, est une base de données de chiffres écrits à la main. C'est un jeu de données très utilisé en
apprentissage automatique. La reconnaissance de l'écriture manuscrite est un problème difficile, et un bon
test pour les algorithmes d'apprentissage. La base MNIST est devenue un test standard. Elle regroupe
60000 images d'apprentissage et 10000 images de test, issues d'une base de données antérieure, appelée
simplement NIST. Ce sont des images en noir et blanc, normalisées centrées de 28 pixels de côté.

Figure 1. Échantillon de la base de données MNIST


A.1) Importation de la base MNIST
## Importation du dataset « mnist ». Cela peut prendre du temps.
from sklearn.datasets import fetch_openml
mnist = fetch_openml('mnist_784', version=1)
A.2) Échantionnage des données
• Cette base de données est composée de 70 000 images de taille 28 × 28 pixels. On utilisera ici que
15% des images, soit 10 500 (on utilise ici que 15% pour des raisons de temps de calcul).
## Importation d’une fonction permettant de séparer les données en deux groupes.

from sklearn.model_selection import train_test_split

# 15% des données seront utilisées et stockées dans vect_x_utile (28x28 pixels)
# et vect_y_utile le label de l’image

vect_x_utile ,vect_x_non_utile ,vect_y_utile ,vect_y_non_utile=train_test_split(mnist.data ,


mnist.target , train_size =0.15)
vect_x_train , vect_x_test , etiquettes_train , etiquettes_test = train_test_split(vect_x_utile ,
vect_y_utile , train_size=0.8)

IA – KNN-classification & régression 1 IPEST 2023


• La fonction train_test_split permet de séparer les données en deux groupes.
• Les images et leurs étiquettes utiles sont stockées dans les variables vect_x_utile et vect_y_utile.
• vect_x_utile représente les pixels de l’image. Il s’agit donc d’une matrice de taille 28 × 28 (en
réalité, c’est un vecteur de taille 784 × 1) dont les valeurs sont comprises entre 0 et 255 (image en
niveau de gris).
• vect_y_utile est l’étiquette associée à l’image. Ici, il y a 10 possibilités : 0, 1, ··· , 9.
Pour tester la qualité du modèle des k plus proches voisins :
• 80% des données sont utilisées comme données d’entraînement : vect_x_train
• 20% des données restantes seront les données de tests (x*) : vect_x_test
• On a donc au total 10500×0.8 = 8400 images connues (vect_x_train) et 10500 × 0.2 = 2100 images
dont on va chercher à prédire le chiffre écrit (vect_x_test).
A.3) Algorithme des k plus proches voisins : Le nombre k est fixé
# Importation de la bibliothèque utile pour l’algorithme des k plus proches voisins

from sklearn import neighbors

# Création du modèle. Ici on fixe k=3

knn = neighbors.KNeighborsClassifier(3)

# Sauvegarde des données utiles : Phase d’apprentissage

knn.fit(vect_x_train ,etiquettes_train)

# Prédictions des étiquettes pour les données vect_x_test

predictions=knn.predict(vect_x_test)

# liste des predictions correctes

liste_prediction_correcte=[predictions[i]==etiquettes_test.values[i] for i in range (len(predictions))]

# Pourcentage d’erreur dans la prédiction

pourcentage_erreur=(1- sum(liste_prediction_correcte)/ len(liste_prediction_correcte))*100


print('le pourcentage d"erreur est:',pourcentage_erreur )

• # Création du modèle. Ici on fixe k=3 : On crée le modèle que l’on souhaite utiliser. Ici, on va
utiliser l’algorithme pour k = 3. Cette ligne permet d’initialiser l’algorithme.
• # Sauvegarde des données utiles : l’algorithme ici n’effectue aucune optimisation mais va juste
sauvegarder toutes les données en mémoire. C’est sa manière d’apprendre en quelque sorte.
• # Prédictions des étiquettes pour les données vect_x_test : On effectue les prédictions (phase
d’inférence) pour chaque image de vect_x_test.
• # liste : On construit la liste des prédictions qui sont correctes. La liste liste_prediction_correcte
est donc une liste de booléen True et False.
• # Pourcentage d’erreur dans la prédiction : On calcule le pourcentage d’erreur avec la moyenne
des réussites à l’aide de la commande : sum(liste_prediction_correcte)/len(liste_prediction_correcte).

NB. On rappelle que True+True=2 et False + False=0

IA – KNN-classification & régression 2 IPEST 2023


A.4) Recherche de la meilleure valeur de k
errors = []

for k in range (2,15):

# Création du modèle

knn = neighbors.KNeighborsClassifier(k)

# Sauvegarde des données utiles : Phase d’apprentissage

knn.fit(vect_x_train , etiquettes_train)

# Calculs de l’erreur pour chaque valeur de k

errors.append(100*(1 - knn.score(vect_x_test , etiquettes_test)))

from matplotlib import pyplot as plt


plt.plot( range (2,15), errors , 'o-')
plt.xlabel(" Nombre k")
plt.ylabel(" Erreur en %")
plt.grid()
plt.show()

• La fonction knn.score(vect_x_test,etiquettes_test) réalise ce qui a été réalisé au code précèdent.


Cette méthode score calcule donc le taux de réussite du classifieur.

IA – KNN-classification & régression 3 IPEST 2023


A.5) Efficacité du modèle

# On calcule l’efficacité du modèle sur l’échantillon de test

a=knn.score(vect_x_test , etiquettes_test)
print('Le modèle est efficace à', a*100,'%')

A.6) Matrice de confusion


Grâce à la fonction score, on peut connaître la qualité de prédiction du classifieur. Cependant, il pourrait
être très intéressant de savoir où les erreurs sont produites et comment. Pour cela, on va utiliser la matrice
de confusion.
Matrice de confusion non normalisée
La matrice de confusion non normalisée permet de visualiser les plus importantes sources d’erreurs.
# Les données vect_x_train, etiquettes_train, vect_x_test et etiquettes_test sont disponibles.

from sklearn.metrics import plot_confusion_matrix

# Création du modèle

knn = neighbors.KNeighborsClassifier(3)
knn.fit(vect_x_train , etiquettes_train)
class_names= list ( range (10)) # liste de nombre de 0 à 9

# Matrice de confusion non normalisée

disp = plot_confusion_matrix(knn , vect_x_test , etiquettes_test ,display_labels=class_names


,cmap=plt.cm.Blues ,normalize= None )

disp.ax_.set_title(" Matrice de confusion , sans normalisation ")

IA – KNN-classification & régression 4 IPEST 2023


Dans le cadre de l’évaluation des performances d’une fonction de prédiction sur un problème de
classification multi-classe à 𝑚 étiquettes, on souhaite disposer d’une mesure de performance permettant
d’inspecter en détail le comportement de la fonction de prédiction et notamment ses difficultés à prédire
chacune des étiquettes. La matrice de confusion est un tableau de dimension 𝑚 × 𝑚 qui répertorie toutes
les informations concernant les prédictions effectuées et les vraies étiquettes. A chaque étiquette possible
est associée un entier de 1 à 𝑚 permettant de l’identifier.
Le tableau se lit alors de la manière suivante :
• Chaque élément du tableau, placé à la ligne 𝑖 ∈ {1, . . . , 𝑚} et à la colonne 𝑗 ∈ {1, . . . , 𝑚} (noté
𝑀𝑖𝑗 ) correspond au nombre de fois où la fonction de prédiction a produit la sortie 𝑗 alors que la
vraie étiquette était 𝑖.
• Ainsi les éléments sur la diagonale correspondent au nombre de prédictions justes (l’élément (𝑖, 𝑖)
correspond au nombre de fois où l’étiquette 𝑖 à été correctement prédite).

Matrice de confusion normalisée

La matrice de confusion normalisée ne tient plus compte du déséquilibre entre étiquettes en divisant
chaque ligne 𝑖 par le nombre d’apparition de l’étiquette 𝑖 dans la base de données (c’est à dire la somme
des éléments de la ligne 𝑖 de la matrice de confusion non normalisée). Celle-ci permettra d’observer les
erreurs commises par la fonction de prédiction, indépendamment de la répartition des étiquettes.
On peut construire une matrice de confusion normalisée en divisant chaque élément par la somme des
éléments sur la même ligne. En notant 𝑀𝑛 la matrice de confusion normalisée, on a : quel que soit 𝑖, 𝑗 ∈
𝑀𝑖𝑗
{1, . . . , 𝑚}, 𝑀𝑛𝑖𝑗 = ∑𝑚
𝑐=1 𝑀𝑖𝑐

#### Les données vect_x_train, etiquettes_train, vect_x_test et etiquettes_test sont disponibles.

from sklearn.metrics import plot_confusion_matrix

# Création du modèle

knn = neighbors.KNeighborsClassifier(3)
knn.fit(vect_x_train , etiquettes_train)
class_names= list ( range (10)) # liste de nombre de 0 à 9

plt.rcParams.update({'font.size': 6}) # pour meilleur affichage de la matrice de confusion non normalisée

# Matrice de confusion non normalisée

disp = plot_confusion_matrix(knn , vect_x_test , etiquettes_test ,display_labels=class_names


,cmap=plt.cm.Blues ,normalize='true',)
disp.ax_.set_title(" Matrice de confusion normalisee")

IA – KNN-classification & régression 5 IPEST 2023


A.7) Sensibilité et spécificité
Dans le cadre d’un test de prédiction d’une classe d’une donnée, on cherche à valider si celle-ci a été
correctement faite ou non et à comprendre la répartition des erreurs. Prenons l’exemple de prédiction du
chiffre 8 présenté dans la section précédente. Il en résulte la matrice de confusion ci-dessous :

Nature du chiffre prédit


Correcte Incorrecte
Correcte VP FN
Nature réelle du chiffre
Incorrecte FP VN

Où les valeurs du tableau représentent :

• VP (Vrais Positifs) est le nombre de chiffres 8 corrects effectivement reconnus comme tels,
• FP (Faux Positifs) représente le nombre de chiffres réellement différents de 8 mais qui ont été
jugés comme étant égal à 8,
• FN (Faux Négatifs) représente le nombre de chiffres 8 réellement corrects mais qui n’ont pas été
correctement classés,
• VN (Vrais Négatifs) représente le nombre de chiffres réellement différents de 8 qui ont été
catégorisés comme tels.

IA – KNN-classification & régression 6 IPEST 2023


Pour le chiffre 8, on obtient alors la matrice suivante :
Nature du chiffre 8 prédit
Correcte Incorrecte
Correcte 157 20
Nature réelle du chiffre 8
Incorrecte 4 1831
• La sensibilité d’un critère est la probabilité que celui-ci détecte la catégorie positive parmi les
𝑉𝑃
exemples qui le sont réellement. Il s’agit donc du rapport : 𝑉𝑃+𝐹𝑁
• La spécificité d’un critère est la probabilité que celui-ci détecte la catégorie négative parmi les
𝑉𝑁
exemples qui le sont réellement. Il s’agit donc du rapport 𝑉𝑁+𝐹𝑃
𝑉𝑃+𝑉𝑁
• Avec ces notations, la justesse (Accuracy) vaut 𝑎𝑐𝑐𝑢𝑟𝑎𝑐𝑦 = 𝑉𝑃+𝑉𝑁+𝐹𝑃+𝐹𝑁

A.8) Importance de la mise en forme des données


Par exemple, dans le domaine médical si on s’intéresse à la fréquence cardiaque (autour de 70
battements/min) et au taux de cholestérol (variant autour de 1,5 à 2,5 g/L). On comprend qu’une variation
d’une unité sur le battement cardiaque aura une faible influence sur l’état de santé du patient. Cependant,
une variation d’une unité sur le taux de cholestérol a une influence significative. Voici les données de
quatre patients (ceci est bien sûr un exemple fictif) :

Numéro Fréquence cardiaque Taux de cholestérol Etat santé


(bat/min) (g/l)
1 80 1,8 Bon
2 70 2,3 Mauvais
3 65 1,6 Bon
4 90 2,1 Mauvais

Pour réaliser un algorithme des k plus proches voisins de bonne qualité, il est nécessaire que les données
soient dans des unités ou à une échelle comparable. Pour cela, on retiendra principalement deux
possibilités :
• Ramener les données à une échelle commune (généralement entre 0 et 1)
• Normer les données par rapport à leur écart-type (représentant la dispersion moyenne de celles-
ci)
L’ensemble des données sont stockées dans une matrice M. Pour notre exemple :
80 1,8
70 2,3
𝑀=( )
65 1,6
90 2,1
Normalisation dans l’intervalle [0, 1]
On note 𝑐𝑜𝑙𝑗 (𝑀) la colonne 𝑗 de la matrice 𝑀. Un élément de la ième ligne et de la jème colonne est noté
𝑛𝑜𝑟𝑚
𝑀𝑖𝑗 . La normalisation de la donnée 𝑀𝑖𝑗 est notée 𝑀𝑖𝑗 et calculée par :
𝑀𝑖𝑗 − min (𝑐𝑜𝑙𝑗 (𝑀))
𝑛𝑜𝑟𝑚
𝑀𝑖𝑗 =
max (𝑐𝑜𝑙𝑗 (𝑀)) − min (𝑐𝑜𝑙𝑗 (𝑀))
On trouve alors :
0,6 0,286
0,2 1
𝑀𝑛𝑜𝑟𝑚 =( )
0 0
1 0,714

IA – KNN-classification & régression 7 IPEST 2023


Normalisation dans l’intervalle grâce à l’écart-type des données
On note 𝜎𝑐𝑜𝑙𝑗(𝑀) , l’écart-type des valeurs de la colonne 𝑐𝑜𝑙𝑗 (𝑀) et ̅̅̅̅̅̅̅̅̅̅
𝑐𝑜𝑙𝑗 (𝑀), la moyenne des valeurs de la
colonne 𝑐𝑜𝑙𝑗 (𝑀).
On calcule :
𝑛𝑜𝑟𝑚
𝑀𝑖𝑗 − ̅̅̅̅̅̅̅̅̅̅
𝑐𝑜𝑙𝑗 (𝑀)
𝑀𝑖𝑗 =
𝜎𝑐𝑜𝑙𝑗(𝑀)
∑𝑛 ̅̅̅̅̅̅̅̅̅̅̅ 2
𝑖=1 𝑛𝑖 (𝑀𝑖𝑗 −𝑐𝑜𝑙𝑗 (𝑀))
Avec : 𝜎𝑐𝑜𝑙𝑗(𝑀) = √ 𝑁
On trouve ainsi :
̅̅̅̅̅̅̅̅̅̅̅
𝑐𝑜𝑙0 (𝑀) = 76,25 𝜎𝑐𝑜𝑙0(𝑀) = 9,6 ̅̅̅̅̅̅̅̅̅̅̅
𝑐𝑜𝑙1 (𝑀) = 1,95 𝜎𝑐𝑜𝑙1(𝑀) = 0,27
De ce fait :
0,39 −0,56
−0,65 1,30
𝑀𝑛𝑜𝑟𝑚 =( )
−1,17 −1,30
1,43 0,56

IA – KNN-classification & régression 8 IPEST 2023


B) Exercice 1 : Classification des plantes « iris » en utilisant
l’algorithme KNN de la bibliothèque « sklearn »

L’iris est un genre de plantes vivaces à rhizomes ou à bulbes de la famille des Iridacées. Le genre Iris
contient 210 espèces et d’innombrables variétés horticoles. On se propose ici d’appliquer l’algorithme
des k plus proches voisins sur une banque de données appelée « Iris de Fischer ». Il s’agit de données
collectées dans le cadre d’une étude numérique sur l’utilisation de multiples mesures dans le cadre des
problèmes taxonomiques (1). Trois espèces d’iris sont classées selon quatre critères : la longueur des
sépales, la largeur des sépales, la longueur des pétales et la largeur des pétales. Les trois variétés d’iris
sont « Iris setosa », « Iris versicolor » et « Iris virginica ». ((1) The Use of Multiple Measurements in Taxonomic
Problems, R.Fischer, 1936)

Objectif : On cherche à mettre en place un algorithme des k plus proches voisins permettant de
déterminer à quelle variété d’iris appartient une nouvelle entrée selon la base d’apprentissage disponible.
Par la connaissance de la réponse attendue, on pourra en déduire l’efficacité de notre algorithme.

Les iris sont classifiés suivant quatre critères, qui sont dans l’ordre :

• La longueur des sépales (en cm) ;


• La largeur des sépales (en cm) ; Width petal
• La longueur des pétales (en cm) ;
• La largeur des pétales (en cm) ;
Length petal
Le fichier « iris » est constitué de 150 lignes et 5 colonnes.
Le format est le suivant :
Length sepal
• 50 lignes contenant les informations des Iris-
setosa (Iris numéro 0) ; Width sepal
• 50 lignes contenant les informations des Iris-
versicolor (Iris numéro 1) ;
• 50 lignes contenant les informations des Iris-
virginica (Iris numéro 2) ;

IA – KNN-classification & régression 9 IPEST 2023


Avec le script suivant, les données et leurs étiquettes (numéro des iris) sont importées et stockées.

from sklearn.datasets import load_iris #importation de la commande


from sklearn.model_selection import train_test_split
from sklearn import neighbors
import numpy as np
import matplotlib.pyplot as plt

# Chargement du fichier, celui fait 150 lignes et 5 colonnes (longueur et largeur des sépales,
# longueur et largeur des pétales et nom de l'iris)

irisData=load_iris()

# Récupération des données 150 lignes et 4 colonnes


donnees=irisData.data

# Récupération des étiquettes 150 noms

numero_iris=irisData.target

Q1. A l’aide de la fonction train_test_split, réaliser une base d’entraînement contenant 120 iris constituée
de 40 Iris-setosa, 40 Iris-versicolor et 40 Iris-virginica. Construire également une base test des données
que l’on va tester constituée des 30 iris restants.
Indication : Construire trois bases d’entrainement de 40 iris chacune, et assembler les trois pour créer la
base finale. Utiliser la méthode concatenate de numpy pour faire cela.
Q2. A l’aide du code fourni dans le cours (exemple précédent), tester la qualité de prédiction faite sur les
30 exemples de la base test de données à l’aide de la méthode score, pour k = 5.
Q3. Tracer alors la qualité de la réponse, pour k variant de 3 à 15.
Q4. Relancer le code et observer les variabilités de la qualité de prédiction faite.

IA – KNN-classification & régression 10 IPEST 2023


C) Exercice 2 : Estimation la masse des pingouins en utilisant la
bibliothèque « sklearn » et la méthode de régression
Objectif : On cherche à déterminer la masse estimée de plusieurs pingouins à partir des mesures
disponibles sur une population de pingouins.
On fournit dans un fichier « penguins.csv » des informations sur 3
espèces de pingouins (à placer dans le même dossier du code
python). Celle que l’on étudiera particulièrement est l’espèce «
Chinstrap ».
Le fichier « penguins.csv » est constitué de 345 lignes et 7 colonnes
(la première ligne n’est pas utile). Le format est le suivant :
• L’espèce du pingouin (on ne s’intéressera qu’au pingouin de
l’espèce « Chinstrap » ;
• L’île où les pingouins vivent (on ne s’intéressera pas à ce
paramètre) ;
• La longueur du bec (en mm) ;
• La hauteur du bec (en mm) ;
• La longueur des nageoires (en mm) ;
• La masse du corps (en g) ;
• Le sexe du pingouin ;

Avec le script suivant, les données et les masses des pingouins sont importées et stockées.

from sklearn import neighbors


import numpy as np
fichier=open("penguins.csv","r") # Ouverture du fichier penguins.csv en mode lecture
fichier.readline() # Lecture de la première ligne sans la stocker. On saute donc cette ligne.
M=[] # Initialisation de la matrice
masse=[] # Initialisation de la liste des masses
for ligne in fichier : # Parcours du reste du fichier
ligne=ligne.strip() # Suppression du saut de ligne
liste=ligne.split(",") # Récupération des informations sous forme de liste
if liste[0]=="Chinstrap": # On ne veut récupérer que les données sur les pingouins Chinstrp
# Récupération des paramètres culmen length, culmen depth, flipper length
donnees=[float(liste[i]) for i in range(2,5)]
if liste[-1]=="MALE": # Récupération de la donnée du sexe du pingouin
donnees.append(0)
else:
donnees.append(1)
M.append(donnees) # Ajout à la matrice
masse.append(float(liste[-2])) # Ajout à la liste masse
M=np.array(M) # Conversion en array
masse=np.array(masse)# Conversion en array

IA – KNN-classification & régression 11 IPEST 2023


Dans cet exercice, on va chercher à prédire la masse d’un pingouin connaissant :
• La longueur du bec (en mm) ;
• La hauteur du bec (en mm) ;
• La longueur des nageoires (en mm) ;
• Le sexe du pingouin ;

Q1. Observez le code permettant de récupérer les données des pingouins dans la matrice M et la masse
de ceux-ci dans le vecteur masse.
Q2. Déterminer le nombre de pingouins « Chinstrap » constituant les données étudiées.

On va créer deux jeux de données : celui d’apprentissage et celui de test. Les données utilisées pour
réaliser l’algorithme (jeu de données d’apprentissage) seront l’ensemble des données récupérées à la
question précédente, excepté celles des 10 derniers pingouins. Les données utilisées pour tester
l’algorithme (jeu de données test) seront les données des 10 derniers pingouins des données récupérées.

Q3. Créez deux matrices, ensemble_apprentissage et ensemble_test qui seront les paramètres
d’évaluation sur lesquels l’algorithme des k plus proches voisins se fera à partir de la matrice M. Créez
deux vecteurs masse_apprentissage et masse_test représentatifs de la grandeur étudiée (la masse des
pingouins). Bien entendu, la i-ème ligne de la matrice ensemble_apprentissage et ensemble_test sera en
correspondance avec à la i-ème grandeur du vecteur masse_apprentissage ou masse_test.

L’algorithme des k plus proches voisins que l’on va utiliser ici ne diffère pas beaucoup de celui utilisé
dans les deux exercices précédents. La différence tient dans le traitement des grandeurs évaluées. Dans
les deux premiers exercices, on cherchait à faire de la classification, alors qu’ici on fait de la régression.
Dans un problème de classification, on appliquait l’approche du vote majoritaire pour obtenir le label
estimé de celui-ci. Dans le cas de la régression, on effectue la moyenne des grandeurs d’intérêts des k
plus proches voisins. On utilisera donc ici la méthode KNeighborsRegressor plutôt que
KNeighborsClassifier.

Q4. Appliquez l’algorithme des k plus proches voisins pour le premier pingouin du jeu de test. Faites
ainsi l’estimation de la masse de celui-ci, pour k = 5. Vérifier que vous trouvez que la masse estimée de
celui-ci est : 4120.
Q5. Calculer l’erreur relative entre les masses estimées des 10 pingouins et leur masse réelle pour k = 5.

IA – KNN-classification & régression 12 IPEST 2023

Vous aimerez peut-être aussi