Как метод transpose() NumPy переставляет оси массива?

In [28]: arr = np.arange(16).reshape((2, 2, 4))

In [29]: arr
Out[29]: 
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])


In [32]: arr.transpose((1, 0, 2))
Out[32]: 
array([[[ 0,  1,  2,  3],
        [ 8,  9, 10, 11]],

       [[ 4,  5,  6,  7],
        [12, 13, 14, 15]]])

когда мы передаем кортеж целых чисел в

5 ответов


чтобы транспонировать массив, NumPy просто меняет форму и информацию шага для каждой оси. Вот шаги:

>>> arr.strides
(64, 32, 8)

>>> arr.transpose(1, 0, 2).strides
(32, 64, 8)

обратите внимание, что операция транспонирования поменяла шаги для оси 0 и оси 1. Длины этих осей также были заменены (обе длины 2 в этом примере).

для этого не нужно копировать данные; NumPy может просто изменить, как он смотрит на базовую память для создания нового матрица.


визуализация успехов

значение stride представляет количество байтов,которые должны быть перемещены в памяти для достижения следующего значения оси массива.

теперь, наш 3D массив arr выглядит это (с маркировкой осей):

enter image description here

этот массив хранится в непрерывный блок памяти; по существу, он одномерен. Чтобы интерпретировать его как 3D-объект, NumPy необходимо перепрыгнуть через определенное постоянное количество байтов, чтобы двигаться по одной из трех осей:

enter image description here

поскольку каждое целое число занимает 8 байт памяти (мы используем int64 dtype), значение шага для каждого измерения в 8 раз больше количества значений, которые нам нужно перейти. Например, для перемещения вдоль оси 1 необходимо перейти к четырем значениям (32 байта), а для перемещения вдоль оси 0-к восьми значениям (64 байта).

когда мы пишем arr.transpose(1, 0, 2) мы меняем оси 0 и 1. Транспонированный массив выглядит следующим образом:

enter image description here

все, что NumPy нужно сделать, это поменять информацию о шаге для оси 0 и оси 1 (ось 2 не изменилась). Теперь мы должны прыгать дальше двигаться вдоль оси 1, чем ось 0:

enter image description here

эта основная концепция работает для любой перестановки осей массива. Фактический код, который обрабатывает транспонирование, написан на C и может быть найденным здесь.


Как пояснил документации:

по умолчанию измените размеры, в противном случае переставьте оси в соответствии с заданными значениями.

таким образом, вы можете передать необязательный параметр axes определение нового порядка измерений.

например. транспонирование первых двух измерений массива пикселей RGB VGA:

 >>> x = np.ones((480, 640, 3))
 >>> np.transpose(x, (1, 0, 2)).shape
 (640, 480, 3)

в нотации C Ваш массив будет:

int arr[2][2][4]

который представляет собой 3D-массив, имеющий 2 2D-массива. Каждый из этих 2D массивов имеет 2 1D массива, каждый из этих 1D массивов имеет 4 элемента.

поэтому у вас есть три измерения. Оси 0, 1, 2, с размерами 2, 2, 4. Именно так numpy обрабатывает оси N-мерного массива.

и arr.transpose((1, 0, 2)) взял бы ось 1 и поставил ее в положение 0, ось 0 и поставил ее в положение 1, а ось 2 и оставил ее в позиция 2. Вы эффективно переставляете оси:

0 -\/-> 0
1 -/\-> 1
2 ----> 2

другими словами, 1 -> 0, 0 -> 1, 2 -> 2. Оси назначения всегда в порядке, поэтому все, что вам нужно, это указать оси источника. Прочтите Кортеж в таком порядке:(1, 0, 2).

в этом случае ваши новые размеры массива снова [2][2][4], только потому, что оси 0 и 1 имеют одинаковый размер (2).

более интересным является транспонированной по (2, 1, 0) что дает вам массив [4][2][2].

0 -\ /--> 0
1 --X---> 1
2 -/ \--> 2

другими словами, 2 -> 0, 1 -> 1, 0 -> 2. Прочтите Кортеж в таком порядке:(2, 1, 0).

>>> arr.transpose((2,1,0))
array([[[ 0,  8],
        [ 4, 12]],

       [[ 1,  9],
        [ 5, 13]],

       [[ 2, 10],
        [ 6, 14]],

       [[ 3, 11],
        [ 7, 15]]])

вы закончили с int[4][2][2].

вы, вероятно, получите лучшее понимание, если все измерения были разного размера, так что вы могли видеть, где каждая ось пошла.

почему первый внутренний элемент [0, 8]? Потому что, если вы визуализируете свой 3D-массив в виде двух листов бумаги,0 и 8 выстроились в ряд, один на одной бумаге и один на другой бумаге, обе в левом верхнем углу. Путем транспонирования (2, 1, 0) вы говорите, что хотите, чтобы направление от бумаги к бумаге теперь маршировать по бумаге слева направо, а направление слева направо теперь перейти от бумаги к бумаге. У вас было 4 элемента, идущих слева направо, поэтому теперь у вас есть четыре листа бумаги. И у вас было 2 статьи, так что теперь у вас есть 2 элемента, идущих слева направо.

извините за ужасное искусство ASCII. ¯\_(ツ)_/¯


.перекроить(num1,пит2,клавиша num3).... три числа соотносятся с num1 = 0, num2 = 1 и num3 = 2. Таким образом, при транспонировании наличие (2,0,1) означает переключение вокруг исходного порядка num1,num2 и num3.

.reshape works like .reshape(5,5,2)
                             ^ ^ ^
                             | | |
                      I want 5,5x2's

ex.
переменная.перекроить(5,5,2) ... ... .транспонировать(2,0,1) / / действительно означает переделывать reshape(2,5,5)...то есть я хочу матрицы 2, 5x5

-вся документация в мире не могла сделать это ясно, пока я не протестировал его с:

import numpy as np
arr = np.arange(50).reshape(5,5,2)
print(arr)
arr3d = arr.transpose(2,0,1)
print(arr3d)

-С тем не менее, используя мою теорию, я не знаю, почему.транспонирование (1,0,2) не дает выхода, который выглядит так же, как оригинал, переключение 5 с 5 ничего не должно делать, но это делает следующее:

[[[ 0  1]
  [10 11]
  [20 21]
  [30 31]
  [40 41]]

 [[ 2  3]
  [12 13]
  [22 23]
  [32 33]
  [42 43]]

 [[ 4  5]
  [14 15]
  [24 25]
  [34 35]
  [44 45]]

 [[ 6  7]
  [16 17]
  [26 27]
  [36 37]
  [46 47]]

 [[ 8  9]
  [18 19]
  [28 29]
  [38 39]
  [48 49]]]
  • мой intsructor на udemy не мог понять, почему и как (1,0,2) сделать это.

подводя итоги a.transpose () [i,j,k] = a[k,j,i]

a = np.array( range(24), int).reshape((2,3,4))
a.shape gives (2,3,4)
a.transpose().shape gives (4,3,2)  shape tuple is reversed.

когда передается параметр кортежа, оси переставляются в соответствии с кортежем. Например

a = np.массив (диапазон (24), int).изменить форму ((2,3,4))

a [i,j,k] равно a.транспонировать ((2,0,1)) [k,i,j]

оси 0 занимает 2-е место

оси 1 занимает 3-е место

ось 2 сказки 1-е место

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