Wie man Python für Anfänger schneller macht [numpy]

Eigentlich wollte ich Zahlen in 〇〇 einfügen und es wie ein Geschäftsbuch aussehen lassen, Ich habe es geschafft, weil ich die Nummer nicht richtig entschieden habe und ich werde sie von Zeit zu Zeit hinzufügen: unschuldig :.

Hinweis

Dies ist für Anfänger, die gerade erst mit Python anfangen Für diejenigen, die kürzlich etwas über Numpy oder Scipy gelernt haben. Wenn Sie mit Python vertraut sind, können Sie einige Ratschläge geben. Ich wäre Ihnen dankbar, wenn Sie mir einen anderen Fall oder einen besseren Weg nennen könnten: smiley :.

Außerdem war die Ausführungsumgebung ** Python 3.5.3 **. Seien Sie also besonders vorsichtig, wenn Sie ** Python 2-Serie ** verwenden. (Weil der Rückgabewert von Map oder Filter unterschiedlich ist)

Überblick

Mit dem jüngsten Boom des maschinellen Lernens haben viele Menschen möglicherweise begonnen, Python zu lernen. Möglicherweise stellen Sie fest, dass Bibliotheken wie numpy vorhanden sind, insbesondere wenn es sich um einfache numerische Verarbeitung und tatsächliche Daten handelt.

