Как работает numpy.newaxis и когда его использовать?

187

Когда я пытаюсь

numpy.newaxis

результат дает мне двухмерный график с осью х от 0 до 1. Однако, когда я пытаюсь использовать numpy.newaxisдля нарезки вектор,

vector[0:4,]
[ 0.04965172  0.04979645  0.04994022  0.05008303]
vector[:, np.newaxis][0:4,]
[[ 0.04965172]
[ 0.04979645]
[ 0.04994022]
[ 0.05008303]]

Это то же самое, за исключением того, что он заменяет вектор строки на вектор столбца?

Какова польза от numpy.newaxisнее и при каких обстоятельствах мы должны ее использовать?

Юэ Харриет Хуан
источник
1
except that it changes a row vector to a column vector? Первый пример не является вектором строк. Это концепция Matlab. В питоне это просто одномерный вектор без понятия строки или столбца. Векторы строки или столбца являются 2-мерными, как и во втором примере
эндолит

Ответы:

331

Проще говоря, numpy.newaxisиспользуется для увеличения размера существующего массива еще на одно измерение , когда используется один раз . Таким образом,

  • 1D массив станет 2D массивом

  • 2D массив станет 3D массивом

  • 3D массив станет 4D массивом

  • Массив 4D станет массивом 5D

и так далее..

Вот наглядная иллюстрация, которая изображает продвижение 1D массива в 2D массивы.

визуализация канвы ньюаксиса


Сценарий 1 : np.newaxisможет пригодиться, если вы хотите явно преобразовать одномерный массив в вектор-строку или вектор-столбец , как показано на рисунке выше.

Пример:

# 1D array
In [7]: arr = np.arange(4)
In [8]: arr.shape
Out[8]: (4,)

# make it as row vector by inserting an axis along first dimension
In [9]: row_vec = arr[np.newaxis, :]     # arr[None, :]
In [10]: row_vec.shape
Out[10]: (1, 4)

# make it as column vector by inserting an axis along second dimension
In [11]: col_vec = arr[:, np.newaxis]     # arr[:, None]
In [12]: col_vec.shape
Out[12]: (4, 1)

Сценарий 2 : Когда мы хотим использовать пустое вещание как часть какой-либо операции, например, при добавлении некоторых массивов.

Пример:

Допустим, вы хотите добавить следующие два массива:

 x1 = np.array([1, 2, 3, 4, 5])
 x2 = np.array([5, 4, 3])

Если вы попытаетесь добавить это просто так, NumPy выдаст следующее ValueError :

ValueError: operands could not be broadcast together with shapes (5,) (3,)

В этой ситуации вы можете использовать, np.newaxisчтобы увеличить размерность одного из массивов, чтобы NumPy мог транслировать .

In [2]: x1_new = x1[:, np.newaxis]    # x1[:, None]
# now, the shape of x1_new is (5, 1)
# array([[1],
#        [2],
#        [3],
#        [4],
#        [5]])

Теперь добавьте:

In [3]: x1_new + x2
Out[3]:
array([[ 6,  5,  4],
       [ 7,  6,  5],
       [ 8,  7,  6],
       [ 9,  8,  7],
       [10,  9,  8]])

Также вы можете добавить новую ось в массив x2:

In [6]: x2_new = x2[:, np.newaxis]    # x2[:, None]
In [7]: x2_new     # shape is (3, 1)
Out[7]: 
array([[5],
       [4],
       [3]])

Теперь добавьте:

In [8]: x1 + x2_new
Out[8]: 
array([[ 6,  7,  8,  9, 10],
       [ 5,  6,  7,  8,  9],
       [ 4,  5,  6,  7,  8]])

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


Сценарий-3 : Это похоже на сценарий-1. Но, вы можете использовать np.newaxisболее чем один раз , чтобы продвигать массив в более высокие измерения. Такая операция иногда необходима для массивов более высокого порядка ( т. Е. Тензоров ).

Пример:

In [124]: arr = np.arange(5*5).reshape(5,5)

