【问题标题】:subsetting affects .view(np.float64) behaviour子集影响 .view(np.float64) 行为
【发布时间】:2017-12-13 15:03:18
【问题描述】:

我正在尝试使用一些 sklearn 估计器对一些快速傅立叶变换(技术上的离散傅立叶变换)的系数进行分类。我获得了一个 numpy 数组 X_c 作为 np.fft.fft(X) 的输出,我想将其转换为一个真正的 numpy 数组 X_r,原始 X_c 的每个(复杂)列都转换为两个(实/浮点)列X_r,即形状从 (r, c) 到 (r, 2c)。所以我使用 .view(np.float64)。并且一开始就有效。

问题是,如果我首先决定只保留原始复数数组的一些系数 X_c2 = X_c[:, range(3)] 然后做和以前一样的事情,而不是让列数加倍,我得到的秩数加倍(每个元素的虚部放在原来的下面的新行中)。

我真的不明白为什么会这样。

为了让自己更清楚,这里是一个玩具示例:

import numpy as np

# I create a complex array
X_c = np.arange(8, dtype = np.complex128).reshape(2, 4)
print(X_c.shape) # -> (2, 4)

# I use .view to transform it into something real and it works
# the way I want it.
X_r = X_c.view(np.float64)
print(X_r.shape) # -> (2, 8)

# Now I subset the array.
indices_coef = range(3)
X_c2 = X_c[:, indices_coef]
print(X_c2.shape) # -> (2, 3)
X_r2 = X_c2.view(np.float64)

# In the next line I obtain (4, 3), when I was expecting (2, 6)...
print(X_r2.shape) # -> (4, 3)

有人看到造成这种行为差异的原因吗?

【问题讨论】:

    标签: python arrays numpy casting subset


    【解决方案1】:

    我收到警告:

    In [5]: X_c2 = X_c[:,range(3)]
    In [6]: X_c2
    Out[6]: 
    array([[ 0.+0.j,  1.+0.j,  2.+0.j],
           [ 4.+0.j,  5.+0.j,  6.+0.j]])
    In [7]: X_c2.view(np.float64)
    /usr/local/bin/ipython3:1: DeprecationWarning: Changing the shape of non-C contiguous array by
    descriptor assignment is deprecated. To maintain
    the Fortran contiguity of a multidimensional Fortran
    array, use 'a.T.view(...).T' instead
      #!/usr/bin/python3
    Out[7]: 
    array([[ 0.,  1.,  2.],
           [ 0.,  0.,  0.],
           [ 4.,  5.,  6.],
           [ 0.,  0.,  0.]])
    
    
    In [12]: X_c2.strides
    Out[12]: (16, 32)
    In [13]: X_c2.flags
    Out[13]: 
      C_CONTIGUOUS : False
      F_CONTIGUOUS : True
    

    所以这个副本(或者是一个视图?)是 Fortran 命令。推荐的 X_c2.T.view(float).T 会生成相同的 4x3 数组而不会发出警告。

    正如您的第一个视图所示,复杂数组的数据布局与两倍的浮点数相同。

    我在尝试view 结构化数组时看到了有趣的形状行为。我想知道 complex dtype 的行为很像 dtype('f8,f8') 数组。


    如果我将您的 X_c2 更改为副本,我会得到预期的行为

    In [19]: X_c3 = X_c[:,range(3)].copy()
    In [20]: X_c3.flags
    Out[20]: 
      C_CONTIGUOUS : True
      F_CONTIGUOUS : False
      OWNDATA : True
      WRITEABLE : True
      ALIGNED : True
      UPDATEIFCOPY : False
    In [21]: X_c3.strides
    Out[21]: (48, 16)
    In [22]: X_c3.view(float)
    Out[22]: 
    array([[ 0.,  0.,  1.,  0.,  2.,  0.],
           [ 4.,  0.,  5.,  0.,  6.,  0.]])
    

    这让人放心。但我很困惑为什么[:, range(3)] 索引会创建一个 F 顺序视图。那应该是提前索引。

    确实,真正的切片不允许这种视图

    In [28]: X_c[:,:3].view(np.float64)
    ---------------------------------------------------------------------------
    ValueError: new type not compatible with array.
    

    所以范围索引创建了某种混合对象。

    【讨论】:

    • 如果你想保证结果的特定内存顺序,numpy.asarray(result, order='C') 可以完成这项工作。 numpy.array(result, order='C', copy='False') 也可以;它略显冗长,但与文档更一致。
    • 还有numpy.ascontiguousarray(result),保证了一个C连续数组(Fortran contiguous不算)。
    • 谢谢你们俩。我对 python 很陌生,所以我不太了解这种内存分配是如何工作的,以及这个 .copy() 命令是什么,但现在它可以工作了。我也不知道这些连续的问题。我看到了警告,但按照说明操作似乎并没有改变我的问题,所以我在发布代码时留下了代码。
    • @GWa (@user2357112),我只是把这个谜更深了一点。我仍然不知道为什么它改变了做这个索引的顺序。这对我来说似乎是错误的。第一个维度的高级索引不会这样做,例如arr[[0],[1]], range(3)].
    猜你喜欢
    • 2014-03-27
    • 1970-01-01
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多