NumPy рассчитать квадрат нормы 2 вектора

У меня есть вектор a,
Я хочу посчитать np.inner(a, a)
Но мне интересно, есть ли более красивый способ рассчитать это.

[Недостаток этого способа в том, что если я хочу рассчитать его для a-b или немного более сложное выражение, я должен сделать это еще с одной строкой. c = a - b а также np.inner(c, c) вместо somewhat(a - b)]

3 ответа

Решение

Честно говоря, там, вероятно, не будет ничего быстрее, чем np.inner или же np.dot, Если вы находите промежуточные переменные раздражающими, вы всегда можете создать лямбда-функцию:

sqeuclidean = lambda x: np.inner(x, x)

np.inner а также np.dot использовать процедуры BLAS, и почти наверняка будет быстрее, чем стандартное поэлементное умножение с последующим суммированием.

In [1]: %%timeit -n 1 -r 100 a, b = np.random.randn(2, 1000000)
((a - b) ** 2).sum()
   ....: 
The slowest run took 36.13 times longer than the fastest. This could mean that an intermediate result is being cached 
1 loops, best of 100: 6.45 ms per loop

In [2]: %%timeit -n 1 -r 100 a, b = np.random.randn(2, 1000000)                                                                                                                                                                              
np.linalg.norm(a - b, ord=2) ** 2
   ....: 
1 loops, best of 100: 2.74 ms per loop

In [3]: %%timeit -n 1 -r 100 a, b = np.random.randn(2, 1000000)
sqeuclidean(a - b)
   ....: 
1 loops, best of 100: 2.64 ms per loop

np.linalg.norm(..., ord=2) использования np.dot внутренне, и дает очень похожую производительность при использовании np.inner непосредственно.

Я не знаю, если производительность хорошая, но (a**2).sum() вычисляет правильное значение и имеет неповторяющийся аргумент, который вы хотите. Вы можете заменить a с некоторым сложным выражением без привязки его к переменной, просто не забудьте использовать скобки по мере необходимости, так как ** связывает более плотно, чем большинство других операторов: ((a-b)**2).sum()

Рассчитать норм2

numpy.linalg.norm(x, ord=2) 

numpy.linalg.norm(x, ord=2)**2 для квадрата

Если вы в конечном итоге здесь ищете быстрый способ получить квадрат нормы, вот несколько тестов, показывающих distances = np.sum((descriptors - desc[None])**2, axis=1) быть самым быстрым.

import timeit

setup_code = """
import numpy as np
descriptors = np.random.rand(3000, 512)
desc = np.random.rand(512)
"""

norm_code = """
np.linalg.norm(descriptors - desc[None], axis=-1)
"""
norm_time = timeit.timeit(stmt=norm_code, setup=setup_code, number=100, )

einsum_code = """
x = descriptors - desc[None]
sqrd_dist = np.einsum('ij,ij -> i', x, x)
"""
einsum_time = timeit.timeit(stmt=einsum_code, setup=setup_code, number=100, )

norm_sqrd_code = """
distances = np.sum((descriptors - desc[None])**2, axis=1)
"""
norm_sqrd_time = timeit.timeit(stmt=norm_sqrd_code, setup=setup_code, number=100, )

print(norm_time) # 0.7688689678907394
print(einsum_time) # 0.29194538854062557
print(norm_sqrd_time) # 0.274090813472867

Другие вопросы по тегам