In [125]: arr.shape
Out[125]: (5, 5)

# promoting 2D array to a 5D array
In [126]: arr_5D = arr[np.newaxis, ..., np.newaxis, np.newaxis]    # arr[None, ..., None, None]

In [127]: arr_5D.shape
Out[127]: (1, 5, 5, 1, 1)

Больше информации о np.newaxis vs np.reshape

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

np.newaxisиспользует оператор нарезки для воссоздания массива, в то время как np.reshapeпреобразует массив в желаемый макет (при условии, что размеры совпадают; и это необходимо дляreshape произойдет).

пример

In [13]: A = np.ones((3,4,5,6))
In [14]: B = np.ones((4,6))
In [15]: (A + B[:, np.newaxis, :]).shape     # B[:, None, :]
Out[15]: (3, 4, 5, 6)

В приведенном выше примере мы вставили временную ось между первой и второй осями B(для использования трансляции). Здесь заполняется отсутствующая ось, np.newaxisчтобы заставить работу вещания работать.


Общий совет : вы также можете использоватьNoneвместоnp.newaxis; На самом деле это одни и те же объекты .

In [13]: np.newaxis is None
Out[13]: True

PS Также см. Этот отличный ответ: newaxis vs reshape, чтобы добавить размеры

kmario23
источник
3
Какой тип операции x1_new + x2? Это странно для меня, потому что я думал, что две матрицы могут быть добавлены, только если они имеют одинаковые размеры (или если одна из них на самом деле просто скаляр).
Стивен
2
@Stephen Как я также отметил в ответе, это из-за NumPy Broadcasting.
kmario23
2
Это потрясающее объяснение
Valdrinium
2
@valdrinit рад, что это полезно для вас :)
kmario23
1
@ kmario23 Действительно, атрибуция скрыта в самом последнем предложении статьи, неудивительно, что я этого не увидел. Я считаю это пограничным плагиатом даже при такой атрибуции. В моей книге слово в слово копирование допустимо, только если один и тот же автор публикует на разных платформах. Я ожидал лучшего от Medium.
Chiraz BenAbdelkader
29

Что такое np.newaxis?

Это np.newaxisпросто псевдоним для константы Python None, что означает, что везде, где вы используете, np.newaxisвы также можете использовать None:

>>> np.newaxis is None
True

Это просто более наглядно, если вы читаете код, который использует np.newaxisвместо None.

Как использовать np.newaxis?

np.newaxis, Как правило , используются с нарезкой. Это указывает на то, что вы хотите добавить дополнительное измерение в массив. Положение np.newaxisпредставляет, где я хочу добавить размеры.

>>> import numpy as np
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a.shape
(10,)

В первом примере я использую все элементы из первого измерения и добавляю второе измерение:

>>> a[:, np.newaxis]
array([[0],
       [1],
       [2],
       [3],
       [4],
       [5],
       [6],
       [7],
       [8],
       [9]])
>>> a[:, np.newaxis].shape
(10, 1)

Второй пример добавляет измерение в качестве первого измерения, а затем использует все элементы из первого измерения исходного массива в качестве элементов во втором измерении результирующего массива:

>>> a[np.newaxis, :]  # The output has 2 [] pairs!
array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])
>>> a[np.newaxis, :].shape
(1, 10)

Точно так же вы можете использовать несколько, np.newaxisчтобы добавить несколько измерений:

>>> a[np.newaxis, :, np.newaxis]  # note the 3 [] pairs in the output
array([[[0],
        [1],
        [2],
        [3],
        [4],
        [5],
        [6],
        [7],
        [8],
        [9]]])
>>> a[np.newaxis, :, np.newaxis].shape
(1, 10, 1)

Есть ли альтернативы np.newaxis ?

В NumPy: есть еще одна очень похожая функциональность np.expand_dims, которую также можно использовать для вставки одного измерения:

>>> np.expand_dims(a, 1)  # like a[:, np.newaxis]
>>> np.expand_dims(a, 0)  # like a[np.newaxis, :]

