2015-11-18 3 views
5

मैंने पायथन में कुछ कोड लिखा जो ठीक काम करता है लेकिन बहुत धीमा है; मुझे लगता है कि लूप के कारण। मुझे उम्मीद है कि कोई numpy कमांड का उपयोग कर निम्न परिचालनों को तेज कर सकता है। मुझे लक्ष्य को परिभाषित करने दें।लूप के लिए numpy vectorization

मान लीजिए कि मेरे पास 2 डी numpy सरणी all_CMs आयाम row x col है। उदाहरण के लिए 6 x 11 सरणी पर विचार करें (नीचे चित्र देखें)।

  1. मैं, सभी पंक्तियों के लिए मतलब की गणना करने के अर्थात राशि ⱼ aᵢⱼ एक सरणी में जिसके परिणामस्वरूप चाहते हैं। यह, निश्चित रूप से आसानी से किया जा सकता है। (मैं यह मान फोन CM_tilde)

  2. अब, के लिए प्रत्येक पंक्ति मैं उनका योग कंप्यूटिंग और सभी स्तंभों की संख्या से विभाजित करके कुछ चयनित मूल्यों, अर्थात् एक निश्चित सीमा से नीचे के सभी मूल्यों का मतलब गणना करना चाहते हैं (N)। यदि मान इस परिभाषित दहलीज से ऊपर है, तो CM_tilde मान (संपूर्ण पंक्ति का माध्य) जोड़ा जाता है। यह मान CM

  3. बाद में कहा जाता है, CM मूल्य

इसके अलावा इस के लिए पंक्ति में प्रत्येक तत्व से घटाया जाता है मैं एक numpy सरणी या सूची जहां उन सभी CM मूल्यों सूचीबद्ध हैं करना चाहते हैं ।

आंकड़ा:

figure

निम्नलिखित कोड काम कर रहा है लेकिन बहुत धीमी गति से (सरणियों बड़ी हो रही है, खासकर अगर)

CM_tilde = np.mean(data, axis=1) 
N = data.shape[1] 
data_cm = np.zeros((data.shape[0], data.shape[1], data.shape[2])) 
all_CMs = np.zeros((data.shape[0], data.shape[2])) 
for frame in range(data.shape[2]): 
    for row in range(data.shape[0]): 
     CM=0 
     for col in range(data.shape[1]): 
      if data[row, col, frame] < (CM_tilde[row, frame]+threshold): 
       CM += data[row, col, frame] 
      else: 
       CM += CM_tilde[row, frame] 
     CM = CM/N 
     all_CMs[row, frame] = CM 
     # calculate CM corrected value 
     for col in range(data.shape[1]): 
      data_cm[row, col, frame] = data[row, col, frame] - CM 
    print "frame: ", frame 
return data_cm, all_CMs 

कोई भी विचार?

+0

चरण 2 में, आप अनिवार्य रूप से CM_tilde द्वारा treshold से ऊपर है कि किसी भी मूल्य की जगह है, और * तो * पूरी पंक्ति से अधिक मतलब की गणना, प्रतिस्थापित मान सहित? – Evert

+0

अपने आंतरिक लूप को प्रतिस्थापित करने के लिए 'np.where' का उपयोग करके प्रारंभ करें। फिर, प्रसारण का उपयोग करके, आप बाहरी 2 loops को हटा सकते हैं। [जहां] (http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.where.html) के लिए प्रलेखन देखें – mtadd

उत्तर

12

यह आप क्या कर रहे vectorize करने के लिए काफी आसान है:

import numpy as np 

#generate dummy data 
nrows=6 
ncols=11 
nframes=3 
threshold=0.3 
data=np.random.rand(nrows,ncols,nframes) 

CM_tilde = np.mean(data, axis=1) 
N = data.shape[1] 

all_CMs2 = np.mean(np.where(data < (CM_tilde[:,None,:]+threshold),data,CM_tilde[:,None,:]),axis=1) 
data_cm2 = data - all_CMs2[:,None,:] 

आपकी मूल सामग्री के साथ इस तुलना:

In [684]: (data_cm==data_cm2).all() 
Out[684]: True 

In [685]: (all_CMs==all_CMs2).all() 
Out[685]: True 

तर्क है कि हम एक साथ आकार [nrows,ncols,nframes] की सरणियों के साथ काम करते हैं। मुख्य चाल है कि CM_tilde आकार [nrows,nframes] आकार [nrows,1,nframes] के CM_tilde को बदलकर, पाइथन के प्रसारण का उपयोग करना है। पाइथन तब प्रत्येक कॉलम के लिए समान मानों का उपयोग करेगा, क्योंकि यह इस संशोधित CM_tilde का सिंगलटन आयाम है।

