Wiederholte Berechnung des nächsten Nachbarn für Millionen von Datenpunkten zu langsam


14

Ich habe einen Datensatz, der in Millionen von Datenpunkten in 3D läuft. Für die Berechnung, die ich mache, muss ich Nachbarn (Entfernungssuche) für jeden Datenpunkt in einem Radius berechnen, versuchen, eine Funktion anzupassen, den Fehler für die Anpassung berechnen, dies für den nächsten Datenpunkt wiederholen und so weiter. Mein Code funktioniert einwandfrei, die Ausführung dauert jedoch sehr lange, etwa 1 Sekunde pro Datenpunkt! Dies liegt wahrscheinlich daran, dass für jeden Punkt der gesamte Datensatz durchsucht werden muss. Gibt es eine Möglichkeit, den Prozess zu beschleunigen? Ich habe die Idee, dass, wenn ich irgendwie eine Nachbarschaftsbeziehung zwischen den ersten Nachbarn herstellen kann, dies weniger langsam sein kann. Wenn es hilft, versuche ich, die optimale Parzen-Fensterbreite in 3D zu finden.

Antworten:


9

Ich würde vorschlagen, nach begrenzten Volume-Hierarchien zu googeln (insbesondere nach BSP-Bäumen). Unter Berücksichtigung Ihrer Punktwolke können Sie eine Ebene finden, die diese in zwei gleiche Teilwolken aufteilt. Wenn Sie dann die Ansammlung von Punkten finden müssen, die sich innerhalb eines Radius R eines Testpunkts befinden, können Sie Ihren Testpunkt zunächst mit dieser Ebene vergleichen. Wenn die Höhe darüber mehr als R beträgt, dann die gesamte Teilwolke unter der Ebene muss auch weiter entfernt sein als R (daher müssen Sie keinen dieser Punkte überprüfen). Sie können diese Idee auch rekursiv anwenden, was letztendlich zu n log n-Typ-Komplexitäten anstelle von n-Quadrat führt. (Dies ist BSP / Binary Space Partitioning,


7

Es gibt verschiedene Datenstrukturen zum Speichern von Daten, bei denen Informationen über Position und Nähe erhalten bleiben. dort durch Ermöglichen einer schnellen Bestimmung des nächsten Nachbarn.

Insbesondere R-Bäume (und spezielle Formen wie R * -Bäume ) und X-Bäume . Viele Optionen, die für leicht unterschiedliche Verwendungszwecke optimiert sind.

Die Wahl eines R * -Baums anstelle einer naiven Suche nach dem nächsten Nachbarn war ein großer Teil meiner Bemühungen, einen Faktor von 10000 aus einem bestimmten Code herauszuholen. (OK, vielleicht ein paar hundert davon war die R * -Baum, die meisten der Rest war , weil der naive Nachschau schlecht so codiert worden war , dass sie den Cache zertrümmert. :: seufzen :: )

Ö(NLogN)NÖ(LogN)


5

Dies ist einer der größten Herausforderungen auf dem Gebiet der Molekulardynamik sehr ähnlich - der Berechnung aller paarweisen Wechselwirkungen zwischen nicht gebundenen Partikeln.

Dort verwenden wir Zelllisten (oder Nachbarlisten ), um herauszufinden, was in der Nähe ist. Für diese Anwendung ist die Zellenliste wahrscheinlich der am einfachsten zu verwendende Algorithmus:

  • Teilen Sie die Box in eine Reihe von Zellen.
  • Bestimmen Sie für jedes Partikel, welcher Zelle es zugewiesen werden soll (O (1) pro Partikel).
  • Überprüfen Sie dann für jedes Partikel die "eigene" Zelle und die Nachbarzellen. Wenn eine davon belegt ist, ist keine weitere Suche erforderlich.
  • Wenn alle nächsten Nachbarn leer sind, erweitern Sie sie zu den nächsten Nachbarn usw., bis ein Partikel gefunden wird.

Wenn Ihr System eine mehr oder weniger gleichmäßige Partikelverteilung aufweist, werden die Kosten Ihres Algorithmus entsprechend der Grobheit des Gitters erheblich gesenkt. Es ist jedoch eine Feinabstimmung erforderlich: Wenn Sie ein zu grobes Raster verwenden, sparen Sie nicht viel Zeit. zu fein, und Sie werden viel Zeit damit verbringen, über leere Gitterzellen zu radeln!


Sie sollten darauf hinweisen, dass die Zellenkantenlänge mindestens dem Suchradius oder, wenn jedes Partikel einen eigenen Suchradius hat, dem maximalen Radius entsprechen sollte.
Pedro

Das stimmt im MD-Fall; hier wissen wir nicht, was dieser Radius von vornherein ist .
Aeismail

Ein ähnliches Schema wurde lange Zeit in Simulationen der Partikelwolkengravitation in großem Maßstab angewendet. Ich weiß nicht, ob es noch zum Stand der Technik gehört.
dmckee

4

Sie sollten auf jeden Fall KD-Bäume überprüfen und Octrees die die Methode der Wahl für Punktmengen sind (während BSPs für allgemeine Objekte und Gitter für mehr oder weniger gleichmäßige Dichten gelten). Sie können sehr kompakt und schnell sein, den Speicher- und Rechenaufwand minimieren und sind einfach zu implementieren.

Wenn Ihre Punkte mehr oder weniger gleichmäßig verteilt sind (auch bei leeren Bereichen, es darf jedoch keine Dichte-Singularität oder andere hohe Konzentration geben), überprüfen Sie die Kugelpackungen, wenn Sie eine gitterartige, nicht hierarchische Raumunterteilung versuchen möchten.


3

Sie sollten sich wahrscheinlich überlegen, die Delaunay-Triangulation zu erstellen (nun, ihre 3D-Analogie). In 2D ist dies eine spezielle Triangulation der Datenpunkte, die immer den nächsten Nachbarn enthält. Das gleiche gilt in 3D, aber mit Tetraedern.

Sie können die Triangulation ein für alle Mal erstellen und dann direkt in der Triangulation nach dem nächsten Nachbarn suchen. Ich denke, dass es einige gute Algorithmen gibt, um die Triangulation zu erstellen: In 2D befindet sich die Konstruktion der Triangulation innLog(n) und die spätere Suche nach dem nächsten Nachbarn ist in der Anzahl der Datenpunkte linear.

Ich hoffe es hilft!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.