I. La métrique de la distance
Tout d'abord, le nombre de caractéristiques (colonnes) dans un ensemble de données n'est pas un facteur dans la sélection d'une métrique de distance à utiliser dans kNN. Il existe un grand nombre d'études publiées portant précisément sur cette question, et les bases habituelles de comparaison sont les suivantes :
-
la distribution statistique sous-jacente distribution de vos données ;
-
la relation entre les caractéristiques qui composent vos données (sont-elles indépendantes - c'est-à-dire, à quoi ressemble la matrice de covariance) ; et
-
l'espace de coordonnées à partir duquel vos données ont été obtenues.
Si vous n'avez aucune connaissance préalable de la (des) distribution(s) à partir de laquelle (desquelles) vos données ont été échantillonnées, au moins un (bien documenté et approfondi) étude conclut que la distance euclidienne est le meilleur choix.
Métrique YEuclidienne utilisée dans les moteurs de recommandation Web à grande échelle ainsi que dans la recherche universitaire actuelle. Les distances calculées par la métrique euclidienne ont une signification intuitive et le calcul est échelonné - c'est-à-dire que la distance euclidienne est calculée de la même manière, que les deux points soient dans un espace à deux dimensions ou à vingt-deux dimensions.
Il n'a échoué pour moi qu'à quelques reprises, à chaque fois la distance euclidienne a échoué parce que le système de coordonnées (cartésien) sous-jacent était un mauvais choix. Et vous vous en rendrez généralement compte parce que, par exemple, les longueurs de chemin (distances) ne sont plus additives - par exemple, lorsque l'espace métrique est un échiquier, la distance de Manhattan est meilleure que la distance euclidienne, de même lorsque l'espace métrique est la Terre et que vos distances sont des vols transcontinentaux, une métrique de distance adaptée à un système de coordonnées polaires est une bonne idée (par exemple, Londres à Vienne est 2,5 heures, Vienne à Saint-Pétersbourg est 3 heures de plus, plus ou moins dans la même direction, mais Londres à Saint-Pétersbourg n'est pas 5,5 heures, mais un peu plus de 3 heures).
Mais en dehors des cas où vos données appartiennent à un système de coordonnées non cartésien, le choix de la métrique de distance n'est généralement pas important. (Voir cette article de blog d'un étudiant en informatique, comparant plusieurs mesures de distance en examinant leur effet sur le classificateur kNN - le carré de chi donne les meilleurs résultats, mais les différences ne sont pas importantes ; une étude plus complète se trouve dans l'article universitaire, Étude comparative des fonctions de distance pour les plus proches voisins --Mahalanobis (essentiellement Euclidien normalisé par pour tenir compte de la covariance des dimensions) était le meilleur dans cette étude.
Une réserve importante : pour que les calculs de la distance métrique soient significatifs, vous devez redimensionner vos données - il est rarement possible de construire un modèle kNN pour générer des prédictions précises sans faire cela. Par exemple, si vous construisez un modèle kNN pour prédire les performances athlétiques, et que vos variables d'attente sont la taille (cm), le poids (kg), la graisse corporelle (%) et le pouls au repos (battements par minute), alors un point de données typique pourrait ressembler à ceci : [ 180.4, 66.1, 11.3, 71 ]. Il est clair que le calcul de la distance sera dominé par la taille, tandis que la contribution du pourcentage de graisse corporelle sera presque négligeable. En d'autres termes, si les données étaient rapportées différemment, de manière à ce que le poids corporel soit exprimé en grammes plutôt qu'en kilogrammes, la valeur originale de 86,1 deviendrait 86,100, ce qui aurait un effet important sur vos résultats, ce qui est exactement ce que vous ne voulez pas. La technique de mise à l'échelle la plus courante consiste probablement à soustraire la moyenne et à la diviser par l'écart type (la moyenne et l'écart type sont calculés séparément pour chaque colonne ou élément de cet ensemble de données ; X désigne une entrée/cellule individuelle dans une ligne de données) :
X_new = (X_old - mu) / sigma
II. La structure des données
Si vous êtes préoccupé par les performances de la structure kd-tree, A Tessellation de Voronoï est un conteneur simple d'un point de vue conceptuel, mais qui améliore considérablement les performances et s'adapte mieux que les kd-Trees.
Ce n'est pas la façon la plus courante de conserver les données d'entraînement des kNN, bien que l'application de la VT à cette fin, ainsi que les avantages de performance qui en découlent, soient bien documentés (voir, par exemple, l'article suivant Rapport de Microsoft Research ). En pratique, cela signifie que, si vous utilisez un langage "courant" (par exemple, dans le cadre de l Indice TIOBE ), vous devriez trouver une bibliothèque pour effectuer le VT. Je sais qu'en Python et R, il y a plusieurs options pour chaque langage (par exemple, la librairie voronoï pour R disponible sur CRAN )
L'utilisation d'un VT pour kNN fonctionne comme suit : :
À partir de vos données, sélectionnez au hasard w points - ce sont vos centres de Voronoï. Une cellule de Voronoï englobe tous les points voisins qui sont les plus proches de chaque centre. Imaginez que vous attribuiez une couleur différente à chacun des centres de Voronoï, de sorte que chaque point attribué à un centre donné soit peint de cette couleur. Tant que la densité est suffisante, cette méthode permet de faire apparaître les limites de chaque centre de Voronoï (comme la limite qui sépare deux couleurs).
Comment sélectionner les centres de Voronoï ? J'utilise deux directives orthogonales. Après avoir sélectionné aléatoirement les points w, calculez le VT pour vos données d'entraînement. Vérifiez ensuite le nombre de points de données attribués à chaque centre de Voronoï - ces valeurs devraient être à peu près identiques (étant donné la densité uniforme des points dans votre espace de données). En deux dimensions, cela donnerait un VT avec des tuiles de la même taille.c'est la première règle, voici la seconde. Sélectionnez w par itération - exécutez votre algorithme kNN avec w comme paramètre variable, et mesurez la performance (temps nécessaire pour retourner une prédiction en interrogeant le VT).
Imaginons donc que vous ayez un million de points de données...... Si les points étaient conservés dans une structure de données 2D ordinaire, ou dans un arbre kd, vous effectueriez en moyenne quelques millions de calculs de distance pour les points suivants chaque de nouveaux points de données dont vous souhaitez prédire la variable de réponse. Bien entendu, ces calculs sont effectués sur un seul ensemble de données. Avec un V/T, la recherche du plus proche voisin est effectuée en deux étapes, l'une après l'autre, sur deux populations de données différentes : d'abord sur les centres de Voronoï, puis une fois le centre le plus proche trouvé, les points à l'intérieur de la cellule correspondant à ce centre sont recherchés pour trouver le plus proche voisin réel (par des calculs de distance successifs). C'est facile à voir : pour 1M de points de données, supposons que vous sélectionniez 250 centres de Voronoï pour tesseler votre espace de données. En moyenne, chaque cellule de Voronoï comportera 4 000 points de données. Ainsi, au lieu d'effectuer en moyenne 500 000 calculs de distance (force brute), vous en effectuez beaucoup moins, en moyenne seulement 125 + 2 000.
III. Calcul du résultat (la variable de réponse prédite)
Le calcul de la valeur prédite à partir d'un ensemble de données de formation kNN se fait en deux étapes. La première consiste à identifier n, ou le nombre de voisins les plus proches à utiliser pour ce calcul. Le second est comment pondérer leur contribution à la valeur prédite.
Pour la première composante, vous pouvez déterminer la meilleure valeur de n en résolvant un problème d'optimisation (très similaire à l'optimisation par les moindres carrés). C'est la théorie ; en pratique, la plupart des gens utilisent simplement n=3. Quoi qu'il en soit, il est simple d'exécuter votre algorithme kNN sur un ensemble d'instances de test (pour calculer les valeurs prédites) pour n=1, n=2, n=3, etc. et de tracer l'erreur en fonction de n. Si vous souhaitez simplement une valeur plausible pour n pour commencer, utilisez n = 3.
La deuxième composante est la manière de pondérer la contribution de chacun des voisins (en supposant que n > 1).
La technique de pondération la plus simple consiste à multiplier chaque voisin par un coefficient de pondération, qui est juste le 1/(dist * K), ou l'inverse de la distance entre ce voisin et l'instance de test, souvent multiplié par une constante empirique, K. Je ne suis pas un fan de cette technique parce qu'elle surpondère souvent les voisins les plus proches (et sous-pondère concomitamment les plus éloignés) ; la signification de ceci est qu'une prédiction donnée peut dépendre presque entièrement d'un seul voisin, ce qui augmente la sensibilité de l'algorithme au bruit.
Une fonction de pondération nettement meilleure, qui évite sensiblement cette limitation, est la fonction de pondération suivante fonction gaussienne qui, en python, ressemble à ceci :
def weight_gauss(dist, sig=2.0) :
return math.e**(-dist**2/(2*sig**2))
Pour calculer une valeur prédite à l'aide de votre code kNN, vous devez identifier les n voisins les plus proches du point de données dont vous souhaitez prédire la variable de réponse ("instance de test"), puis appeler la fonction weight_gauss, une fois pour chacun des n voisins, en indiquant la distance entre chaque voisin et le point de test.
1 votes
Essayez de demander sur metaoptimize.com
4 votes
"Haute dimension" signifie 20 pour certaines personnes et certaines données, 50 ou 100 ou 1000 pour d'autres. Veuillez donner des chiffres si vous le pouvez, par exemple : "J'ai fait dim 21, 1000000 points de données, en utilisant xx".
0 votes
KD-Tree divise les données en deux selon une seule dimension à la fois. Si vous avez 20 dimensions et seulement 1M de points de données, vous obtenez environ 1 niveau d'arbre - où le niveau signifie la division sur chaque axe. Comme il n'y a pas de profondeur réelle, vous ne bénéficiez pas de l'avantage d'ignorer les branches de l'arbre. Il est utile de ne pas trop penser à un arbre binaire, mais plutôt à un arbre quadruple, octuple, etc. même s'il est implémenté comme un arbre binaire.
0 votes
@denis, est-ce que 'dim 21, 1000000 points de données' était pour le jeu de données de Higgs ?
0 votes
@nikk, non, je viens de l'inventer. Pouvez-vous indiquer des données réelles en ligne ? Ce serait utile pour les programmes et les personnes de NN.
1 votes
Voici le lien pour télécharger l'ensemble de données sur le boson de Higgs. 11 millions d'observations avec 28 attributs. La dernière colonne est l'étiquette : 1 pour le signal, zéro pour le bruit. archive.ics.uci.edu/ml/datasets/HIGGS
0 votes
J'ai eu un problème similaire. J'ai utilisé l'ANN mais l'approximation n'était pas suffisante pour moi. J'ai utilisé l'algorithme KNN bruteforce sur GPU.
0 votes
Je vote pour clore cette question parce que Les questions sur la théorie de l'apprentissage automatique (ML) sont hors sujet sur Stack Overflow - candidat à l'emballage cadeau pour le Cross-Validated