Python 是否有numpy/scipy点积,仅计算结果的对角线条目?

Python 是否有numpy/scipy点积,仅计算结果的对角线条目?,python,numpy,scipy,product,Python,Numpy,Scipy,Product,想象一下有2个numpy阵列: > A, A.shape = (n,p) > B, B.shape = (p,p) 通常,p是一个较小的数字(p我想我是自己得到的,但是我将分享解决方案: 因为只得到矩阵乘法的对角线 > Z = N.diag(X.dot(Y)) 相当于X行和Y列的标量积的单个和,前面的语句相当于: > Z = (X * Y.T).sum(-1) 对于原始变量,这意味着: > result = (A.dot(B) * A).sum(-1) 如果

想象一下有2个numpy阵列:

> A, A.shape = (n,p)
> B, B.shape = (p,p)

通常,p是一个较小的数字(p我想我是自己得到的,但是我将分享解决方案:

因为只得到矩阵乘法的对角线

> Z = N.diag(X.dot(Y))
相当于X行和Y列的标量积的单个和,前面的语句相当于:

> Z = (X * Y.T).sum(-1)
对于原始变量,这意味着:

> result = (A.dot(B) * A).sum(-1)

如果我错了,请纠正我,但这应该是它…

你几乎可以得到任何你曾经梦想过的东西。在你开始掌握窍门之前,它基本上看起来像黑色巫术

>>> a = np.arange(15).reshape(5, 3)
>>> b = np.arange(9).reshape(3, 3)

>>> np.diag(np.dot(np.dot(a, b), a.T))
array([  60,  672, 1932, 3840, 6396])
>>> np.einsum('ij,ji->i', np.dot(a, b), a.T)
array([  60,  672, 1932, 3840, 6396])
>>> np.einsum('ij,ij->i', np.dot(a, b), a)
array([  60,  672, 1932, 3840, 6396])
编辑你实际上可以在一次拍摄中获得整个画面,这太荒谬了

>>> np.einsum('ij,jk,ki->i', a, b, a.T)
array([  60,  672, 1932, 3840, 6396])
>>> np.einsum('ij,jk,ik->i', a, b, a)
array([  60,  672, 1932, 3840, 6396])
编辑不过,你不想让它自己占据太多的位置……还为自己的问题添加了OP的答案,以供比较

n, p = 10000, 200
a = np.random.rand(n, p)
b = np.random.rand(p, p)

In [2]: %timeit np.einsum('ij,jk,ki->i', a, b, a.T)
1 loops, best of 3: 1.3 s per loop

In [3]: %timeit np.einsum('ij,ij->i', np.dot(a, b), a)
10 loops, best of 3: 105 ms per loop

In [4]: %timeit np.diag(np.dot(np.dot(a, b), a.T))
1 loops, best of 3: 5.73 s per loop

In [5]: %timeit (a.dot(b) * a).sum(-1)
10 loops, best of 3: 115 ms per loop

避免构建大型中间阵列的简单答案是:

result=np.empty([n,], dtype=A.dtype )
for i in xrange(n):
    result[i]=A[i,:].dot(B).dot(A[i,:])

+1智能代数总是比复杂的算法好。如果有人是numpy新手,这里的重点是X.dot(Y)运算符和*运算符X.dot(Y)之间的区别表示线性代数中的常规矩阵积,而X*Y返回X和Y项之间的逐点积,因此X和Y需要具有相同的形状。我不知道这个函数,但现在肯定会知道。Thx用于共享!!!我相信[3]依赖于“点”是高度优化的c代码这一事实(blas?)但是这确实构造了一个潜在的大型中间数组。我不确定np.einsum('ij,ij->I',np.dot(a,b,a)给出了什么,但它肯定是一个不同于Z=N.diag(X.dot(Y))的结果,Z=N.diag(X.dot(Y))的结果,它提供了点积的对角线元素(在本例中为[15,54,111])。
[N.]
不是有效的Python。你是说
A.shape
?@wkschwartz已修复。不,只是预先分配结果数组。
n, p = 10000, 200
a = np.random.rand(n, p)
b = np.random.rand(p, p)

In [2]: %timeit np.einsum('ij,jk,ki->i', a, b, a.T)
1 loops, best of 3: 1.3 s per loop

In [3]: %timeit np.einsum('ij,ij->i', np.dot(a, b), a)
10 loops, best of 3: 105 ms per loop

In [4]: %timeit np.diag(np.dot(np.dot(a, b), a.T))
1 loops, best of 3: 5.73 s per loop

In [5]: %timeit (a.dot(b) * a).sum(-1)
10 loops, best of 3: 115 ms per loop
result=np.empty([n,], dtype=A.dtype )
for i in xrange(n):
    result[i]=A[i,:].dot(B).dot(A[i,:])