2016-10-02 88 views
1

我有形狀(N*2)的矩陣M1和另一矩陣M2(2*N),我想獲得的(N)結果,每個元件ii第i行的乘積M1i第012列的M2。 我試圖在NumPy的使用點,但它只能給我的矩陣乘法結果,這是(N*N),當然,我可以採取對角線這是我想要的,我想知道有沒有更好的方式來做到這個?計算產品 - NumPy的

回答

1

方法#1

您可以使用np.einsum -

np.einsum('ij,ji->i',M1,M2) 

說明:

原來糊塗的解決方案將是這個樣子 -

def original_app(M1,M2): 
    N = M1.shape[0] 
    out = np.zeros(N) 
    for i in range(N): 
     out[i] = M1[i].dot(M2[:,i]) 
    return out 

因此,對於每一次迭代,我們有:

out[i] = M1[i].dot(M2[:,i]) 

在迭代器尋找,我們需要對齊的M1第一軸線與M2第二軸線。同樣,因爲我們正在執行matrix-multiplication並且由於其本身的定義與的M2第一軸線對準的M1第二軸線,並且還總結減少在每一次迭代這些元素。

當移植到einsum,保持軸的兩個輸入端之間的對準指定字符串符號給它時具有相同的字符串。所以,輸入分別爲'ij,ji,M1M2。從M1失去第二串後的輸出,這是與從在總和還原M2第一串,應該保留i。因此,完整的字符串符號將爲:'ij,ji->i',最終解決方案爲:np.einsum('ij,ji->i',M1,M2)

方法2

M1 COLS或行數的在M2數量是2。因此,另外,我們就可以切片,進行逐元素乘法和總結這些,就像這樣 -

M1[:,0]*M2[0] + M1[:,1]*M2[1] 

運行測試

In [431]: # Setup inputs 
    ...: N = 1000 
    ...: M1 = np.random.rand(N,2) 
    ...: M2 = np.random.rand(2,N) 
    ...: 

In [432]: np.allclose(original_app(M1,M2),np.einsum('ij,ji->i',M1,M2)) 
Out[432]: True 

In [433]: np.allclose(original_app(M1,M2),M1[:,0]*M2[0] + M1[:,1]*M2[1]) 
Out[433]: True 

In [434]: %timeit original_app(M1,M2) 
100 loops, best of 3: 2.09 ms per loop 

In [435]: %timeit np.einsum('ij,ji->i',M1,M2) 
100000 loops, best of 3: 13 µs per loop 

In [436]: %timeit M1[:,0]*M2[0] + M1[:,1]*M2[1] 
100000 loops, best of 3: 14.2 µs per loop 

大規模加速那裏!

+0

不錯的答案,讓我消化了一段時間。愛因斯坦是強大的,但對於初學者來說似乎並不容易理解。 – 1a1a11a

+0

你能解釋一點這是如何工作的?我正在閱讀文檔,很難理解 – 1a1a11a

+0

@ 1a1a11a查看添加的評論是否有意義。 – Divakar