2013-08-28 18 views
5

Ich schreibe ein Python-Modul, das den Mittelwert und die Standardabweichung von Pixelwerten über 1000 Arrays (identische Dimensionen) berechnen muss.Berechnen von Statistiken über 1000 Arrays

Ich suche den schnellsten Weg, dies zu tun.

Derzeit bin ich Schleifen durch die Arrays und mit numpy.dstack, um die 1000 Arrays in eine ziemlich große 3D-Array zu stapeln ... und dann wird der Mittelwert über die 3. (?) Dimension berechnet. Jedes Array hat eine Form (5000,4000).

Dieser Ansatz dauert ziemlich lange!

Würde jemand in der Lage sein, auf eine effizientere Methode zur Lösung dieses Problems zu beraten?

+0

Können Sie uns irgendeinen Code zeigen? – arshajii

+2

Warum dstack sie? Warum nicht einfach die Statistiken für jede Schleife berechnen? – mgilson

+0

@mgilson: for-Schleifen in Python sind langsam, wenn er das Achsenschlüsselwort verwendet, kann er die for-Schleifen hinunter zu numpy (C) drücken, die viel schneller ist – usethedeathstar

Antwort

2

Vielleicht könnten Sie mean und std in kumulativer Weise so etwas wie diese (nicht getestet) berechnen:

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) 

Dies wird wahrscheinlich dadurch begrenzt, wie schnell Sie Bilder von der Festplatte gelesen werden können. Es ist nicht durch den Speicher beschränkt, da Sie immer nur ein Bild im Speicher haben. Die Berechnung von std auf diese Weise kann unter numerischen Problemen leiden, da Sie möglicherweise zwei große Zahlen subtrahieren. Wenn das ein Problem ist, müssen Sie die Dateien zweimal durchlaufen, zuerst den Mittelwert berechnen und dann im zweiten Durchlauf (image - mean_image)**2 akkumulieren.

1

vorbelegen und füllen. Dies reduzierte meine Laufzeit von etwa 1000 Sekunden auf 20 Sekunden.

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] 

Ich machte etwas ähnliches. dstack ist keine gute Lösung für dieses Problem. Ein Kollege erinnerte mich an das dynamische Array-Problem und die amortisierte Analyse. http://anh.cs.luc.edu/363/notes/06A_Amortizing.html

Wenn Sie ein dynamisches Array erweitern möchten, müssen Sie ein neues Array zuweisen, das die ursprünglichen Daten und die neuen Daten enthalten kann. Sie kopieren dann das alte Array in das neue Array und die neuen Daten in das neue Array. Das ist eine teure Operation.

Angenommen, Sie haben ein Array der Größe 10 und möchten 2 Elemente gleichzeitig hinzufügen. Um das erste Element hinzuzufügen, müssen Sie das Array auf Größe 11 erweitern und 11 Elemente kopieren (Original 10 + 1 neues Element). Um das zweite Element hinzuzufügen, müssen Sie das Array auf 12 erweitern und 12 Elemente kopieren. Wenn Sie im Voraus wissen, dass Sie 2 Elemente hinzufügen, könnten Sie die Größe des Arrays auf 12 geändert haben und nur 12 Elemente anstelle von insgesamt 23 kopieren. Es stellt sich heraus, dass die Größe des Arrays jedes Mal verdoppelt wird, wenn Sie ausgehen der Raum ist eine viel effizientere Lösung.

Wie das hier gilt: dstack verdoppelt die Größe des ndarray nicht, es soll nur so viel Speicher wie nötig zugewiesen werden. Jedes Mal, wenn Sie dstack aufrufen, kopieren Sie also alle Daten, die Sie in Ihrem ndarray haben, in ein neues ndarray mit Platz für die neuen Daten. Beachten Sie, dass die Zeit für das Stoppen mit jedem Aufruf zunimmt.

0

Wenn Sie die Rechenzeit drastisch reduzieren möchten, können Sie sich für eine Lösung für Multi Threading entscheiden. Es gibt mehrere Bibliotheken für Python wie this.

Verwandte Themen