In Numpy ist die Verwendung von Schleifen langsam, daher werden verschiedene Techniken verwendet. Es ist einfach, im Vektor- oder Matrixformat zu schreiben, aber es gibt einige, die Broadcast verwenden. Ein Beispiel ist die Erzeugung einer Distanzmatrix. Wie berechnen Sie den Abstand zwischen den Standorten mehrerer Standorte, die in "x" gespeichert sind?
Ich bin seit vielen Jahren mit Fortran vertraut, daher möchte ich mit Schleifen schreiben.
do j = 1, n
do i = 1, n
r(i, j) = sqrt((x(i) - x(j))**2)
end do
end do
Wörtlich übersetzt in Python
for i in range(len(x)):
for j in range(len(x)):
r[i, j] = math.sqrt((x[i] - x[j])**2)
Es wird sein. Selbst mit ndarray gibt es keinen Unterschied, ob die Länge etwa 10 beträgt, sondern es ist schneller, die Liste zu führen.
Die Array-Operationen von Numpy (einschließlich Produkte) erfolgen grundsätzlich Element für Element. Operationen an Arrays derselben Form, wie z. B. zweidimensionale 4x3-Arrays, werden an jedem Element ausgeführt. Für Elemente mit unterschiedlichen Größen, wie z. B. ein zweidimensionales 4x3-Array und ein eindimensionales 1x3-Array, wird die Berechnung unter der Annahme durchgeführt, dass die Zeilen des eindimensionalen Arrays wiederholt werden, sodass die Größen gleich sind. Diese Konvertierung wird als "Broadcast" bezeichnet.
Für das "x", das die Position speichert, scheint es, dass ein Array zurückgegeben wird, wenn die Operation mit der Translokation ausgeführt wird, aber das ist nicht der Fall. Es wird als dieselbe Form angesehen und ist eine Liste von 0.
Erhöhen Sie eine Dimension, um mithilfe von Broadcast die gewünschte Entfernungsmatrix ohne Schleifen zu generieren. Verwenden Sie np.newaxis
, um die Dimension zu vergrößern. Gleiches gilt für "Keine". Die Länge der Abmessung, für die "np.newaxis" oder "None" angegeben ist, beträgt 1. Obwohl ich es noch nie benutzt habe, hat Fortran95 eine eingebaute Funktion namens "Spread".
np.sqrt((x - x[:, np.newaxis])**2)
Sie können auch nx1- und 1xn-Operationen verwenden.
np.sqrt((x[np.newaxis, :] - x[:, np.newaxis])**2)
In meiner Umgebung betrug die Schleife von ndarray, gemessen mit "% timeit" für 10 Punkte, 69,1 μs, die Listenschleife 54,1 μs und diejenige, die die Schleife vermieden und die Dimension der Matrix vergrößerte, 3,04 μs. Bei 1000 Punkten betrug die Schleife von ndarray 660 ms und die mit erhöhten Matrixdimensionen 2,47 ms.
Die Verwendung von "..." entspricht der Anordnung von ":", sodass die Anzahl der Dimensionen der Dimension des Arrays entspricht. Der euklidische Abstand eines Punktes im n-dimensionalen Raum kann wie folgt berechnet werden.
np.sqrt(((x[..., np.newaxis, :] - x[..., :, np.newaxis])**2).sum(axis=0))
Recommended Posts