Python在处理大型数组的np.std函数时是否存在Bug?

3

我正在尝试使用np.std(array,ddof = 0)来计算方差。如果我碰巧有一个很长的delta数组,也就是说,数组中的所有值都相同,就会出现问题。它不返回std=0,而是返回一些小值,这反过来又会导致进一步的估计误差。平均值被正确地返回...... 例子:

np.std([0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1],ddof = 0)

输出结果为1.80411241502e-16。

但是

np.std([0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1],ddof = 0)

给定std = 0

除了每次迭代都检查数据的唯一性而不计算std之外,是否有其他方法可以克服这个问题?

谢谢

P.S. 根据Is floating point math broken?的标记为重复,复制@kxr的回复以解释为什么这是一个不同的问题:

"当前的重复标记是错误的。它不仅仅是关于简单的浮点比较,而是关于使用np.std对长数组进行内部聚合小误差的结果 - 正如提问者额外指出的那样。例如比较>>> np.std([0.1, 0.1, 0.1, 0.1, 0.1, 0.1]*200000) -> 2.0808632594793153e-12。因此,他可以通过以下方式解决:>>> mean = a.mean(); xmean = round(mean, int(-log10(mean)+9)); std = np.sqrt(((a - xmean) ** 2).sum()/ a.size)"

问题确实始于浮点表示,但并不止于此。

@kxr - 我感谢你的评论和示例


编程的第一条规则:首先要假设错误是你自己造成的。 - Martijn Pieters
好的评论。那我的错误是什么?谢谢。 - user3861925
我无法解析那个字符串。标准应该是什么? - Carlos
2
当前的重复标记是错误的。它不仅仅是简单的浮点数比较,而是通过在数组上使用np.std对近零结果进行内部聚合的小误差 - 正如提问者所指出的额外问题。例如,比较>>> np.std([0.1, 0.1, 0.1, 0.1, 0.1, 0.1]*200000) -> 2.0808632594793153e-12。因此,他可以通过以下方式解决: >>> mean = a.mean(); xmean = round(mean, int(-log10(mean)+9)); std = np.sqrt(((a - xmean) ** 2).sum()/ a.size) - kxr
@Carlos - 标准应该是0。该字符串只是0.1或您选择的任何其他浮点数/双精度数的重复长列表。正如kxr指出的那样,将浮点数乘以大数并不能解决问题。 - user3861925
1个回答

4
欢迎来到实用数值算法的世界!在现实生活中,如果你有两个浮点数 x 和 y,检查 x==y 是没有意义的。因此,对于标准差是否为0的问题是没有意义的,它要么接近于0,要么不是。我们可以使用 np.isclose 进行检查。请参考np.isclose
import numpy as np

>>> np.isclose(1.80411241502e-16, 0)
True

这实际上是你能期望的最好结果。在现实生活中,你甚至无法像你所建议的那样检查所有项目是否相同。它们是浮点数吗?它们是由其他过程生成的吗?它们也会有小的误差。


好观点。在我正在尝试解决的实际问题的真实世界中,比较的问题是合法和关键的,但正如你指出的那样,数值算法只是数字,sigma 0只是sigma 0。谢谢! - user3861925

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