你如何得到Numpy中的vector的大小?
按照“只有一个明显的方法去做”,你如何得到Numpy中的向量(一维数组)的大小?
def mag(x): return math.sqrt(sum(i**2 for i in x))
以上的作品,但我不能相信自己必须指定这样一个微不足道的核心function。
你之后的function是numpy.linalg.norm
。 (我认为它应该在基础numpy作为一个数组的属性 – 说x.norm()
– 但哦)。
import numpy as np x = np.array([1,2,3,4,5]) np.linalg.norm(x)
你也可以为你想要的第n个订单规范提供一个可选的订单。 假设你想要1范数:
np.linalg.norm(x,ord=1)
等等。
如果您对速度感到担心,则应该使用:
mag = np.sqrt(x.dot(x))
这里有一些基准:
>>> 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
编辑:真正的速度提高来,当你必须采取许多载体的规范。 使用纯粹的numpy函数不需要任何for循环。 例如:
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
另一种select是在数组中使用numpy的einsum
函数:
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
或vector:
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
但是,似乎有一些与调用它有关的开销,可能会使它在较小的input时变慢:
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
我发现最快的方法是通过inner1d。 这是如何比较其他numpy方法:
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比linalg.norm快约3倍,比头发快
在scipy.linalg (或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