numpy

2013-08-21 7 views
7

में एक 3 डी सरणी के 2 डी टुकड़ा की मतलब हो जाओ मैं का एक आकार के साथ एक numpy सरणी है:numpy

(11L, 5L, 5L) 

मैं प्रत्येक सरणी के 'टुकड़ा' के 25 तत्वों से अधिक मतलब गणना करना चाहते हैं [ 0,:,:], [1,:,:] आदि, 11 मूल्य लौट रहे हैं।

यह मूर्खतापूर्ण प्रतीत होता है, लेकिन मैं यह नहीं कर सकता कि यह कैसे करें। मैंने सोचा है कि mean(axis=x) फ़ंक्शन ऐसा करेगा, लेकिन मैंने धुरी के सभी संभावित संयोजनों को आजमाया है और उनमें से कोई भी मुझे वह परिणाम नहीं देता है जो मैं चाहता हूं।

मैं स्पष्ट रूप से लूप और स्लाइसिंग के लिए ऐसा कर सकता हूं, लेकिन निश्चित रूप से एक बेहतर तरीका है?

उत्तर

11

एक टपल का प्रयोग करें धुरी के लिए:

>>> a = np.arange(11*5*5).reshape(11,5,5) 
>>> a.mean(axis=(1,2)) 
array([ 12., 37., 62., 87., 112., 137., 162., 187., 212., 
     237., 262.]) 

संपादित करें: यह बदतर केएस केवल numpy संस्करण 1.7+ के साथ।

+2

यह काम करता है? एक ऐसा लगता है कि 1.7 और बाद में, लेकिन दस्तावेज़ अभी भी केवल एक अक्ष कहते हैं। – Jaime

+1

ने numpy संस्करण के बारे में नहीं सोचा था, मेरे पास 1.7.1 है और यह काम करता है। यह प्रलेखन में नहीं है लेकिन चेंजलॉग यूफुनक्स के बारे में बात कर रहा है: http://www.softpedia.com/progChangelog/Numpy-Changelog-103892.html –

+2

कूल, यह नहीं पता था कि यह जोड़ा गया था! – lmjohns3

4

आप reshape(11, 25) और फिर mean कॉल कर सकते हैं केवल एक बार (तेज):

a.reshape(11, 25).mean(axis=1) 

वैकल्पिक रूप से, आप (अपने कंप्यूटर पर धीमी 2X के बारे में) दो बार np.mean कॉल कर सकते हैं:

a.mean(axis=2).mean(axis=1) 
+1

मैं, लगता है, हालांकि यह सबसे सरल जवाब है इन्सम तेजी से प्रतीत होता है। – lmjohns3

5

हमेशा उपयोग कर सकते हैं np.einsum: उच्च आयामी सरणियों पर

>>> a = np.arange(11*5*5).reshape(11,5,5) 
>>> np.einsum('...ijk->...i',a)/(a.shape[-1]*a.shape[-2]) 
array([ 12, 37, 62, 87, 112, 137, 162, 187, 212, 237, 262]) 

काम करता है (इन सभी विधियों अक्ष लेबल बदल जाएगा अगर कर रहे हैं):

>>> a = np.arange(10*11*5*5).reshape(10,11,5,5) 
>>> (np.einsum('...ijk->...i',a)/(a.shape[-1]*a.shape[-2])).shape 
(10, 11) 

तेज़ बूट करने के लिए:

a = np.arange(11*5*5).reshape(11,5,5) 

%timeit a.reshape(11, 25).mean(axis=1) 
10000 loops, best of 3: 21.4 us per loop 

%timeit a.mean(axis=(1,2)) 
10000 loops, best of 3: 19.4 us per loop 

%timeit np.einsum('...ijk->...i',a)/(a.shape[-1]*a.shape[-2]) 
100000 loops, best of 3: 8.26 us per loop 

सरणी आकार बढ़ने के साथ अन्य तरीकों के बाद थोड़ा बेहतर स्केल करता है।

dtype=np.float64 का उपयोग पर्याप्त रूप से ऊपर समय परिवर्तन नहीं करता है, तो बस दोहरी जांच करने के लिए:

a = np.arange(110*50*50,dtype=np.float64).reshape(110,50,50) 

%timeit a.reshape(110,2500).mean(axis=1) 
1000 loops, best of 3: 307 us per loop 

%timeit a.mean(axis=(1,2)) 
1000 loops, best of 3: 308 us per loop 

%timeit np.einsum('...ijk->...i',a)/(a.shape[-1]*a.shape[-2]) 
10000 loops, best of 3: 145 us per loop 
इसके अलावा

कुछ है कि दिलचस्प है:

%timeit np.sum(a) #37812362500.0 
100000 loops, best of 3: 293 us per loop 

%timeit np.einsum('ijk->',a) #37812362500.0 
100000 loops, best of 3: 144 us per loop 
+1

मुझे लगता है कि 'फ्लोट' या 'डबल' की बजाय, 'int' accumulator का उपयोग करके आपकी कॉल से 'np.einsum' तक की गति आ रही है, सुनिश्चित नहीं है कि' np.mean' उपयोग करता है। कंप्यूटिंग आंकड़ों के साथ यह एक जोखिम भरा बात है, क्योंकि आप संचयक को ओवरफ्लो कर सकते हैं और बहुत गलत परिणाम प्राप्त कर सकते हैं। 'Np.einsum'' dtype = np.float' या 'dtype = np.double' दोनों को गणना करना अधिक मजबूत बना देगा, और (मैं यहां अनुमान लगा रहा हूं) मानक कार्यों के प्रदर्शन में अधिक समान है। लेकिन 'np.einsum' अभी भी एक शानदार कूल फ़ंक्शन है, इसलिए आपको अपना +1 मिल गया है ... – Jaime

+0

@Jamie। यह मेरा विचार भी था, लेकिन मेरे आंतरिक परीक्षण में दिखाया गया कि 'ईन्सम' वास्तव में किसी भी आकार और प्रकार के लिए तेज़ था।मैंने पोस्ट को 'np.double' समय के साथ अपडेट किया है। – Daniel

+0

@ ओफियन ... यह अजीब बात है कि 'sum()' एक ही गति नहीं देता है जो 'einsum() '... बहुत अच्छी तरह से मनाया जाता है ... वास्तव में माध्य की गणना करने के लिए दूसरी तेज़ विधि होगी:' timeit a.sum (अक्ष = (1,2))/a.shape [-1] /a.shape [-2] ' –

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