2015-09-29 27 views
8

Ben MxN olan tamsayılar bir 2D dizi var döşeme yakın komşusu tarafından numpy dizi upsample için, ben için diziyi genişletmek istiyorum (BM) x (BN)B olduğu Bir kare kiremit tarafının uzunluğu dolayısıyla, giriş dizisinin her elemanı son dizide BxB blok olarak tekrarlanır. Aşağıda, iç içe geçmiş bir döngü ile bir örnek verilmiştir. Daha hızlı/yerleşik bir yolu var mı?Hızlı yolu

import numpy as np 

a = np.arange(9).reshape([3,3])   # input array - 3x3 
B=2.          # block size - 2 
A = np.zeros([a.shape[0]*B,a.shape[1]*B]) # output array - 6x6 

# Loop, filling A with tiled values of a at each index 
for i,l in enumerate(a):     # lines in a 
    for j,aij in enumerate(l):    # a[i,j] 
     A[B*i:B*(i+1),B*j:B*(j+1)] = aij 

Sonucu ...

a=  [[0 1 2] 
     [3 4 5] 
     [6 7 8]] 

A =  [[ 0. 0. 1. 1. 2. 2.] 
     [ 0. 0. 1. 1. 2. 2.] 
     [ 3. 3. 4. 4. 5. 5.] 
     [ 3. 3. 4. 4. 5. 5.] 
     [ 6. 6. 7. 7. 8. 8.] 
     [ 6. 6. 7. 7. 8. 8.]] 

cevap

11

Seçeneklerden biri nedeniyle ara diziye

>>> a.repeat(2, axis=0).repeat(2, axis=1) 
array([[0, 0, 1, 1, 2, 2], 
     [0, 0, 1, 1, 2, 2], 
     [3, 3, 4, 4, 5, 5], 
     [3, 3, 4, 4, 5, 5], 
     [6, 6, 7, 7, 8, 8], 
     [6, 6, 7, 7, 8, 8]]) 

Bu biraz savurgan olduğunu ama en azından özlü bulunuyor.

3
Muhtemelen

değil hızlı ama ..

np.kron(a, np.ones((B,B), a.dtype)) 

O Kronecker product yapar, bu nedenle çıktı her öğesi için bir çarpma içerir.

11

İşte adım hileler kullanarak ve yeniden şekillendirilmesi potansiyel hızlı bir şekilde açıklanmıştır: reshape çağrıldığında a yılında

from numpy.lib.stride_tricks import as_strided 

def tile_array(a, b0, b1): 
    r, c = a.shape         # number of rows/columns 
    rs, cs = a.strides        # row/column strides 
    x = as_strided(a, (r, b0, c, b1), (rs, 0, cs, 0)) # view a as larger 4D array 
    return x.reshape(r*b0, c*b1)      # create new 2D array 

temel veri kopyalanır, dolayısıyla bu işlev bir görünüm döndürmez. Ancak, çoklu eksenler boyunca repeat kullanımıyla karşılaştırıldığında, daha az kopyalama işlemi gereklidir.

>>> a = np.arange(9).reshape(3, 3) 
>>> a 
array([[0, 1, 2], 
     [3, 4, 5], 
     [6, 7, 8]]) 

>>> tile_array(a, 2, 2) 
array([[0, 0, 1, 1, 2, 2], 
     [0, 0, 1, 1, 2, 2], 
     [3, 3, 4, 4, 5, 5], 
     [3, 3, 4, 4, 5, 5], 
     [6, 6, 7, 7, 8, 8], 
     [6, 6, 7, 7, 8, 8]]) 

>>> tile_array(a, 3, 4) 
array([[0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], 
     [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], 
     [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], 
     [3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5], 
     [3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5], 
     [3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5], 
     [6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8], 
     [6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8], 
     [6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8]]) 

Şimdi küçük bloklar için bu yöntem biraz repeat kullanmaktan daha yavaş fakat daha hızlı kron aşağıdaki gibidir:

işlevi

sonra kullanılabilir. Bununla birlikte, biraz daha büyük bloklar için, diğer alternatiflerden daha hızlı bir hale gelmektedir. Örneğin, (20, 20) bir blok şeklini kullanarak:

>>> %timeit tile_array(a, 20, 20) 
100000 loops, best of 3: 18.7 µs per loop 

>>> %timeit a.repeat(20, axis=0).repeat(20, axis=1) 
10000 loops, best of 3: 26 µs per loop 

>>> %timeit np.kron(a, np.ones((20,20), a.dtype)) 
10000 loops, best of 3: 106 µs per loop 

blok boyutu arttıkça yöntemler artışları arasındaki boşluk.

>>> a2 = np.arange(1000000).reshape(1000, 1000) 
>>> %timeit tile_array(a2, 2, 2) 
100 loops, best of 3: 11.4 ms per loop 

>>> %timeit a2.repeat(2, axis=0).repeat(2, axis=1) 
1 loops, best of 3: 30.9 ms per loop 
: a Büyük bir dizi halinde

Ayrıca, alternatiflerden daha hızlı olabilir