Как вы получаете величину вектора в Numpy?

В соответствии с "Есть только один очевидный способ сделать это", как вы получаете величину вектора (1D-массив) в Numpy?

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

Вышеупомянутые работы, но я не могу поверить, что я должен сам указать такую ​​тривиальную и основную функцию.

Ответ 1

Функция, за которой вы находитесь, numpy.linalg.norm. (Я полагаю, он должен быть в base numpy как свойство массива - скажем x.norm() - но хорошо).

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

Вы также можете подать дополнительный ord для нужной вам нормы порядка. Скажите, что вам нужна 1-норма:

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

И так далее.

Ответ 2

Если вы беспокоитесь о скорости, вы должны использовать:

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

EDIT: реальное повышение скорости происходит, когда вам нужно принять норму многих векторов. Использование чистых функций 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: 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

Ответ 3

Еще одна альтернатива - использовать функцию 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

или векторы:

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

Ответ 4

Самый быстрый способ, который я нашел, - через 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 ~ 3 раза быстрее, чем linalg.norm и волосы быстрее, чем einsum

Ответ 5

используйте функцию норма в 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 function:
>>> import math
>>> mag = lambda x : math.sqrt(sum(i**2 for i in x))
>>> mag(a)
     23.36461979210312

Ответ 6

Вы можете сделать это кратко, используя toolbelt 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.

Ответ 7

просто используйте встроенную функцию:

numpy.absolute(x)