Но, учитывая, что он просто вставляет 1s в массив, shapeвы также reshapeможете добавить эти измерения:

>>> a.reshape(a.shape + (1,))  # like a[:, np.newaxis]
>>> a.reshape((1,) + a.shape)  # like a[np.newaxis, :]

В большинстве случаев np.newaxisэто самый простой способ добавить размеры, но хорошо знать альтернативы.

Когда использовать np.newaxis?

В нескольких контекстах добавление измерений полезно:

  • Если данные должны иметь указанное количество измерений. Например, если вы хотите использовать matplotlib.pyplot.imshowдля отображения одномерного массива.

  • Если вы хотите, чтобы NumPy транслировал массивы. Добавляя измерение можно, например , получить разницу между всеми элементами одного массива: a - a[:, np.newaxis]. Это работает, потому что операции NumPy транслируются, начиная с последнего измерения 1 .

  • Чтобы добавить необходимое измерение, чтобы NumPy мог транслировать массивы. Это работает , потому что каждая длина-1 измерение просто транслируется на длину соответствующего 1 размерность другого массива.


1 Если вы хотите узнать больше о правилах вещания, документация NumPy на эту тему очень хороша. Это также включает пример с np.newaxis:

>>> a = np.array([0.0, 10.0, 20.0, 30.0])
>>> b = np.array([1.0, 2.0, 3.0])
>>> a[:, np.newaxis] + b
array([[  1.,   2.,   3.],
       [ 11.,  12.,  13.],
       [ 21.,  22.,  23.],
       [ 31.,  32.,  33.]])
MSeifert
источник
Я не вижу разницы между 2-м и 3-м вариантами использования; они оба позволяют NumPy транслировать массив как часть какой-то операции. Если нет, то было бы полезно добавить пример для третьего варианта использования, чтобы прояснить суть.
Chiraz BenAbdelkader
@ChirazBenAbdelkader Да, различие не так уж и отчетливо. Я не уверен, должен ли я удалить третий пункт или объединить его со вторым.
MSeifert
9

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

Затем вы можете использовать эту матрицу для умножения матриц или задействовать ее в построении более крупной матрицы 4хn.

Kevin
источник
5

newaxisОбъект в кортеже выбора служит для расширения размеров результирующего выбора на одно измерение единичной длины .

Это не просто преобразование матрицы строк в матрицу столбцов.

Рассмотрим пример ниже:

In [1]:x1 = np.arange(1,10).reshape(3,3)
       print(x1)
Out[1]: array([[1, 2, 3],
               [4, 5, 6],
               [7, 8, 9]])

Теперь давайте добавим новое измерение к нашим данным,

In [2]:x1_new = x1[:,np.newaxis]
       print(x1_new)
Out[2]:array([[[1, 2, 3]],

              [[4, 5, 6]],

              [[7, 8, 9]]])

Вы можете видеть, что здесь newaxisдобавлено дополнительное измерение, x1 имеет измерение (3,3), а X1_new имеет измерение (3,1,3).

Как наше новое измерение позволяет нам выполнять различные операции:

In [3]:x2 = np.arange(11,20).reshape(3,3)
       print(x2)
Out[3]:array([[11, 12, 13],
              [14, 15, 16],
              [17, 18, 19]]) 

Добавив x1_new и x2, мы получим:

In [4]:x1_new+x2
Out[4]:array([[[12, 14, 16],
               [15, 17, 19],
               [18, 20, 22]],

              [[15, 17, 19],
               [18, 20, 22],
               [21, 23, 25]],

              [[18, 20, 22],
               [21, 23, 25],
               [24, 26, 28]]])

Таким образом, newaxisэто не просто преобразование строки в матрицу столбца. Это увеличивает размерность матрицы, что позволяет нам делать больше операций над ней.

суровая хундивала
источник
1
Это не просто матрица, она работает с любой ndarrayтерминологией NumPy.
kmario23