2016-09-13 26 views
2

說我有兩個矩陣BM,我想執行以下語句:新增多個沒有建立一個新的

B += 3*M 

我執行該指令多次,所以我不希望建立每次矩陣3*M3可能會改變,這只是爲了讓我只做一個標量矩陣產品)。它是一個numpy函數,它使得這個計算「到位」?

更確切地說,我有標量as列表和矩陣Ms的名單,我想執行「點積」(這是不是真的一個,因爲兩個操作數是不同類型的)兩個,也就是說:

sum(a*M for a, M in zip(as, Ms)) 

np.dot功能沒有做什麼,我除外...

回答

5

您可以使用np.tensordot -

np.tensordot(As,Ms,axes=(0,0)) 

或者np.einsum -

np.einsum('i,ijk->jk',As,Ms) 

採樣運行 -

In [41]: As = [2,5,6] 

In [42]: Ms = [np.random.rand(2,3),np.random.rand(2,3),np.random.rand(2,3)] 

In [43]: sum(a*M for a, M in zip(As, Ms)) 
Out[43]: 
array([[ 6.79630284, 5.04212877, 10.76217631], 
     [ 4.91927651, 1.98115548, 6.13705742]]) 

In [44]: np.tensordot(As,Ms,axes=(0,0)) 
Out[44]: 
array([[ 6.79630284, 5.04212877, 10.76217631], 
     [ 4.91927651, 1.98115548, 6.13705742]]) 

In [45]: np.einsum('i,ijk->jk',As,Ms) 
Out[45]: 
array([[ 6.79630284, 5.04212877, 10.76217631], 
     [ 4.91927651, 1.98115548, 6.13705742]]) 
1

另一種方法可以做到這一點,特別是如果你青睞的可讀性,是利用broadcasting

所以,你可以從一維和二維陣列進行三維數組,然後在合適的軸總結:

>>> Ms = np.random.randn(4, 2, 3) # 4 arrays of size 2x3 
>>> As = np.random.randn(4) 
>>> np.sum(As[:, np.newaxis, np.newaxis] * Ms) 
array([[-1.40199248, -0.40337845, -0.69986566], 
     [ 3.52724279, 0.19547118, 2.1485559 ]]) 
>>> sum(a*M for a, M in zip(As, Ms)) 
array([[-1.40199248, -0.40337845, -0.69986566], 
     [ 3.52724279, 0.19547118, 2.1485559 ]]) 

不過,值得注意的是,np.einsumnp.tensordot通常更有效:

>>> %timeit np.sum(As[:, np.newaxis, np.newaxis] * Ms, axis=0) 
The slowest run took 7.38 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 8.58 µs per loop 
>>> %timeit np.einsum('i,ijk->jk', As, Ms) 
The slowest run took 19.16 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 2.44 µs per loop 

這也適用於更大的數字:

>>> Ms = np.random.randn(100, 200, 300) 
>>> As = np.random.randn(100) 
>>> %timeit np.einsum('i,ijk->jk', As, Ms) 
100 loops, best of 3: 5.03 ms per loop 
>>> %timeit np.sum(As[:, np.newaxis, np.newaxis] * Ms, axis=0) 
100 loops, best of 3: 14.8 ms per loop 
>>> %timeit np.tensordot(As,Ms,axes=(0,0)) 
100 loops, best of 3: 2.79 ms per loop 

所以np.tensordot在這種情況下效果最好。

使用np.sum和廣播的唯一好理由是使代碼更具可讀性(當你有小矩陣時有幫助)。

相關問題