你如何在Numpy中获得向量的大小?

Nic*_*k T 139 python numpy

为了与"只有一种明显的方法"相符,你如何在Numpy中获得向量(1D数组)的大小?

def mag(x): 
    return math.sqrt(sum(i**2 for i in x))
Run Code Online (Sandbox Code Playgroud)

上面的作品,但我不敢相信我必须自己指定这样一个琐碎的核心功能.

mat*_*fee 181

你所追求的功能是numpy.linalg.norm.(我认为它应该在基础numpy中作为数组的属性 - 比如说x.norm()- 但是很好).

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

您也可以ord为您想要的第n个订单提供可选项.说你想要1-norm:

np.linalg.norm(x,ord=1)
Run Code Online (Sandbox Code Playgroud)

等等.

  • "应该是数组的属性:x.norm()"我完全同意.通常在使用numpy时,我使用自己的Array和Matrix子类,这些子类具有我常用的所有函数作为方法.`Matrix.randn([5,5])` (12认同)
  • 另外,对于由向量组成的矩阵,`np.linalg.norm`现在有一个新的`axis`参数,在这里讨论:http://stackoverflow.com/a/19794741/1959808 (2认同)

use*_*424 87

如果你对速度感到担忧,你应该使用:

mag = np.sqrt(x.dot(x))
Run Code Online (Sandbox Code Playgroud)

以下是一些基准测试:

>>> 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
Run Code Online (Sandbox Code Playgroud)

编辑:真正的速度改进来自你必须采取许多向量的规范.使用纯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
Run Code Online (Sandbox Code Playgroud)

  • 在发现 `np.linalg.norm` 是一个瓶颈之后,我实际上确实使用了这种稍微不那么明确的方法,但后来我更进一步,只使用了 `math.sqrt(x[0]**2 + x[ 1]**2)`这是另一个重大改进。 (2认同)
  • 点产品的酷应用! (2认同)
  • `numpy.linalg.norm` 包含防止此实现跳过的溢出的保护措施。例如,尝试计算`[1e200, 1e200]` 的范数。如果它更慢是有原因的...... (2认同)
  • @FedericoPoloni,至少在 numpy 版本 1.13.3 中,我在计算“np.linalg.norm([1e200,1e200])”时得到“inf”。 (2认同)

n8y*_*der 16

另一种方法是einsum在numpy中使用这两个数组的函数:

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
Run Code Online (Sandbox Code Playgroud)

或矢量:

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
Run Code Online (Sandbox Code Playgroud)

但是,似乎有一些与调用它相关的开销可能会因为小输入而变慢:

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
Run Code Online (Sandbox Code Playgroud)


Fno*_*ord 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
Run Code Online (Sandbox Code Playgroud)

inner1d比linalg.norm快3倍,头发比einsum快