Wie kann ich die Effizienz dieser Schleife verbessern?

8

Ich habe ein numpliges Array mit Labels. Ich würde gerne eine Zahl für jedes Etikett basierend auf seiner Größe und Begrenzungsbox berechnen. Wie kann ich dies effizienter schreiben, so dass es realistisch ist, auf großen Arrays (~ 15000 Etiketten) zu verwenden?

%Vor%     
ajwood 23.11.2011, 16:37
quelle

5 Antworten

7

Ich konnte dies mit einigen vektorisierten Funktionen von NumPy nicht wirklich effizient umsetzen, daher wird eine clevere Python-Implementierung vielleicht schneller sein.

%Vor%

Diese Funktion gibt ein Dictionary zurück, das jedes Label dem Index der ersten Zeile zuordnet, in der es erscheint. Wenn Sie die Funktion auf A , A.T , A[::-1] und A.T[::-1] anwenden, erhalten Sie auch die erste Spalte die letzte Zeile und Spalte.

Wenn Sie lieber eine Liste als ein Wörterbuch wünschen, können Sie das Wörterbuch mithilfe von map(d.get, labels) in eine Liste umwandeln. Alternativ können Sie von Anfang an statt eines Wörterbuchs ein NumPy-Array verwenden, aber Sie verlieren die Möglichkeit, die Schleife vorzeitig zu verlassen, sobald alle Beschriftungen gefunden wurden.

Es würde mich interessieren, ob (und wie viel) dies tatsächlich Ihren Code beschleunigt, aber ich bin zuversichtlich, dass es schneller ist als Ihre ursprüngliche Lösung.

    
Sven Marnach 23.11.2011, 17:04
quelle
5

Eine andere Methode:

Verwenden Sie bincount (), um die Anzahl der Beschriftungen in jeder Zeile und Spalte zu ermitteln, und speichern Sie die Informationen im Zeilen- und Spalten-Array.

Für jedes Etikett müssen Sie nur den Bereich in Zeilen und Spalten durchsuchen. Es ist schneller als Sortieren, auf meinem PC kann es die Berechnung in ein paar Sekunden tun.

%Vor%     
HYRY 24.11.2011 02:25
quelle
5

Algorithmus:

  1. ändert das Array in eine Dimension
  2. erhält den Sortierindex von argsort ()
  3. ruft die sortierte Version von on dimension array als sorted_A
  4. ab
  5. Verwenden Sie where () und diff (), um die Etikettenwechselposition in sorted_A
  6. zu finden
  7. Verwenden Sie die Änderungsposition und den Sortierindex, um die ursprüngliche Position des Etiketts in einer Dimension zu erhalten.
  8. Berechnen Sie die Position für zwei Dimensionen von der Position der Ein-Dimension.

für große Arrays wie (7000, 9000), kann die Berechnung in 30 Sekunden abgeschlossen werden.

Hier ist der Code:

%Vor%     
HYRY 24.11.2011 01:48
quelle
1

Der Performace-Engpass scheint tatsächlich der Aufruf von argmax zu sein. Es kann vermieden werden, indem die Schleife wie folgt geändert wird (nur Berechnen von y0, y1, aber leicht verallgemeinern zu x0, x1):

%Vor%

Ich bin nicht sicher über den Grund für den Leistungsunterschied, aber ein Grund könnte sein, dass alle Operationen wie == , argmax und max ihr Ausgabe-Array direkt von der Form des Eingabe-Arrays vorbelegen können , was für argwhere nicht möglich ist.

    
silvado 23.11.2011 20:00
quelle
1

Mit PyPy können Sie einfach die Schleife ausführen und sich nicht um die Vektorisierung kümmern. Es sollte schnell sein.

    
fijal 28.11.2011 11:58
quelle

Tags und Links