gpt4 book ai didi

python - 为什么将大小为 1 的维度插入 numpy 数组会使其 'contiguous' 标志无效?

转载 作者:太空宇宙 更新时间:2023-11-03 12:06:59 24 4
gpt4 key购买 nike

考虑这个数组:

In [1]: a = numpy.array([[1,2],[3,4]], dtype=numpy.uint8)

In [2]: a.strides
Out[2]: (2, 1)

In [3]: a.flat[:]
Out[3]: array([1, 2, 3, 4], dtype=uint8)

In [4]: a.flags['C_CONTIGUOUS']
Out[4]: True

In [5]: numpy.getbuffer(a)[:]
Out[5]: '\x01\x02\x03\x04'

到目前为止,还不错。但是请注意当我创建该数组的 View 时会发生什么,我在其中插入了一个大小为 1 的维度:

In [6]: b = a[:, numpy.newaxis, :] # Insert dimension

In [7]: b.strides
Out[7]: (2, 0, 1)

In [8]: b.flat[:]
Out[8]: array([1, 2, 3, 4], dtype=uint8)

In [9]: b.flags['C_CONTIGUOUS']
Out[9]: False

In [10]: numpy.getbuffer(b)[:]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/.../<ipython-input-28-0127b71fae43> in <module>()
----> 1 numpy.getbuffer(b)[:]

TypeError: single-segment buffer object expected

什么给了?为什么 numpy 认为 b 不是 C_CONTIGUOUS?绝对是,对吧?还是我遗漏了什么?

更新:@senderle 指出 numpy.reshape() 按预期工作:

In [11]: b = numpy.reshape(a, (2,1,2))

In [12]: b.flags['C_CONTIGUOUS']
Out[12]: True

真奇怪,我原以为两种情况下的 View 都是一样的。

最佳答案

这有点神秘,在看到hpaulj之前我什至深入研究了源代码。的评论。他观察到 reshape 和使用 newaxis 进行切片会产生不同的步幅,这说明了导致这种行为的原因 - 回答了为什么问题。

但是仍然存在什么激发这种行为的问题——为什么问题。我对此没有任何确凿的证据,但我的直觉是 numpy 尽其所能快速确保切片是 View ,而不是副本,在这种情况下,这需要打破 c 连续性。问题是可能很难确定如何将一个正确跨度维度添加到具有奇怪跨度的数组中;在某些情况下甚至可能是不可能的。但是您始终可以将步长为 0 的维度添加到任何数组。因此,numpy 不是特殊的大小写检查 c 连续性和其他可能的步幅排列,而是简单地添加一个步幅 0 维度。

这种懒惰是有道理的,因为它更简单,而且(可能)因为它更快(尽管对 c 连续性的单次检查不会花费很多时间)。我认为这里的简单解释优先——在这种情况下,事情会很快变得非常复杂。

另一方面,

reshape 需要能够生成任意形状的数组,因此它遵守连续性要求,并在必须这样做时进行复制。

关于python - 为什么将大小为 1 的维度插入 numpy 数组会使其 'contiguous' 标志无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28207077/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com