Как я могу применить один и тот же набор значений в различных позициях в большем массиве, указанном масками? - PullRequest
0 голосов
/ 08 марта 2020

У меня есть двумерный массив Y измерений N x N и массив K двоичных масок X, каждое из измерений M x M (поэтому X имеет форму K x M x M). Каждая двоичная маска в X имеет ровно один N x N патч единиц, а остальные элементы равны нулю. Я хотел бы создать K x M x M массив Z, с элементами Y в местах, указанных X, и нулем везде.

Например, если M = 3, N = 2, K = 3 и

X = [[[1., 1., 0.],
     [1., 1., 0.],
     [0., 0., 0.]],

    [[0., 1., 1.],
     [0., 1., 1.],
     [0., 0., 0.]],

    [[0., 0., 0.],
     [0., 1., 1.],
     [0., 1., 1.]]]

и

Y = [[0.1, 0.2],
    [0.3, 0.4]]

, тогда Z должно быть

Z = [[[0.1, 0.2, 0.],
     [0.3, 0.4, 0.],
     [0., 0., 0.]],

    [[0., 0.1, 0.2],
     [0., 0.3, 0.4],
     [0., 0., 0.]],

    [[0., 0., 0.],
     [0., 0.1, 0.2],
     [0., 0.3, 0.4]]]

Я хотел бы сделать это, используя функции либо от Numpy или Pytorch. Я подумал, что возможно сделать это, используя numpy.where(), возможно, как

Z = numpy.zeros((3,3,3))
Z[numpy.where(X == 1)] = Y

, но это дает ошибку несоответствия формы.

Что было бы наиболее кратким и эффективным способом сделать это (кроме явного использования циклов для установки значений)?

Ответы [ 3 ]

2 голосов
/ 08 марта 2020

Попробуйте это:

X[X == 1] = np.tile(Y.flatten(), X.shape[0])
1 голос
/ 08 марта 2020

Вы можете изменить маску на индекс, а затем изменить форму, чтобы использовать широковещательную передачу:

idx = *np.reshape(X.nonzero(),(3,3,2,2)),
Z = np.zeros_like(X)
Z[idx] = Y
Z
array([[[0.1, 0.2, 0. ],
        [0.3, 0.4, 0. ],
        [0. , 0. , 0. ]],

       [[0. , 0.1, 0.2],
        [0. , 0.3, 0.4],
        [0. , 0. , 0. ]],

       [[0. , 0. , 0. ],
        [0. , 0.1, 0.2],
        [0. , 0.3, 0.4]]])

или то же самое с помощью плоской индексации:

idx = X.ravel().nonzero()[0].reshape(3,4)
Z = np.zeros_like(X)
Z.ravel()[idx] = Y.ravel()
1 голос
/ 08 марта 2020

Обращаясь к числовому примеру, вы можете использовать:

Z[X==1] = np.tile(Y.reshape(-1,),3)
Z

array([[[0.1, 0.2, 0. ],
       [0.3, 0.4, 0. ],
        [0. , 0. , 0. ]],

       [[0. , 0.1, 0.2],
        [0. , 0.3, 0.4],
        [0. , 0. , 0. ]],

       [[0. , 0. , 0. ],
        [0. , 0.1, 0.2],
        [0. , 0.3, 0.4]]])

Для общего случая вам нужно только заменить K вместо 3 в np.tile.

...