我正在尝试使用一些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)
有没有人看到这种行为差异的原因?
答案 0 :(得分:0)
我收到警告:
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.
因此范围索引创建了某种混合对象。