4

我想在numpy中做兩個二維數組的元素明智的外積。numpy元素外部產品

A.shape = (100, 3) # A numpy ndarray 
B.shape = (100, 5) # A numpy ndarray 

C = element_wise_outer_product(A, B) # A function that does the trick 
C.shape = (100, 3, 5) # This should be the result 
C[i] = np.outer(A[i], B[i]) # This should be the result 

一個天真的實現可以如下。

tmp = [] 
for i in range(len(A): 
    outer_product = np.outer(A[i], B[i]) 
    tmp.append(outer_product) 
C = np.array(tmp) 

來自堆棧溢出的更好解決方案。

big_outer = np.multiply.outer(A, B) 
tmp = np.swapaxes(tmp, 1, 2) 
C_tmp = [tmp[i][i] for i in range(len(A)] 
C = np.array(C_tmp) 

我正在尋找擺脫for循環的矢量化實現。 有沒有人有想法? 謝謝!

+0

對於它的價值,'np.multiply.outer(A,B)'是'到不同np.outer ',賦予形狀'100,3,100,5' – Eric

回答

7

擴展AB3D保持他們的第一軸線對齊,並且沿所述第三和第二個與None/np.newaxis分別引入新的軸,然後彼此相乘。這將允許broadcasting發揮矢量化解決方案的作用。

因此,實現將是 -

A[:,:,None]*B[:,None,:] 

我們可以使用ellipsis爲A的縮短了一點::,:,並跳過與B上市剩最後一個軸,像這樣 -

A[...,None]*B[:,None] 

至於另一量化的方法,我們還可以使用np.einsum,一旦我們得到過去的字符串表示法,這可能是更直觀語法和考慮這些符號被捲入一個天真糊塗實現迭代器的代表,像這樣 -

np.einsum('ij,ik->ijk',A,B) 
+0

或'np.einsum( '...,J,...,K - > ... JK',A,B)'到超過3名維工作 – Eric

+0

這些方法都不比循環更快。 'Einsum'對於一個數組來說需要900ms,一個簡單的'loop'需要700ms。 'A [:,:,無] * B [:,無,:]'大約是800。 – Swift