2013-01-23 12 views
13

संपादित करें मैंने नीचे की जटिल समस्या को नीचे रखा है, लेकिन np.take के साथ मेरी समस्याएं निम्नानुसार संक्षेप में सारांशित की जा सकती हैं। मान लें कि आपके पास आकार (planes, rows) का आकार है, और आकार का एक और सरणी lut है, और आप (planes, rows) आकार के नए सरणी out बनाने के लिए उनका उपयोग करना चाहते हैं। यह कल्पना अनुक्रमण के साथ इस प्रकार प्राप्त किया जा सकता:तेजी से फैंसी इंडेक्सिंग के लिए numpy.take का उपयोग

In [4]: %timeit lut[np.arange(planes).reshape(-1, 1), img] 
1000 loops, best of 3: 471 us per loop 

लेकिन अगर, फैंसी अनुक्रमण के बजाय, आप और लेने का उपयोग planes बातों पर एक अजगर पाश काफी तेज किया जा सकता है:

In [6]: %timeit for _ in (lut[j].take(img[j]) for j in xrange(planes)) : pass 
10000 loops, best of 3: 59 us per loop 

कर सकते हैं lut और img किसी भी तरह से पुन: व्यवस्थित हो, ताकि पूरा ऑपरेशन पाइथन लूप के बिना हो, लेकिन गति लाभ रखने के लिए परंपरागत फैंसी इंडेक्सिंग के बजाय numpy.take (या वैकल्पिक विधि) का उपयोग करना?


मूल प्रश्न मैं लुक-अप टेबल (luts) है कि मैं एक छवि पर उपयोग करना चाहते हैं का एक सेट है। एलयूटी धारण करने वाला सरणी (planes, 256, n) आकार का है, और छवि (planes, rows, cols) आकार है। दोनों dtype = 'uint8' हैं, जो LUT के 256 धुरी से मेल खाते हैं। विचार pn LUTs के p LUT के प्रत्येक विमान के माध्यम से छवि के प्रत्येक विमान को p चलाने के लिए है।

अगर मेरे lut और img निम्नलिखित हैं:

