Dies ist eine eher konzeptionelle Frage, aber ich hatte gehofft, dass ich dazu einen guten Rat bekommen könnte. Ein Großteil der Programmierung, die ich mache, erfolgt mit ( NumPy ) Arrays. Ich muss häufig Elemente in zwei oder mehr Arrays unterschiedlicher Größe zuordnen. Als Erstes gehe ich zu einer for-Schleife oder, noch schlimmer, zu einer verschachtelten for-Schleife. Ich möchte for-Schleifen so weit wie möglich vermeiden, weil sie langsam sind (zumindest in Python).
Ich weiß, dass es für viele Dinge mit NumPy vordefinierte Befehle gibt, die ich nur erforschen muss, aber haben Sie (als erfahrenere Programmierer) einen allgemeinen Denkprozess, der Ihnen einfällt, wenn Sie etwas wiederholen müssen?
Also habe ich oft so etwas, was schrecklich ist und ich möchte es vermeiden:
small_array = np.array(["one", "two"])
big_array = np.array(["one", "two", "three", "one"])
for i in range(len(small_array)):
for p in range(len(big_array)):
if small_array[i] == big_array[p]:
print "This item is matched: ", small_array[i]
Ich weiß, dass es mehrere verschiedene Wege gibt, um dies zu erreichen, aber ich bin an einer allgemeinen Denkweise interessiert, falls es sie gibt.
I want to avoid for-loops as much as possible because they are slow (at least in Python).
Klingt so, als würden Sie hier das falsche Problem lösen. Wenn Sie über etwas iterieren müssen, müssen Sie über etwas iterieren. Sie werden einen ähnlichen Leistungstreffer erzielen, egal welches Python-Konstrukt Sie verwenden. Wenn Ihr Code langsam ist, dann nicht, weil Siefor
Schleifen haben. Das liegt daran, dass Sie unnötige Arbeit oder Arbeit auf der Python-Seite erledigen, die auf der C-Seite erledigt werden könnte. In Ihrem Beispiel erledigen Sie zusätzliche Arbeit. Du hättest es mit einer Schleife anstatt mit zwei machen können.Antworten:
Dies ist eine häufige konzeptionelle Schwierigkeit, wenn Sie lernen, NumPy effektiv einzusetzen . Normalerweise wird die Datenverarbeitung in Python am besten in Form von Iteratoren ausgedrückt , um die Speichernutzung gering zu halten, die Möglichkeiten für Parallelität mit dem E / A-System zu maximieren und die Wiederverwendung und Kombination von Teilen von Algorithmen zu ermöglichen.
Aber NumPy dreht all das um: Der beste Ansatz besteht darin, den Algorithmus als Folge von Ganz-Array-Operationen auszudrücken , um den Zeitaufwand im langsamen Python-Interpreter zu minimieren und den Zeitaufwand für schnell kompilierte NumPy-Routinen zu maximieren.
Hier ist mein allgemeiner Ansatz:
Behalten Sie die Originalversion der Funktion bei (von der Sie sicher sind, dass sie korrekt ist), damit Sie sie mit Ihren verbesserten Versionen auf Richtigkeit und Geschwindigkeit testen können.
Arbeiten Sie von innen nach außen: Beginnen Sie mit der innersten Schleife und prüfen Sie, ob eine Vektorisierung möglich ist. Wenn Sie das getan haben, gehen Sie eine Ebene weiter und fahren Sie fort.
Verbringen Sie viel Zeit mit dem Lesen der NumPy-Dokumentation . Es gibt viele Funktionen und Operationen, die nicht immer einen hervorragenden Namen haben. Es lohnt sich also, sie kennenzulernen. Vor allem, wenn Sie denken: "Wenn es nur eine Funktion gibt, die so und so funktioniert", lohnt es sich, zehn Minuten lang danach zu suchen. Es ist normalerweise irgendwo da drin.
Es gibt keinen Ersatz für das Üben, deshalb werde ich Ihnen einige Beispielprobleme nennen. Das Ziel für jedes Problem ist es, die Funktion so umzuschreiben, dass sie vollständig vektorisiert ist : Das heißt, dass sie aus einer Folge von NumPy-Operationen für ganze Arrays besteht, ohne native Python-Schleifen (keine
for
oderwhile
Anweisungen, keine Iteratoren oder Verstehen).Problem 1
Problem 2
Problem 3
Spoiler unten. Sie werden viel die besten Ergebnisse erzielen, wenn Sie es selbst versuchen, bevor Sie sich meine Lösungen ansehen!
Antwort 1
Antwort 2
Antwort 3
quelle
list
Um die Dinge schneller zu machen, müssen Sie Ihre Datenstrukturen nachlesen und die entsprechenden verwenden.
Für nicht triviale Größen von kleinen Arrays und großen Arrays (sagen wir kleine = 100 Elemente und große = 10.000 Elemente) besteht eine Möglichkeit darin, das kleine Array zu sortieren, dann über große Arrays zu iterieren und mit einer binären Suche nach passenden Elementen zu suchen in der kleinen Reihe.
Dies würde die maximale Zeitkomplexität O (N log N) (und für kleine und sehr große große Arrays ist es näher an O (N)), wo Ihre Lösung mit verschachtelten Schleifen O (N ^ 2) ist.
Jedoch. Welche Datenstrukturen am effizientesten sind, hängt stark vom eigentlichen Problem ab.
quelle
Sie können ein Wörterbuch verwenden, um die Leistung erheblich zu optimieren
Dies ist ein weiteres Beispiel:
quelle