2013-10-26 36 views
1

假設array_1array_2是兩個相同大小的矩陣陣列。是否有矢量乘法元素的方式,這兩個數組的元素(它們的元素的乘法已被很好地定義)?矩陣數組的元素有效乘法

僞代碼:

def mat_multiply(array_1,array_2): 
    size=np.shape(array_1)[0] 

    result=np.array([]) 
    for i in range(size): 
     result=np.append(result,np.dot(array_1[i],array_2[i]),axis=0) 
    return np.reshape(result,(size,2)) 

例如輸入:

a=[[[1,2],[3,4]],[[1,2],[3,4]]] 
b=[[1,3],[4,5]] 

輸出:

[[ 7. 15.] 
[ 14. 32.]] 
+0

HTTP:// WWW。 python-course.eu/matrix_arithmetic.php – lucemia

+0

@lucemia,我在那裏找不到任何相關的東西。 – Cupitor

回答

3

相反,你的第一句話,ab是不一樣的尺寸。但讓我們專注於你的例子。

所以,你想這一點 - 2級的產品,一個爲a每一行和b

np.array([np.dot(x,y) for x,y in zip(a,b)]) 

或避免附加

X = np.zeros((2,2)) 
for i in range(2): 
    X[i,...] = np.dot(a[i],b[i]) 

dot產品可與einsum(矩陣指數來表示符號)如

[np.einsum('ij,j->i',x,y) for x,y in zip(a,b)] 

所以下一步就是那個第一個維度指數:

np.einsum('kij,kj->ki',a,b) 

我很熟悉einsum,但它仍然採取了一些試驗和錯誤要弄清楚你想要什麼。現在問題很清楚,我可以用其他幾種方法計算它

A, B = np.array(a), np.array(b)  
np.multiply(A,B[:,np.newaxis,:]).sum(axis=2) 
(A*B[:,None,:]).sum(2) 
np.dot(A,B.T)[0,...] 
np.tensordot(b,a,(-1,-1))[:,0,:] 

我發現使用具有不同大小的數組很有幫助。例如,如果A(2,3,4)B(2,4),則點總和必須位於最後一個維上。


另一個numpy迭代工具是np.nditereinsum使用此(在C中)。 http://docs.scipy.org/doc/numpy/reference/arrays.nditer.html

it = np.nditer([A, B, None],flags=['external_loop'], 
    op_axes=[[0,1,2], [0,-1,1], None]) 
for x,y,w in it: 
    # x, y are shape (2,) 
    w[...] = np.dot(x,y) 
it.operands[2][...,0] 

避免[...,0]一步,需要更復雜的設置。

C = np.zeros((2,2)) 
it = np.nditer([A, B, C],flags=['external_loop','reduce_ok'], 
    op_axes=[[0,1,2], [0,-1,1], [0,1,-1]], 
    op_flags=[['readonly'],['readonly'],['readwrite']]) 
for x,y,w in it: 
    w[...] = np.dot(x,y) 
    # w[...] += x*y 
print C 
# array([[ 7., 15.],[ 14., 32.]]) 
+0

謝謝。投票!但他們是相同的大小!一個由兩個矩陣組成:[[1,2],[3,4]]和[[1,2],[3,4]]。而b由兩個矩陣組成:[1,3]和[4,5]。 – Cupitor

+0

我想你可以用'...'替換'np.einsum'調用中的'k',並讓它適用於矩陣和向量的可廣播陣列,而不僅僅是1D陣列。 – Jaime

+0

Naji - 你的'a'和'b'是列表清單。 'A'是一個3d陣列,'B'2d。如果你想要矢量化操作,你需要考慮這些更高維的數組。否則,你會堅持迭代低維數組。 – hpaulj

2

有這麼@hpaulj在他的廣泛和全面的選項列表冷落多了一個選擇:

>>> a = np.array(a) 
>>> b = np.array(b) 
>>> from numpy.core.umath_tests import matrix_multiply 
>>> matrix_multiply.signature 
'(m,n),(n,p)->(m,p)' 
>>> matrix_multiply(a, b[..., np.newaxis]) 
array([[[ 7], 
     [15]], 

     [[14], 
     [32]]]) 
>>> matrix_multiply(a, b[..., np.newaxis]).shape 
(2L, 2L, 1L) 
>>> np.squeeze(matrix_multiply(a, b[..., np.newaxis]), axis=-1) 
array([[ 7, 15], 
     [14, 32]]) 

的好處約matrix_multiply的是,它是一個gufunc,它不僅會工作與一維矩陣陣列,但也與可廣播陣列。舉個例子,如果不是與第一向量的第一矩陣,並與第二向量的第二矩陣相乘,你要計算所有可能的乘法,你可以簡單地做:

>>> a = np.arange(8).reshape(2, 2, 2) # to have different matrices 
>>> np.squeeze(matrix_multiply(a[...,np.newaxis, :, :], 
...       b[..., np.newaxis]), axis=-1) 
array([[[ 3, 11], 
     [ 5, 23]], 

     [[19, 27], 
     [41, 59]]])