何时使用.shape和何时使用.reshape?

6
当我尝试在NumPy数组上使用.reshape时,遇到了内存问题,想着如果我能以某种方式就地重新整形数组,那就太好了。
我意识到我可以通过简单地更改.shape的值来重塑数组。不幸的是,当我尝试使用.shape时,我再次遇到了内存错误,这让我认为它不会在原地重塑。
我想知道何时使用其中一个,何时使用另一个?
感谢任何帮助。
如果您需要其他信息,请告诉我。
编辑:
我添加了我的代码以及创建要重塑的矩阵的方法(以防这很重要)。
根据您的内存更改N值。
import numpy as np
N = 100
a = np.random.rand(N, N)
b = np.random.rand(N, N)
c = a[:, np.newaxis, :, np.newaxis] * b[np.newaxis, :, np.newaxis, :]
c = c.reshape([N*N, N*N])
c.shape = ([N, N, N, N])

编辑2: 这是一个更好的表述。显然,转置似乎很重要,因为它将数组从C连续变为F连续,上面情况下的乘法是连续的,而下面情况下的乘法不是。

import numpy as np
N = 100
a = np.random.rand(N, N).T
b = np.random.rand(N, N).T
c = a[:, np.newaxis, :, np.newaxis] * b[np.newaxis, :, np.newaxis, :]
c = c.reshape([N*N, N*N])
c.shape = ([N, N, N, N])

这会占用我所有的RAM。 - evan54
请展示一些带有样本输入的代码(您可以使用numpy.random生成虚假数据或其他任何东西,只需使其具有实际大小)。 - John Zwinck
你的意思是要模拟出一个内存问题还是不想引起内存问题? - evan54
抱歉,我不得不重新启动,因为使用了太多的内存导致崩溃。此外,我添加了一些额外的代码,更好地反映了我的实际代码,如果这很重要的话。 - evan54
你的代码对我来说仍然很好用。创建 c 占用了 762 MB 的内存,但之后的重塑操作不会增加内存使用量。 - John Zwinck
显示剩余7条评论
2个回答

8

numpy.reshape函数在无法创建合适视图的情况下会复制数据,而设置shape会引发错误而不是复制数据。

并非总能在不复制数据的情况下改变数组的形状。如果希望在复制数据时引发错误,则应将新形状分配给数组的形状属性。


所以行为完全相同,除了它们如何处理复制的需求?还有什么情况下需要复制? - evan54
如果数组不是连续的,就无法原地重塑,参见 reshape an array in numpy 的答案中的评论。 - ryanpattison

0

我想重新审视这个问题,重点关注面向对象编程范例,尽管存在内存问题。

何时使用 .shape 和何时使用 .reshape?

封装的面向对象编程原则

遵循面向对象编程范式,由于 shapenumpy.array 对象的属性,因此始终建议调用 对象.方法 来更改属性。这符合封装的面向对象编程原则。

性能问题

至于性能,似乎没有区别。

import numpy as np
# creates an array of 1,000,000 random floats
a = np.array(np.random.rand(1_000_000))

# (1000000,)
a.shape                   

# using IPython to time both operations resulted in

# 201 ns ± 4.85 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
%timeit a.shape = (5_000, 200)

# 217 ns ± 0.957 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit a.reshape (5_000, 200)

运行硬件

操作系统:Linux 4.15.0-142-generic #146~16.04.1-Ubuntu CPU:Intel(R) Core(TM) i3-4170 CPU @ 3.70GHz 四核心 内存:16GB


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接