it-swarm.com.de

Wie erhält man die Größe eines Vektors in Numpy?

Wie erhält man in Numpy die Größe eines Vektors (1D-Array)?

def mag(x): 
    return math.sqrt(sum(i**2 for i in x))

Das Obige funktioniert, aber ichkannnicht glauben, dass ich selbst eine solche triviale und Kernfunktion spezifizieren muss.

123
Nick T

Die Funktion, die Sie suchen, ist numpy.linalg.norm . (Ich denke, es sollte in der Grundeinstellung als Eigenschaft eines Arrays stehen - sagen Sie x.norm() - aber na ja).

import numpy as np
x = np.array([1,2,3,4,5])
np.linalg.norm(x)

Sie können auch eine optionale ord für die gewünschte n-te Ordnung eingeben. Sagen Sie, Sie wollten die 1-Norm:

np.linalg.norm(x,ord=1)

Und so weiter.

155

Wenn Sie sich Sorgen um die Geschwindigkeit machen, sollten Sie stattdessen Folgendes verwenden:

mag = np.sqrt(x.dot(x))

Hier sind einige Benchmarks:

>>> import timeit
>>> timeit.timeit('np.linalg.norm(x)', setup='import numpy as np; x = np.arange(100)', number=1000)
0.0450878
>>> timeit.timeit('np.sqrt(x.dot(x))', setup='import numpy as np; x = np.arange(100)', number=1000)
0.0181372

BEARBEITEN: Die reale Geschwindigkeitsverbesserung tritt auf, wenn Sie die Norm vieler Vektoren verwenden müssen. Die Verwendung reiner Numpy-Funktionen erfordert keine for-Schleifen. Zum Beispiel:

In [1]: import numpy as np

In [2]: a = np.arange(1200.0).reshape((-1,3))

In [3]: %timeit [np.linalg.norm(x) for x in a]
100 loops, best of 3: 4.23 ms per loop

In [4]: %timeit np.sqrt((a*a).sum(axis=1))
100000 loops, best of 3: 18.9 us per loop

In [5]: np.allclose([np.linalg.norm(x) for x in a],np.sqrt((a*a).sum(axis=1)))
Out[5]: True
74
user545424

Eine weitere Alternative ist die Verwendung der einsum-Funktion in numpy für beide Arrays:

In [1]: import numpy as np

In [2]: a = np.arange(1200.0).reshape((-1,3))

In [3]: %timeit [np.linalg.norm(x) for x in a]
100 loops, best of 3: 3.86 ms per loop

In [4]: %timeit np.sqrt((a*a).sum(axis=1))
100000 loops, best of 3: 15.6 µs per loop

In [5]: %timeit np.sqrt(np.einsum('ij,ij->i',a,a))
100000 loops, best of 3: 8.71 µs per loop

oder Vektoren:

In [5]: a = np.arange(100000)

In [6]: %timeit np.sqrt(a.dot(a))
10000 loops, best of 3: 80.8 µs per loop

In [7]: %timeit np.sqrt(np.einsum('i,i', a, a))
10000 loops, best of 3: 60.6 µs per loop

Es scheint jedoch ein gewisser Aufwand zu sein, der mit dem Aufruf des Aufrufs einhergeht, der bei kleinen Eingaben langsamer werden könnte:

In [2]: a = np.arange(100)

In [3]: %timeit np.sqrt(a.dot(a))
100000 loops, best of 3: 3.73 µs per loop

In [4]: %timeit np.sqrt(np.einsum('i,i', a, a))
100000 loops, best of 3: 4.68 µs per loop
16
n8yoder

Der schnellste Weg, den ich gefunden habe, ist via inner1d. So wird es mit anderen numpy-Methoden verglichen:

import numpy as np
from numpy.core.umath_tests import inner1d

V = np.random.random_sample((10**6,3,)) # 1 million vectors
A = np.sqrt(np.einsum('...i,...i', V, V))
B = np.linalg.norm(V,axis=1)   
C = np.sqrt((V ** 2).sum(-1))
D = np.sqrt((V*V).sum(axis=1))
E = np.sqrt(inner1d(V,V))

print [np.allclose(E,x) for x in [A,B,C,D]] # [True, True, True, True]

import cProfile
cProfile.run("np.sqrt(np.einsum('...i,...i', V, V))") # 3 function calls in 0.013 seconds
cProfile.run('np.linalg.norm(V,axis=1)')              # 9 function calls in 0.029 seconds
cProfile.run('np.sqrt((V ** 2).sum(-1))')             # 5 function calls in 0.028 seconds
cProfile.run('np.sqrt((V*V).sum(axis=1))')            # 5 function calls in 0.027 seconds
cProfile.run('np.sqrt(inner1d(V,V))')                 # 2 function calls in 0.009 seconds

inner1d ist ~ 3x schneller als linalg.norm und ein Haar schneller als einsum

7
Fnord

benutze die Funktionnormin scipy.linalg (oder numpy.linalg )

>>> from scipy import linalg as LA
>>> a = 10*NP.random.randn(6)
>>> a
  array([  9.62141594,   1.29279592,   4.80091404,  -2.93714318,
          17.06608678, -11.34617065])
>>> LA.norm(a)
    23.36461979210312

>>> # compare with OP's function:
>>> import math
>>> mag = lambda x : math.sqrt(sum(i**2 for i in x))
>>> mag(a)
     23.36461979210312
2
doug

Sie können dies mit dem Toolbelt vg auf einfache Weise tun. Es ist eine helle Ebene über Numpy und unterstützt Einzelwerte und gestapelte Vektoren.

import numpy as np
import vg

x = np.array([1, 2, 3, 4, 5])
mag1 = np.linalg.norm(x)
mag2 = vg.magnitude(x)
print mag1 == mag2
# True

Ich habe die Bibliothek in meinem letzten Startup erstellt, wo sie durch solche Verwendungszwecke motiviert wurde: einfache Ideen, die in NumPy viel zu ausführlich sind.

0
paulmelnikow