Vous êtes sur la page 1sur 4

NSI – Algorithme ALG

ALG 08 Algorithme des k plus proches voisins ou k-NN (k Nearest Neighbors)


Sources : David Roche – Pixees.fr; wikipedia et chaîne Youtube Temath
Lien DOCSHARE pour les scripts en Python : link.dgpad.net/8wu1

I- Qu'est-ce que c'est ?


L'algorithme k-NN est un algorithme essentiel en apprentissage automatique ou "machine
learning". Il a été inventé dans les années 1960 mais il a connu un regain d'intérêt au début des
années 2000 avec l'explosion des données disponibles.
Il est très simple et est principalement utilisé pour :
 déterminer la classe d'un élément dans une classification déjà déterminée
 faire une suggestion en fonction des choix d'autres personnes
 prédire l'évolution d'un élément en analysant l'évolution d'autres éléments

II- Fonctionnement
L'algorithme des k plus proches voisins nécessite un jeu de données E et une donnée X que l'on
cherche à classifier, pour laquelle on veut faire une suggestion, dont on veut prédire l'évolution, …
Le principe de l'algorithme k-NN est :
 On calcule les distances entre la donnée X et chaque donnée du jeu de données.
 On retient les k données du jeu de données E les plus proches de la donnée X
 On attribue à X la classe qui est la plus fréquente parmi les k données les plus proches
Exemple : Carac2
Le jeu de données concerne 2 classes (carré bleu et triangle rouge) qui ont
2 caractéristiques (Carac1 et Carac2). Les caractéristiques peuvent être,
par exemple, une longueur, une masse, le prix, …
On désire savoir à quelle classe appartient un élément "X" noté en vert et
placé dans le graphique en fonction de ces 2 caractéristiques.
 Si k=3 : on considère les 3 plus proches voisins (cercle en trait
plein) et on voit qu'il y a 2 triangles rouges et 1 carré bleu donc
l'élément X est un triangle rouge.
 Si k=5 : on considère les 5 plus proches voisins et on voit qu'il y a 3
carrés bleus et 2 triangles rouges donc l'élément X est un carré bleu.
Vous voyez que le choix du nombre k n'est pas anodin … Carac1
Source : Antti Ajanki -Wikipedia

II- Implémentation de l'algorithme kNN en Python


1) La fonction Distance_euclidienne
La distance que nous calculerons entre la donnée X et chaque donnée du jeu de données sera la
distance euclidienne (mais elle pourrait être la distance de Manhattan cf bit.ly/3c9nNcN par exemple).
Dans un repère à 3 dim, vous connaissez la formule permettant de calculer la distance euclidienne
AB entre 2 points A(xA,yA,zA) et B(xB,yB,zB) : 𝑨𝑩 = √(𝒙𝑩 − 𝒙𝑨 )𝟐 + (𝒚𝑩 − 𝒚𝑨 )𝟐 + (𝒛𝑩 − 𝒛𝑨 )𝟐
Exo01*:
Faire une fonction distEuclid(point1,point2) permettent de calculer la distance euclidienne entre 2
points ayant n coordonnées représentants n caractéristiques. Les points sont des tuples ou des listes contenant les n
coordonnées et on ne vérifie pas que les 2 points ont bien le même nb de coordonnées.
Pour vérifier votre fonction distEuclid, ajouter la fonction test et lancer cette fonction test
def test() :
pt1=(5, 3.1, -2)
pt2=(-4.7, 0, 4)
pt3=[1, 2.0, 3, 4.5, 5, 6.1, 2]
pt4=[-4, -3, 0, 8, 10, 2.1, -3.5]
assert distEuclid(pt1,pt2)==sqrt(13970)/10, "erreur distance 3 coord"
assert distEuclid(pt3,pt4)==sqrt(570)/2, "erreur distance n coord"
NSI – Algorithme ALG
2) La fonction kNN
Les données sont une liste de tuple (ou une liste de liste). Chaque tuple (ou liste) contient les n
caractéristiques.
Exo02*:
Proposer une fonction kNN(pt,donnees,k) permettent de donner une liste contenant le rang des points
dans données des k plus petites distances euclidiennes entre le point pt et les points contenus dans
donnees (chaque point est un tuple ou une liste de longeur n).
Vous devez vous servir de la fonction distEuclid établi précédemment.
Aide : sorted([variables itérables]) renvoie une liste triée suivant, par défaut, l'élément de rang 0 de chaque élément
de la liste de variable itérable (Un itérable est un objet dont on peut parcourir les valeurs : liste, tuple, dictionnaire, chaîne de caractère, …)
Exemple: sorted([(4,-1,-2),(-2,4,3),(1,2,3)]) renvoie [(-2,4,3),(1,2,3),(4,-1,-2)]
Pour tester cette fonction, on donne :
def test():
La présentation du tableau data sur plusieurs lignes n'est pas
point1=[70,140]
obligatoire mais permet de mieux voir les différents points
point2=[69,136]
data = [ [65.75, 112.99], [71.52,136.49], [69.40,153.03],
[68.22,142.34], [67.79,144.30], [68.70,123.30],
[69.80,141.49], [70.01,136.46], [67.90,112.37],
[66.49,127.45] ]
assert kNN(point1, data, 3)==[6,3,7], "erreur assert1"
assert kNN(point2, data, 5)==[7,1,6,3,4], "erreur assert2"
Cela signifie que
 les 3 plus proches voisins de point1=[70,140] sont les points de data de rang 6, 3 et 7.
 les 5 plus proches voisins de point2=[69,136] sont les points de data de rang 7, 1, 6, 3 et 4.

