【问题标题】:Weird numpy.sum behavior when adding zeros添加零时奇怪的 numpy.sum 行为
【发布时间】:2015-06-23 09:00:24
【问题描述】:

我了解数学上等效的算术运算如何由于数值错误(例如,以不同顺序求和浮点数)而导致不同的结果。

然而,令我惊讶的是,在sum 中添加零会改变结果。我认为这始终适用于浮点数,无论如何:x + 0. == x

这是一个例子。我希望所有的行都完全为零。谁能解释一下为什么会这样?

M = 4  # number of random values
Z = 4  # number of additional zeros
for i in range(20):
    a = np.random.rand(M)
    b = np.zeros(M+Z)
    b[:M] = a
    print a.sum() - b.sum()

-4.4408920985e-16
0.0
0.0
0.0
4.4408920985e-16
0.0
-4.4408920985e-16
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
2.22044604925e-16
0.0
4.4408920985e-16
4.4408920985e-16
0.0

MZ 的较小值似乎不会发生这种情况。

我还确定了a.dtype==b.dtype

这里还有一个例子,它也演示了 python 的内置 sum 的行为符合预期:

a = np.array([0.1,      1.0/3,      1.0/7,      1.0/13, 1.0/23])
b = np.array([0.1, 0.0, 1.0/3, 0.0, 1.0/7, 0.0, 1.0/13, 1.0/23])
print a.sum() - b.sum()
=> -1.11022302463e-16
print sum(a) - sum(b)
=> 0.0

我正在使用 numpy V1.9.2。

【问题讨论】:

  • 我可以用 1.9.2 复制,但不能用 1.6.1。我的猜测是较长的数组会以某种方式导致元素以不同的顺序添加,例如为了促进 SMID。
  • math.fsum() 一样,这与sum() 不同,它似乎不会发生(至少在2.7.x 中)。
  • 我大胆猜测它是成对求和,github.com/numpy/numpy/pull/3685
  • 无法用 python 2.7.6 和 numpy 1.8.0 重现
  • 在 python 2.7.5 和 numpy 1.6.2 上也无法重现

标签: python numpy sum numerical-stability


【解决方案1】:

简答:您看到了两者之间的区别

a + b + c + d

(a + b) + (c + d)

因为浮点数不准确所以不一样。

长答案: Numpy 实现了成对求和作为速度(它允许更容易矢量化)和舍入误差的优化。

numpy sum-implementation 可以在here(函数pairwise_sum_@TYPE@)中找到。它基本上做了以下事情:

  1. 如果数组的长度小于 8,则执行常规的 for 循环求和。这就是为什么如果在您的情况下W < 4 不会观察到奇怪的结果 - 在两种情况下都将使用相同的 for 循环求和。
  2. 如果长度在 8 到 128 之间,它将在 8 个 bin 中累加 r[0]-r[7],然后将它们累加到 ((r[0] + r[1]) + (r[2] + r[3])) + ((r[4] + r[5]) + (r[6] + r[7]))
  3. 否则,它将递归地对数组的两半求和。

因此,在第一种情况下你会得到a.sum() = a[0] + a[1] + a[2] + a[3],在第二种情况下b.sum() = (a[0] + a[1]) + (a[2] + a[3])会导致a.sum() - b.sum() != 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    • 2017-09-05
    • 1970-01-01
    • 2018-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多