Schnellste paarweise Entfernungsmetrik in Python

8

Ich habe ein 1D-Array von Zahlen und möchte alle paarweisen euklidischen Abstände berechnen. Ich habe eine Methode (dank SO), dies mit dem Rundfunk zu tun, aber es ist ineffizient, weil es jede Entfernung zweimal berechnet. Und es skaliert nicht gut.

Hier ist ein Beispiel, das mir zeigt, was ich mit einem Array von 1000 Zahlen will.

%Vor%

Was ist die schnellste Implementierung in scipy / numpy / scikit-learn, die ich dazu verwenden kann, da sie in Situationen skaliert werden muss, in denen das 1D-Array & gt; 10k-Werte hat.

Hinweis: Die Matrix ist symmetrisch, also nehme ich an, dass es möglich ist, mindestens eine zweifache Beschleunigung zu erreichen, indem ich das adressiere, ich weiß einfach nicht wie.

    
roblanf 29.11.2013, 03:40
quelle

3 Antworten

15

Keine der anderen Antworten beantwortete die Frage - 1 war in Cython, eine war langsamer. Aber beides lieferte sehr nützliche Hinweise. Folgt man ihnen, deutet dies an, dass scipy.spatial.distance.pdist der richtige Weg ist.

Hier ist ein Code:

%Vor%

Timing mit IPython:

%Vor%

Ich habe die Cython-Implementierung nicht getestet (ich kann sie nicht für dieses Projekt verwenden), aber wenn ich meine Ergebnisse mit der anderen Antwort vergleiche, sieht scipy.spatial.distance.pdist ungefähr ein Drittel langsamer aus als die Cython-Implementierung ( Berücksichtigung der verschiedenen Maschinen durch Benchmarking auf der np.abs-Lösung).

    
roblanf 02.12.2013, 00:59
quelle
5

Hier ist eine Cython-Implementierung, die für dieses Beispiel mehr als 3-fache Geschwindigkeitssteigerung auf meinem Computer bietet. Dieses Timing sollte für größere Arrays unbedingt überprüft werden, da die BLAS-Routinen wahrscheinlich wesentlich besser skalieren können als dieser eher naive Code.

Ich weiß, dass du etwas in scipy / numpy / scikit-learn gefragt hast, aber vielleicht eröffnet dir das neue Möglichkeiten:

Datei my_cython.pyx :

%Vor%

Die Antwort ist ein 1-D-Array, das alle nicht wiederholten Auswertungen enthält.

Um in Python zu importieren:

%Vor%

Timing mit IPython:

%Vor%     
Saullo Castro 29.11.2013 11:03
quelle
3

Verwenden Sie die Hälfte des Speichers, aber 6 mal langsamer als np.abs(r - r[:, None]) :

%Vor%     
cyborg 30.11.2013 23:38
quelle