我通常处理大型模拟。有时,我需要计算粒子集的质心。我注意到,在许多情况下,numpy.mean()
返回的平均值是错误的。我可以计算出这是由于累加器饱和。为了避免这个问题,我可以将所有粒子的总和拆分为一个小的粒子集。但是这是不舒服的。有人知道如何用一种优雅的方式解决这个问题吗?
为了激发你的好奇心,下面的例子产生了一些类似于我在模拟中观察到的东西:
import numpy as np
a = np.ones((1024,1024), dtype=np.float32)*30504.00005
如果检查.max
和.min
值,则会得到:
a.max()
=> 30504.0
a.min()
=> 30504.0
但是,平均值为:
a.mean()
=> 30687.236328125
你可以发现这里出了问题,在使用dtype=np.float64
时不会发生这种情况,所以单精度解决这个问题应该不错。
4条答案
按热度按时间gcmastyq1#
这不是一个NumPy问题,而是一个浮点数问题,同样的情况也发生在C语言中:
(Live demo)
问题是浮点数的精度有限;随着累加器值相对于被加到其上的元素增长,相对精度下降。
一种解决方案是通过构造加法树来限制相对增长,下面是一个C语言的例子(我的Python还不够好......):
(Live demo)
nzkunb0c2#
您可以使用
dtype
关键字参数调用np.mean
,该参数指定累加器的类型(对于浮点数组,其默认类型与array相同)。因此,调用
a.mean(dtype=np.float64)
将解决您的玩具示例,也许还可以解决使用较大数组的问题。6g8kf2rb3#
您可以使用内置的
math.fsum
部分地解决这个问题,它可以跟踪部分和(文档包含一个到AS配方原型的链接):据我所知,
numpy
没有模拟。2ledvvac4#
快速而肮脏的回答
这给出了1024 * 1024矩阵的预期结果,但当然对于较大的阵列这将不是真的...
如果计算平均值不会成为代码的瓶颈,我会在python中实现一个特别的算法:但是,详细信息取决于您的数据结构。
如果计算平均值是一个瓶颈,那么一些专门的(并行)约简算法可以解决这个问题。
这种方法可能看起来很愚蠢,但肯定会缓解这个问题,而且几乎和
.mean()
本身一样高效。给出一个更合理的答案需要更多关于数据结构、大小和目标体系结构的信息。