2

我不明白为什么将 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,)
4

3 回答 3

6

@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
于 2013-04-24T15:38:09.370 回答
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
于 2013-04-24T12:38:29.110 回答
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

会给你更正确的结果。

于 2013-04-24T12:27:38.463 回答