III- La classification des iris …


En 1935, le botaniste américain Edgar Anderson mesure 4 caractéristiques (longueur et largeur des pétales et
longueur et largeur des sépales) sur 150 iris de 3 espèces différentes (Iris Setosa, Iris Virginica et Iris Versicolor).
Cette base données est connue sous le nom d'Iris de Fischer (car Ronald Fischer, biologiste et statisticien anglais
l'a utilisé en 1936 pour un article scientifique) ou d'Iris d'Anderson. Cette base de données est très devenue un
classique de la classification automatique en apprentissage automatique (machine learning).
Pour simplifier, nous n'allons étudier que 2 caractéristiques la longueur des pétales ("petal_length") et
la largeur des pétales ("petal_width"). Vous trouverez le fichier simplifié ("ALG08_iris.csv") à
bit.ly/3aEc6qX et le fichier original est disponible à bit.ly/3aGvN1a.
L'espèce ("species") est notée 0 pour l'iris Setosa, 1 pour l'iris Virginica et 2 pour l'iris Versicolor.
1) Visualiser les données
Exo03:
Ouvrir le fichier dans un éditeur de texte (comme NotePad++) et dans un tableur (comme Excel ou LibreOfficeCalc),
les séparateurs sont des "," et les valeurs sont en cm)

Exo04:
Saisir le programme Python suivant, l'enregistrer dans le même répertoire que le fichier
"ALG08_iris.csv", l'étudier et le tester (ne pas copier les commentaires)
import pandas
import matplotlib.pyplot as plt # bibliothèque permettant de tracer des graphiques
iris=pandas.read_csv("iris.csv")
x=iris.loc[:,"petal_length"]
y=iris.loc[:,"petal_width"]
lab=iris.loc[:,"species"]
plt.scatter(x[lab == 0],y[lab == 0],color='green',label='setosa') # scatter: nuages de points
plt.scatter(x[lab == 1], y[lab == 1], color='red', label='virginica')
plt.scatter(x[lab == 2], y[lab == 2], color='blue', label='versicolor')
plt.legend() # la légende est affichée grâce à l'attribut "label" noté dans "scatter"
plt.show() # permet l'affichage du graphique
NSI – Algorithme ALG
Exo05:
Afficher des instructions au programme précédent pour faire apparaitre sur le graphique précédent un
point correspondant à un iris "test" dont la longueur des pétales est de 2,5 cm et la largeur est de 0,75 cm.
2) Classification en utilisant les fonctions déjà réalisées
Exo06:
Faire un programme Python permettant de déterminer l'espèce d'un iris dont on entre la longueur des
pétales et la largeur des pétales en cm sous forme d'une liste (exemple : [2.5,0.75])
Aide :
 Fonction kNN réalisée de Exo02
 Programmes de Exo04 et Exo05
 x=iris.loc[:,"petal_length"] #dataframe nommée x contenant les valeurs de la colonne "petal_length"
 y=iris.loc[:,"petal_width"] #dataframe nommée y contenant les valeurs de la colonne "petal_width"
 nouvelle_liste= list(zip(x,y)) #permet de former des tuples de valeurs x, y
