2013-08-28 42 views
5

我正在寫一個python模塊,需要計算1000個陣列(相同維度)中像素值的平均值和標準偏差。跨1000個陣列計算統計信息

我正在尋找最快的方法來做到這一點。

目前我正在循環訪問數組,並使用numpy.dstack將1000個數組堆疊到一個相當大的3d數組中......然後將計算第3個(?)維上的平均值。每個陣列都有形狀(5000,4000)。

這種方法需要相當長的時間!

任何人都可以建議一個更有效的方法來解決這個問題?

+0

有沒有機會向我們展示一些代碼? – arshajii

+2

爲什麼要將它們疊加?爲什麼不計算每個循環中的統計數據? – mgilson

+0

@mgilson:python中的循環很慢,如果他使用axis關鍵字,他可以將for循環下推到numpy(C),這會快得多 – usethedeathstar

回答

2

也許你可以在一個累加的方式是這樣的(未經測試)計算meanstd

im_size = (5000,4000) 

cum_sum = np.zeros(im_size) 
cum_sum_of_squares = np.zeros(im_size) 
n = 0 

for filename in filenames: 
    image = read_your_image(filename) 
    cum_sum += image 
    cum_sum_of_squares += image**2 
    n += 1 

mean_image = cum_sum/n 
std_image = np.sqrt(cum_sum_of_squares/n - (mean_image)**2) 

這可能是由於有多快,你可以從磁盤中讀取圖像的限制。它不受內存的限制,因爲一次只能在內存中存儲一​​張圖像。以這種方式計算std可能會遇到數值問題,因爲您可能會減去兩個大數。如果這是一個問題,你必須遍歷文件兩次,首先計算平均值,然後在第二遍中累積(image - mean_image)**2

1

預分配和填充。這減少了我的運行時間約1000秒到20秒

data_stack = numpy.empty((321, 720, 1000), dtype=numpy.float32) 
for index in range(len(data)): 
    data_stack[0:321,0:720,index] = data[index] 

我在做類似的事情。 dstack不是解決這個問題的好方法。一位同事提醒我,動態陣列問題和攤銷分析。 http://anh.cs.luc.edu/363/notes/06A_Amortizing.html

當你想展開一個動態數組時,你需要分配一個新的數組來保存原始數據和新數據。然後,將舊數組複製到新數組中,並將新數據複製到新數組中。這是一項昂貴的操作。

假設您有一個大小爲10的數組,並且您想每次向其添加2個項目。要添加第一個項目,您需要將數組展開爲11並複製11個項目(原始10 + 1個新項目)。要添加第二個項目,您需要將數組展開至12並複製12個項目。如果您事先知道要添加2個項目,您可以將數組大小調整爲12以開始,並且只複製12個項目,而不是總共23個。事實證明,每次用完時數組的大小加倍的空間是一個更有效的解決方案。

這是如何適用的:dstack不會使ndarray的大小加倍,它只是爲了根據需要分配儘可能多的內存。因此,每次調用dstack時,都會將您在ndarray中擁有的所有數據複製到新的ndarray中,併爲新數據留出空間。請注意,隨着每次調用,dstack的時間都會增加。

0

如果要大幅度縮短計算時間,可以選擇多線程解決方案。 Python中有幾個庫,如this