python - View 中的 Numpy reshape

标签 python numpy reshape

我对 View 上的 numpy reshape 操作的结果感到困惑。 下面的 q.flags 表明它不拥有数据,但是 q.base 既不是 x 也不是 y,那是什么呢?我很惊讶地看到 q.strides 是 8,这意味着它每次在内存中移动 8 个字节时都会获取下一个元素(如果我理解正确的话)。然而,如果除 x 之外的数组都没有数据,则唯一的数据缓冲区来自 x,这不允许通过移动 8 个字节来获取 q 的下一个元素。

In [99]: x = np.random.rand(4, 4)

In [100]: y = x.T

In [101]: q = y.reshape(16)

In [102]: q.base is y
Out[102]: False

In [103]: q.base is x
Out[103]: False

In [104]: y.flags
Out[104]: 
  C_CONTIGUOUS : False
  F_CONTIGUOUS : True
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False

In [105]: q.flags
Out[105]: 
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False

In [106]: q.strides
Out[106]: (8,)

In [107]: x
Out[107]: 
array([[ 0.62529694,  0.20813211,  0.73932923,  0.43183722],
       [ 0.09755023,  0.67082005,  0.78412615,  0.40307291],
       [ 0.2138691 ,  0.35191283,  0.57455781,  0.2449898 ],
       [ 0.36476299,  0.36590522,  0.24371933,  0.24837697]])

In [108]: q
Out[108]: 
array([ 0.62529694,  0.09755023,  0.2138691 ,  0.36476299,  0.20813211,
        0.67082005,  0.35191283,  0.36590522,  0.73932923,  0.78412615,
        0.57455781,  0.24371933,  0.43183722,  0.40307291,  0.2449898 ,
        0.24837697])

更新:

原来在numpy讨论区有人问过这个问题: http://numpy-discussion.10968.n7.nabble.com/OWNDATA-flag-and-reshape-views-vs-copies-td10363.html

最佳答案

简而言之:您不能总是依赖 ndarray.flags['OWNDATA']

>>> import numpy as np
>>> x = np.random.rand(2,2)
>>> y = x.T
>>> q = y.reshape(4)
>>> y[0,0]
0.86751629121019136
>>> y[0,0] = 1
>>> q
array([ 0.86751629,  0.87671107,  0.65239976,  0.41761267])
>>> x
array([[ 1.        ,  0.65239976],
       [ 0.87671107,  0.41761267]])
>>> y
array([[ 1.        ,  0.87671107],
       [ 0.65239976,  0.41761267]])
>>> y.flags['OWNDATA']
False
>>> x.flags['OWNDATA']
True
>>> q.flags['OWNDATA']
False
>>> np.may_share_memory(x,y)
True
>>> np.may_share_memory(x,q)
False

因为 q 没有反射(reflect)第一个元素的变化,比如 xy,它一定是第一个元素的所有者数据(下面以某种方式解释)。

关于 OWNDATA 标志的更多讨论在 numpy-discussion mailinglist .在How can I tell if NumPy creates a view or a copy?问题,简单地提到,简单地检查 ndarrayflags.owndata 有时似乎会失败,而且它似乎不可靠,正如您提到的那样。那是因为每个 ndarray 也有一个 base 属性:

base of an ndarray如果内存源自其他地方,则为对另一个数组的引用(否则,基数为 None)。 y.reshape(4) 操作创建一个副本,而不是 View ,因为 y 的步幅是 (8,16)。要将其 reshape (C-连续)为 (4,),内存指针必须跳转 0->16->8->24,这不是迈出一步即可。因此 q.base 指向由强制复制操作 y.reshape 生成的内存位置,它与 y 具有相同的形状,但是复制了元素,因此再次具有正常的步幅:(16, 8)q.base 因此不受任何其他名称的约束,因为它是强制复制操作 y.reshape(4) 的结果。只有现在才能以 (4,) 形状查看对象 q.base,因为步长允许这样做。 q 确实是 q.base 上的一个 View 。

对于大多数人来说,看到 q.flags.owndataFalse 会感到困惑,因为,如上所示,它不是 上的 View y。但是,它是 y 副本上的一个 View 。然而,该副本 q.base 是数据的所有者。因此,如果您仔细检查,这些标志实际上是正确的。

关于python - View 中的 Numpy reshape ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28886731/

相关文章:

从长格式的值重建对称矩阵

r - Melt 和 dcast with/字符串连接

python - 根据表中值的数量删除 Pandas 中的 DataFrame 行

python - 这段代码 : %(var)s ? Python 可能是什么?

Python(sympy)类型错误: cannot concatenate 'str' and 'Add' objects

python - Pandas 按工作日分组 (M/T/W/T/F/S/S)

python - 如何将一个 numpy 数组切片为另一个不同大小的 numpy 数组?

Python:交叉索引numpy数组

python - 使用 Panda/Numpy 搜索匹配字符串

python - Pandas: reshape 和多索引