2016-10-06 32 views
2

我需要計算N行的點積;假設對於每一行我需要計算1xM倍MxM乘以Mx1。如果我只查看一行,我會從這個計算中得到1x1。然而,我有N行,所以我想我會堆疊行,並將其饋送到點積;但是,我得到了NxN矩陣。我需要的結果是對角線,但是有沒有更快的方法來做這種計算,這也不會浪費空間?理想情況下,我想最終得到一個Nx1向量,而不是NxN矩陣。有效計算1xM次MxM次Mx1,N次

單列

r = np.array([[1,2]]).T 
R = np.array([[2,2],[2,2]]) 

[[18]] 

多行

rs = np.array([[1,2],[4,4]]).T 
R = np.array([[2,2],[2,2]]) 
print np.dot(np.dot(rs.T,R), rs) 

[[ 18 48] 
[ 48 128]] 

回答

4

使用np.einsum非常久遠內點積,像這樣 -

np.einsum('ij,ji->i',np.dot(rs.T,R),rs) 

採樣運行 -

In [215]: rs = np.random.rand(3,4) 
    ...: R = np.random.rand(3,3) 
    ...: out = np.dot(np.dot(rs.T,R), rs) 
    ...: 

In [216]: np.diag(out) # Diagonal elems is the expected o/p 
Out[216]: array([ 1.11476081, 1.05112902, 0.32136029, 0.31318894]) 

In [217]: np.einsum('ij,ji->i',np.dot(rs.T,R),rs) 
Out[217]: array([ 1.11476081, 1.05112902, 0.32136029, 0.31318894]) 

運行測試 -

In [233]: rs = np.random.rand(300,400) 

In [234]: R = np.random.rand(300,300) 

In [235]: %timeit np.diag(np.dot(np.dot(rs.T,R), rs))# Original soln 
10 loops, best of 3: 84 ms per loop 

In [236]: %timeit np.einsum('ij,kj,ki->j', rs, rs, R)# @DSM's soln 
10 loops, best of 3: 65.2 ms per loop 

In [237]: %timeit np.einsum('ij,ji->i',np.dot(rs.T,R),rs) 
10 loops, best of 3: 37.2 ms per loop 
+0

在我的機器,我的三個參數einsum實際上比使用大型陣列的方法要慢十倍。 (diag7.4ms,einsum + dot = 3.6,3-einsum = 73.2)。太糟糕了,我喜歡它。: -/ – DSM

+0

@DSM是的,我也喜歡它,做'einsum'裏面的一切都是我認爲的好工作!可能會刪除它,人們可能會喜歡其他選擇? :) – Divakar