I. Die Entfernungsmetrik
Erstens ist die Anzahl der Merkmale (Spalten) in einem Datensatz kein Faktor bei der Auswahl einer Abstandsmetrik zur Verwendung in kNN. Es gibt einige veröffentlichte Studien, die sich genau mit dieser Frage befassen, und die üblichen Vergleichsgrundlagen sind:
die zugrunde liegende statistische Verteilung Ihrer Daten;
die Beziehung zwischen den Merkmalen, aus denen Ihre Daten bestehen (sind sie unabhängig - dh wie sieht die Kovarianzmatrix aus); und
Der Koordinatenraum, aus dem Ihre Daten stammen.
Wenn Sie keine vorherige Kenntnis der Verteilung haben (s) , von dem die Daten abgetastet wurden, mindestens ein (gut dokumentiert und gründlich) Studie kommt zu dem Schluss , dass euklidischer Abstand die beste Wahl ist.
YEuklidische Metrik, die in Mega-Web-Empfehlungs-Engines sowie in der aktuellen akademischen Forschung verwendet wird. Von Euklidisch berechnete Entfernungen haben eine intuitive Bedeutung und die Berechnungsskalen - dh die euklidische Entfernung wird auf dieselbe Weise berechnet, unabhängig davon, ob sich die beiden Punkte in zwei Dimensionen oder im Raum mit zweiundzwanzig Dimensionen befinden.
Es ist für mich nur ein paar Mal gescheitert, jeder dieser Fälle ist fehlgeschlagen, weil das zugrunde liegende (kartesische) Koordinatensystem eine schlechte Wahl war. Und Sie werden dies normalerweise erkennen, weil beispielsweise Pfadlängen (Entfernungen) nicht mehr additiv sind - z. B. wenn der metrische Raum ein Schachbrett ist, ist die Manhattan-Entfernung besser als die euklidische, ebenso wenn der metrische Raum Erde ist und Ihre Entfernungen trans sind -Kontinentalflüge, eine für ein Polarkoordinatensystem geeignete Entfernungsmetrik ist eine gute Idee (z. B. London nach Wien dauert 2,5 Stunden, Wien nach St. Petersburg weitere 3 Stunden, mehr oder weniger in die gleiche Richtung, London nach St. Petersburg ist nicht 5,5 Stunden, sondern etwas mehr als 3 Stunden.)
Abgesehen von den Fällen, in denen Ihre Daten zu einem nicht kartesischen Koordinatensystem gehören, ist die Wahl der Entfernungsmetrik normalerweise nicht wesentlich. (Siehe diesen Blog-Beitrag eines CS-Studenten, in dem verschiedene Entfernungsmetriken verglichen werden, indem ihre Wirkung auf den kNN-Klassifikator untersucht wird. Das Chi-Quadrat liefert die besten Ergebnisse, aber die Unterschiede sind nicht groß. Eine umfassendere Studie finden Sie in der wissenschaftlichen Arbeit Comparative Study of Entfernungsfunktionen für die nächsten Nachbarn - Mahalanobis (im Wesentlichen euklidisch normalisiert durch, um die Dimensionskovarianz zu berücksichtigen) war die beste in dieser Studie.
Eine wichtige Voraussetzung: Damit Entfernungsmetrikberechnungen aussagekräftig sind, müssen Sie neu skalierenIhre Daten - selten ist es möglich, ein kNN-Modell zu erstellen, um genaue Vorhersagen zu generieren, ohne dies zu tun. Wenn Sie beispielsweise ein kNN-Modell erstellen, um die sportliche Leistung vorherzusagen, und Ihre Erwartungsvariablen Größe (cm), Gewicht (kg), Körperfett (%) und Ruhepuls (Schläge pro Minute) sind, kann dies ein typischer Datenpunkt sein sehen ungefähr so aus: [180.4, 66.1, 11.3, 71]. Es ist klar, dass die Entfernungsberechnung von der Höhe dominiert wird, während der Beitrag von Körperfett% fast vernachlässigbar sein wird. Anders ausgedrückt: Wenn stattdessen die Daten anders angegeben würden, sodass das Körpergewicht in Gramm statt in Kilogramm angegeben würde, wäre der ursprüngliche Wert von 86,1 86.100, was einen großen Einfluss auf Ihre Ergebnisse hätte, und genau das tun Sie will nicht.
X_new = (X_old - mu) / sigma
II. Die Datenstruktur
Wenn Sie sich Gedanken über die Leistung der kd-Baumstruktur machen, ist A Voronoi Tessellation ein konzeptionell einfacher Container, der jedoch die Leistung drastisch verbessert und besser skaliert als kd-Bäume.
Dies ist nicht die gebräuchlichste Methode, um kNN-Trainingsdaten beizubehalten, obwohl die Anwendung von VT für diesen Zweck sowie die daraus resultierenden Leistungsvorteile gut dokumentiert sind (siehe z. B. diesen Microsoft Research-Bericht ). Die praktische Bedeutung davon ist, dass Sie, vorausgesetzt Sie verwenden eine 'Mainstream'-Sprache (z. B. im TIOBE-Index ), eine Bibliothek finden sollten, um VT durchzuführen. Ich weiß, dass es in Python und R für jede Sprache mehrere Optionen gibt (z. B. das auf CRAN verfügbare Voronoi- Paket für R ).
Die Verwendung eines VT für kNN funktioniert folgendermaßen:
Wählen Sie aus Ihren Daten zufällig w Punkte aus - dies sind Ihre Voronoi-Zentren. Eine Voronoi-Zelle kapselt alle benachbarten Punkte, die jedem Zentrum am nächsten liegen. Stellen Sie sich vor, Sie weisen jedem Voronoi-Zentrum eine andere Farbe zu, sodass jeder Punkt, der einem bestimmten Zentrum zugewiesen ist, in dieser Farbe gezeichnet wird. Solange Sie eine ausreichende Dichte haben, werden auf diese Weise die Grenzen jedes Voronoi-Zentrums gut angezeigt (als die Grenze, die zwei Farben trennt.
Wie wähle ich die Voronoi-Zentren aus? Ich benutze zwei orthogonale Richtlinien. Berechnen Sie nach zufälliger Auswahl der w-Punkte die VT für Ihre Trainingsdaten. Überprüfen Sie als Nächstes die Anzahl der Datenpunkte, die jedem Voronoi-Zentrum zugewiesen sind. Diese Werte sollten ungefähr gleich sein (bei gleichmäßiger Punktdichte über Ihren Datenraum). In zwei Dimensionen würde dies eine VT mit Kacheln gleicher Größe verursachen. Dies ist die erste Regel, hier die zweite. Wählen Sie w durch Iteration aus - führen Sie Ihren kNN-Algorithmus mit w als variablem Parameter aus und messen Sie die Leistung (Zeit, die erforderlich ist, um eine Vorhersage durch Abfragen der VT zurückzugeben).
So stellen Sie haben eine Million Datenpunkte ..... Wenn die Punkte in einer gewöhnlichen 2D - Datenstruktur beibehalten wurden, oder in einem kd-Baum, würden Sie im Durchschnitt ein paar Millionen Abstandsberechnungen für führen jedenneue Datenpunkte, deren Antwortvariable Sie vorhersagen möchten. Natürlich werden diese Berechnungen an einem einzelnen Datensatz durchgeführt. Bei einem V / T wird die Suche nach dem nächsten Nachbarn in zwei Schritten nacheinander gegen zwei verschiedene Datenpopulationen durchgeführt - zuerst gegen die Voronoi-Zentren, dann, sobald das nächste Zentrum gefunden ist, entsprechen die Punkte innerhalb der Zelle Diese Zentren werden durchsucht, um den tatsächlichen nächsten Nachbarn zu finden (durch aufeinanderfolgende Entfernungsberechnungen). Zusammen sind diese beiden Suchvorgänge viel schneller als eine einzelne Brute-Force-Suche. Das ist leicht zu erkennen: Angenommen, Sie wählen für 1 Millionen Datenpunkte 250 Voronoi-Zentren aus, um Ihren Datenraum zu tesselieren. Im Durchschnitt hat jede Voronoi-Zelle 4.000 Datenpunkte. Anstatt durchschnittlich 500.000 Entfernungsberechnungen (Brute Force) durchzuführen, führen Sie weitaus weniger aus, im Durchschnitt nur 125 + 2.000.
III. Berechnung des Ergebnisses (der vorhergesagten Antwortvariablen)
Es gibt zwei Schritte zum Berechnen des vorhergesagten Werts aus einem Satz von kNN-Trainingsdaten. Der erste ist die Identifizierung von n oder der Anzahl der nächsten Nachbarn , die für diese Berechnung verwendet werden sollen. Die zweite ist, wie ihr Beitrag zum vorhergesagten Wert gewichtet wird.
Mit der ersten Komponente können Sie den besten Wert von n bestimmen, indem Sie ein Optimierungsproblem lösen (sehr ähnlich der Optimierung der kleinsten Quadrate). Das ist die Theorie; In der Praxis verwenden die meisten Leute nur n = 3. In jedem Fall ist es einfach, Ihren kNN-Algorithmus über eine Reihe von Testinstanzen (um vorhergesagte Werte zu berechnen) für n = 1, n = 2, n = 3 usw. auszuführen und den Fehler als Funktion von n darzustellen. Wenn Sie nur einen plausiblen Wert für n haben möchten, verwenden Sie einfach n = 3.
Die zweite Komponente ist die Gewichtung des Beitrags jedes Nachbarn (unter der Annahme von n> 1).
Die einfachste Gewichtungstechnik besteht darin, jeden Nachbarn mit einem Gewichtungskoeffizienten zu multiplizieren, der nur 1 / (dist * K) ist, oder die Umkehrung des Abstands von diesem Nachbarn zur Testinstanz, häufig multipliziert mit einer empirisch abgeleiteten Konstante K. I. Ich bin kein Fan dieser Technik, weil sie oft die nächsten Nachbarn übergewichtet (und gleichzeitig die entfernteren Nachbarn untergewichtet). Die Bedeutung davon ist, dass eine gegebene Vorhersage fast vollständig von einem einzelnen Nachbarn abhängig sein kann, was wiederum die Empfindlichkeit des Algorithmus gegenüber Rauschen erhöht.
Eine bessere Gewichtungsfunktion, die diese Einschränkung im Wesentlichen vermeidet, ist die Gauß-Funktion , die in Python folgendermaßen aussieht:
def weight_gauss(dist, sig=2.0) :
return math.e**(-dist**2/(2*sig**2))
Um einen vorhergesagten Wert unter Verwendung Ihres kNN-Codes zu berechnen, identifizieren Sie die n nächsten Nachbarn zu dem Datenpunkt, dessen Antwortvariable Sie vorhersagen möchten ('Testinstanz'), und rufen dann die Funktion weight_gauss einmal für jeden der n übergebenen Nachbarn auf in der Entfernung zwischen jedem Nachbarn der Testpunkt. Diese Funktion gibt das Gewicht für jeden Nachbarn zurück, das dann als Koeffizient dieses Nachbarn in der Berechnung des gewichteten Durchschnitts verwendet wird.