如何有效地将numpy数组相加后再乘以数组?
其实我需要计算:如何有效地将numpy数组相加后再乘以数组?
S_i = sum(U_j * U_j.transpose) * K_i
其中
U_j is a n * k dim matrix,
K_i is a n * n dim matrix,
j != i,
i = 1, 2, ..., n
而且我用这样的循环:
import numpy as np
for i in xrange(n):
temp = np.zeros((n, n))
for j in xrange (n):
if j != i:
temp += np.dot(U[j], U[j].T)
S[i] = np.dot(temp, K[i])
有没有更有效的方法来做到这一点?
import numpy as np
n, k = 30, 40
U = np.random.random((n, n, k))
K = np.random.random((n, n, n))
def using_loops(U, K):
S = np.empty((n, n, n))
for i in xrange(n):
temp = np.zeros((n, n))
for j in xrange (n):
if j != i:
temp += np.dot(U[j], U[j].T)
S[i] = np.dot(temp, K[i])
return S
def using_einsum(U, K):
uut = np.einsum('ijk,ilk->ijl', U, U)
total = uut.sum(axis=0)
total = total - uut
S = np.einsum('ijk,ikl->ijl', total, K)
return S
此测试一些using_loops
和using_einsum
产生相同的结果。
In [260]: np.allclose(using_loops(U, K), using_einsum(U, K))
Out[260]: True
这表明using_einsum更快;快多少取决于n
和k
大小:
In [262]: %timeit using_loops(U, K)
100 loops, best of 3: 17.1 ms per loop
In [263]: %timeit using_einsum(U, K)
1000 loops, best of 3: 1.92 ms per loop
在一般情况下,当你看到产品的总和,有一个很好的机会, np.einsum 会产生一个比较快的方法结果。它几乎肯定会打败 Python for-loops。
我已经阅读过使用'np.einsum'的文档,但我对参数'操作数'很困惑。最后一个例子是'np.einsum('ki,jk-> ij',a,b)',如果我没有错,我认为它等于'np.dot(a.T,b.T)'。但为什么操作数是'ki,jk-> ij'而不是'ji,kj-> ik'?如果你能解释我〜THX ~~ – AnnabellChan 2014-11-25 07:37:06
而如果公式** S_I = SUM(U_j * U_j.transpose)* ** K_I其中i不一定等于n,而是远远小于n,是有使用'np.dot'和'np.einsum'之间时间效率差异的任何变化? – AnnabellChan 2014-11-25 08:08:15
关于'numpy.einsum'中的操作数,我想通了〜谢谢〜:) – AnnabellChan 2014-11-25 11:15:12
对于xrange(n)中的j和j!= i'应该引发了一个SyntaxError。你的意思是把它分成一个'for-loop'和一个'if-statement'? – unutbu 2014-11-25 02:59:30
@unutbu是的你是对的,我的意思是'对于xrange(n)中的j:if j!= i:'但是我在语法上犯了一个错误,我想知道有没有更好的方法来做到这一点〜 – AnnabellChan 2014-11-25 05:58:01