我有一个2d数组vv.shape=(M_1,M_2),我想用v.shape=(M_2,N_1,N_2)M_1=N_1*N_2将其重塑为3d数组。
我想出了以下几行,得出了同样的结果:

np.reshape(v.T, reshape_tuple)


np.reshape(v.ravel(order='F'), reshape_tuple)

对于reshape_tuple=(M_2,N_1,N_2)
如果原始的v是一个巨大的(可能是复值的)矩阵,哪一个在计算上更好,在什么意义上(comp time,memory,等等)?
我的猜测是使用转置更好,但是如果reshape执行自动ravel操作,那么ravel选项可能更快(尽管reshape可能在c或fortran中执行ravel操作,然后就不清楚了)?

最佳答案

他们做事的顺序——重塑、改变步调、复制——不同,但他们最终还是做了同样的事情。
我喜欢使用__array_interface__查看数据缓冲区的位置以及其他更改。我想我应该添加flags来查看order。但我们/你知道transpose已经将顺序更改为F,对吧?

In [549]: x=np.arange(6).reshape(2,3)
In [550]: x.__array_interface__
Out[550]:
{'data': (187732024, False),
 'descr': [('', '<i4')],
 'shape': (2, 3),
 'strides': None,
 'typestr': '<i4',
 'version': 3}

转置是一种具有不同形状、步幅和顺序的视图:
In [551]: x.T.__array_interface__
Out[551]:
{'data': (187732024, False),
 'descr': [('', '<i4')],
 'shape': (3, 2),
 'strides': (4, 12),
 'typestr': '<i4',
 'version': 3}

不同顺序的ravel是一个副本(不同的数据缓冲指针)
In [552]: x.ravel(order='F').__array_interface__
Out[552]:
{'data': (182286992, False),
 'descr': [('', '<i4')],
 'shape': (6,),
 'strides': None,
 'typestr': '<i4',
 'version': 3}

转置ravel也是一个副本。我认为同一个数据指针只是内存重用的一个例子(因为我没有分配给变量),但这是可以检查的。
In [553]: x.T.ravel().__array_interface__
Out[553]:
{'data': (182286992, False),
 'descr': [('', '<i4')],
 'shape': (6,),
 'strides': None,
 'typestr': '<i4',
 'version': 3}

添加形状:
In [554]: x.T.ravel().reshape(2,3).__array_interface__
Out[554]:
{'data': (182286992, False),
 'descr': [('', '<i4')],
 'shape': (2, 3),
 'strides': None,
 'typestr': '<i4',
 'version': 3}
In [555]: x.ravel(order='F').reshape(2,3).__array_interface__
Out[555]:
{'data': (182286992, False),
 'descr': [('', '<i4')],
 'shape': (2, 3),
 'strides': None,
 'typestr': '<i4',
 'version': 3}

我认为重塑中隐含着一种“狂欢”:
In [558]: x.T.reshape(2,3).__array_interface__
Out[558]:
{'data': (182286992, False),
 'descr': [('', '<i4')],
 'shape': (2, 3),
 'strides': None,
 'typestr': '<i4',
 'version': 3}

(我应该重新编写这些示例以消除内存重用的歧义。)在任何情况下,转置后的整形都需要与带顺序更改的ravel相同的内存副本。据我所知,这两种情况都只需要一份。其他操作只涉及对shape等属性的更改。
如果我们看一下这些数组
In [565]: x.T
Out[565]:
array([[0, 3],
       [1, 4],
       [2, 5]])

T中,我们仍然可以按数字顺序遍历数组。但经过整形后,10并不接近。很明显有一本。
In [566]: x.T.reshape(2,3)
Out[566]:
array([[0, 3, 1],
       [4, 2, 5]])

在ravel之后的值的顺序看起来很相似,而在整形之后更明显。
In [567]: x.ravel(order='F')
Out[567]: array([0, 3, 1, 4, 2, 5])
In [568]: x.ravel(order='F').reshape(2,3)
Out[568]:
array([[0, 3, 1],
       [4, 2, 5]])

09-06 00:47