Numpy 大型阵列的平均精度

Numpy 大型阵列的平均精度,numpy,precision,Numpy,Precision,我不明白为什么将float32数组强制转换为float64数组会显著改变数组的平均值 import numpy as n a = n.float32(100. * n.random.random_sample((10000000))+1000.) b = a.astype(n.float64) print n.mean(a), a.dtype, a.shape print n.mean(b), b.dtype, b.shape 结果(应大约为1050,因此float64是

我不明白为什么将float32数组强制转换为float64数组会显著改变数组的平均值

import numpy as n  

a = n.float32(100. * n.random.random_sample((10000000))+1000.)
b = a.astype(n.float64)        
print n.mean(a), a.dtype, a.shape
print n.mean(b), b.dtype, b.shape
结果(应大约为1050,因此float64是正确的):


问题在于均值和和和函数的实现

浮点值具有恒定的精度。将小值添加到某个大值时,将丢失小值的精度

要解决此问题,需要对数组进行除法并部分计算和:

s=n.float32(0)
for p in xrange(0,a.size,1000):
    s+= n.sum(a[p:p+1000])
print 'Sum:',s
print 'Mean:',s/a.size

将为您提供更准确的结果。

32位浮点数仅精确到约7位有效数字。随着值之和的增加,较小数字的准确性开始下降。64位数字的有效值约为13-16,因此需要更大的总和才能看到相同的效果

要在示例中看到这种效果,请注意增加数组子集的方法:

>>> for i in [j * 1000000 for j in range(1, 11)]:
...   print i, n.mean(a[:i]), n.mean(b[:i])
... 
1000000  1050.92768    1049.95339668
2000000  1045.289856   1049.96298122
3000000  1038.47466667 1049.97903538
4000000  1034.856      1049.98635745
5000000  1032.6848512  1049.98521094
6000000  1031.237376   1049.98658562
7000000  1030.20346514 1049.98757511
8000000  1029.428032   1049.98615102
9000000  1028.82497422 1049.98925409
10000000 1028.3424768  1049.98771529

@bogatron解释了造成精度损失的原因。为了解决这类问题,
np.mean
有一个可选的
dtype
参数,用于指定内部操作使用的类型。因此,您可以:

>>> np.mean(a)
1028.3446272000001
>>> np.mean(a.astype(np.float64))
1049.9776601123901
>>> np.mean(a, dtype=np.float64)
1049.9776601123901
第三种情况明显快于第二种情况,尽管比第一种情况慢:

In [3]: %timeit np.mean(a)
100 loops, best of 3: 10.9 ms per loop

In [4]: %timeit np.mean(a.astype(np.float64))
10 loops, best of 3: 51 ms per loop

In [5]: %timeit np.mean(a, dtype=np.float64)
100 loops, best of 3: 19.2 ms per loop
在第2页,在公式(1.6)之后,他们描述了他们所谓的两两求和算法,类似于您的解决方案,并描述了它如何将舍入误差从O(N)减少到O(logn)。
In [3]: %timeit np.mean(a)
100 loops, best of 3: 10.9 ms per loop

In [4]: %timeit np.mean(a.astype(np.float64))
10 loops, best of 3: 51 ms per loop

In [5]: %timeit np.mean(a, dtype=np.float64)
100 loops, best of 3: 19.2 ms per loop