2013-08-28 7 views
5

मैं एक पायथन मॉड्यूल लिख रहा हूं जिसे 1000+ सरणी (समान आयाम) में पिक्सेल मानों के माध्य और मानक विचलन की गणना करने की आवश्यकता है।1000 सरणी में आंकड़ों की गणना

मैं ऐसा करने का सबसे तेज़ तरीका ढूंढ रहा हूं।

वर्तमान में मैं सरणी के माध्यम से लूपिंग कर रहा हूं और 1000 सरणी को एक बड़े 3 डी सरणी में ढेर करने के लिए numpy.dstack का उपयोग कर रहा हूं ... और फिर तीसरे (?) आयाम में माध्य की गणना करेगा। प्रत्येक सरणी में आकार (5000,4000) होता है।

इस दृष्टिकोण में काफी समय लग रहा है!

क्या कोई इस समस्या के करीब आने की एक और अधिक प्रभावी विधि पर सलाह दे सकता है?

+0

कोई मौका आप हमें कुछ कोड दिखा सकते हैं? – arshajii

+2

उन्हें डस्टैक क्यों करें? एक लूप में प्रत्येक पर आंकड़ों की गणना क्यों न करें? – mgilson

+0

@mgilson: पाइथन में फॉर-लूप धीमे होते हैं, यदि वह धुरी कीवर्ड का उपयोग करता है, तो वह फॉर-लूप को नीचे (सी) तक धक्का दे सकता है, जो – usethedeathstar

उत्तर

2

हो सकता है कि आप इस (untested) की तरह एक संचयी तरह से कुछ में mean और std गणना कर सकते हैं:

im_size = (5000,4000) 

cum_sum = np.zeros(im_size) 
cum_sum_of_squares = np.zeros(im_size) 
n = 0 

for filename in filenames: 
    image = read_your_image(filename) 
    cum_sum += image 
    cum_sum_of_squares += image**2 
    n += 1 

mean_image = cum_sum/n 
std_image = np.sqrt(cum_sum_of_squares/n - (mean_image)**2) 

यह शायद कितनी तेजी से आप डिस्क से छवियों को पढ़ सकते हैं द्वारा सीमित है। यह स्मृति द्वारा सीमित नहीं है, क्योंकि आपके पास एक समय में स्मृति में केवल एक छवि है। std की गणना इस तरह से संख्यात्मक समस्याओं से ग्रस्त हो सकती है, क्योंकि आप दो बड़ी संख्याओं को घटा सकते हैं। यदि यह एक समस्या है तो आपको फ़ाइलों को दो बार लूप करना होगा, पहले माध्य की गणना करने के लिए और फिर दूसरे पास में (image - mean_image)**2 जमा करें।

1

प्रीलोकेट और भरें। इसने मेरे रनटाइम फॉर्म को लगभग 1000 सेकंड से 20 सेकंड

data_stack = numpy.empty((321, 720, 1000), dtype=numpy.float32) 
for index in range(len(data)): 
    data_stack[0:321,0:720,index] = data[index] 

मैं कुछ ऐसा ही कर रहा था। डस्टैक इस समस्या का अच्छा समाधान नहीं है। एक सहयोगी ने मुझे गतिशील सरणी समस्या और अमूर्त विश्लेषण की याद दिला दी। http://anh.cs.luc.edu/363/notes/06A_Amortizing.html

जब आप एक गतिशील सरणी का विस्तार करना चाहते हैं, तो आपको एक नया सरणी आवंटित करने की आवश्यकता है जो मूल डेटा और नया डेटा रख सके। फिर आप पुरानी सरणी को नई सरणी में और नए डेटा को नए सरणी में कॉपी करते हैं। यह एक महंगा ऑपरेशन है।

मान लें कि आपके पास आकार 10 की एक सरणी है और आप एक समय में 2 आइटम जोड़ना चाहते हैं। पहले आइटम को जोड़ने के लिए आपको सरणी को आकार 11 में विस्तारित करने और 11 आइटम (मूल 10 + 1 नई आइटम) में कॉपी करने की आवश्यकता है। दूसरी वस्तु को जोड़ने के लिए आपको सरणी को आकार 12 में विस्तारित करने और 12 आइटमों में प्रतिलिपि बनाने की आवश्यकता है। यदि आप समय से पहले जानते थे कि आप 2 आइटम जोड़ रहे थे तो आप शुरू करने के लिए सरणी को 12 में बदल सकते थे और केवल 23 आइटमों की बजाय 12 आइटम कॉपी कर सकते थे। यह पता चला है कि प्रत्येक बार जब आप बाहर निकलते हैं तो सरणी के आकार को दोगुना करना अंतरिक्ष का एक और अधिक कुशल समाधान है।

यह कैसे लागू होता है: dstack ndarray के आकार को दोगुना नहीं करता है, इसका मतलब केवल आवश्यक स्मृति जितना आवंटित करना है। तो हर बार जब आप डस्टैक को कॉल करते हैं तो आप अपने डेटा में अपने सभी डेटा को नए डेटा के लिए स्पेस के साथ एक नए ndarray में कॉपी कर रहे हैं। ध्यान दें कि प्रत्येक कॉल के साथ बढ़ने का समय।

0

यदि आप गणना समय को काफी कम करना चाहते हैं तो बहु थ्रेडिंग के लिए समाधान का चयन कर सकते हैं। this जैसे पायथन के लिए कई पुस्तकालय हैं।

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