Numpy 大型阵列的平均精度
我不明白为什么将float32数组强制转换为float64数组会显著改变数组的平均值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是
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