planes, rows, cols, n = 3, 4000, 4000, 4 
lut = np.random.randint(-2**31, 2**31 - 1, 
         size=(planes * 256 * n // 4,)).view('uint8') 
lut = lut.reshape(planes, 256, n) 
img = np.random.randint(-2**31, 2**31 - 1, 
        size=(planes * rows * cols // 4,)).view('uint8') 
img = img.reshape(planes, rows, cols) 

मैं प्राप्त कर सकते हैं इस

out = lut[np.arange(planes).reshape(-1, 1, 1), img] 

जो मुझे आकार (planes, rows, cols, n) की एक सरणी देता है, जहां out[i, :, :, j] की तरह कल्पना अनुक्रमण उपयोग करने के बाद मैं क्या हूँ i- img का विमान j के माध्यम से चलाया गया है- i- LUT के केंद्र ...

सभी अच्छा है, इस के अलावा:

In [2]: %timeit lut[np.arange(planes).reshape(-1, 1, 1), img] 
1 loops, best of 3: 5.65 s per loop 

जो पूरी तरह से अस्वीकार्य है, खासकर जब से मैं np.take का उपयोग कर निम्नलिखित इतना अच्छा नहीं लग रही विकल्प के सभी की तुलना में बहुत तेजी से चलाने के:

  1. एक एकल विमान पर एक एकल LUT लगभग x70 तेज़ चलता है:

    In [2]: %timeit np.take(lut[0, :, 0], img[0]) 
    10 loops, best of 3: 78.5 ms per loop 
    
  2. एक अजगर पाश सभी वांछित संयोजन के माध्यम से चल तेजी से लगभग x6 खत्म:

    In [2]: %timeit for _ in (np.take(lut[j, :, k], img[j]) for j in xrange(planes) for k in xrange(n)) : pass 
    1 loops, best of 3: 947 ms per loop 
    
  3. यहां तक ​​कि lut और छवि में विमानों के सभी संयोजनों चल रहा है और उसके बाद planes**2 - planes अवांछित लोगों को त्यागकर फैंसी अनुक्रमण की तुलना में तेजी है:

    In [2]: %timeit np.take(lut, img, axis=1)[np.arange(planes), np.arange(planes)] 
    1 loops, best of 3: 3.79 s per loop 
    
  4. और सबसे तेजी से संयोजन मैं साथ आने के लिए सक्षम किया गया है विमानों पर एक अजगर पाश-बार दोहराना है और तेजी से x13 खत्म:

    In [2]: %timeit for _ in (np.take(lut[j], img[j], axis=0) for j in xrange(planes)) : pass 
    1 loops, best of 3: 434 ms per loop 
    

पाठ्यक्रम का सवाल यह है कि np.take के साथ कोई पाइथन लूप के बिना ऐसा करने का कोई तरीका नहीं है? आदर्श रूप से जो कुछ भी दोबारा बदलना या आकार बदलना आवश्यक है, एलयूटी पर होना चाहिए, छवि नहीं, लेकिन मैं जो कुछ भी लोगों के साथ आ सकता हूं उसके लिए खुला हूं ...

+0

क्या 'अपने स्निपेट में bkpt' है - समझाने की कोई जरूरत नहीं है, मैं सिर्फ मामले में आप अपने मुद्रण की गलती सतर्क करना चाहता हूँ - मुझे लगता है कि यह 'लूट' होना चाहिए? –

+0

... इस पूरे लाइन को 'lut = lut.reshape (विमान, 256, 4)', तो अंतिम मंद में '4' नहीं पढ़ना चाहिए? –

+0

@TheodrosZelleke उनको पकड़ने के लिए धन्यवाद! मेरा 'लूट' वास्तव में एक ** ब्रेकपॉइंट टेबल ** है, इसलिए मेरे कोड में इसे 'बीकेपीटी' कहा जाता है, और जब मैं प्रश्न के लिए * अनुवाद * करता हूं तो मुझे याद आया। – Jaime

उत्तर

5

मुझे लगता है कि मुझे वास्तव में आपका प्रश्न पसंद आया। LUT या IMG उलटफेर के बिना निम्नलिखित समाधान काम किया:

%timeit a=np.take(lut, img, axis=1) 
# 1 loops, best of 3: 1.93s per loop 

लेकिन परिणाम से आप विकर्ण क्वेरी करने के लिए है: एक [0,0], एक [1,1], एक [2,2]; आप जो चाहते हैं उसे प्राप्त करने के लिए। मैंने केवल विकर्ण तत्वों के लिए इस अनुक्रमण को करने का एक तरीका खोजने का प्रयास किया है, लेकिन अभी भी इसका प्रबंधन नहीं हुआ है। निम्नलिखित काम करता है अगर IMG में अनुक्रमित 1 विमान, 256-511 2 विमान के लिए के लिए, 0-255 से हैं, और 512-767 3 के लिए:

यहाँ अपने LUT और IMG पुनर्व्यवस्थित करने के लिए कुछ तरीके हैं विमान है, लेकिन है कि आप 'uint8' का उपयोग करने से रोका जा सके, जो एक बड़ा मुद्दा हो सकता है ...:

lut2 = lut.reshape(-1,4) 
%timeit np.take(lut2,img,axis=0) 
# 1 loops, best of 3: 716 ms per loop 
# or 
%timeit np.take(lut2, img.flatten(), axis=0).reshape(3,4000,4000,4) 
# 1 loops, best of 3: 709 ms per loop 
मेरी मशीन में

अपने समाधान अभी भी सबसे अच्छा विकल्प है, और बहुत पर्याप्त के बाद से आप सिर्फ विकर्ण मूल्यांकन की जरूरत है, यानी विमान 1-प्लेन 1, प्लेन 2-प्लेन 2 और प्लेन 3-प्लेन 3:

%timeit for _ in (np.take(lut[j], img[j], axis=0) for j in xrange(planes)) : pass 
# 1 loops, best of 3: 677 ms per loop 

मुझे उम्मीद है कि यह आपको एक बेहतर समाधान के बारे में कुछ अंतर्दृष्टि दे सकता है। flatten() के साथ और अधिक विकल्प देखने के लिए अच्छा लगेगा, और np.apply_over_axes() या np.apply_along_axis() जैसी ही विधियां, जो आशाजनक प्रतीत होती हैं।

मैं डेटा उत्पन्न करने के लिए नीचे दिए गए इस कोड का इस्तेमाल किया:

import numpy as np 
num = 4000 
planes, rows, cols, n = 3, num, num, 4 
lut = np.random.randint(-2**31, 2**31-1,size=(planes*256*n//4,)).view('uint8') 
lut = lut.reshape(planes, 256, n) 
img = np.random.randint(-2**31, 2**31-1,size=(planes*rows*cols//4,)).view('uint8') 
img = img.reshape(planes, rows, cols) 
संबंधित मुद्दे