np.where का उपयोग कर हम फिर से (threshold के आधार पर) का चयन हम data संबंधित मान प्राप्त करना चाहते हैं, या,, CM_tilde के प्रसारण मूल्य तक। np.mean का एक नया उपयोग हमें all_CMs2 पर गणना करने की अनुमति देता है।

अंतिम चरण में हमने data के संबंधित तत्वों से सीधे इस नए all_CMs2 को घटाकर प्रसारण का उपयोग किया।

यह आपके अस्थायी चर के निहित सूचकांक को देखकर इस तरह वेक्टरिंग कोड में मदद कर सकता है। मेरा मतलब यह है कि आपका अस्थायी परिवर्तनीय CM[nrows,nframes] पर लूप के अंदर रहता है, और इसका मान प्रत्येक पुनरावृत्ति के साथ रीसेट किया जाता है। इसका मतलब है कि CM प्रभाव CM[row,frame] (बाद में स्पष्ट रूप से 2 डी सर all_CMs को असाइन किया गया है), और यहां से यह देखना आसान है कि आप इसे अपने कॉलम आयाम के साथ उपयुक्त CMtmp[row,col,frames] मात्रा एकत्र करके इसे बना सकते हैं। यदि यह मदद करता है, तो आप इस उद्देश्य के लिए np.where(...) भाग CMtmp के रूप में नाम दे सकते हैं, और उसके बाद np.mean(CMtmp,axis=1) की गणना कर सकते हैं। वही परिणाम, जाहिर है, लेकिन शायद अधिक पारदर्शी।

+0

बहुत बहुत धन्यवाद; लूप – pallago

+1

10001 की तुलना में यह बहुत तेज है प्रतिनिधि के लिए एक अच्छा मूल्य है, अगर कोई इसे कम करता है तो यह शर्म की बात होगी। –

+0

@ भार्गवराव \ o/धन्यवाद, महोदय! :) या, डाउनवॉटिंग के लिए धन्यवाद: डी –

1

यहां आपके फ़ंक्शन का मेरा सदिशकरण है। मैंने अंदर से काम किया, और साथ ही साथ गए संस्करणों के बारे में टिप्पणी की। तो पहले लूप जिसे मैंने सदिश किया है ### टिप्पणी अंक है।

यह @Andras's उत्तर के रूप में साफ और अच्छी तरह से तर्कसंगत नहीं है, लेकिन उम्मीद है कि यह निर्देशक है, इस बारे में एक विचार देकर कि आप इस मुद्दे को कैसे बढ़ा सकते हैं।

def foo2(data, threshold): 
    CM_tilde = np.mean(data, axis=1) 
    N = data.shape[1] 
    #data_cm = np.zeros((data.shape[0], data.shape[1], data.shape[2])) 
    ##all_CMs = np.zeros((data.shape[0], data.shape[2])) 
    bmask = data < (CM_tilde[:,None,:] + threshold) 
    CM = np.zeros_like(data) 
    CM[:] = CM_tilde[:,None,:] 
    CM[bmask] = data[bmask] 
    CM = CM.sum(axis=1) 
    CM = CM/N 
    all_CMs = CM.copy() 
    """ 
    for frame in range(data.shape[2]): 
     for row in range(data.shape[0]): 
      ###print(frame, row) 
      ###mask = data[row, :, frame] < (CM_tilde[row, frame]+threshold) 
      ###print(mask) 
      ##mask = bmask[row,:,frame] 
      ##CM = data[row, mask, frame].sum() 
      ##CM += (CM_tilde[row, frame]*(~mask)).sum() 

      ##CM = CM/N 
      ##all_CMs[row, frame] = CM 
      ## calculate CM corrected value 
      #for col in range(data.shape[1]): 
      # data_cm[row, col, frame] = data[row, col, frame] - CM[row,frame] 
     print "frame: ", frame 
    """ 
    data_cm = data - CM[:,None,:] 
    return data_cm, all_CMs 

आउटपुट इस छोटे परीक्षण मामले के लिए मेल खाता है, जो किसी भी चीज़ से मुझे आयामों को सही करने में मदद करता है।

threshold = .1 
data = np.arange(4*3*2,dtype=float).reshape(4,3,2) 
संबंधित मुद्दे