【问题标题】:Trying to calcuate mean and std using float32 numpy arrays. Getting float64 returned尝试使用 float32 numpy 数组计算均值和标准差。返回 float64
【发布时间】:2013-06-03 14:17:48
【问题描述】:

[编辑]

好吧,我的测试用例考虑不周。我只测试了一维数组。在这种情况下,我会返回一个 64 位标量。如果我在 3D 数组上执行此操作,我会按预期得到 32 位。

我正在尝试计算一个非常大的 numpy 数组 (600*600*4044) 的均值和标准差,并且我已接近内存的限制(64 位机器上为 16GB)。因此,我试图将所有内容处理为 float32 而不是默认的 float64。但是,每当我尝试处理数据时,即使我将 dtype 指定为 float32,我也会返回 float64。为什么会这样?是的,我可以在之后进行转换,但就像我说的那样,我已经接近我的 RAM 的极限,即使在处理步骤期间,我也会尽量保持一切尽可能小。下面是我得到的一个例子。

import scipy
a = scipy.ones((600,600,4044), dtype=scipy.float32)
print(a.dtype)

a_mean = scipy.mean(a, 2, dtype=scipy.float32)
a_std = scipy.std(a, 2, dtype=scipy.float32)

print(a_mean.dtype)
print(a_std.dtype)

返回

float32
float32
float32

【问题讨论】:

  • 切换到 64 位 Python 会容易得多
  • 为什么?我不明白这会有什么帮助。
  • 因为那样你就不会被限制在 32 位地址空间。这就是我所期望的真正限制,而不是物理 RAM。
  • 那会怎样使用更少的内存?
  • 它不会使用更少的内存。但这将允许您的进程使用更多内存。我假设实际限制是地址空间而不是物理 RAM。我错了吗?机器有多少物理内存?机器是64位系统吗?

标签: python numpy


【解决方案1】:

注意此答案适用于原始问题

您必须切换到 64 位 Python。根据您的 cmets,即使使用 32 位浮点数,您的对象也有 5.7GB 的大小。这最多不适合 4GB 的 32 位地址空间。

一旦您切换到 64 位 Python,我认为您可以不用担心使用 64 位浮点数的中间值。事实上,您很可能使用 64 位浮点数来执行整个计算。

如果您已经在使用 64 位 Python(并且您的 cmets 在这件事上让我感到困惑),那么您根本不需要担心 scipy.meanscipy.std 返回 64 位浮点数。这是您数组中约 15 亿个值中的一个值。没什么好担心的。

注意此答案适用于新问题

您问题中的代码会产生以下输出:

浮动32 浮动32 浮动32

换句话说,您报告的症状实际上并不代表现实。造成混淆的原因是您之前的代码(我的原始答案所应用的代码)完全不同并且在单维数组上运行。它看起来非常像scipy 返回标量为float64。但是当返回值不是一个标量时,那么数据类型并没有按照你想象的方式进行转换。

【讨论】:

  • 感谢您抽出宝贵时间回复。但我不认为你理解我的问题。我正在使用 64 位 Python。我不想让我的数组适合 32 位地址空间。我只是想保留我所拥有的记忆。 11.5Gb太大了,不是因为我刚才没有处理的空间。但是因为我还有更多的东西要加载。还有来自操作系统的内存占用空间。
  • hmm,OP 想要 32 位浮点数作为基值,但数组本身可以通过 64 位指针来寻址。
  • 您在“为什么?我看不出这有什么帮助”上方的评论。表明您使用的是 32 位 Python。这些中间值不是问题。
  • @georgesl OP 有 32 位浮点数。那么如果scipy.mean 返回一个 64 位浮点数呢?这是 5.7GB 中的 4 个字节。
  • @Caustic 虽然我认为您没有什么可担心的,但我也想知道为什么 scipy 会从 32 位转换为 64 位。它清楚地以 32 位执行所有计算,然后在最后转换回 64 位。奇数。
【解决方案2】:

您可以强制更改基本类型:

a_mean = numpy.ndarray( scipy.mean(a, dtype=scipy.float32) , dtype = scipy.float32 )

我已经测试过了,如果我错了,请随时纠正我。

有一个out 选项:http://docs.scipy.org/doc/numpy/reference/generated/numpy.mean.html

a = scipy.ones(10, dtype=scipy.float32)
b = numpy.array(0,dtype=scipy.float32)

scipy.mean(a, dtype=scipy.float32, out=b)

测试:

In [34]: b= numpy.array(0)

In [35]: b= numpy.array(0,dtype = scipy.float32)

In [36]: b.dtype
Out[36]: dtype('float32')

In [37]: scipy.mean(a, dtype=scipy.float32, out = numpy.array(b) )                                                       
Out[37]: 1.0

In [38]: b
Out[38]: array(0.0, dtype=float32)

In [39]: 

【讨论】:

  • 从问题“是的,我可以在之后转换”,所以我猜 Caustic 知道如何做到这一点。
  • 我还没有测试过这个。我认为这仍然会产生非常大的数组(11.5GB)然后转换它。所以在执行的某个时刻,它会最大化我的记忆。这就是为什么我要避免转换并希望强制 numpy 全部使用 32 位本地完成。
  • @Caustic numpy 已经在 32 位本地完成了这一切!我建议您执行问题中的代码,并将您看到的输出与您声称的输出进行比较。
  • 好的,谢谢大卫。我发布的他们的代码确实返回了 float32。但是,我最初发布的其他更复杂的代码返回。我需要回去再看看它,因为很明显我在某个地方犯了一个不同的错误。是的,我知道 numpy 原生 32。我的措辞不好,我的意思是我不希望它返回 64 然后转换为 32,因为这不能解决我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-17
  • 1970-01-01
  • 1970-01-01
  • 2014-03-21
  • 1970-01-01
相关资源
最近更新 更多