Exemple de résultats :
 Pour k = 3 et iris_test=[2.5, 0.75], vous devez trouver "iris Setosa"
 Pour k=5 et iris_test=[2.5, 0.75], vous devez trouver "iris Virginica"
 Pour k=3, 5 ou 7 et iris_test=[5, 1.75], vous devez trouver "iris Versicolor"
3) Classification avec la bibliothèque Scikit Learn
La bibliothèque Python Scikit Learn propose un grand nombre d'algorithmes liés au machine
learning dont l'algorithme des k plus proches voisins kNN.

Exo07 :
Saisir le programme Python suivant, l'enregistrer dans le même répertoire que le fichier
"ALG08_iris.csv", l'étudier et le tester
import pandas
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier
iris=pandas.read_csv("ALG08_iris.csv") #traitement CSV
x=iris.loc[:,"petal_length"]
y=iris.loc[:,"petal_width"]
lab=iris.loc[:,"species"] #fin traitement CSV
longueur=2.5 #valeurs
largeur=0.75
k=3 #fin valeurs
plt.scatter(x[lab == 0], y[lab == 0], color='g', label='setosa') #graphique
plt.scatter(x[lab == 1], y[lab == 1], color='r', label='virginica')
plt.scatter(x[lab == 2], y[lab == 2], color='b', label='versicolor')
plt.scatter(longueur, largeur, color='k')
plt.legend() #fin graphique
d=list(zip(x,y)) #algo knn
model = KNeighborsClassifier(n_neighbors=k)
model.fit(d,lab)
prediction= model.predict([[longueur,largeur]]) #fin algo knn
txt="Résultat : " #Affichage résultat
if prediction[0]==0:
txt=txt+"setosa"
if prediction[0]==1:
txt=txt+"virginica"
if prediction[0]==2:
txt=txt+"versicolor"
plt.text(3,0.5, "largeur : {} cm longueur : {} cm".format(longueur,largeur), fontsize=12)
plt.text(3,0.3, "k : {}".format(k), fontsize=12)
plt.text(3,0.1, txt, fontsize=12) #fin affichage résultats
plt.show()
NSI – Algorithme ALG
Explications :
 KNeighborsClassifier est une méthode issue de la bibliothèque scikit-learn qui prend en paramètre le
modèle choisi (Ici le nombre de "plus proches voisins" : model = KNeighborsClassifier(n_neighbors=k))
 model.fit(d, lab) permet d'associer les tuples présents dans la liste d avec les labels (0 : "iris setosa", 1 :
"iris virginica" ou 2 : "iris versicolor"). Par exemple le premier tuple de la liste d, (1.4, 0.2) est associé au premier label de la liste lab
(0), et ainsi de suite...

 La ligne prediction= model.predict([[longueur,largeur]]) permet d'effectuer une prédiction


pour un couple [longueur, largeur] (dans l'exemple ci-dessus "longueur=2.5" et "largeur=0.75").
La variable prediction contient alors le label trouvé par l'algorithme kNN.
Attention : prediction est une liste qui contient un seul élément (le label), il est donc nécessaire d'écrire
prediction[0] afin d'obtenir le label.

Vous aimerez peut-être aussi