为什么NumPy为x创建视图[[slice(None),1,2]] [英] Why NumPy creates a view for x[[slice(None), 1, 2]]

查看:201
本文介绍了为什么NumPy为x创建视图[[slice(None),1,2]]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

高级索引,提到


同时认识到 x [[1,2,3]] 将触发高级索引,而 x [[1,2,切片(无)]] 将触发基本切片。

Also recognize that x[[1, 2, 3]] will trigger advanced indexing, whereas x[[1, 2, slice(None)]] will trigger basic slicing.

矩阵按顺序存储到内存中。我理解,查看 x [[1,2,slice(None)]] 是有意义的,因为元素按顺序存储到内存中。但为什么Numpy返回 x [[1,slice(None),2]] x [[slice(None),1, 2]] 。例如,假设

A matrix is stored sequentially into the memory. I understand that it makes sense to make a view of x[[1, 2, slice(None)]] since the elements are stored sequentially into the memory. But why Numpy returns a view of x[[1, slice(None), 2]] or x[[slice(None), 1, 2]]. For instance, assume

x = [[[ 0,  1,  2],
      [ 3,  4,  5],
      [ 6,  7,  8]],
     [[ 9, 10, 11],
      [12, 13, 14],
      [15, 16, 17]],
     [[18, 19, 20],
      [21, 22, 23],
      [24, 25, 26]]]

x [[1,切片(无),2]] 返回视图 [11,14,17] 这不是按顺序存储在内存中以及 x [[slice(None),1,2] ] 返回 [5,14,23]

x[[1, slice(None), 2]] returns a view of [11, 14, 17] which is not sequentially stored in the memory as well as for x[[slice(None), 1, 2]] which returns [5, 14, 23].

我想要知道


  1. 为什么NumPy甚至会在这两种情况下返回一个视图

  1. Why NumPy even returns a view in these two cases

NumPy如何处理内存寻址以创建这些视图

How NumPy handles memory addressing to create these views


推荐答案

来自 SciPy cookbook


创建切片视图的经验法则是否可以使用原始数组中的偏移,步幅和计数来查看所查看的元素。

The rule of thumb for creating a slice view is that the viewed elements can be addressed with offsets, strides, and counts in the original array.

当您的索引类似 x [[1,slice(None),2]] ,你得到一个视图,因为切片整个轴允许一定的偏移,步幅和计数来表示原始数组的切片。

When you have an indexing like x[[1, slice(None), 2]], you get a view because slicing an entire axis allows for a certain offset, stride and count to represent the slice with the original array.

例如, x = np.arange(27).reshape(3,3,3).copy(),我们有:

In [79]: x_view = x[1, :, 2]  # or equivalently x[[1, slice(None), 2]]

In [80]: x_view
Out[80]: array([11, 14, 17])

In [81]: x_view.base
Out[81]: 
array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8]],

       [[ 9, 10, 11],
        [12, 13, 14],
        [15, 16, 17]],

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

然后我们可以使用 numpy.byte_bounds (不是公共API,YMMV的一部分)来说明偏移以从我们的原始数组中获取切片。

Then we can use numpy.byte_bounds (not part of the public API, YMMV) to illustrate the offset to get our slice from our original array.

In [82]: np.byte_bounds(x_view)[0] - np.byte_bounds(x_view.base)[0]
Out[82]: 88

这是有道理的,因为有11个8字节在切片中第一个值之前的整数,11。NumPy使用公式计算此偏移量见这里,使用原始数组的步幅。

This makes sense, since there are 11 8-byte integers before the first value in the slice, 11. NumPy calculates this offset with a formula you can see here, using the strides of the original array.

In [93]: (x.strides * np.array([1, 0, 2])).sum()
Out[93]: 88

我们切片中的步幅简直就是大步前进是沿着我们正在切片的轴(或轴)上的 x 。即 x.strides [1] == x_view.strides [0] 。现在,偏移量,新步幅和计数一起是NumPy从原始数组中查看切片的足够信息。

The strides in our slice simply become whatever the strides were for x along the axis (or axes) on which we are slicing. i.e. x.strides[1] == x_view.strides[0]. Now together the offset, new strides and count are enough information for NumPy to view our slice from our original array.

In [94]: x_view.strides
Out[94]: (24,)

In [95]: x_view.size
Out[95]: 3

最后,你为什么用 x [[0,1,2]] 触发花式索引的原因是因为在没有完整的轴切片的情况下,它不是通常可以制定一些新的偏移量,字节顺序,步幅和计数,以便我们可以查看具有相同基础数据的切片。

Finally, the reason why you trigger fancy indexing with x[[0, 1, 2]] for instance is because in the absence of a full axis slice, it isn't generally possible to formulate some new offset, byte order, strides and count such that we can view the slice with the same underlying data.

这篇关于为什么NumPy为x创建视图[[slice(None),1,2]]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