Mam dwa punkty w 3D:
(xa, ya, za)
(xb, yb, zb)
I chcę obliczyć odległość:
dist = sqrt((xa-xb)^2 + (ya-yb)^2 + (za-zb)^2)
Jaki jest najlepszy sposób, aby to zrobić za pomocą NumPy lub ogólnie Pythona? Mam:
import numpy
a = numpy.array((xa ,ya, za))
b = numpy.array((xb, yb, zb))
python
numpy
euclidean-distance
Nathan Fellman
źródło
źródło
Jest taka funkcja w SciPy. To się nazywa euklidesowe .
Przykład:
źródło
Dla wszystkich zainteresowanych obliczeniem wielu odległości naraz zrobiłem małe porównanie przy użyciu perfplot ( mały projekt).
Pierwsza rada to takie uporządkowanie danych, aby tablice miały wymiar
(3, n)
(i oczywiście są ciągłe w C). Jeśli dodawanie odbywa się w ciągłym pierwszym wymiarze, rzeczy są szybsze i nie ma to większego znaczenia, jeśli używaszsqrt-sum
zaxis=0
,linalg.norm
zaxis=0
lubktóry jest, z niewielkim marginesem, najszybszym wariantem. (Tak naprawdę dotyczy to tylko jednego rzędu).
Warianty, w których sumuje się na drugiej osi
axis=1
, są znacznie wolniejsze.Kod do odtworzenia fabuły:
źródło
i,i->
data
musi wyglądać?Chcę wyjaśnić prostą odpowiedź z różnymi notatkami dotyczącymi wydajności. np.linalg.norm zrobi może więcej niż potrzebujesz:
Po pierwsze - ta funkcja została zaprojektowana do pracy nad listą i zwracania wszystkich wartości, np. W celu porównania odległości od
pA
zestawu punktówsP
:Pamiętaj o kilku rzeczach:
Więc
nie jest tak niewinny jak się wydaje.
Po pierwsze - za każdym razem, gdy go nazywamy, musimy przeprowadzić globalne wyszukiwanie dla „np”, wyszukiwanie w zakresie dla „linalg” i wyszukiwanie w zakresie dla „normy”, a narzut związany z samym wywoływaniem funkcji może być równy kilkudziesięciu pytonom instrukcje.
Na koniec zmarnowaliśmy dwie operacje, aby zapisać wynik i załadować go ponownie w celu zwrotu ...
Pierwszy krok do poprawy: przyspiesz wyszukiwanie, pomiń sklep
Otrzymujemy znacznie bardziej usprawnione:
Narzut związany z wywoływaniem funkcji nadal jednak wymaga pewnej pracy. I będziesz chciał przeprowadzić testy porównawcze, aby ustalić, czy lepiej byłoby, gdybyś sam wykonał matematykę:
Na niektórych platformach
**0.5
jest szybszy niżmath.sqrt
. Twój przebieg może się różnić.**** Zaawansowane uwagi dotyczące wydajności.
Dlaczego obliczasz odległość? Jeśli jedynym celem jest wyświetlenie go,
poruszać się. Ale jeśli porównujesz odległości, sprawdzasz zasięg itp., Chciałbym dodać kilka przydatnych obserwacji wydajności.
Weźmy dwa przypadki: sortowanie według odległości lub ubijanie listy do elementów spełniających ograniczenie zakresu.
Pierwszą rzeczą, o której musimy pamiętać, jest to, że używamy Pitagorasa do obliczania odległości (
dist = sqrt(x^2 + y^2 + z^2)
), więc wykonujemy wielesqrt
połączeń. Matematyka 101:Krótko mówiąc: dopóki faktycznie nie będziemy potrzebować odległości w jednostce X zamiast X ^ 2, możemy wyeliminować najtrudniejszą część obliczeń.
Świetnie, obie funkcje nie powodują już żadnych drogich pierwiastków kwadratowych. To będzie znacznie szybsze. Możemy również ulepszyć in_range, przekształcając go w generator:
Ma to szczególne zalety, jeśli robisz coś takiego:
Ale jeśli następna rzecz, którą zamierzasz zrobić, wymaga dystansu,
rozważ uzyskanie krotek:
Może to być szczególnie przydatne, jeśli możesz połączyć sprawdzanie zasięgu („znajdź rzeczy, które są w pobliżu X i w Nm od Y”, ponieważ nie musisz ponownie obliczać odległości).
Ale co, jeśli szukamy naprawdę dużej listy
things
i spodziewamy się, że wiele z nich nie będzie wartych rozważenia?W rzeczywistości istnieje bardzo prosta optymalizacja:
To, czy jest to przydatne, będzie zależeć od wielkości „rzeczy”.
I jeszcze raz zastanów się nad uzyskaniem dist_sq. Nasz przykład Hot-Dog to:
źródło
pointZ
nieistniejącego. Myślę, że miałeś na myśli dwa punkty w trójwymiarowej przestrzeni i odpowiednio je zredagowałem. Jeśli się myliłem, proszę dać mi znać.Kolejne wystąpienie tej metody rozwiązywania problemów :
źródło
norm = lambda x: N.sqrt(N.square(x).sum())
;norm(x-y)
numpy.linalg.norm(x-y)
Zaczynając
Python 3.8
,math
moduł bezpośrednio udostępniadist
funkcję, która zwraca odległość euklidesową między dwoma punktami (podanymi jako krotki lub listy współrzędnych):A jeśli pracujesz z listami:
źródło
Można to zrobić w następujący sposób. Nie wiem, jak szybko to jest, ale nie używa NumPy.
źródło
for a, b in zip(a, b)
. Ale mimo to przydatne.Znajduję funkcję „dist” w matplotlib.mlab, ale nie sądzę, aby była wystarczająco przydatna.
Zamieszczam go tutaj tylko w celach informacyjnych.
źródło
Lubię
np.dot
(produkt kropka):źródło
Miły jednowarstwowy:
Jeśli jednak chodzi o szybkość, zalecam eksperymentowanie na komputerze. Przekonałem się, że używając
math
bibliotekisqrt
z**
operatorem kwadratu jest znacznie szybsze na moim komputerze niż jedno-liniowe rozwiązanie NumPy.Przeprowadziłem testy przy użyciu tego prostego programu:
Na mojej maszynie
math_calc_dist
działa znacznie szybciej niżnumpy_calc_dist
: 1,5 sekundy w porównaniu do 23,5 sekundy.Aby uzyskać mierzalną różnicę między
fastest_calc_dist
imath_calc_dist
musiałemTOTAL_LOCATIONS
do 6000. Potemfastest_calc_dist
zajmuje ~ 50 sekundmath_calc_dist
zajmuje ~ 60 sekund.Możesz także eksperymentować z
numpy.sqrt
inumpy.square
choć oba były wolniejsze niżmath
alternatywy na mojej maszynie.Moje testy zostały uruchomione w języku Python 2.6.6.
źródło
scipy.spatial.distance.cdist(p1, p2).sum()
. To jest to.numpy.linalg.norm(p1-p2).sum()
aby uzyskać sumę między każdym punktem w p1 a odpowiednim punktem w p2 (tj. Nie każdy punkt w p1 do każdego punktu w p2). A jeśli chcesz każdy punkt w p1 do każdego punktu w p2 i nie chcesz używać scipy jak w poprzednim komentarzu, możesz użyć np.apply_along_axis wraz z numpy.linalg.norm, aby nadal robić to dużo, znacznie szybciej to twoje „najszybsze” rozwiązanie.Możesz po prostu odjąć wektory, a następnie produkt wewnętrzny.
Idąc za twoim przykładem,
źródło
Posiadanie
a
ib
jak je określono, można użyć również:źródło
Z Python 3.8 jest to bardzo łatwe.
https://docs.python.org/3/library/math.html#math.dist
źródło
Oto zwięzły kod odległości euklidesowej w Pythonie, biorąc pod uwagę dwa punkty reprezentowane jako listy w Pythonie.
źródło
Od wersji Python 3.8
Od wersji Python 3.8
math
moduł zawiera funkcjęmath.dist()
.Zobacz tutaj https://docs.python.org/3.8/library/math.html#math.dist .
źródło
Oblicz odległość euklidesową dla przestrzeni wielowymiarowej:
źródło
źródło
źródło
Możesz łatwo użyć formuły
co właściwie nie robi nic więcej niż użycie twierdzenia Pitagorasa do obliczenia odległości, poprzez dodanie kwadratów ofx, yy i zz i zrootowanie wyniku.
źródło
Najpierw znajdź różnicę dwóch macierzy. Następnie zastosuj mnożenie elementu za pomocą polecenia mnożenia numpy. Następnie znajdź sumę elementu pod kątem pomnożonej nowej macierzy. Na koniec znajdź pierwiastek kwadratowy sumy.
źródło
Państwo listę pierwsza zmiana na numpy tablicy i zrobić tak:
print(np.linalg.norm(np.array(a) - np.array(b)))
. Druga metoda bezpośrednio z listy python jako:print(np.linalg.norm(np.subtract(a,b)))
źródło