Misalkan saya punya,

x = [[1 ,2],
     [3 ,4]]

Dan id ingin memiliki,

y = [[1 ,1 ,2 ,2],
     [1 ,1 ,2 ,2],
     [3 ,3 ,4 ,4],
     [3 ,3 ,4 ,4]]

Saya sudah melakukannya menggunakan pengulangan tetapi pertanyaan saya adalah, apakah ada cara dalam numpy murni yang lebih cepat dan vektor.

Pertanyaan kedua saya adalah, bagaimana Anda bisa downsaple secara efisien dari y kembali ke x?

Terima kasih dan semoga harimu menyenangkan :)

1
user15770670 12 Mei 2021, 17:29

3 jawaban

Jawaban Terbaik

Anda dapat mencoba yang ini: Menggunakan perkalian sederhana yang disiarkan diikuti dengan operasi transpose dan reshape.

x = np.array([[1, 2], [3, 4]])
m, n = x.shape
k = 2 # upsampling factor

tmp = x.reshape(-1, 1, 1) * np.ones((1, k, k))
y = tmp.reshape(m, n, k, k).transpose(0, 2, 1, 3).reshape(m*k, n*k)
print(y)
array([[1., 1., 2., 2.],
       [1., 1., 2., 2.],
       [3., 3., 4., 4.],
       [3., 3., 4., 4.]])

Untuk mendapatkan x kembali dari y, cukup balikkan operasi reshape dan transpose dan lakukan jenis operasi maxpool di sepanjang dua sumbu terakhir untuk mendapatkan kembali larik berbentuk m x n asli:

x = y.reshape(m, n, k, k).transpose(0, 2, 1, 3).max(axis = (2, 3))

Metode ini bekerja untuk semua bentuk array m x n dan faktor upsampling k.

1
swag2198 12 Mei 2021, 15:13

Jika Anda tidak peduli dengan bentuk keluaran, Anda dapat melakukan operasi ini hanya dengan mengubah metadata

x = np.array([[1, 2], [3, 4]])
np.lib.stride_tricks.as_strided(x, (4,2,2), (8,0,0))

Keluaran:

array([[[1, 1],
        [1, 1]],

       [[2, 2],
        [2, 2]],

       [[3, 3],
        [3, 3]],

       [[4, 4],
        [4, 4]]])

Selanjutnya, np.block akan memberikan bentuk output yang diinginkan (dengan menyalin)

x = np.lib.stride_tricks.as_strided(x, (4,2,2), (8,0,0))
np.block([[x[0], x[1]], 
          [x[2], x[3]]])

Keluaran:

array([[1, 1, 2, 2],
       [1, 1, 2, 2],
       [3, 3, 4, 4],
       [3, 3, 4, 4]])

np.block juga dapat disimulasikan dengan menggunakan transpose dan reshape:

x = np.lib.stride_tricks.as_strided(x, (1,2,2,2,2), (32,16,0,8,0))
x.reshape(4,4) # copy!

Keluaran:

array([[1, 1, 2, 2],
       [1, 1, 2, 2],
       [3, 3, 4, 4],
       [3, 3, 4, 4]])

Meskipun, ini akan menyalin memori seperti np.block. Anda dapat memverifikasi ini dengan mencoba menyetel bentuk secara langsung dengan x.shape = (4,4):

AttributeError: Incompatible shape for in-place modification. Use `.reshape()` to make a copy with the desired shape.

Dengan cara yang sama, output dapat di-down-sampling hanya dengan mengubah bentuk dan langkahnya:

np.lib.stride_tricks.as_strided(x, (2,2), (8*8,8*2))

Keluaran:

array([[1, 2],
       [3, 4]])

Perhatikan bahwa ini dilakukan tanpa penyalinan. Alasan saya mengalikan dengan 8 adalah karena ukurannya dalam byte dari bilangan bulat 64 bit.

Solusi yang dapat digeneralisasikan

def upsample(x, k):
    return np.lib.stride_tricks.as_strided(x, (np.prod(x.shape), k, k), (x.dtype.itemsize, 0, 0))
1
Kevin 12 Mei 2021, 16:21

Menggunakan np.kron() produk kronecker:

x = np.array([[1, 2], [3, 4]])
y = np.kron(x,np.ones((2,2))   # np.ones((n,n)) where n indicate the number of repetition. 
1
obchardon 12 Mei 2021, 15:04