Mir ist jedoch klar, dass ich Daten einer bestimmten Größe verarbeite. Die Ausführung kann jedoch einige Zeit dauern, wenn ich keine Schreibweise entwerfe (ich persönlich bin der Meinung, dass es sich beim ersten Programmieren oder vor Python um eine statisch typisierte Sprache handelt. Ich denke, es ist einfach aufzustehen, wenn du es tust.

Besonders wenn ich lerne, möchte ich verschiedene Dinge ausprobieren. Wenn die Ausführung also lange dauert, kann ich es nicht tun. Ich hasse Programmierung: wütend :.

Daher hier durch Verwendung von ** numpy ** usw. in dem Fall, in dem es scheint, dass es "relativ leicht" beschleunigt werden kann. Ich werde es vorstellen.

Grobe Politik

Ich persönlich bin vorsichtig. Wenn es aufgrund von Schreibproblemen langsam ist, ist es wahrscheinlich, dass Sie mit einem der folgenden Probleme konfrontiert sind:

Das folgende Beispiel ist für diejenigen, die den folgenden Teilen folgen, nicht erforderlich.

Konkretes Beispiel

Vorbereitung

Die folgenden Bibliotheken werden vorab importiert.

import numpy as np
import pandas as pd
import scipy as sp

Fall 1: denn ich möchte das Ergebnis der Anweisung in einer Liste speichern

Sample.py


def func1(n):
    a = []
    for i in range(n):
        a.append(i)
    return a

def func2(n):
    a = [0 for i in range(n)]  #Liste der mit n initialisierten Länge n
    for i in range(n):
        a[i] = i
    return a

def func3(n):
    a = [i for i in range(n)]  #Initialisieren Sie zuerst mit der Einschlussnotation
    return a

def func4(n):
    return [i for i in range(n)]  #Direkt definieren und zurückgeben

%time a = func1(10000000)
%time b = func2(10000000)
%time c = func3(10000000)
%time d = func4(10000000)

result


CPU times: user 660 ms, sys: 100 ms, total: 760 ms
Wall time: 762 ms
CPU times: user 690 ms, sys: 60 ms, total: 750 ms
Wall time: 760 ms
CPU times: user 290 ms, sys: 90 ms, total: 380 ms
Wall time: 388 ms
CPU times: user 320 ms, sys: 90 ms, total: 410 ms
Wall time: 413 ms

Wenn Sie die Länge der Liste kennen, die im Voraus zurückgegeben werden soll, verwenden Sie die Einschlussnotation Es wird schneller sein. Tatsächlich halbiert dies allein die Ausführungszeit. Es ist eine gute Idee, sich dessen bewusst zu sein, insbesondere wenn Sie eine for-Anweisung auf eine lange Liste setzen.

Fall 2: Ich möchte für alle Elemente in einem Vektor den gleichen Wert berechnen.

Hier wird angenommen, dass die folgenden Vektoren vordefiniert sind.

a = np.array([i for i in range(10000000)])

Stellen Sie sich eine Funktion vor, die alle Elemente im Vektor für diesen Vektor verdoppelt und zurückgibt.

Sample.py


def func1(x):
    y = x.copy()
    for i in range(len(y)):
        y[i] *= 2
    return y

def func2(a):
    return a * 2

%time b = func1(a)
%time c = func2(a)

result


CPU times: user 2.33 s, sys: 0 ns, total: 2.33 s
Wall time: 2.33 s
CPU times: user 10 ms, sys: 10 ms, total: 20 ms
Wall time: 13 ms

Auf diese Weise kann numpy vier Regeln für jeden Vektor ausführen Achten Sie darauf, nicht zu zirkulieren.

Fall 4: Ich möchte nur Elemente mit einem Vektor extrahieren

Verwenden Sie den gleichen Vektor wie oben. Angenommen, Sie möchten nur Elemente, die ein Vielfaches von 3 sind, aus dem obigen Vektor abrufen. Dann denken Sie vielleicht: "Ich habe keine andere Wahl, als die if-Anweisung in der for-Anweisung zu verwenden!" Sie können auch wie folgt schreiben.

Sample.py


def func1(a):
    ans  = []
    for i in range(len(a)):
        if a[i] % 3 == 0:
            ans.append(a[i])
    return np.array(ans)

def func2(a):
    return a[a % 3 == 0]

%time b = func1(a)
%time c = func2(a)

result


CPU times: user 3.44 s, sys: 10 ms, total: 3.45 s
Wall time: 3.45 s
CPU times: user 120 ms, sys: 10 ms, total: 130 ms
Wall time: 131 ms

Nachtrag

Wenn Sie anstelle eines Vektors aus einer Liste abrufen möchten, können Sie die Funktion ** Filter ** verwenden. Wenn Sie ** numpy ** nicht verwenden können oder wollen, sollten Sie dies berücksichtigen.

Sie können sich "Lambda x: y" im Beispiel als eine unbenannte Funktion vorstellen, die "x" als Argument verwendet und "y" zurückgibt.

Sample.py


x = [i for i in range(10000000)]
%time y = list(filter(lambda x: x % 3 == 0, x))

result


CPU times: user 1.67 s, sys: 10 ms, total: 1.68 s
Wall time: 1.68 s

Es ist langsamer als die Verwendung von ** numpy **, aber schneller als die Verwendung von append in einer for-Anweisung!

Fall 5: Ich möchte eine Funktion auf jedes Element eines Vektors anwenden

Als nächstes sollten Sie eine Funktion auf jedes Element der Liste anwenden. Hier stellen wir die Funktion ** map ** vor. Dies ist eine Funktion, die das Ergebnis der Anwendung der angegebenen Funktion auf jedes Element in der Liste zurückgibt (Map-Objekt in Python3).

Außerdem ist die unten stehende Funktion eine Funktion, die $ x ^ 2 + 2x + 1 $ zurückgibt.

Sample.py


a = np.array([i for i in range(10000000)])
def func(x):
    return x**2 + 2*x + 1

def func1(a):
    return np.array([func(i) for i in a])

def func2(a):
    return np.array(list(map(func, a.tolist())))

%time b = func1(a)
%time c = func2(a)
%time d = a**2 + 2*a + 1

result


CPU times: user 5.14 s, sys: 90 ms, total: 5.23 s
Wall time: 5.23 s
CPU times: user 4.95 s, sys: 170 ms, total: 5.12 s
Wall time: 5.11 s
CPU times: user 20 ms, sys: 30 ms, total: 50 ms
Wall time: 51.2 ms

Ich habe die Kartenfunktion eingeführt, aber sie unterschied sich nicht so sehr von der Einschlussnotation: cry :. Sie haben es vielleicht schon mitten im Lesen bemerkt, aber im obigen Beispiel war es eine einfache Funktion, sodass die direkte Vektorberechnung überwältigend schneller ist!

Fall 6: Ich möchte jedes Element (numerischer Wert) der Matrix in eine beliebige Punktzahl (diskreter Wert) konvertieren.

Bisher haben wir uns mit eindimensionalen Arrays (Vektoren) befasst. Im folgenden Beispiel möchte ich mich mit einem zweidimensionalen Array (Matrix) befassen.

In den folgenden Fällen wird davon ausgegangen, dass Sie jeden numerischen Wert durch Vorverarbeitung wie maschinelles Lernen in eine Punktzahl umwandeln möchten. Definieren Sie zunächst die folgende Matrix.

a = np.array([[i % 100 for i in range(1000)] for j in range(10000)])

Bereiten Sie als Nächstes eine Liste vor, die in eine Partitur konvertiert werden soll. In der folgenden Liste 0, wenn die ursprüngliche Zahl kleiner als 20 ist, 1, wenn sie 20 oder mehr beträgt, und weniger als 50, 4, wenn sie 90 oder mehr beträgt. Angenommen, Sie möchten die Zahlen in der Matrix konvertieren, z.

scores = [20, 50, 70, 90]

Zunächst möchte ich meinen Kopf leeren und gehorsam umsetzen.

Sample.py


def func1(x):
    y = np.zeros(x.shape)
    for s in scores:
        for i in range(x.shape[0]):
            for j in range(x.shape[1]):
                if x[i, j] >= s:
                    y[i, j] += 1
    return y

%time b = func1(a)

Das Ergebnis ist eine schöne Dreifachschleife: unschuldig :. (Deep Loops sind nicht nur langsamer, sondern auch schwieriger zu lesen und zu befolgen. Machen Sie nicht zu viele Deep Loops für Menschen.)

Der Inhalt der Funktion wird für jedes Element in der Matrix um 1 erhöht, wenn er größer als die angegebene Punktzahl ist.

result1


CPU times: user 14 s, sys: 10 ms, total: 14 s
Wall time: 14 s

Wie erwartet hat die Ausführungszeit auch ** 10 Sekunden ** überschritten: cry :.

Als nächstes werde ich eine Funktion vorstellen, die entwickelt wurde.

Sample2.py


def func2(x):
    y = np.zeros(x.shape)
    for s in scores:
        y += (x >= s)
    return y

%time c = func2(a)

Folgendes machen wir:

Wie oben erwähnt, ist der Code kurz, enthält jedoch verschiedene Elemente. Es ist jedoch ** 100-mal schneller ** um den Betrag, um den die for-Anweisung nicht mehr umgedreht wird: smile :.

result


CPU times: user 90 ms, sys: 20 ms, total: 110 ms
Wall time: 111 ms

Nachtrag (30.08.2017)

An diesem Punkt könnten Sie das Gefühl haben, "Ich möchte alle ** für ** Sätze löschen, bevor sie geboren werden: wütend:". Also habe ich es als Versuch geschrieben.

Sample3.py


def func3(x):
    len_score = len(scores)
    y = x * np.array([[np.ones(len_score)]]).T
    s = np.array(scores).reshape(len_score, 1, 1)
    z = (y >= s)
    return z.sum(axis=0)

result


CPU times: user 200 ms, sys: 30 ms, total: 230 ms
Wall time: 235 ms

... spät: weinen: (vielleicht wegen schlechten Schreibens) Dies ist langsam, erfordert viel Speicher (da alles zuerst erweitert wird) und vor allem wird es schwer zu verstehen. Daher fand ich, dass es keine gute Idee ist, die for-Anweisung mit Gewalt zu löschen.

Fall 7: Existenzprüfung für Listenelement (hinzugefügt am 20.04.2018)

Ich erinnerte mich daran, als ich einen kürzlich erschienenen Artikel sah, also machte ich mir eine Notiz.

In Python können Sie mit in überprüfen, ob sich ein Element in der Liste befindet.

Wenn Sie dies jedoch auf eine Liste anwenden, ist dies $ O (n) $ für eine Listenlänge von $ n $. Wenn Sie also einen Fehler machen, erhalten Sie einen Unfall.

Wenn Sie die Existenz wiederholt überprüfen möchten, ist es besser, sie durch "set" usw. zu ersetzen, wie unten gezeigt.

JupyterNotebook(GoogleColaboratory)Bestätigt in


L = 100000
x = list(range(L))

def sample1(list_tmp):
    j = 0
    for i in list_tmp:
        if i in list_tmp:
            j += 1
    print("sample1 j: ", j)


def sample2(list_tmp):
    j = 0
    set_tmp = set(list_tmp)  #In Set konvertieren
    for i in list_tmp:
        if i in set_tmp:     #Überprüfen Sie, ob es eingestellt ist
            j += 1
    print("sample2 j: ", j)
    
%time sample1(x)
print("----------------------------------------")
%time sample2(x)

Ergebnis


sample1 j:  100000
CPU times: user 1min 7s, sys: 16 ms, total: 1min 7s
Wall time: 1min 7s
----------------------------------------
sample2 j:  100000
CPU times: user 8 ms, sys: 6 ms, total: 14 ms
Wall time: 14 ms

Extra 1 "Ich möchte immer noch die for-Anweisung verwenden"

Ich sagte oben, dass ich nicht so viel für Aussagen verwenden sollte, Trotzdem denke ich, dass es Situationen gibt, in denen man es benutzen muss oder es leichter zu verstehen ist.

Öffnen Sie es in diesem Fall erneut und verwenden Sie * numba *. * numba * ist ein kleiner Compiler.

"Nun, gibt der Compiler alle Variablen an? Muss ich einen Kompilierungsbefehl eingeben?"

Du denkst vielleicht, aber mach dir keine Sorgen. Fügen Sie einfach eine Zeile hinzu (zwei Zeilen, wenn Sie "Import" einschließen).

Sehen wir uns ein aktuelles Anwendungsbeispiel an.


import numba

def sample1(n):
    ans = 0
    for i in range(n):
        ans += i
    return ans

@numba.jit
def sample2(n):
    ans = 0
    for i in range(n):
        ans += i
    return ans

@numba.jit('i8(i8)', nopython=True)
def sample3(n):
    ans = 0
    for i in range(n):
        ans += i
    return ans

%time a = sample1(100000000)  #Wenn du nichts tust
%time b = sample2(100000000)  #Bei Verwendung von jit
%time c = sample3(100000000)  # jit(Typenspezifikation)Beim Benutzen

Von oben nach unten: "Ich habe nichts getan", "Ich habe Numba verwendet" und "Ich habe Numba verwendet (Typenspezifikation)". Es ist eine Funktion. Innerhalb der Funktion befindet sich eine Funktion, die 0 zu $ n -1 $ hinzufügt und von diesen zurückgibt.

Eine Typspezifikation finden Sie im Blog von Python Acceleration Numba Introduction Part 2-tkm2261.

Die Ausführungszeit ist wie folgt. Wenn Sie nichts tun, dauert es 5 Sekunden, aber wenn Sie "numba (Typenspezifikation)" verwenden, dauert es ungefähr 5,5 Mikrosekunden. Es ist nur eine andere Ziffer (in diesem Beispiel ist es ** ungefähr 940.000 Mal schneller **: unschuldig :).

CPU times: user 5.16 s, sys: 0 ns, total: 5.16 s
Wall time: 5.16 s
CPU times: user 30 ms, sys: 0 ns, total: 30 ms
Wall time: 25.9 ms
CPU times: user 0 ns, sys: 0 ns, total: 0 ns
Wall time: 5.48 µs

abschließend

Ich habe das Gefühl, dass ich viel geschrieben habe, aber im obigen Fall habe ich das Gefühl, dass es mit "Nicht für Aussage verwenden" endete. In Zukunft möchte ich verschiedene Dinge wie ** scipy ** und ** pandas ** zusammenstellen.

Recommended Posts

Wie man Python für Anfänger schneller macht [numpy]
So erstellen Sie ein Spigot-Plug-In (für Java-Anfänger)
~ Tipps für Python-Anfänger mit Liebe von Pythonista ③ ~
[Für Anfänger] Wie man den Befehl say mit Python benutzt!
[Für Anfänger] So studieren Sie den Python3-Datenanalysetest
Python # So überprüfen Sie Typ und Typ für Super-Anfänger
TensorFlow-Lernmethode für Profis der freien Künste und Python-Anfänger
Wie erstelle ich ein Python-Paket (geschrieben für Praktikanten)
So konvertieren Sie den Python # -Typ für Python-Superanfänger: int, float
Tipps für Python-Anfänger, um das Scikit-Image-Beispiel für sich selbst zu verwenden 7 Erstellen eines Moduls
[Python] Wie man eine Klasse iterierbar macht
[Python] Organisieren der Verwendung für Anweisungen
Verwendung von "deque" für Python-Daten
Memo Nr. 4, dass Python-Anfänger "Detaillierte Erklärung der Python-Grammatik" lesen
Wie man ein Dialogsystem für Anfänger erstellt
So installieren Sie Python
Python für Super-Anfänger Super-Anfänger Python # Einfach loszuwerden
Memo Nr. 3, dass Python-Anfänger "Detaillierte Erklärung der Python-Grammatik" lesen
So installieren Sie Python
Memo Nr. 1, dass Python-Anfänger "Detaillierte Erklärung der Python-Grammatik" lesen
Verwendung von Datenanalysetools für Anfänger
Python Lehrbuch für Anfänger
Versuchen Sie, RPN mit Python zu berechnen (für Anfänger)
Memo Nr. 2, dass Python-Anfänger "Detaillierte Erklärung der Python-Grammatik" lesen
Wie benutzt man numpy?
So erstellen Sie das Substance Painter Python-Plugin (Einführung)
Memo Nr. 7, dass Python-Anfänger "Detaillierte Erklärung der Python-Grammatik" lesen
Memo Nr. 6 für Python-Anfänger zum Lesen von "Detaillierte Erklärung der Python-Grammatik"
So bedienen Sie NumPy
So nehmen Sie Python Interpreter-Änderungen in Pycharm vor
[Für Anfänger] Wie man Programmierung studiert Private Memo
OpenCV für Python-Anfänger
Memo Nr. 5, dass Python-Anfänger "Detaillierte Erklärung der Python-Grammatik" lesen
Ein Tool zum Erstellen von Maskenbildern für ETC in Python
[BigQuery] Verwendung der BigQuery-API für die Python-Tabellenerstellung-
Erklären Sie ausführlich, wie Sie mit Python einen Sound erzeugen
So führen Sie Python im virtuellen Raum aus (für MacOS)
So führen Sie einen Komponententest durch Teil 2 Klassendesign zum Testen
Python-Anfänger sagen, dass es gut ist, sich an so viel zu erinnern
So erstellen Sie ein Python-Paket mit VS Code
Wie man schneller schreibt, wenn man numpy wie deque verwendet
[Einführung in Python] So schreiben Sie sich wiederholende Anweisungen mit for-Anweisungen
[Neueste Version 2020.8] So installieren Sie Python
Konvertieren Sie numpy int64 in python int
python3: Verwendung der Flasche (2)
Lernablauf für Python-Anfänger
[Python] Verwendung von Liste 1
So aktualisieren Sie Pythons Tkinter auf 8.6
Wie benutzt man Python Argparse?
Python3-Umgebungskonstruktion (für Anfänger)
3 Gründe für die Programmierung Anfänger sollten mit Python beginnen
So installieren Sie mkl numpy
Python: Wie man pydub benutzt
[Python] Verwendung von checkio
Python #Funktion 2 für Super-Anfänger
So führen Sie Notepad ++ Python aus
Grundlegende Python-Grammatik für Anfänger
So ändern Sie die Python-Version