numpy中的切片中的None含义

发布时间 2023-07-28 09:37:14作者: 海_纳百川

pytorch的tensor同理。

先说结论:

None实际上是增加了一个维度,它不是原维度的索引。

为什么引入None

说一下我找原文档的心路历程:

numpy的官方文档里搜索“slice”,也就是切片,很容易就能找到关于slice的介绍:

Basic slicing extends Python’s basic concept of slicing to N dimensions. Basic slicing occurs when obj is asliceobject (constructed bystart:stop:stepnotation inside of brackets), an integer, or a tuple ofsliceobjects and integers.Ellipsisandnewaxisobjects can be interspersed with these as well.

简单来说就是numpy的切片扩展了python的切片。当索引是切片对象(由括号内的start:stop:step语法构造)、整数、切片对象的元组或整数的元组,切片操作就会发生。后面一句话特别重要:省略号和newaxis对象也可以穿插其中

省略号就是python语法的“...”,那么newaxis是什么呢?直觉告诉我它和None有关。找到newaxis的文档,里面第一句话就是:

A convenient alias for None, useful for indexing arrays.

也就是说,numpy.newaxis是None的别名,在索引数组时有用。而文档紧接着给的例子也特别直接:

 

第一句newaxis is None , is None 。。。

官方这么直白,这下不用我多说,你也知道None是什么意思了吧?None就是newaxis,也就是建立一个新的索引维度。其实就是为了写法上的方便,本来新建一个维度用reshape函数、unsqueeze函数也可以做到。其实文档后面也给出了解释[3]

This can be handy to combine two arrays in a way that otherwise would require explicit reshaping operations.

这种写法很方便地把两个数组结合起来,否则,还需要明确的reshape操作。

那么,怎么用呢?

以一维为例

x = np.arange(3) # array([0, 1, 2])

( 注意,这个一维数组的shape是(3,),而不是(1,3),初学者很容易犯错。)

如果想把x的shape变成(1,3),只需要把None放在第一个维度的位置,以下两种写法等价:

x[None,:]
x[None]

结果如下:

array([[0, 1, 2]])

如果想把x的shape变成(3,1),只需要把None放在第二个维度的位置:

x[:,None]

结果如下:

array([[0],
       [1],
       [2]])

其实,None可以任意添加和组合,例如下面的写法:

x[None,:,None,None]

结果如下:

array([[[[0]],
        [[1]],
        [[2]]]])

这个数组的shape是(1,3,1,1)。

以二维为例

x = np.arange(6).reshape((2,3))

x如下:

array([[0, 1, 2],
       [3, 4, 5]])

在第一个维度插入,以下三种写法等价:

x[None]
x[None,:]
x[None,:,:]

输出结果如下,shape为(1, 2, 3):

array([[[0, 1, 2],
        [3, 4, 5]]])

在第二个维度插入,以下两种写法等价:

x[:,None]
x[:,None,:]

输出结果如下,shape为(2, 1, 3):

array([[[0, 1, 2]],
       [[3, 4, 5]]])

在第三个维度插入:

x[:,:,None]

输出结果如下,shape为(2, 3, 1):

array([[[0],
        [1],
        [2]],

       [[3],
        [4],
        [5]]])

 

更高维的情况以此类推。

这种写法一般在进行矩阵运算的时候会用到。比如:

x = np.arange(5)
x[:, None] + x[None, :]

这样可以很优雅地获得 列向量+行向量 的结果(划重点:优雅~):

array([[0, 1, 2, 3, 4],
      [1, 2, 3, 4, 5],
      [2, 3, 4, 5, 6],
      [3, 4, 5, 6, 7],
      [4, 5, 6, 7, 8]])

参考

  1. https://zhuanlan.zhihu.com/p/486373530?utm_id=0