numpy.mean大数组的精度

时间:2013-04-24 11:26:04

标签: numpy precision

我不明白为什么将float32-Array转换为float64-Array会显着改变数组的平均值。

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是正确的):

1028.346368   float32 (10000000,)                                                          
1049.98284473 float64 (10000000,)

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:4)

@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 :(得分:2)

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

浮点值具有恒定的精度。当你向一个大的值添加小值时,你会失去小值的精度。

要克服这个问题,你需要划分数组并部分计算总和:

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

会给你更正确的结果。