2010-05-05 15 views
5

मेरे पास एक फ़ंक्शन foo है जो एक तर्क के रूप में एक NxM numpy सरणी लेता है और एक स्केलर मान देता है। मैं, मुझे लंबाई ए के एक परिणामी numpy सरणी2 डी numpy arrays के मैपिंग फ़ंक्शन

curently देने के लिए एक AxNxM numpy सरणी data, जिसकी मैं मैप करने के लिए foo करना चाहते हैं मैं यह कर रहा हूँ:

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

यह काम करता है, लेकिन ऐसा लगता है कि मैं numpy जादू (और गति) का लाभ नहीं ले रहा हूँ। क्या कोई बेहतर तरीका है?

मैंने numpy.vectorize, और numpy.apply_along_axis पर देखा है, लेकिन न तो 2 डी arrays के फ़ंक्शन के लिए काम करता है।

संपादित करें: मैं 24x24 छवि पैच पर बढ़ा हुआ रिग्रेशन कर रहा हूं, इसलिए मेरा एक्सएक्सएक्सएम 1000x24x24 जैसा कुछ है। जिसे मैंने foo कहा है, एक पैच को एक हायर जैसी सुविधा लागू करता है (इसलिए, बहुत कम्प्यूटेशनल रूप से गहन नहीं)।

+1

वहाँ इतना है कि यह मनमाना आयाम के एक numpy सरणी स्वीकार कर सकते हैं 'foo' पुनःकूटित के लिए एक रास्ता हो सकता है, इसकी संगणना को लागू करने पिछले दो अक्षों के लिए। लेकिन हमें यह देखना होगा कि विशिष्ट सुझाव बनाने के लिए 'foo' को कोड किया गया है। – unutbu

+0

मैंने अपनी विशिष्ट समस्या के बारे में अधिक जानकारी दी है। क्या 'डेटा' को छोड़ना समझदारी होगी, इंडेक्स पैरामीटर लेने के लिए 'foo' को फिर से कोड करें, और उसके बाद इसे सदिश करें और इसे' arange (len (x)) 'पर मैप करें? – perimosocordiae

उत्तर

3

यदि एनएक्सएम बड़ा है (कहें, 100), तो ए पर पुनरावृत्ति की लागत मूल रूप से कुछ भी नहीं हो जाएगी।

कहो सरणी 1000 X 100 X 100

पुनरावृत्ति हे (1000) है, लेकिन अंदर समारोह का संचयी लागत हे (1000 एक्स 100 X 100) है - 10,000 गुना धीमी। (ध्यान दें, मेरे शब्दावली थोड़ा wonky है, लेकिन मैं जानता हूँ कि मैं किस बारे में बात कर रहा हूँ है)

मुझे यकीन है कि नहीं कर रहा हूँ, लेकिन आप इस कोशिश कर सकते:

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

आप का एक बड़ा बचत होगी सूची बनाने पर स्मृति आवंटन ... लेकिन लूप ओवरहेड अधिक होगा।

या आप लूप का समांतर संस्करण लिख सकते हैं, और इसे कई प्रक्रियाओं में विभाजित कर सकते हैं। foo कितना गहन है (क्योंकि डेटा डेटा हैंडलिंग को ऑफ़सेट करना होगा) के आधार पर यह बहुत तेज़ हो सकता है।

+4

भिन्नता: 'परिणाम = एनपी.फॉमिटर (itertools.imap (एफ, डेटा), dtype = data.dtype, count = data.shape [0]) ' – jfs

1

आप एक ही अग्रणी आयाम के साथ एक 2 डी सरणी के रूप में अपने 3 डी सरणी देगी द्वारा प्राप्त है, और एक समारोह है कि उन्हें reshaping के रूप foo के लिए आवश्यक द्वारा -1 डी सरणियों पर काम करता है के साथ अपने समारोह foo लपेट कर सकते हैं। एक उदाहरण (का उपयोग कर foo की trace बजाय):

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 ('संस्करण 3-5 बार है 'apply2d _ ..()' से तेज़ – jfs

संबंधित मुद्दे