2013-04-24 18 views
2

我不明白爲什麼將一個float32數組轉換爲float64數組會顯着改變數組的均值。numpy.mean大型數組的精度

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,) 

回答

2

的問題是與均值和功能的實現。

浮點值具有恆定精度。當你爲某個大的值增加一個小值時,就會失去小值的精度。

爲了克服需要劃分陣列和partialy計算總和的問題:

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 

會給你更多的正確的結果。

+3

在[本文](HTTP://www.cs.yale。 edu/publications/techreports/tr222.pdf),在第2頁中,在公式(1.6)之後,他們描述了他們所稱的_pairwise求和算法_,與您的解決方案相似,並描述了它如何將O(N) O(log N)。 – Jaime 2013-04-24 17:11:06

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 
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