2016-08-26 31 views
5

Bir m x n matrisi verildiğinde, Matematiği a x a (a = 3 veya a = 4) matrislerini rasgele ofset olarak (minimum sapma = 1, maksimum ofset = blok boyutu), Mathematica gibi Partition işlev yapar:Numpy - ofsetleri dikkate alan bir matrisi bölme

1 2 3 
5 6 7 
9 10 11 

2 3 4 
6 7 8 
10 11 12 

5 6 7 
9 10 11 
13 14 15 

6 7 8 
10 11 12 
14 15 16 
: 4 x 4 matris A I 3 x 3 blok vermek ve, bunun 4 matrisler almak isteyen = 1 Kayma
1 2 3 4 
5 6 7 8 
9 10 11 12 
13 14 15 16 

benzeri verilir Örneğin

,

matris AA = np.arange(1, 37).reshape((6,6)) ve = 3, istediğim ofset Ben çıktı olarak blokları 3 x 3 blok kullanıyorsanız:

1 2 3 
7 8 9 
3 14 15 

4 5 6 
10 11 12 
16 17 18 

19 20 21 
25 26 27 
31 32 33 

22 23 24 
28 29 30 
34 35 36 

Ben matrisi A listelerin bir listesini olmak Tamam ve ben düşünüyorum NumPy'in işlevselliğine ihtiyacım yok. Ne array_split ne de numpy.split'un bu ofset seçeneğini kutudan çıkarmamıza şaşırdım, bunu saf Python'da dilimleme ile kodlamak daha kolay mı yoksa Numpy'nin adımlarına bakmalı mıyım? Kodun okunaklı olmasını istiyorum. Eğer ipucu gibi

+0

Benzer sorular çalışırken veya sürgülü pencereler açısından deyim alır. Birisi iyi bir kopya bile bulabilir. – hpaulj

cevap

3

, orada strides

In [900]: M = np.lib.stride_tricks.as_strided(A, shape=(2,2,3,3), strides=(16,4,16,4)) 
In [901]: M 
Out[901]: 
array([[[[ 1, 2, 3], 
     [ 5, 6, 7], 
     [ 9, 10, 11]], 

     [[ 2, 3, 4], 
     [ 6, 7, 8], 
     [10, 11, 12]]], 


     [[[ 5, 6, 7], 
     [ 9, 10, 11], 
     [13, 14, 15]], 

     [[ 6, 7, 8], 
     [10, 11, 12], 
     [14, 15, 16]]]]) 
In [902]: M.reshape(4,3,3) # to get it in form you list 
Out[902]: 
array([[[ 1, 2, 3], 
     [ 5, 6, 7], 
     [ 9, 10, 11]], 

     [[ 2, 3, 4], 
     [ 6, 7, 8], 
     [10, 11, 12]], 

     [[ 5, 6, 7], 
     [ 9, 10, 11], 
     [13, 14, 15]], 

     [[ 6, 7, 8], 
     [10, 11, 12], 
     [14, 15, 16]]]) 

ile adımlarla bir sorunu bunu yapmanın bir yolu çok numpy tecrübesi olmayan birine anlatmak için gelişmiş ve sabit olmasıdır. Formu fazla deneme ve yanılma olmadan çözdüm, ama burada çok uzun zamandır asılıyorum. :)).

Ama bu iteratif çözüm açıklamak kolaydır: np.array(alist) ile bir dizi dönüştürülebilir

In [909]: alist=[] 
In [910]: for i in range(2): 
    ...:  for j in range(2): 
    ...:   alist.append(A[np.ix_(range(i,i+3),range(j,j+3))]) 
    ...:   
In [911]: alist 
Out[911]: 
[array([[ 1, 2, 3], 
     [ 5, 6, 7], 
     [ 9, 10, 11]]), 
array([[ 2, 3, 4], 
     [ 6, 7, 8], 
     [10, 11, 12]]), 
array([[ 5, 6, 7], 
     [ 9, 10, 11], 
     [13, 14, 15]]), 
array([[ 6, 7, 8], 
     [10, 11, 12], 
     [14, 15, 16]])] 

. Açıksa, bunu kullanmakta yanlış bir şey yoktur. o bir görünümdür ve M değişiklikler A değişebilir ve M tek bir yerde bir değişiklik M birkaç yerde değiştirebileceğini as_strided yaklaşımı hakkında akılda tutulması gereken

bir şey olduğunu. Ancak, M yeniden biçimlendirmek, bir kopyaya dönüştürebilir. Genel olarak M değerlerini okumak ve sum ve mean gibi hesaplamalar için bunları kullanmak daha güvenlidir. Yerinde değişiklikler öngörülemez olabilir.

Yinelemeli çözüm, her yerinde kopyalar üretir.

np.ogrid yerine np.ix_ ile tekrarlı çözeltisi (aksi takdirde aynı fikri):

In [970]: np.ogrid[0:3, 0:3] 
Out[970]: 
[array([[0], 
     [1], 
     [2]]), array([[0, 1, 2]])] 
:

np.array([A[np.ogrid[i:i+3, j:j+3]] for i in range(2) for j in range(2)]) 

hem ix_ ve ogrid bir blok indeksleme için vektörlerin çifti oluşturmak sadece kolay yolu vardır

Aynı şey ama slice numaralı nesneler:

np.array([A[slice(i,i+3), slice(j,j+3)] for i in range(2) for j in range(2)]) 

Bunun liste sürümü, as_strided çözümüyle (listenin öğeleri görünümlerdir) benzer view davranışına sahip olur. örtüşmeyen bloklarla 6x6 için

, deneyin:

In [1016]: np.array([A[slice(i,i+3), slice(j,j+3)] for i in range(0,6,3) for j i 
     ...: n range(0,6,3)]) 
Out[1016]: 
array([[[ 1, 2, 3], 
     [ 7, 8, 9], 
     [13, 14, 15]], 

     [[ 4, 5, 6], 
     [10, 11, 12], 
     [16, 17, 18]], 

     [[19, 20, 21], 
     [25, 26, 27], 
     [31, 32, 33]], 

     [[22, 23, 24], 
     [28, 29, 30], 
     [34, 35, 36]]]) 

Eğer bitişik bloklar istediğiniz varsayarsak, iç dilimler/aralıkları dış i ve j

için, sadece adımlamasını değişmez
In [1017]: np.arange(0,6,3) 
Out[1017]: array([0, 3]) 
+0

@hpauji teşekkürler, 'np.ix_' sürümünü beğendim ve bunun kolay bir şekilde kullanılacağını düşündüm, ancak ofseti belirlerken başka bir matris üzerinde çalışmasını alamıyorum, örneğin np A = np.arange (1, 37) .reshape ((6,6)) baskı aralığında i için bir alist = [] blok boyutu = 3 offset = 3 (0, blok boyutu -1, ofset): j aralığında (0, blockSize -1, offset): alist.append (A [np.ix_ (aralık (i, i + blockSize, offset), aralık (j, j + blockSize, offset))]) np.array (alist) 'her iki ofset 3 ve 1 ile başarısız olur, bunu nasıl düzeltebilirim? – andandandand

+0

Bu yorumu, okumak için bir editöre ve satır sonlarına eklemeliydim. Bu ofsetin amacı nedir? "Aralığında" ise 3 değer "adım" dır. – hpaulj

+0

, sürgülü pencere geçişi gibi bloklar arasındaki uzaklıktır. A = np.arange (1, 37) .reshape ((6,6)) 'da 3 x 3 blok için 3 ofseti 'np.split'den (A, 3) alacağı 4 blok verir.) '. Göstermek için soruyu genişlettim. – andandandand