【问题标题】:How to relaibly create a multi-dimensional array and a one-dimensional view of it in numpy, so that the memory layout be contiguous?如何在numpy中可靠地创建多维数组和它的一维视图,使内存布局连续?
【发布时间】:2022-01-05 02:38:17
【问题描述】:

根据numpy.ravel的文档,

返回一个连续的扁平数组。

返回一个包含输入元素的一维数组。仅在需要时才制作副本。

为了索引的方便和效率,我想要一个二维数组的一维视图。我正在使用ravel 创建视图,到目前为止一切顺利。

但是,我不清楚“仅在需要时制作副本”是什么意思。如果某天在我的代码执行时创建了一个副本,代码将停止工作。

我知道有numpy.reshape,但它的文档说:

在不复制数据的情况下改变数组的形状并不总是可能的。

无论如何,我希望数据是连续的。

如何可靠地创建二维数组和一维视图?我希望数据在内存中是连续的(为了提高效率)。在创建二维数组时是否需要指定任何属性以确保它是连续的并且ravel 不需要复制它?

相关问题:What is the difference between flatten and ravel functions in numpy?

【问题讨论】:

  • 正如文档和提供的帖子所说,您无法在 Numpy 的内存中创建不连续的数组视图。您必须复制 2D 数组以使其连续(除非它已经是)或创建扁平版本的 1D 副本(这在内部几乎是相同的操作)。如果您不希望这样,那么您必须处理非连续视图。这种约束来自(虚拟)内存中的数据布局,无法避免(独立于 Numpy)。
  • @JérômeRichard,是否有文件保证(1)当我创建一个二维数组时,它将连续存储,(2)如果二维数组连续存储,@987654329 @不会复制吗?
  • (1) 我认为是的,但如果这很关键,您可以创建一个 1D 数组并将其重塑为 2D 数组以 100% 确定。 (2) 是的(除非您使用通常不使用的 F/C 订单)。您可以使用arr.base 检查一个数组是否是另一个数组的副本/视图。
  • 猜测取决于您使用的顺序{'C','F','A','K'}。 @JérômeRichard 为什么 arr.base 而不是 numpy.shares_memory numpy.org/doc/stable/reference/generated/…
  • @pippo1980 确实如此。我不知道这个;)。谢谢。在实践中,我认为这两者可以在这里互换使用。

标签: numpy numpy-ndarray memory-layout


【解决方案1】:

ravelreshape 的警告是相同的。 ravel 只是 reshape(-1),到 1d。相反,reshape docs 告诉我们,我们可以将其视为首先做一个 ravel。

正常的数组构造会产生一个连续的数组,以相同的顺序进行 reshape 会产生一个视图。您可以通过查看 ravel 并检查值是否按预期顺序显示来直观地测试它。

In [348]: x = np.arange(6).reshape(2,3)
In [349]: x
Out[349]: 
array([[0, 1, 2],
       [3, 4, 5]])
In [350]: x.ravel()
Out[350]: array([0, 1, 2, 3, 4, 5])

我从arange 开始,将其重新整形为 2d,然后又恢复为 1d。顺序没有变化。

但是如果我做一个切片视图:

In [351]: x[:,:2]
Out[351]: 
array([[0, 1],
       [3, 4]])
In [352]: x[:,:2].ravel()
Out[352]: array([0, 1, 3, 4])

这个解谜有一个间隙,因此是一个副本。

Transpose 也是一个视图,不能重新整形为一个视图:

In [353]: x.T
Out[353]: 
array([[0, 3],
       [1, 4],
       [2, 5]])
In [354]: x.T.ravel()
Out[354]: array([0, 3, 1, 4, 2, 5])

除了,如果我们指定正确的顺序,ravel 就是一个视图。

In [355]: x.T.ravel(order='F')
Out[355]: array([0, 1, 2, 3, 4, 5])

reshape 对顺序进行了广泛的讨论。而transpose 实际上是通过返回具有不同形状和步幅的视图来工作的。对于二维数组transpose 产生一个订单F 数组。

因此,只要您知道这样的操作,您就可以放心地假设 reshape/ravel 是连续的。

请注意,即使 [354] 是一个副本,分配给 flat 也会更改原始文件

In [361]: x[:,:2].flat[:] = [3,4,2,1]
In [362]: x
Out[362]: 
array([[3, 4, 2],
       [2, 1, 5]])

x[:,:2].ravel()[:] = [10,11,2,3] 不会更改 x。在这种情况下,y = x[:,:2].flat 可能比等效的 ravel 更有用。

【讨论】:

  • numpy.org/doc/stable/reference/generated/numpy.ravel.htmlF' 表示以列优先、Fortran 风格的顺序索引元素,第一个索引变化最快,最后一个索引变化最慢。 --> @hpaulj 抱歉打扰了,我得到了主要的专栏,但是 changin fastes slowest 是什么意思?
  • @pippo1980,在我的 [353] 示例中,我们通过向下一列,然后超过一列,然后向下等来按顺序进行赋值。这与 [349] 不同的是,我们获得连续值通过跨行。这就是所有“最快”的意思。不用担心实际的执行速度。
猜你喜欢
  • 2011-05-08
  • 2019-07-27
  • 2011-09-21
  • 2022-01-24
  • 2019-06-09
  • 1970-01-01
  • 2013-06-19
  • 1970-01-01
  • 2020-09-10
相关资源
最近更新 更多