2011-03-17 133 views
6

我正在尋找在python(numpy)中執行以下操作。Python中的空洞3D矩陣乘法

Matrix A is M x N x R 
Matrix B is N x 1 x R 

矩陣乘法AB = C,其中C是一個M×1×R矩陣。 本質上,每個M×N層的A(它們中的R)是由B中每個N×1向量獨立乘上的矩陣。我相信這是一個單行線。我一直在嘗試使用tensordot(),但我似乎給我的答案,我不期望。

我一直在Igor Pro編程近10年,現在我正試圖將它的頁面轉換爲python。

回答

8

numpy.tensordot()是做正確的方式:

a = numpy.arange(24).reshape(2, 3, 4) 
b = numpy.arange(12).reshape(3, 1, 4) 
c = numpy.tensordot(a, b, axes=[1, 0]).diagonal(axis1=1, axis2=3) 

編輯:這樣做的第一個版本是錯誤的,這個版本計算更涵它應該和扔掉大部分。也許上一個軸上的Python循環是更好的方法。

另一個編輯:我得出的結論是numpy.tensordot()的最佳解決方案在這裏。

c = (a[:,:,None] * b).sum(axis=1) 

會更有效率(儘管更難掌握)。

+0

謝謝你很快回到我身邊。至少,它會讓我開始。我將要嘗試編寫的大部分代碼都是以矩陣操作爲導向的......所以我應該真正理解這裏發生了什麼。話雖如此,代碼有兩部分讓我困惑。首先是在tensordot裏面調用「軸」。我對實際上做了什麼感到困惑,因爲我希望x b應該給你c(就像我上面描述的那樣),而不用聲明任何特殊的東西。也許一旦我明白了,我會明白爲什麼有必要使用.diagonal。 – Jason 2011-03-18 00:55:45

+0

這很聰明......我不知道需要多長時間才能做出這樣的事情(看起來你創建了一個新的軸來乘法和,然後基本上重新組合),我非常感謝你的時間,謝謝許多! – Jason 2011-03-18 18:33:32

+1

如果第一維是矩陣列表(R),第二維是公共矩陣維(N),即a(4,3,2)的形狀和b是(4)的形狀,則更容易想到這一點。 ,3,1)。乘法運算成爲(a * b).sum(axis = 1)。 (a * b)是矩陣中每個元素的行和列的乘積,您需要對每行求和以獲得最終矩陣。就像你手動多個矩陣一樣。 – 2013-09-25 23:25:36

10

對不起死靈,但這個答案可以大大改善,使用無價的np.einsum。

import numpy as np 

D,M,N,R = 1,2,3,4 
A = np.random.rand(M,N,R) 
B = np.random.rand(N,D,R) 

print np.einsum('mnr,ndr->mdr', A, B).shape 

請注意,它有幾個優點:首先,其速度快。 np.einsum一般都進行了很好的優化,但是np.einsum足夠聰明,可以避免創建一個MxNxR臨時數組,但是直接執行N的收縮。

但也許更重要的是,它的可讀性很強。毫無疑問,這段代碼是正確的;而且你可以在沒有任何問題的情況下使它變得複雜得多。

請注意,如果您願意,虛擬'D'軸可以簡單地從B和einsum語句中刪除。

+0

我看到np.dot()也可以做一些多維操作,但是在一些奇怪的規則下工作。你有什麼知識嗎? – Martian2049 2016-01-28 06:18:02

+0

我的知識可以被最好地總結爲'使用艾爾辛姆代替'。可能會稍微冗長些,但在我看來,「明確優於隱含」從來沒有應用過更多。 – 2017-08-29 20:14:05