Table des matières
KNN : problème du calcul de distance
Dans le cas des iris, toutes les mesures sont en cm et ont la même unité. Le calcul de distance ne pose donc pas de problème. Mais est-il bien raisonnable de faire un calcul de distance avec des axes qui représentent des quantités totalement différentes, dans des unité différentes ?
Exemple
Voici un exemple pour illustrer ce problème : Prenons 3 hommes.
- A mesure 1m80 et a 36 ans
- B mesure 1m85 et a 38 ans
- C mesure 1m78 et a 40 ans
entre B et C, qui est le plus proche de A ?
- si on mesure en mètres, A(1.8,36) B(1.85,38) C(1.78,40) et le calcul donne AB < AC
- si on mesure en mm, A(1800,36) B(1850,38) C(1780,40) et le calcul donne AB > AC
Cela montre qu'il faudra peut-être choisir une échelle de mesure adaptée car les données brutes peuvent conduire à surestimer, ou sous-estimer, des distances.
Normaliser
Une technique classique pour contourner le problème précédent est de normaliser les grandeurs.
En effet l'unité de mesure que l'on choisit n'a rien de naturel. Elle ne devrait pas avoir d'effet sur le problème. On voudrait trouver une échelle plus naturelle.
Par exemple, comment savoir si un homme de 1m73 est grand ? On ne peut pas le savoir sans connaissance de la population :
- Au XVIIe siècle, cet homme est grand par rapport à la moyenne de son temps,
- Aujourd'hui, si c'est un Français, il est de taille moyenne,
- Si c'est un Danois, il est plus petit que la moyenne.
Les paramètres statistiques, moyenne et écart-type, donne des unités plus naturelles.
Par exemple, si une fois normalisée, la taille de l'homme est 2, j'en déduis qu'il a une taille de 2 écart-type au-dessus de la moyenne. Il est donc très grand.
Pour normaliser notre base, on pourra donc soustraire la moyenne puis diviser par l'écart-type.
Avec Pandas
Pandas permet de faire tout cela très vite.
Supposons que les données de ces hommes soient dans un dataframe Pandas data et que nous voulions normaliser la colonne "taille".
Sur chaque valeur taille de la colonne, nous voulons la remplacer par (taille - m)/std où m et std sont la moyenne et l'écart-type (standard deviation).
Le calcul est immédiat :
m = data['taille'].mean() std = data['taille'].std() data['taille'] = (data['taille'] - m)/std
Dans ce caclul, m est une float alors que data['taille'] est une sorte de tableau. Comment peut-on alors calculer data['taille'] - m ? C'est une particularité des dataframes Pandas qui reprennent les tableaux Numpy : le calcul sera automatiquement appliqué à chaque item. Cela signifie que ce calcul contient une boucle for cachée qui s'exécute sur chaque item de la colonne. Cette boucle for est optimisée et s'exécute très vite.
