2014-11-25 60 views
4

其實我需要計算:如何有效地將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]) 

有沒有更有效的方法來做到這一點?

+0

對於xrange(n)中的j和j!= i'應該引發了一個SyntaxError。你的意思是把它分成一個'for-loop'和一個'if-statement'? – unutbu 2014-11-25 02:59:30

+0

@unutbu是的你是對的,我的意思是'對於xrange(n)中的j:if j!= i:'但是我在語法上犯了一個錯誤,我想知道有沒有更好的方法來做到這一點〜 – AnnabellChan 2014-11-25 05:58:01

回答

3
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_loopsusing_einsum產生相同的結果。

In [260]: np.allclose(using_loops(U, K), using_einsum(U, K)) 
Out[260]: True 

這表明using_einsum更快;快多少取決於nk大小:

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。

+0

我已經閱讀過使用'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

+0

而如果公式** S_I = SUM(U_j * U_j.transpose)* ** K_I其中i不一定等於n,而是遠遠小於n,是有使用'np.dot'和'np.einsum'之間時間效率差異的任何變化? – AnnabellChan 2014-11-25 08:08:15

+0

關於'numpy.einsum'中的操作數,我想通了〜謝謝〜:) – AnnabellChan 2014-11-25 11:15:12