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

3 番目のケースは、最初のケースよりは遅いですが、2 番目のケースよりも大幅に高速です。

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 に答える