Просто, чтобы добавить отличный ответ @AndyK, я узнал о бесшабашных шагах от Numpy MedKit . Там они показывают использование с проблемой следующим образом:
С учетом ввода :
x = np.arange(20).reshape([4, 5])
>>> x
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
Ожидаемый результат :
array([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9]],
[[ 5, 6, 7, 8, 9],
[ 10, 11, 12, 13, 14]],
[[ 10, 11, 12, 13, 14],
[ 15, 16, 17, 18, 19]]])
Для этого нам нужно знать следующие термины:
shape - Размеры массива вдоль каждой оси.
шагов - количество байтов памяти, которые необходимо пропустить, чтобы перейти к следующему элементу по определенному измерению.
>>> x.strides
(20, 4)
>>> np.int32().itemsize
4
Теперь, если мы посмотрим на Ожидаемый результат :
array([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9]],
[[ 5, 6, 7, 8, 9],
[ 10, 11, 12, 13, 14]],
[[ 10, 11, 12, 13, 14],
[ 15, 16, 17, 18, 19]]])
Нам нужно манипулировать формой массива и шагами. Выходная форма должна быть (3, 2, 5), то есть 3 элемента, каждый из которых содержит две строки (m == 2), а каждая строка имеет 5 элементов.
Шаг должен быть изменен с (20, 4) на (20, 20, 4). Каждый элемент в новом выходном массиве начинается с новой строки, каждая строка состоит из 20 байтов (5 элементов по 4 байта в каждом), а каждый элемент занимает 4 байта (int32).
Итак:
>>> from numpy.lib import stride_tricks
>>> stride_tricks.as_strided(x, shape=(3, 2, 5),
strides=(20, 20, 4))
...
array([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9]],
[[ 5, 6, 7, 8, 9],
[ 10, 11, 12, 13, 14]],
[[ 10, 11, 12, 13, 14],
[ 15, 16, 17, 18, 19]]])
Альтернативой будет:
>>> d = dict(x.__array_interface__)
>>> d['shape'] = (3, 2, 5)
>>> s['strides'] = (20, 20, 4)
>>> class Arr:
... __array_interface__ = d
... base = x
>>> np.array(Arr())
array([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9]],
[[ 5, 6, 7, 8, 9],
[ 10, 11, 12, 13, 14]],
[[ 10, 11, 12, 13, 14],
[ 15, 16, 17, 18, 19]]])
Я очень часто использую этот метод вместо numpy.hstack или numpy.vstack и, поверьте мне, в вычислительном отношении это намного быстрее.
Примечание:
При использовании очень больших массивов с этим трюком вычисление точных шагов не так тривиально. Я обычно делаю массив numpy.zeroes
желаемой формы и получаю шаги, используя array.strides
, и использую это в функции stride_tricks.as_strided
.
Надеюсь, это поможет!