2010-05-05 162 views
5

我有一個函數foo,它將一個NxM numpy數組作爲參數並返回一個標量值。我有一個AxNxM numpy的陣列data,我想映射foo在這給我的長度A的合成numpy的陣列二維numpy陣列的映射函數

Curently,我這樣做:

result = numpy.array([foo(x) for x in data]) 

它的工作原理,但似乎我並沒有利用numpy的魔法(和速度)。有沒有更好的辦法?

我看過numpy.vectorizenumpy.apply_along_axis,但都不適用於二維數組的功能。

編輯:我在24x24圖像補丁上做了推動迴歸,所以我的AxNxM就像1000x24x24。上面我所說的foo將一個Haar-like特徵應用到補丁(所以,不是非常計算密集的)。

+1

有可能是重新編碼'foo',以便它可以接受任意尺寸的numpy的陣列的方式,施加它的計算到最後兩個軸。但是我們必須看看'foo'是如何編碼以提出具體建議的。 – unutbu 2010-05-05 11:58:37

+0

我已經添加了更多關於我的具體問題的細節。將數據保持原樣,重新編碼foo以獲得索引參數,然後將其矢量化並將其映射到arange(len(x))'上? – perimosocordiae 2010-05-05 19:57:55

回答

3

如果NxM很大(比如說100),它們在A上的迭代成本將被分攤到基本上沒有的東西上。

說陣列是1000×100×100

迭代是O(1000),但內部功能的累計成本是O(1000×100×100) - 10,000倍慢。 (請注意,我的術語有點靠不住,但我不知道我在說什麼)

我不知道,不過你可以試試這個:

result = numpy.empty(data.shape[0]) 
for i in range(len(data)): 
    result[i] = foo(data[i]) 

您將節省很大的內存分配建立清單......但循環開銷會更大。

或者你可以編寫一個並行版本的循環,並將其分成多個進程。這可能會快得多,這取決於foo的密集程度(因爲它必須抵消數據處理)。

+4

Variation:'result = np.fromiter(itertools.imap(f,data),dtype = data.dtype,count = data.shape [0])' – jfs 2010-05-05 12:17:08

1

您可以通過將3D數組重塑爲具有相同超前維度的二維數組,並將函數foo用一種適用於一維數組的函數按照foo的要求進行變形來實現。一個例子(使用的trace代替foo):

from numpy import * 

def apply2d_along_first(func2d, arr3d): 
    a, n, m = arr3d.shape 
    def func1d(arr1d): 
     return func2d(arr1d.reshape((n,m))) 
    arr2d = arr3d.reshape((a,n*m)) 
    return apply_along_axis(func1d, -1, arr2d) 

A, N, M = 3, 4, 5 
data = arange(A*N*M).reshape((A,N,M)) 

print data 
print apply2d_along_first(trace, data) 

輸出:

[[[ 0 1 2 3 4] 
    [ 5 6 7 8 9] 
    [10 11 12 13 14] 
    [15 16 17 18 19]] 

[[20 21 22 23 24] 
    [25 26 27 28 29] 
    [30 31 32 33 34] 
    [35 36 37 38 39]] 

[[40 41 42 43 44] 
    [45 46 47 48 49] 
    [50 51 52 53 54] 
    [55 56 57 58 59]]] 
[ 36 116 196] 
+1

'np.fromiter(imap('variant is 3-5 times比'apply2d _ ..()'快 – jfs 2010-05-05 15:38:33