Векторизация назначения тензора для среза в PyTorch - PullRequest
1 голос
/ 27 сентября 2019

Я пытаюсь векторизовать назначение фрагмента в форме

for i in range(a.shape[1]):
    for j in range(a.shape[2]):
        a[:,i,j,:,i:i+b.shape[2],j:j+b.shape[3]] = b

, где b сам является массивом.Это потому, что вложенный цикл Python слишком неэффективен и занимает большую часть времени выполнения.Есть ли способ сделать это?

В более простом случае рассмотрим следующее:

for i in range(a.shape[1]):
    a[:,i,:,i:i+b.shape[2]] = b

Вот как b и a могут выглядеть:

enter image description here

Вы можете видеть диагональную, «скользящую» структуру результирующей матрицы.

Ответы [ 2 ]

1 голос
/ 28 сентября 2019

Мы можем использовать np.lib.stride_tricks.as_strided на основе scikit-image's view_as_windows, чтобы получить скользящие оконные представления в 0s дополненной версии ввода, и представление будет эффективным для памяти ипредставление. Больше информации об использовании as_strided на основе view_as_windows.

Следовательно, для более простого случая это будет -

from skimage.util.shape import view_as_windows

def sliding_2D_windows(b, outshp_axis1):
    # outshp_axis1 is desired output's shape along axis=1
    n = outshp_axis1-1
    b1 = np.pad(b,((0,0),(0,0),(n,n)),'constant')
    w_shp = (1,b1.shape[1],b.shape[2]+n)
    return view_as_windows(b1,w_shp)[...,0,::-1,0,:,:]

Пример выполнения -

In [192]: b
Out[192]: 
array([[[54, 57, 74, 77],
        [77, 19, 93, 31],
        [46, 97, 80, 98]],

       [[98, 22, 68, 75],
        [49, 97, 56, 98],
        [91, 47, 35, 87]]])

In [193]: sliding_2D_windows(b, outshp_axis1=3)
Out[193]: 
array([[[[54, 57, 74, 77,  0,  0],
         [77, 19, 93, 31,  0,  0],
         [46, 97, 80, 98,  0,  0]],

        [[ 0, 54, 57, 74, 77,  0],
         [ 0, 77, 19, 93, 31,  0],
         [ 0, 46, 97, 80, 98,  0]],

        [[ 0,  0, 54, 57, 74, 77],
         [ 0,  0, 77, 19, 93, 31],
         [ 0,  0, 46, 97, 80, 98]]],


       [[[98, 22, 68, 75,  0,  0],
         [49, 97, 56, 98,  0,  0],
         [91, 47, 35, 87,  0,  0]],

        ....

        [[ 0,  0, 98, 22, 68, 75],
         [ 0,  0, 49, 97, 56, 98],
         [ 0,  0, 91, 47, 35, 87]]]])
0 голосов
/ 28 сентября 2019

Предполагая, что b имеет форму (2,3,x1), а a имеет форму (2,x2-x1+1,3,x2).На вашем скриншоте мы можем сделать вывод, что x1=4, x2=6.

import numpy as np

b_shape = (2,3,4)
a_shape = (2,3,3,6)

b = np.arange(1,25).reshape(b_shape)
#array([[[ 1,  2,  3,  4],
#        [ 5,  6,  7,  8],
#        [ 9, 10, 11, 12]],
#
#       [[13, 14, 15, 16],
#        [17, 18, 19, 20],
#        [21, 22, 23, 24]]])

c = np.pad(b, (*[(0,0) for _ in range(len(b_shape[:-1]))], (0,a_shape[-1]-b_shape[-1])), 'constant')

#array([[[ 1,  2,  3,  4,  0,  0],
#        [ 5,  6,  7,  8,  0,  0],
#        [ 9, 10, 11, 12,  0,  0]],
#
#       [[13, 14, 15, 16,  0,  0],
#        [17, 18, 19, 20,  0,  0],
#        [21, 22, 23, 24,  0,  0]]])

a = np.stack([np.roll(c, shift=i) for i in range(a_shape[-1]-b_shape[-1]+1)], axis=1)

# array([[[[ 1,  2,  3,  4,  0,  0],
#          [ 5,  6,  7,  8,  0,  0],
#          [ 9, 10, 11, 12,  0,  0]],

#         [[ 0,  1,  2,  3,  4,  0],
#          [ 0,  5,  6,  7,  8,  0],
#          [ 0,  9, 10, 11, 12,  0]],

#         [[ 0,  0,  1,  2,  3,  4],
#          [ 0,  0,  5,  6,  7,  8],
#          [ 0,  0,  9, 10, 11, 12]]],


#        [[[13, 14, 15, 16,  0,  0],
#          [17, 18, 19, 20,  0,  0],
#          [21, 22, 23, 24,  0,  0]],

#         [[ 0, 13, 14, 15, 16,  0],
#          [ 0, 17, 18, 19, 20,  0],
#          [ 0, 21, 22, 23, 24,  0]],

#         [[ 0,  0, 13, 14, 15, 16],
#          [ 0,  0, 17, 18, 19, 20],
#          [ 0,  0, 21, 22, 23, 24]]]])
...