【问题标题】:How does numpy.newaxis work and when to use it?numpy.newaxis 如何工作以及何时使用它?
【发布时间】:2024-04-20 14:15:02
【问题描述】:

当我尝试时

numpy.newaxis

结果给了我一个二维图框,x 轴从 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有什么用,在什么情况下应该使用?

【问题讨论】:

  • except that it changes a row vector to a column vector? 第一个例子不是行向量。这是一个matlab概念。在 python 中,它只是一个没有行或列概念的一维向量。行或列向量是二维的,如第二个示例
  • 该术语并非来自 matlab,它是一个数学概念,也是描述他的示例中的数组的一种完全有效的方式。 math.stackexchange.com/questions/1198729/…

标签: python numpy multidimensional-array array-broadcasting numpy-ndarray


【解决方案1】:

简单地说,numpy.newaxis 用于增加现有数组的维度一个维度,使用时一次。因此,

  • 1D 数组将变为 2D 数组

  • 2D 数组将变为 3D 数组

  • 3D 数组将变为 4D 数组

  • 4D数组会变成5D数组

等等..

这是一个视觉插图,描述了提升一维数组到二维数组。


场景 1:当您想要显式将一维数组转换为 行向量 或一个列向量,如上图所示。

示例:

# 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:当我们想将 numpy broadcasting 用作某些操作的一部分时,例如在对某些数组进行加法时。

示例:

假设您要添加以下两个数组:

 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 可以broadcast

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)

作为替代方案,您可以使用具有直观 axis kwarg 的 numpy.expand_dims

# adding new axes at 1st, 4th, and last dimension of the resulting array
In [131]: newaxes = (0, 3, -1)
In [132]: arr_5D = np.expand_dims(arr, axis=newaxes)
In [133]: arr_5D.shape
Out[133]: (1, 5, 5, 1, 1)

更多关于np.newaxisnp.reshape的背景

newaxis 也称为伪索引,允许将轴临时添加到多数组中。

np.newaxis 使用切片运算符重新创建数组,而numpy.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 填充缺少的轴,以使broadcasting 操作起作用。


一般提示:您也可以使用None 代替np.newaxis;这些实际上是same objects

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

附:另请参阅这个很棒的答案:newaxis vs reshape to add dimensions

【讨论】:

  • x1_new + x2是什么类型的操作?这对我来说很奇怪,因为我认为只有当它们具有相同的维度(或者其中一个实际上只是一个标量)时才能添加两个矩阵。
  • @Stephen 正如我在答案中所指出的,这是因为 NumPy 广播。
  • 这是一个很棒的解释
  • @valdrinit 很高兴它对你有帮助:)
  • “等等,都是None?-一直都是。”
【解决方案2】:

什么是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, :]

但鉴于它只是在shape 中插入1s,您还可以通过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 documentation on that subject 非常好。它还包括一个带有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.]])

【讨论】:

  • 我看不出第二个和第三个用例之间的区别;它们都是关于允许 NumPy 广播数组作为某些操作的一部分。如果不是,那么为第三个用例添加一个示例以澄清这一点将有所帮助。
  • @ChirazBenAbdelkader 是的,区别并不是那么明显。我不确定是否应该删除第三点或将其合并到第二点。
【解决方案3】:

您从一维数字列表开始。一旦你使用了numpy.newaxis,你就把它变成了一个二维矩阵,由四行一列组成。

然后您可以使用该矩阵进行矩阵乘法,或将其用于构建更大的 4 x n 矩阵。

【讨论】:

    【解决方案4】:
    选择元组中的

    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 不仅仅是将行矩阵转换为列矩阵。它增加了矩阵的维度,从而使我们能够对其进行更多的操作。

    【讨论】:

    • 它不仅仅是矩阵,它适用于 NumPy 术语中的任何ndarray