Effiziente und genaue Berechnung der euklidischen Distanz
Folgenden einige online-Forschung (Eins, Zwei, numpy, scipy, scikit, Mathematik), ich habe Wege gefunden, das für die Berechnung der euklidische Distanz in Python:
# 1
numpy.linalg.norm(a-b)
# 2
distance.euclidean(vector1, vector2)
# 3
sklearn.metrics.pairwise.euclidean_distances
# 4
sqrt((xa-xb)^2 + (ya-yb)^2 + (za-zb)^2)
# 5
dist = [(a - b)**2 for a, b in zip(vector1, vector2)]
dist = math.sqrt(sum(dist))
# 6
math.hypot(x, y)
Ich Frage mich, wenn jemand könnte einen Einblick, auf welche der oben genannten (oder jede andere, die ich noch nicht gefunden) gilt als das beste in Bezug auf Effizienz und Präzision. Wenn jemand Kenntnis über Ressource(N), der diskutiert, das Thema, das wäre auch toll.
Den Kontext ich bin interessant ist bei der Berechnung der euklidischen Distanz zwischen Paaren von Anzahl-Tupel, z.B. der Abstand zwischen (52, 106, 35, 12)
und (33, 153, 75, 10)
.
- Vergessen Sie nicht, den integrierten
math.hypot()
. Können Sie leicht testen Sie die Geschwindigkeit mit dertimeit
- Modul. - Toller Vorschlag, hatte keine Ahnung, dass so eine integrierte Methode existiert! (bearbeitet meine Frage, es aufzunehmen)
- Mögliche Einschränkung mit
math.hypot()
ist, dass es macht nur 2D-Vektoren, in der Erwägung, dass viele der anderen, die Sie erwähnen, behandeln können Vektoren von 3 oder mehr Dimensionen. Auf der anderen Seite, wenn alles, was Sie tun, ist 2D, die nicht-generalisierte gebaut-vielleicht haben Sie einen speed-Vorteil. - Interessant VORBEHALT, obwohl es für meinen Fall kann es ideal sein. Möglicherweise naive Frage: bei der Berechnung der euklidischen Distanz zwischen
(52, 106, 35, 12)
und(33, 153, 75, 10)
sind die zwei 4D-Vektoren?? - Alles hängt davon ab, wie man Sie zu interpretieren in das Programm. Konnte zwei 4D-Vektoren oder vier 2D-Vektoren...der ehemalige scheint wahrscheinlich — ich kann nicht sagen, aus deinem Beispiel-code.
- Nun, alles, was mich interessiert ist der Vergleich der euklidischen Distanz der
x1
mity1
,x2
mity2
etc., wo(x1, x2, x3, x4)
und(y1, y2, y3, y4)
. Und ich kann mehr als 4 Werte auf den Tupeln. Könnten Sie mir bitte helfen zu verstehen, was Art von dimension, Vektoren, die ich brauche? - Gute news, das was du beschrieben hast sind drei 2D-Vektoren zwischen den 4 Punkten, die
math.hypot()
und Griff in Ordnung. - Nicht du meinst zwei 2D-Vektoren zwischen den 4 Punkten?
- Nein, ich meinte den drei 2D-Vektoren definiert, die von den Paaren von Endpunkten zwischen (52,33) und (106,153), (106,153) und (35,75), plus (35,75) und (12,10). Vielleicht sollten Sie Bearbeiten Ihre Frage und zeigen die gewünschten Ergebnisse.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Fazit zuerst:
Vom test-Ergebnis mit
timeit
für Effizienz-test, können wir schließen, dass in Bezug auf die Effizienz:Method5 (zip, math.sqrt)
>Method1 (numpy.linalg.norm)
>Method2 (scipy.spatial.distance)
>Method3 (sklearn.metrics.pairwise.euclidean_distances )
Während ich nicht wirklich testen Sie Ihre
Method4
wie es ist nicht geeignet für Allgemeine Fälle und es ist im Allgemeinen äquivalent zuMethod5
.Für den rest, ganz überraschend,
Method5
ist das Schnellste. Während fürMethod1
verwendetnumpy
als das, was wir erwartet haben, die stark optimiert in C, ist die zweite Schnellste.Für
scipy.spatial.distance
, wenn Sie gehen direkt auf die definition der Funktion, werden Sie sehen, dass es tatsächlich mitnumpy.linalg.norm
, außer es wird die Validierung auf die beiden input-Vektoren vor der eigentlichennumpy.linalg.norm
. Deswegen ist es etwas langsamer thantnumpy.linalg.norm
.Schließlich für
sklearn
, laut der Dokumentation:Da in Ihrer Frage, die Sie verwenden möchten, um einen festen Satz von Daten, der Vorteil dieser Implementierung ist, nicht reflektiert. Und aufgrund der trade-off zwischen der Leistung und Präzision, es gibt auch die schlechteste Präzision zwischen den Methoden.
Hinsichtlich der Genauigkeit,
Method5
=Metho1
=Method2
>Method3
Effizienz-Test-Skript:
Effizienz-Test-Ausgabe:
Präzisions-mess-Skript & Ergebnis:
math.hypot()
. (Die OP ist mit Python 3, BTW).math.hypot()
das wäre erstaunlich. Vor allem, da ich bisher noch nie verwendet habe/davon gehört.Dies ist nicht genau die Frage zu beantworten, aber es ist wohl erwähnenswert, dass, wenn Sie nicht daran interessiert sind, die tatsächliche euklidische Distanz, sondern wollen einfach nur, um zu vergleichen euklidischen Entfernungen gegen einander, Quadratwurzeln sind monotone Funktionen, d.h. x**(1/2) < y**(1/2) wenn und nur wenn x < y.
Also, wenn Sie nicht wollen, dass die explizite Entfernung, sondern zum Beispiel einfach nur wissen wollen, ob der euklidische Abstand von vector1 ist näher an eine Liste von Vektoren, genannt vectorlist, können Sie vermeiden, die teuer sind (sowohl in Bezug auf Präzision und Zeit) square root, aber können Sie mit so etwas wie
min(vectorlist, key = lambda compare: sum([(a - b)**2 for a, b in zip(vector1, compare)])
Als Allgemeine Faustregel gilt, halten Sie sich an die
scipy
undnumpy
Implementierungen, wo möglich, als Sie sind vektorisiert und viel schneller als native Python-code. (Hauptgründe sind: Implementierungen in C, Vektorisierung eliminiert Typ-Prüfung overhead-looping macht.)(Beiseite: Meine Antwort nicht gerade präzise, aber ich denke, das gleiche Prinzip gilt für die Genauigkeit wie für die Effizienz.)
Als ein bisschen von einem bonus, ich werde chip-in mit ein wenig Informationen darüber, wie Sie Profil-Ihr code, um zu Messen, Effizienz. Wenn Sie die IPython interpreter, das Geheimnis ist die Verwendung der
%prun
line magic.Was
%prun
tut, ist Ihnen sagen, wie lange eine Funktion aufrufen, die benötigt wird, um, einschließlich ein bisschen trace um herauszufinden, wo der Flaschenhals sein könnte. In diesem Fall werden sowohl derscipy.spatial.distance.euclidean
undnumpy.linalg.norm
Implementierungen sind ziemlich schnell. Angenommen, man definiert eine Funktiondist(vect1, vect2)
können Sie ein Profil mit der gleichen IPython Magie nennen. Als ein zusätzlicher bonus,%prun
funktioniert auch innerhalb der Jupyter notebook, und Sie können tun%%prun
zu Profil, eine ganze Zelle von code, anstatt nur eine Funktion, indem Sie einfach%%prun
die erste Zeile der Zelle.Ich weiß nicht, wie die Präzision und die Geschwindigkeit im Vergleich zu den anderen Bibliotheken, die Sie erwähnt, aber Sie können es tun für 2D-Vektoren mit Hilfe des built-in
math.hypot()
Funktion:pairwise
- Methode funktioniert?pairwise()
Funktion ist eine leichte Abwandlung der im itertools Rezepte - Dokumentation. Und die ursprüngliche return-Werte aus den wiederholenden argument übergeben wird, in der Reihenfolge, die in dem doc-string an den Anfang der Funktion.