2016-11-18 148 views
0

我有許多矩陣要添加。假設矩陣是[M1,M2 ...,M_n]。然後,一個簡單的辦法就是numpy矩陣加法的有效方法

X = np.zeros() 
for M in matrices: 
    X += M 

在操作上,X + = M,並Python中創建一個新的內存X每次+ =執行?如果是這樣的話,那似乎是低效的。在沒有爲X創建新內存的情況下進行就地操作有什麼方法嗎?

+0

你究竟做了什麼:'[M1,M2 ...,M_n]'?它是一個數組列表嗎?添加一個樣本? – Divakar

+0

@Divakar我認爲這是一個矩陣列表。 – TuanDT

+0

@Divakar,M是np.ndarray。 – DSKim

回答

1

這工作,但不是我的機器上更快:

numpy.sum(matrices, axis=0) 
0

除非你得到的MemoryError,試圖第二次猜測內存使用numpy的是不值得的。將其留給知道編譯代碼的開發人員。

但是我們可以執行一些時間測試 - 這纔是真正重要的,不是嗎?

我會測試添加一個好的大小數組100次。

In [479]: M=np.ones((1000,1000)) 

您與+ =

In [480]: %%timeit 
    ...: X=np.zeros_like(M) 
    ...: for _ in range(100): X+=M 
    ...: 
1 loop, best of 3: 627 ms per loop 

或者使尺寸的陣列(100,1000,1000),並應用np.sum跨過第一軸線迭代方法。

In [481]: timeit np.sum(np.array([M for _ in range(100)]),axis=0) 
1 loop, best of 3: 1.54 s per loop 

並使用np.add ufunc。通過reduce,我們可以將它依次應用於列表中的所有值。

In [482]: timeit np.add.reduce([M for _ in range(100)]) 
1 loop, best of 3: 1.53 s per loop 

np.sum情況下給我的MemoryError如果我使用range(1000)。我沒有足夠的內存來存放(1000,1000,1000)數組。 add.reduce相同,從列表中構建一個數組。

+=什麼+=在掩護下通常是隱藏的,並且我們通常不關心。但對於下蓋峯看ufunc.athttps://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.at.html#numpy.ufunc.at

上執行操作到位操作無緩衝「A」由「指數」指定的元素。對於另外的ufunc,這個方法等同於[indices] + = b,除了對索引多於一次的元素累計結果。

因此X+=M會將總和寫入緩衝區,然後將該緩衝區複製到X。有一個臨時緩衝區,但最終的內存使用情況不會改變。 但是,該緩衝區的創建和複製是在快速C代碼中完成的。

np.add.at被添加來處理緩衝動作產生一些問題(重複索引)的情況。

因此,它避免了臨時緩衝區 - 但速度相當快。這可能是增加的索引功能會降低速度。 (可能有更公平的add.at測試;但在這種情況下肯定無濟於事。)

In [491]: %%timeit 
    ...: X=np.zeros_like(M) 
    ...: for _ in range(100): np.add.at(X,(slice(None),slice(None)),M) 
1 loop, best of 3: 19.8 s per loop