Перебор матриц в списке остановился на NumPy - PullRequest
0 голосов
/ 31 мая 2019

Я хотел бы перебрать матрицу матриц (действительно, звучит странно),

import numpy as np

ar = np.array

A = ar([[[1,2,3],[4,5,6],[7,8,9]],[[11,12,13],[14,15,16],[17,18,19]], [[1,2,3],[4,5,6],[7,8,9]], [[20,21,22],[23,24,25],[26,27,28]]])

B = np.copy(A)
C = np.copy(A)

im = np.array([A,B,C])

для получения матрицы, в которой хранятся значения (x, y) позиции в последующих матрицах. Например, в [1, 2, 3] для позиции 1 это означает: A [0,0,0], в следующих матрицах появятся только единицы. Таким образом я получу массив в новой матрице (учитывая также A [0,0,1] и A [0,0,2]):

[[1  1  1] [2  2  2] [3  3  3]]

Поэтому для первого массива A:

[[[1  1  1] [2  2  2] [3  3  3]]
[[4  4  4] [5  5  5] [6  6  6]]
[[7  7  7] [8  8  8] [9  9  9]]]

Я создал эту функцию:

def loop_ar(arr):
    matrix, v, c, s = arr.shape
    new = np.zeros((v,c,s,matrix)) #The columns in the last array of new represent the subsequent arrays
    for x in range(v):
        for y in range(c):
            for s in range(s):
                for ma in range(matrix):
                    new[x,y,s,ma] = arr[ma, x, y, s]
    return new

Однако выходные данные указывают, что матрица прекращает итерацию после нескольких оборотов:

[[[[1. 1. 1.]
   [2. 2. 2.]
   [3. 3. 3.]]

  [[4. 4. 4.]
   [5. 5. 5.]
   [0. 0. 0.]]

  [[7. 7. 7.]
   [0. 0. 0.]
   [0. 0. 0.]]]


 [[[0. 0. 0.]
   [0. 0. 0.]
   [0. 0. 0.]]

  [[0. 0. 0.]
   [0. 0. 0.]
   [0. 0. 0.]]

  [[0. 0. 0.]
   [0. 0. 0.]
   [0. 0. 0.]]]

   ...

Когда я тестировал эту функцию в списке списков, она работала. Что случилось в этом случае? Как я могу это исправить? Это всего лишь простой случай, чтобы проиллюстрировать мои ожидания; Тем не менее, я хотел бы знать решение более сложной проблемы, когда B и C не являются копиями A. Как я могу заставить цикл затем повторяться?

B и C в более сложном случае должны иметь ту же форму, что и A, однако они будут отличаться в последнем массиве. Как и в А мы имеем:

[1  2  3]

в B мы бы, например, находились в той же позиции:

[23  34  56]

и в C:

[54  43  32]

Поэтому новая матрица будет включать массив:

[[1  23  54]  [2  34  43]  [3  56  32]]

Я выполнил эту задачу (надеюсь на это), преобразовав список в массив, потому что loop_arr работал для списков. Тем не менее, это окольный путь. Я хочу решение и объяснение прерывания в цикле.

Здесь я привожу случайные данные для более сложного вопроса:

A = ar([[[1,2,3],[4,5,6],[7,8,9]],[[11,12,13],[14,15,16],[17,18,19]],[[20,21,22],[23,24,25],[26,27,28]]])

B = ar([[[23,34,56], [56, 78, 90], [12, 34, 32]], [[74,75,65], [25,57,76], [90,24,35]]])

C = ar([[[13,31,53], [54,96,69], [78, 90, 99]], [[35,64,66], [13,35,53], [37,73,61]], [[62, 87,97], [80,35,62], [75,76,67]]]

Новая матрица будет выглядеть так:

[[[[1  23  13]  [2  34  31]  [3  56  53]]
[[4  56  54]  [5  78  96] [6  90  69]]
[[7  12  78]  [8  34  90]  [9  32  99]]]
      ...so on, so on, so on...
                                     ]]]]

Ответы [ 2 ]

1 голос
/ 01 июня 2019
In [44]: A = np.array([[[1,2,3],[4,5,6],[7,8,9]],[[11,12,13],[14,15,16],[17,18,19]], 
    ...: [[1,2,3],[4,5,6],[7,8,9]], [[20,21,22],[23,24,25],[26,27,28]]]) 
    ...:                                                                         
In [45]: A.shape                                                                     
Out[45]: (4, 3, 3)
In [46]: im = np.array([A,A+10,A+20])                                                
In [47]: im.shape                                                                    
Out[47]: (3, 4, 3, 3)

Похоже, ваш код просто транспонирует оси, ставя размерность matrix последней вместо первой. np.stack принимает параметр оси. В качестве альтернативы мы можем использовать функцию / метод transpose:

In [48]: im1 = np.stack([A,A+10,A+20], axis=3)                                       
In [49]: im1.shape                                                                   
Out[49]: (4, 3, 3, 3)
In [50]: im2 = im.transpose(1,2,3,0)                                                 
In [51]: im2.shape                                                                   
Out[51]: (4, 3, 3, 3)
In [52]: im2                                                                         
Out[52]: 
array([[[[ 1, 11, 21],
         [ 2, 12, 22],
         [ 3, 13, 23]],

        [[ 4, 14, 24],
         [ 5, 15, 25],
         [ 6, 16, 26]],

        [[ 7, 17, 27],
         [ 8, 18, 28],
         [ 9, 19, 29]]],

        ....
        [[26, 36, 46],
         [27, 37, 47],
         [28, 38, 48]]]])
In [53]: np.allclose(im1,im2)                                                        
Out[53]: True

Я не могу проверить вас в более сложном случае, потому что B имеет неправильную форму. И C имеет неправильный завершающий символ.

===

Чтобы увидеть, что не так с вашей итерацией, выведите s в начале цикла. Посмотрите, как это развивается. Затем измените переменную итерации на k и наблюдайте за этим.

1 голос
/ 31 мая 2019

numpy уже векторизован. Вы можете сделать продукт kronecker:

 np.kron(a,np.ones(3)).reshape(np.r_[a.shape,3])

array([[[[ 1.,  1.,  1.],
         [ 2.,  2.,  2.],
         [ 3.,  3.,  3.]],

        [[ 4.,  4.,  4.],
         [ 5.,  5.,  5.],
         [ 6.,  6.,  6.]],

        [[ 7.,  7.,  7.],
         [ 8.,  8.,  8.],
         [ 9.,  9.,  9.]]],


       [[[11., 11., 11.],
         [12., 12., 12.],
         [13., 13., 13.]],


        : : : : 
        : : : :
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...