2013-09-05 9 views
9

Bir dizim var ve 2x2 örtüşmeyen pencereleri tarayarak ve en yüksek değeri elde ederek daha küçük bir dizi oluşturmak istiyorum. Pencereli maksimum sayı

import numpy as np 

np.random.seed(123) 
np.set_printoptions(linewidth=1000,precision=3) 
arr = np.random.uniform(-1,1,(4,4)) 
res = np.zeros((2,2)) 
for i in xrange(res.shape[0]): 
    for j in xrange(res.shape[1]): 
     ii = i*2 
     jj = j*2 
     res[i][j] = max(arr[ii][jj],arr[ii+1][jj],arr[ii][jj+1],arr[ii+1][jj+1]) 

print arr 
print res 

Yani böyle bir matris

:
[[ 0.393 -0.428 -0.546 0.103] 
[ 0.439 -0.154 0.962 0.37 ] 
[-0.038 -0.216 -0.314 0.458] 
[-0.123 -0.881 -0.204 0.476]] 

bu duruma düşerse

: İşte bir örnek

[[ 0.439 0.962] 
[-0.038 0.476]]  

nasıl daha verimli yapabilirim?

+0

Bize neyi denediğinizi ve neden çalışmadığını gösterebilir misiniz? –

+0

Yukarıdaki kod gerekli işi yapıyor, ancak bu hızlı olması gerekiyor ve bu nedenle for döngüsü kaldırmak istiyorum –

+1

[NumBa] (http://numba.pydata.org/) kullanarak düşünün. Çift döngüsünü olduğu gibi bırakabilir, bir dekoratörde yaklaşık 10 karakter ekleyebilir ve bunun için C benzeri performans elde edebilirsiniz. Continuum Analytics'in ["Anaconda"] (https://store.continuum.io/cshop/anaconda/) Python dağıtımı ile çalışıyorsanız, kutudan çıkması kolay. – ely

cevap

9

Bunu yapabilirsin:

print arr.reshape(2,2,2,2).swapaxes(1,2).reshape(2,2,4).max(axis=-1) 

[[ 0.439 0.962] 
[-0.038 0.476]] 

ile başlayan açıklamak için: Biz ilk grubuyla alakalı bölüme eksenlerini istediğiniz

arr=np.array([[0.393,-0.428,-0.546,0.103], 
[0.439,-0.154,0.962,0.37,], 
[-0.038,-0.216,-0.314,0.458], 
[-0.123,-0.881,-0.204,0.476]]) 

.

tmp = arr.reshape(2,2,2,2).swapaxes(1,2) 
print tmp  

[[[[ 0.393 -0.428] 
    [ 0.439 -0.154]] 

    [[-0.546 0.103] 
    [ 0.962 0.37 ]]] 


[[[-0.038 -0.216] 
    [-0.123 -0.881]] 

    [[-0.314 0.458] 
    [-0.204 0.476]]]] 

yeniden şekillendirme kez veri gruplarını elde daha istiyoruz:

tmp = tmp.reshape(2,2,4) 
print tmp 

[[[ 0.393 -0.428 0.439 -0.154] 
    [-0.546 0.103 0.962 0.37 ]] 

[[-0.038 -0.216 -0.123 -0.881] 
    [-0.314 0.458 -0.204 0.476]]] 

Son olarak geçen eksen boyunca max alır. Size daha fazla bu genelleme yapabiliriz Jamie ve Dougal yorumlarına ardından

k = arr.shape[0]/2 
arr.reshape(k,2,k,2).swapaxes(1,2).reshape(k,k,4).max(axis=-1) 

:

Bu kadar kare matrisler için, genelleştirilmiş edilebilir

n = 2     #Height of window 
m = 2     #Width of window 
k = arr.shape[0]/n #Must divide evenly 
l = arr.shape[1]/m #Must divide evenly 
arr.reshape(k,n,l,m).max(axis=(-1,-3))    #Numpy >= 1.7.1 
arr.reshape(k,n,l,m).max(axis=-3).max(axis=-1)  #Numpy < 1.7.1 
+0

. teşekkürler –

+1

Dizilerin bölünebilir olmaları şartıyla, dizilerin kare olması için bir neden olmadığını unutmayın; bunu k = arr.shape [0]/n; l = arr.shape [1]/n; arr.reshape (k, n, l, n) .swapaxes (1, 2) .reshape (k, l, n * n) .max (eksen = -1) ', bence. – Dougal

+4

Son olarak, eksenleri değiştirdikten sonra yeniden biçimlendirmek, tam dizinin bir kopyasını tetikler; bu, büyük diziler için maliyetli olabilir.En iyi seçenek tümüyle atlamak ve (numpy> 1.7 kullanarak) '.max', yani 'arr.reshape (2,2,2,2) .max (eksen = (- 1, -)' ye bir eksen vermektir. 3)) 'Eğer daha eski bir sürüm ile sıkışmış olsanız bile, '.max', yani' arr.reshape (2,2,2,2) .max için iki çağrı yaparsanız, verilerin yarısını kopyalayacaksınız. (eksen = -3) .max (eksen = -1) '. – Jaime

2

ben yorum alanında belirtildiği gibi, NumBa kullanmayı düşünün. Çift döngüsünü olduğu gibi bırakabilir, bir dekoratörde yaklaşık 10 karakter ekleyebilir ve bunun için C benzeri performans elde edebilirsiniz. Continytity Analytics'in "Anaconda" Python dağıtımı ile çalışıyorsanız, kullanımı kolay kutu.

NumBa için neredeyse mükemmel bir kullanım örneğidir, çünkü bu algoritma çift döngüde daha doğal bir şekilde ifade edilir. Yeniden şekillendirme yaklaşımı hızlı dizi işlemlerini kullanır, ancak programın amacını zaten bilmedikçe son derece okunamaz. Bu gibi işlevleri genişletilmiş biçimde bırakmak ve gerçeğin ardından düşük seviyeli bir dile başka bir şeyin dönüşmesine izin vererek hız elde etmek son derece arzu edilir.

+0

Ben numba ve ilgili hızın farkındayım, ama saf bir numpy çözüm arıyordum. teşekkürler –

+4

Ben numba aslında bu sorun üzerinde ne kadar iyi olacağını merak ediyordum, bu yüzden bir şans verdim: http://nbviewer.ipython.org/c22a894f260d17876f01. Bu fonksiyonların biraz modifiye edilmiş versiyonlarımdaki testimde, 200x200'lik bir matriste, orijinal kod 100 ms sürdü, JIT'd sürüm numba ~ 85ms aldı ve @ Ophion'un sürümü 0,5 ms aldı. Scaling, 2k x 2k matris numba üzerinde 8s aldı ve Ophion's 64ms aldı. ~ 150x hızları muhtemelen okunabilirlik konusunda küçük bir kayıptır; Eğer yanlış bir şey yapıyorum eğer numba bu kadar kötü yapmak için neden biliyor musunuz? – Dougal

+0

Emin değilim, ama bu tür bir çekirdek için, bu çok sıradışı geliyor. Defterime bir bakacağım. – ely