K plus proches voisins
L'algorithme des "k plus proches voisins" (en anglais "k nearest neighbors" : knn)
Afin de travailler sur un exemple, nous allons utiliser un jeu de données relativement connu dans le monde du machine learning : le jeu de données "iris".
En 1936, Edgar Anderson a collecté des données sur 3 espèces d'iris : "iris setosa", "iris virginica" et "iris versicolor"
Iris Setosa⚓︎

Iris Virginica⚓︎

Iris Versicolor⚓︎

Pour chaque iris étudié, Anderson a mesuré (en cm) :
-
la largeur des sépales
-
la longueur des sépales
-
la largeur des pétales
-
la longueur des pétales
Par souci de simplification, nous nous intéresserons uniquement à la largeur et à la longueur des pétales.
Pour chaque iris mesuré, Anderson a aussi noté l'espèce ("iris setosa", "iris versicolor" ou "iris virginica")
Vous trouverez 50 de ces mesures dans le fichier iris.csv
En résumé, vous trouverez dans ce fichier :
-
la longueur des pétales
-
la largeur des pétales
-
l'espèce de l'iris (au lieu d'utiliser les noms des espèces, on utilisera des chiffres : 0 pour "iris setosa", 1 pour "iris versicolor" et 2 pour "iris virginica")

Nous pouvons représenter les données à l'aide du module Pandas :
Voici ce que l'on obtient :

Graphisme sans les modules pandas et csv⚓︎
Pour s'entrainer, notamment avec la méthode split(',') qui sépare une chaîne de caractères à chaque virgule.
Chacune des lignes sera séparée en 3 chaînes qui seront ensuite converties en flottants.
Après avoir télécharger le fichier, complétez le code suivant pour obtenir les nuages de points.
Nous obtenons des "nuages" de points, on remarque ces points sont regroupés par espèces d'iris (pour "iris virginica" et "iris versicolor", les points ont un peu tendance à se mélanger).
Imaginez maintenant qu'au cours d'une promenade vous trouviez un iris, n'étant pas un spécialiste, il ne vous est pas vraiment possible de déterminer l'espèce.
En revanche, vous êtes capables de mesurer la longueur et la largeur des pétales de cet iris. Partons du principe qu'un pétale fasse 0,5 cm de large et 2 cm de long.
Plaçons cette nouvelle donnée sur notre graphique (il nous suffit d'ajouter la ligne "plt.scatter(2.0, 0.5, color='k')", le nouveau point va apparaitre en noir (color='k')) :

Je pense que le résultat est sans appel : il y a de fortes chances que votre iris soit de l'espèce "iris setosa".
Il est possible de rencontrer des cas plus difficiles, par exemple : largeur du pétale = 0,75 cm ; longueur du pétale = 2,5 cm :

Dans ce genre de cas, il peut être intéressant d'utiliser l'algorithme des "k plus proches voisins", en quoi consiste cet algorithme :
-
on calcule la distance entre notre point (largeur du pétale = 0,75 cm ; longueur du pétale = 2,5 cm) et chaque point issu du jeu de données "iris" (à chaque fois c'est un calcul de distance entre 2 points tout ce qu'il y a de plus classique)
-
on sélectionne uniquement les k distances les plus petites (les k plus proches voisins)
-
parmi les k plus proches voisins, on détermine quelle est l'espèce majoritaire. On associe à notre "iris mystère" cette "espèce majoritaire parmi les k plus proches voisins"
Prennons k = 3

Les 3 plus proches voisins sont signalés ci-dessus avec des flèches : nous avons deux "iris setosa" (point vert) et un "iris versicolor" (point rouge).
D'après l'algorithme des "k plus proches voisins", notre "iris mystère" appartient à l'espèce "setosa".
Importance du bon choix de k⚓︎
Le choix de la bonne valeur de k est important pour de meilleurs résultats :
-
Une valeur de
ktrop petite peu renforcer l'iportance des valeurs "anormales" de la série de référence -
Une valeur de
ktrop grande inclus des valeurs dont la similitude n'est plus justifiée.
On conseille de prendre k entre 3 et 10.
Code de l'algorithme KNN⚓︎
On souhaite écrire le code de la fonction knn qui prend en argumant la longueur l, largeur w d'un iris inconnu ainsi que le choix du nombre de voisins k utilisé pour la détermination et qui retourne la catégorie supposée de l'iris.
On utilise la fonction annexe distance qui retourne la distance euclidienne entre deux points de coordonnées respectives (x1,y1) et (x2,y2).
Dans le code suivant on dispose d'une variable iris qui contient une liste de 150 tuples au format (l,w,s) longueur l, largeur w et espece s des 150 iris de réféence.
Améliorations possibles :
-
La fonction distance euclidienne peut être remplacée par la distance de Manhattan ou alors en ne calculant pas la racine carrée, on ne change pas l'ordre pour les distances
-
plutôt sur de trier toute la liste des couples, on peut la parcourir et ne mémoriser à chaque itération que le
kvaleur les plus petites. Cela améliore la compléxité d'autant plus que le rapportk/ taille de la série est faible.
# Tests(insensible Ă la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)