2011-04-22 78 views
16

有什麼我可以做的,以加快numpy中的屏蔽數組?我有一個非常低效的函數,我重寫了使用被屏蔽的數組(我可以屏蔽行而不是複製和刪除行)。但是,我驚訝地發現掩碼函數速度慢了10倍,因爲掩碼陣列速度非常慢。Python/Numpy - 屏蔽數組非常慢

作爲一個例子,可採取下列(掩蔽是對我來說更慢然後6次):

import timeit 
import numpy as np 
import numpy.ma as ma 

def test(row): 
    return row[0] + row[1] 

a = np.arange(1000).reshape(500, 2) 
t = timeit.Timer('np.apply_along_axis(test, 1, a)','from __main__ import test, a, np') 
print round(t.timeit(100), 6) 

b = ma.array(a) 
t = timeit.Timer('ma.apply_along_axis(test, 1, b)','from __main__ import test, b, ma') 
print round(t.timeit(100), 6) 
+2

請記住,MaskedArrays比實際解決方案更方便。如果您需要對數組中缺失/未定義值進行密集計算,那麼在大多數情況下,您最好自己處理掩碼和數據。直到在NumPy代碼中更好地實現丟失/未定義的值(這種情況應該很快發生)之前,您將被禁止使用MaskedArrays。是的,它們很慢,因爲它們是用純Python編碼的,當然不能像依賴某些C代碼那樣高效。 – 2012-08-17 11:46:38

+0

感謝您的問題,這證實了我懷疑我的代碼 – 2017-08-29 10:11:50

回答

3

我不知道爲什麼被屏蔽陣列功能的移動得很慢,但因爲它聽起來像你使用面膜來選擇行(而不是單獨的值),你可以創建一個從蒙面行的規則排列,使用NP函數:

b.mask = np.zeros(500) 
b.mask[498] = True 
t = timeit.Timer('c=b.view(np.ndarray)[~b.mask[:,0]]; np.apply_along_axis(test, 1, c)','from __main__ import test, b, ma, np') 
print round(t.timeit(100), 6) 

更重要的是,在所有不使用屏蔽數組;只需將您的數據和一維掩模陣列作爲單獨的變量進行維護:

a = np.arange(1000).reshape(500, 2) 
mask = np.ones(a.shape[0], dtype=bool) 
mask[498] = False 
out = np.apply_along_axis(test, 1, a[mask]) 
+0

減速以及我做了類似於你的第二個例子,但我需要變量'out'具有相同數量的索引,因爲有行在一個'。請參閱[此問題](http://stackoverflow.com/questions/5761642/python-numpy-get-index-into-main-array-from-subset) – 2011-07-07 20:08:59

0

編輯:我被測試它錯誤通過使用np.apply_along_axis代替np.ma.apply_along_axis,抱歉。 所以,我確認屏蔽數組版本比較慢也可以在Linux/numpy的5倍以上1.5.1

In [16]: %timeit np.apply_along_axis(test, 1, a) 
100 loops, best of 3: 15.3 ms per loop 

In [17]: %timeit np.apply_along_axis(test, 1, b) 
100 loops, best of 3: 15.3 ms per loop 

In [12]: %timeit np.ma.apply_along_axis(test, 1, b) 
10 loops, best of 3: 80.8 ms per loop 

In [18]: np.__version__ 
Out[18]: '1.5.1' 
+0

我在Windows XP 32bit上使用python 2.5.2和numpy 1.5.1。當我回家時,我會在我的Linux電腦上試用它。很奇怪。作爲參考,當我運行我的發佈的代碼,我得到的輸出:0.955434和5.136362。 – 2011-04-23 00:20:36

+0

我看到了顯着的性能差異:第一個是1.298489,第二個是7.177839。我在Linux 64bit上使用Python 2.6.4和numpy 1.5.1。 – tkerwin 2011-04-23 00:27:11

+0

實際上,我沒有看到使用'%timeit'命令的區別,就像你在例子中做的那樣,但是我在使用'timeit.Timer'時做了。也許我不明白他們是如何工作的。 – tkerwin 2011-04-23 00:34:31