Python 使用Numpy的成对vdot
我试图计算一个复杂的2D数组的成对Python 使用Numpy的成对vdot,python,numpy,vectorization,Python,Numpy,Vectorization,我试图计算一个复杂的2D数组的成对np.vdot。因此,我想要的行为是: X = np.empty((x.shape[0], x.shape[0]), dtype='complex128') for i in range(x.shape[0]): for j in range(x.shape[0]): X[i, j] = np.vdot(x[i], x[j]) 有没有一种不用显式循环就能做到这一点的方法?我尝试使用sklearn中的pairwise\u内核,但它假设输入
np.vdot
。因此,我想要的行为是:
X = np.empty((x.shape[0], x.shape[0]), dtype='complex128')
for i in range(x.shape[0]):
for j in range(x.shape[0]):
X[i, j] = np.vdot(x[i], x[j])
有没有一种不用显式循环就能做到这一点的方法?我尝试使用sklearn
中的pairwise\u内核
,但它假设输入数组是实数。我也尝试过广播,但vdot
会将其输入平坦化
X = np.einsum('ik,jk->ij', np.conj(x), x)
相当于
X = np.empty((x.shape[0], x.shape[0]), dtype='complex128')
for i in range(x.shape[0]):
for j in range(x.shape[0]):
X[i, j] = np.vdot(x[i], x[j])
取乘积之和。下标'ik,jk->ij'
告诉np.einsum
第二个参数,
np.conj(x)
是一个带有下标ik
的数组,第三个参数x
具有
下标jk
。因此,对所有的变量计算乘积np.conj(x)[i,k]*x[j,k]
i
,j
,k
。该总和将接管重复的下标k,此后
剩下的i
和j
将成为结果数组的下标
比如说,
import numpy as np
N, M = 10, 20
a = np.random.random((N,M))
b = np.random.random((N,M))
x = a + b*1j
def orig(x):
X = np.empty((x.shape[0], x.shape[0]), dtype='complex128')
for i in range(x.shape[0]):
for j in range(x.shape[0]):
X[i, j] = np.vdot(x[i], x[j])
return X
def alt(x):
return np.einsum('ik,jk->ij', np.conj(x), x)
assert np.allclose(orig(x), alt(x))
要将
np.vdot
扩展到所有行,您可以使用,我直接借用共轭思想,如下所示-
np.tensordot(np.conj(x),x,axes=(1,1))
基本上,使用np.tensordot
,我们指定了要缩减的轴,在本例中,这是共轭版本的x
和数组本身的最后一个轴,当应用于这两个轴时
运行时测试-
让我们在这篇文章中讨论时间和建议的解决方案-
In [27]: import numpy as np # From @unutbu's` solution again
...:
...: N, M = 1000, 1000
...: a = np.random.random((N,M))
...: b = np.random.random((N,M))
...: x = a + b*1j
...:
In [28]: %timeit np.einsum('ik,jk->ij', np.conj(x), x) # @unutbu's` solution
1 loops, best of 3: 4.45 s per loop
In [29]: %timeit np.tensordot(np.conj(x),x,axes=(1,1))
1 loops, best of 3: 3.76 s per loop
In [27]: import numpy as np # From @unutbu's` solution again
...:
...: N, M = 1000, 1000
...: a = np.random.random((N,M))
...: b = np.random.random((N,M))
...: x = a + b*1j
...:
In [28]: %timeit np.einsum('ik,jk->ij', np.conj(x), x) # @unutbu's` solution
1 loops, best of 3: 4.45 s per loop
In [29]: %timeit np.tensordot(np.conj(x),x,axes=(1,1))
1 loops, best of 3: 3.76 s per loop