为了与“只有一种显而易见的方法”保持一致,你如何在Numpy中获得向量(1D数组)的大小?
def mag(x):
return math.sqrt(sum(i**2 for i in x))
上述工作,但我不能相信我必须自己指定这样一个简单的核心功能。
答案 0 :(得分:166)
你所追求的功能是numpy.linalg.norm
。 (我认为它应该在基础numpy中作为数组的属性 - 比如x.norm()
- 但是哦,好吧)。
import numpy as np
x = np.array([1,2,3,4,5])
np.linalg.norm(x)
您还可以为您想要的第n个订单标准提供可选的ord
。说你想要1-norm:
np.linalg.norm(x,ord=1)
等等。
答案 1 :(得分:80)
如果你对速度感到担忧,你应该使用:
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
答案 2 :(得分:16)
另一个替代方法是在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
或载体:
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
但是,确实有一些与调用它相关的开销可能会因为小输入而变慢:
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
答案 3 :(得分:7)
我找到的最快方式是通过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倍,头发比einsum快
答案 4 :(得分:2)
在 scipy.linalg (或 numpy.linalg )中使用 norm 功能
>>> 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
答案 5 :(得分:0)
您可以使用工具带vg简洁地执行此操作。它是numpy之上的一个轻层,它支持单个值和堆叠的向量。
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
我在上次启动时创建了该库,它的使用动机是这样的:简单的想法在NumPy中太冗长了。
答案 6 :(得分:-1)
v1 = np.array([ 1, 2 , 3 ])
v1_size = len(v1)
print(v1_size) // 3
答案 7 :(得分:-5)
只需使用内置功能:
numpy.absolute(x)