2016-12-06 16 views
1

Ich habe zwei Arrays, das erste np.array ist die Punkte aus, und die zweite np.array sind alle Entfernungen, die ich berechnen muss.Berechnen Sie die Entfernung zwischen numpy Arrays

Beispiel:

import numpy as np 
from_array = np.array([(0,1), (1,1), ..., (x,y)]) 
to_array = np.array([(5,1), (3,1), ..., (x,y)]) 

Was ich tun muss, ist der erste Eintrag des from_array zu nehmen und berechnen alle Abstände zwischen from_array[0] zu allen Punkten in to_array, halten dann die maximale Distanz.

So kann ich für diese Brute:

def get_distances(from_array, to_array): 
    results = [] 
    distances = [] 
    for pt in from_array: 
     for to in to_array: 
      results.append(calc_dist(pt, to)) 
     distances.append(results) 
    return distances 

Aber das ist langsam, ich für eine optimierte Art und Weise suchen die Berechnung zu tun, da ich tausende von Punkten haben könnte.

Das Endziel ist die Berechnung der Hausdorff-Distanz.

fhd = np.mean(np.min(SomeDistanceArray,axis=0)) 
rhd = np.mean(np.min(SomeDistanceArray,axis=1)) 
print (max(fhd, rhd)) 

Ich möchte für diese Aufgabe verwenden numpy nur. Meine Entfernung kann entweder euklidisch oder quadratisch euklidisch sein.

Also suche ich Hilfe für eine optimierte Methode zur Berechnung der euklidischen Distanzmethoden für zwei np.arrays. Es sollte beachtet werden, dass Array 1 mehr Zeilen als Array 2 haben kann. Bedeutet, dass die Länge des 2D-Arrays (x, y) 10 Zeilen mit 30 Zeilen vergleichen könnte.

+0

Schauen Sie in Scipys Cdist. – Divakar

+1

Ich habe das Gefühl, dass ich gerade dies beantwortet habe [gestern] (http://stackoverflow.com/questions/40969013/theano-row-column-wise-subtraction/40969905#40969905) –

+0

Scipy Version 0.19.0 (Entwicklungsversion von Jan2017) hat eine Implementierung von ['Directed Hausdorff distance'] (https://scipy.github.io/devdocs/generated/scipy.spatial.distance.directed_hausdorff.html#scipy-spatial-distance-directed-hausdorff), die Sie wollen prüfen. Es verwendet einen effizienten Algorithmus (siehe [Papier] (https://dx.doi.org/10.1109/TPAMI.2015.2408351)) mit einer Nähe zu O (m) Laufzeit (anstatt O (m * n)). – weiji14

Antwort

2

Hier ist ein NumPy basierten Ansatz mit np.einsum -

subs = from_array[:,None] - to_array 
sq_eucliean_dist = np.einsum('ijk,ijk->ij',subs,subs) 
eucliean_dist = np.sqrt(sq_eucliean_dist) 

Hinweis: Wenn Sie später np.mean(np.min(SomeDistanceArray,axis=0)) berechnen, können Sie die Berechnung fürüberspringenund verwenden Sie direkt sq_eucliean_dist als SomeDistanceArray, weil Computing Quadratwurzel ziemlich teuer wäre.


Was np.einsum('ijk,ijk->ij',subs,subs) macht? Sie führt eine elementweise Multiplikation zwischen dem gleichen Array subs durch, d. H. Im Wesentlichen quadriert und führt dann eine Summenreduktion entlang der letzten Achse durch, wodurch sie in diesem Reduktionsprozess verloren geht.

Warum also nicht ausdrücklich die Quadrierung und Summierung? Nun, der Vorteil mit np.einsum ist, dass es sowohl die Quadrierung als auch die Summierung in einem Schritt durchführt, was uns spürbare Leistungseffizienz gibt.

So schließlich, wenn from_array(N x 2) Array waren und waren to_array(M x 2) Array, das Ausgangssignal von np.einsum wäre die quadrierten euklidischen Abstände als eine 2D-Anordnung von Form (N x M). Weitere Informationen zur String-Notation selbst würden eine längere Diskussion beinhalten, von denen einige in this post und dem offiziellen Dokumentations-Link, der vorher gepostet wurde, gefunden werden können.

+0

können Sie erklären, die einsum Funktion? Ich bin nicht vertraut mit der Notation ijk, ikj.> ij –

+0

@ josh1234 Hinzugefügt ein paar Kommentare auf it. – Divakar

+0

danke für die Erklärung das funktioniert super! –

0

Nur Numpy. Also keine scipy.spatial.distance.cdist

Erstens, verwenden Sie keine Tupel, verwenden 2xN und 2xM Arrays. Dann senden.

np.linalg.norm(from_array[:,:,None]-to_array[:,None,:], axis=0) 

Wenn Sie eine alte Version von numpy ohne ein vecorizable linalg.norm (dh Sie verwenden Abaqus) dies tun:

np.sum((from_array[:,:,None]-to_array[:,None,:])**2, axis=0).__pow__(0.5) 
+0

ja nein cdist :(. Funktioniert das für unebene Arrays? Sagen Sie ein 30x2 und ein 50x2 Array? –

+0

Ja, stellen Sie einfach sicher, dass die gemeinsame Dimension zuerst ist, also 2x30 und 2x50, so können Sie wie oben –

+0

Broadcast senden So muss ich rotiere mein Array von Spalte X, Y zu X, Y als Zeilen: –

Verwandte Themen