Ответ 1
Чтобы транспонировать массив, NumPy просто меняет информацию о форме и шаге для каждой оси. Вот шаги:
>>> arr.strides
(64, 32, 8)
>>> arr.transpose(1, 0, 2).strides
(32, 64, 8)
Обратите внимание, что операция транспонирования заменила шаги для оси 0 и оси 1. Длина этих осей также была заменена (обе длины 2
в этом примере).
Нет необходимости копировать данные для этого; NumPy может просто изменить, как он смотрит на базовую память, чтобы построить новый массив.
Визуализация шагов
Значение шага представляет собой количество байтов, которое должно быть перемещено в памяти, чтобы достичь следующего значения оси массива.
Теперь наш 3D-массив arr
выглядит так (с мечеными осями):
Этот массив хранится в непрерывном блоке памяти; по существу, одномерна. Чтобы интерпретировать его как трехмерный объект, NumPy должен перепрыгивать через некоторое постоянное количество байтов, чтобы двигаться по одной из трех осей:
Так как каждое целое число занимает 8 байт памяти (мы используем тип int64), значение шага для каждого измерения в 8 раз больше значений, которые нам нужно прыгать. Например, чтобы перемещаться вдоль оси 1, четыре значения (32 байта) подпрыгивают, а для перемещения по оси 0 необходимо поднять восемь значений (64 байта).
Когда мы пишем arr.transpose(1, 0, 2)
, мы обмениваем оси 0 и 1. Транспонированный массив выглядит следующим образом:
Все, что нужно сделать NumPy, - это обмен информацией о шаге для оси 0 и оси 1 (ось 2 не изменяется). Теперь мы должны двигаться дальше по оси 1, чем ось 0:
Эта базовая концепция работает для любой перестановки осей массива. Фактический код, который обрабатывает транспонирование, написан на C и может быть найден здесь.