Wenn Sie das Element von numpy.array mit einer for-Anweisung drehen, sinkt die Ausführungsgeschwindigkeit erheblich.
Um dieses Problem zu umgehen, versuchen Sie es etwas schneller
--list Inklusive Notation --Verwenden Sie np.where, wenn die Bedingungen komplex sind --Verwenden Sie np.frompyfunc (aber seien Sie vorsichtig, wenn Sie es verwenden)
Ich habe das gelernt, also dieses Memorandum.
Dies ist bereits überall geschrieben,
import numpy as np
a = np.array(range(10))
a2 = []
for x in a:
a2.append(x*2)
Wenn du so etwas machst
a2 = [x*2 for x in a]
Die Geschichte, dass Sie es tun sollten. Es wird viel schneller zu erleben sein.
Zum Beispiel, wenn Sie mit Array a herumspielen möchten, aber die Bedingungen basierend auf den Elementen von Array b bestimmen möchten.
Betrachten Sie als Beispiel den Fall, in dem die Elemente des Arrays a verdoppelt werden, wenn die Elemente des Arrays b gerade sind, und die Elemente des Arrays a ansonsten verdreifacht werden.
Verwenden Sie np.where, um zu vermeiden, dass Sie einen Index wie C ++ verwenden möchten, und drehen Sie ihn mit for um.
import numpy as np
a = np.array(range(10))
print "a = ", a
b = a + 100
print "b = ", b
#Bei Verwendung des Index sieht es so aus
result1 = []
for i in range(10) :
answer = a[i]*2 if b[i]%2 == 0 else a[i]*3
result1.append(answer)
print np.array(result1)
# np.Wenn Sie where und die Funktion verwenden, können Sie in eine Zeile schreiben und es ist schnell
def func_double(x) :
return x*2
def func_triple(x) :
return x*3
result2 = np.where(b%2 == 0, func_double(a), func_triple(a))
print result2
Wie Sie kommentiert haben, können Sie, wenn es sich um eine Funktion dieses Grades handelt, die Funktion so einbetten, wie sie in der Listeneinschlussnotation enthalten ist.
(Ich persönlich mag es jedoch nicht, Funktionen direkt in die Listeneinschlussnotation einzubetten ... Es ist schwierig, verschiedene Dinge später zu ändern, ich vergesse, sie zu ändern, und ein junger Student mit einer Erstsprachenliste der Python-Generation Wenn Sie einen beschissenen langen Code in die enthaltene Notation schreiben, wird er scharf sein wie "Es ist wirklich schwer zu lesen !!!" (lacht)
Als ich etwas schneller nach etwas gesucht habe, habe ich die folgende Seite gefunden, also danke ich Ihnen, dass Sie es verwendet haben.
Der schnellste Weg, eine beliebige Funktion auf alle Elemente einer Python-Liste anzuwenden Python-Beschleunigungsexperiment-Kartenfunktion-
Verwenden wir also frompyfunc.
import numpy as np
# prepare input arrays
a = np.array(range(10))
print "array a is", a
b = a + 100
print "array b is", b
def addition(x, y):
return x + y
np_addition = np.frompyfunc(addition, 2, 1)
print "print a + b using frompyfunc"
print np_addition(a, b)
print "print a + 1 using frompyfunc"
print np_addition(a, 1)
print "print 1 + b using frompyfunc"
print np_addition(1, b)
def subtruction(x, y):
return x - y
np_subtruction = np.frompyfunc(subtruction, 2, 1)
print "using np.where and frompyfuncs"
result2 = np.where(b%2 == 0, np_addition(a, b), np_subtruction(a, b))
print result2
Die Argumente der von frompyfunc erstellten Universalfunktion sind das erste Funktionsobjekt, die zweite Anzahl von Argumenten und die dritte Anzahl von Rückgabewerten. Wenn Sie ein Array in das Argument einer universellen Funktion einfügen, wird das Ergebnis der Anwendung der Funktion auf jedes Element als Array zurückgegeben.
Was, wenn es so eine bequeme Sache gäbe, hätte ich sie schnell benutzen sollen. Selbst in Bezug auf die Erfahrung fühlt es sich etwa 30% schneller an als die Notation zur Aufnahme von Listen.
Also, was ich überprüfen wollte, ist ** Ist es möglich, ein Array an das Argument der universellen Funktion zu übergeben, die von diesem frompyfunc erstellt wurde, und den Rest nur zu einem Float zu machen **? Die Geschichte.
Das Ergebnis ist überhaupt kein Problem! ~~ Mit anderen Worten, es gibt das berechnete Ergebnis zurück, während nur der Teil geändert wird, an dem das Array für jedes Element übergeben wird. ~~ ~~ Unabhängig davon, welches Argument als Array verwendet wird, wird es willkürlich entschieden. ~~
~~ Großartig! !! : grinsend: ~~
(Korrektur) Es war kein solches Problem, aber die Funktion, die die + und -Operatoren von numpy, die in den Additions- und Subtruktfunktionen verwendet wurden, einfach sowohl das Argumentarray als auch den Skalar akzeptierten (Korrektur). Tränen) Wenn Sie also in den Argumenten a und b eine einfache Liste anstelle von np.array einfügen, stirbt das obige Beispiel.
Deshalb habe ich den Teil gelöscht, den ich zuvor geschrieben habe. (Ende der Korrektur) </ div>
Frompyfunc hat jedoch einige Aspekte zu beachten, daher werde ich sie im Folgenden beschreiben.
Im Rückgabewert (numpy.array) der von frompyfunc erstellten Universalfunktion wird dtype zum Objekttyp. (Der Typ des darin enthaltenen Elements bleibt erhalten.)
Sie können sich normalerweise nur auf den Inhalt des Arrays beziehen. Wenn Sie jedoch versuchen, es beispielsweise mit numpy.histogramadd zu verwenden, werden Sie wütend, weil Sie nicht wie unten gezeigt vom Objekttyp in andere Typen umwandeln können.
...numpy/lib/function_base.py", line 1014, in histogramdd
flatcount = bincount(xy, weights)
TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'
Um dies zu verhindern, können Sie den Rückgabewert numpy.array mit astype umwandeln, aber ...
result2 = np.where(b%2 == 0, np_addition(a, b).astype(np.float64), np_subtruction(a, b).astype(np.float64))
Das Problem ist, dass Astype eine Funktion ist, die ein neues Array erstellt und zurückgibt, sodass hier eine Kopie des Arrays erstellt wird. Abhängig von den Bedingungen kann diese Kopierzeit zu einer Ausführungsgeschwindigkeit führen, die sich nicht ändert, selbst wenn sie in der Listeneinschlussnotation aktiviert ist.
In den letzten drei Zeilen des Beispiels wurde bestätigt, dass die von np.where und frompyfunc erstellte Universalfunktion zusammen verwendet werden kann. Aber anscheinend ist das ziemlich langsam. Es war ein Fehler im Programm, dass ich dachte, es wäre an einem Punkt zehnmal langsamer, aber es scheint, dass es ungefähr doppelt so langsam ist. Deshalb ist es schwierig, es in Situationen zu verwenden, in denen Geschwindigkeit wichtig ist.
Im Fall eines einfachen Beispiels wie dem hier gegebenen denke ich, dass die Notation der Listeneinbeziehung fast dieselbe ist.
Es gibt jedoch Fälle, in denen Sie nicht möchten, dass die Inklusivnotation mit Funktionen und Bedingungen überfüllt ist und die Lesbarkeit beeinträchtigt wird, oder wenn Sie komplizierte Arbeiten ausführen möchten, die überhaupt nicht in einer Zeile geschrieben werden können. In einem solchen Fall wurde mir klar, dass das Schreiben von Code mit dem gesunden Menschenverstand der Sprache, die ich vor langer Zeit gelernt habe, unerwartet lange dauern würde.
Ich habe verschiedene Pläne ausprobiert, um den bereits geschriebenen Code zu beschleunigen, aber am Ende ist es am besten, das Argument der Funktion, die das Material ist, so umzuschreiben, dass es von Anfang an sowohl Skalar als auch Array akzeptiert und sich schnell bewegt Ich finde es gut.
Wenn Sie dies tun können, sieht die Kombination von np.where und vorhandenen Funktionen am saubersten und schnellsten aus, und Sie müssen mit frompyfunc keine universelle Funktion erstellen.
Da ich eine Person war, die zum ersten Mal Programme in Fortran und C ++ gelernt hat, habe ich eine Funktion geschrieben, die Daten einzeln verarbeitet, und ein Programm geschrieben, das nicht völlig aus der Idee heraus ist, sie durch Drehen mit for zu verarbeiten. Wenn Sie von Anfang an wissen, dass Sie numpy verwenden werden, hat numpy viele Funktionen, die Arrays schnell verarbeiten. Daher dachte ich, es wäre die richtige Antwort, es so zu gestalten, dass mehrere Datensätze von Anfang an als Matrix verarbeitet werden. Überlegen.
Recommended Posts