2017-09-07 3 views
1

私は巨大な(30ギガバイト)を持っているndarrayメモリマップドで失敗します1ギガバイトの下に)私は、標準偏差を計算したい:この行はMemoryErrorで無残に失敗しnumpy.stdはMemoryError

print('stdev: {0:4.4f}\n'.format(numpy.std(arr)))

これがなぜ失敗するのかわかりません。私はメモリ効率的な方法でこれらを計算するヒントに感謝しますか?

環境:stdmeanのvenv + Python3.6.2 + numpyの1.13.1実際

答えて

0
import math 
BLOCKSIZE = 1024**2 
# For numerical stability. The closer this is to mean(arr), the better. 
PIVOT = arr[0] 


n = len(arr) 
sum_ = 0. 
sum_sq = 0. 
for block_start in xrange(0, n, BLOCKSIZE): 
    block_data = arr[block_start:block_start + BLOCKSIZE] 
    block_data -= PIVOT 
    sum_ += math.fsum(block_data) 
    sum_sq += math.fsum(block_data**2) 

stdev = np.sqrt(sum_sq/n - (sum_/n)**2) 
1

numpyのの実装では、配列の完全なコピーを作成し、恐ろしくメモリ非効率的です。ここではより高度な実装である:

# Memory overhead is BLOCKSIZE * itemsize. Should be at least ~1MB 
# for efficient HDD access. 
BLOCKSIZE = 1024**2 
# For numerical stability. The closer this is to mean(arr), the better. 
PIVOT = arr[0] 

n = len(arr) 
sum_ = 0. 
sum_sq = 0. 
for block_start in xrange(0, n, BLOCKSIZE): 
    block_data = arr[block_start:block_start + BLOCKSIZE] 
    block_data -= PIVOT 
    sum_ += np.sum(block_data) 
    sum_sq += np.sum(block_data**2) 
stdev = np.sqrt(sum_sq/n - (sum_/n)**2) 
+0

しかし 'sum'は数値的に不安定であり、正確には大行列の場合には、それは(無残本当に失敗numpyのを使用して実装いただきありがとうございます(HTTPS [SOの質問を参照]: //stackoverflow.com/questions/33004029/is-numpy-sum-implemented-in-such-a-way-that-numerical-errors-are-avoided))。下のバージョンは修正されましたが、以下のバージョンです。 – sophros