向量化计算矩阵和向量之间的欧氏距离
Vectorize the calculation for Euclidean distance between matrix and vector
我想计算矩阵和标准向量之间的欧氏距离。
我所有的矩阵都存储在一个列表中,比方说,A,所以
A = [[1,2,3],[2,3,4]...,[8,9,10]],
标准向量是,比方说,[1,1,1]
,
我可以使用for-loop来做到这一点,但它真的很耗时,因为A中通常有数百个矩阵。
我如何矢量化此计算以缩短运行时间?
A = np.array([[1,2,3],
[2,3,4],
[3,4,5],
[4,5,6],
[5,6,7],
[6,7,8],
[7,8,9],
[8,9,10]])
v = np.array([1,1,1])
# Compute the length (norm) of the distance between the vectors
distance = np.linalg.norm(A - v, axis = 1)
print(distance)
[ 2.23606798 3.74165739 5.38516481 7.07106781 8.77496439 10.48808848
12.20655562 13.92838828]
方法 #1
使用np.einsum
进行距离计算。要在这里解决我们的案例,我们可以做 -
def dist_matrix_vec(matrix, vec):
d = np.subtract(matrix,vec)
return np.sqrt(np.einsum('ij,ij->i',d,d))
样本运行-
In [251]: A = [[1,2,3],[2,3,4],[8,9,10]]
In [252]: B = np.array([1,1,1])
In [253]: dist_matrix_vec(A,B)
Out[253]: array([ 2.23606798, 3.74165739, 13.92838828])
方法 #2
在处理大数据时,如果预期的操作可以表示为算术运算,我们可以使用支持多核处理的numexpr
module。为了解决我们的案例,我们可以这样表达 -
import numexpr as ne
def dist_matrix_vec_numexpr(matrix, vec):
matrix = np.asarray(matrix)
vec = np.asarray(vec)
return np.sqrt(ne.evaluate('sum((matrix-vec)**2,1)'))
大型数组的计时 -
In [295]: np.random.seed(0)
...: A = np.random.randint(0,9,(10000,3))
...: B = np.random.randint(0,9,(3,))
In [296]: %timeit np.linalg.norm(A - B, axis = 1) #@Nathaniel's soln
...: %timeit dist_matrix_vec(A,B)
...: %timeit dist_matrix_vec_numexpr(A,B)
1000 loops, best of 3: 244 µs per loop
10000 loops, best of 3: 131 µs per loop
10000 loops, best of 3: 96.5 µs per loop
In [297]: np.random.seed(0)
...: A = np.random.randint(0,9,(100000,3))
...: B = np.random.randint(0,9,(3,))
In [298]: %timeit np.linalg.norm(A - B, axis = 1) #@Nathaniel's soln
...: %timeit dist_matrix_vec(A,B)
...: %timeit dist_matrix_vec_numexpr(A,B)
100 loops, best of 3: 5.31 ms per loop
1000 loops, best of 3: 1.43 ms per loop
1000 loops, best of 3: 918 µs per loop
基于 numexpr
的线程有 8
个。因此,随着更多线程可用于计算,它应该会进一步改进。 关于如何控制多核功能。
我想计算矩阵和标准向量之间的欧氏距离。 我所有的矩阵都存储在一个列表中,比方说,A,所以
A = [[1,2,3],[2,3,4]...,[8,9,10]],
标准向量是,比方说,[1,1,1]
,
我可以使用for-loop来做到这一点,但它真的很耗时,因为A中通常有数百个矩阵。 我如何矢量化此计算以缩短运行时间?
A = np.array([[1,2,3],
[2,3,4],
[3,4,5],
[4,5,6],
[5,6,7],
[6,7,8],
[7,8,9],
[8,9,10]])
v = np.array([1,1,1])
# Compute the length (norm) of the distance between the vectors
distance = np.linalg.norm(A - v, axis = 1)
print(distance)
[ 2.23606798 3.74165739 5.38516481 7.07106781 8.77496439 10.48808848
12.20655562 13.92838828]
方法 #1
使用np.einsum
进行距离计算。要在这里解决我们的案例,我们可以做 -
def dist_matrix_vec(matrix, vec):
d = np.subtract(matrix,vec)
return np.sqrt(np.einsum('ij,ij->i',d,d))
样本运行-
In [251]: A = [[1,2,3],[2,3,4],[8,9,10]]
In [252]: B = np.array([1,1,1])
In [253]: dist_matrix_vec(A,B)
Out[253]: array([ 2.23606798, 3.74165739, 13.92838828])
方法 #2
在处理大数据时,如果预期的操作可以表示为算术运算,我们可以使用支持多核处理的numexpr
module。为了解决我们的案例,我们可以这样表达 -
import numexpr as ne
def dist_matrix_vec_numexpr(matrix, vec):
matrix = np.asarray(matrix)
vec = np.asarray(vec)
return np.sqrt(ne.evaluate('sum((matrix-vec)**2,1)'))
大型数组的计时 -
In [295]: np.random.seed(0)
...: A = np.random.randint(0,9,(10000,3))
...: B = np.random.randint(0,9,(3,))
In [296]: %timeit np.linalg.norm(A - B, axis = 1) #@Nathaniel's soln
...: %timeit dist_matrix_vec(A,B)
...: %timeit dist_matrix_vec_numexpr(A,B)
1000 loops, best of 3: 244 µs per loop
10000 loops, best of 3: 131 µs per loop
10000 loops, best of 3: 96.5 µs per loop
In [297]: np.random.seed(0)
...: A = np.random.randint(0,9,(100000,3))
...: B = np.random.randint(0,9,(3,))
In [298]: %timeit np.linalg.norm(A - B, axis = 1) #@Nathaniel's soln
...: %timeit dist_matrix_vec(A,B)
...: %timeit dist_matrix_vec_numexpr(A,B)
100 loops, best of 3: 5.31 ms per loop
1000 loops, best of 3: 1.43 ms per loop
1000 loops, best of 3: 918 µs per loop
基于 numexpr
的线程有 8
个。因此,随着更多线程可用于计算,它应该会进一步改进。