NumPy 计算向量的范数 2 的平方
NumPy calculate square of norm 2 of vector
我有矢量 a
.
我想计算 np.inner(a, a)
但是不知道有没有更漂亮的计算方法
[这种方式的缺点是,如果我想为 a-b
或更复杂的表达式计算它,我必须多写一行。 c = a - b
和 np.inner(c, c)
而不是 somewhat(a - b)
]
计算 norm2
numpy.linalg.norm(x, ord=2)
numpy.linalg.norm(x, ord=2)**2
正方形
我不知道性能好不好,但是(a**2).sum()
计算出正确的值并且有你想要的非重复参数。您可以用一些复杂的表达式替换 a
而无需将其绑定到变量,只需记住在必要时使用括号,因为 **
比大多数其他运算符绑定得更紧密:((a-b)**2).sum()
老实说,可能没有比 np.inner
或 np.dot
更快的了。如果你觉得中间变量很烦人,你总是可以创建一个 lambda 函数:
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
非常相似的性能。
如果您最终在这里寻找获得平方范数的快速方法,这些测试显示 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
我有矢量 a
.
我想计算 np.inner(a, a)
但是不知道有没有更漂亮的计算方法
[这种方式的缺点是,如果我想为 a-b
或更复杂的表达式计算它,我必须多写一行。 c = a - b
和 np.inner(c, c)
而不是 somewhat(a - b)
]
计算 norm2
numpy.linalg.norm(x, ord=2)
numpy.linalg.norm(x, ord=2)**2
正方形
我不知道性能好不好,但是(a**2).sum()
计算出正确的值并且有你想要的非重复参数。您可以用一些复杂的表达式替换 a
而无需将其绑定到变量,只需记住在必要时使用括号,因为 **
比大多数其他运算符绑定得更紧密:((a-b)**2).sum()
老实说,可能没有比 np.inner
或 np.dot
更快的了。如果你觉得中间变量很烦人,你总是可以创建一个 lambda 函数:
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
非常相似的性能。
如果您最终在这里寻找获得平方范数的快速方法,这些测试显示 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