Was sind die Vorteile von NumPy gegenüber regulären Python-Listen?

466

Was sind die Vorteile von NumPy gegenüber regulären Python-Listen?

Ich habe ungefähr 100 Finanzmarktserien und werde ein Cube-Array von 100x100x100 = 1 Million Zellen erstellen. Ich werde jedes x mit jedem y und z zurückführen (3 Variablen), um das Array mit Standardfehlern zu füllen.

Ich habe gehört, dass ich für "große Matrizen" aus Gründen der Leistung und Skalierbarkeit NumPy im Gegensatz zu Python-Listen verwenden sollte. Ich kenne Python-Listen und sie scheinen für mich zu funktionieren.

Was sind die Vorteile, wenn ich zu NumPy wechsle?

Was wäre, wenn ich 1000 Serien hätte (dh 1 Milliarde Gleitkommazellen im Würfel)?

Thomas Browne
quelle

Antworten:

727

NumPys Arrays sind kompakter als Python-Listen - eine Liste von Listen, wie Sie sie in Python beschreiben, würde mindestens 20 MB benötigen, während ein NumPy 3D-Array mit Floats mit einfacher Genauigkeit in die Zellen in 4 MB passen würde. Mit NumPy ist der Zugriff auf das Lesen und Schreiben von Elementen ebenfalls schneller.

Vielleicht interessieren Sie sich nicht so sehr für nur eine Million Zellen, aber definitiv für eine Milliarde Zellen - keiner der beiden Ansätze würde in eine 32-Bit-Architektur passen, aber mit 64-Bit-Builds würde NumPy mit 4 GB oder so davonkommen Python allein würde mindestens 12 GB benötigen (viele Zeiger, deren Größe sich verdoppelt) - eine viel teurere Hardware!

Der Unterschied ist hauptsächlich auf "Indirektheit" zurückzuführen - eine Python-Liste ist ein Array von Zeigern auf Python-Objekte, mindestens 4 Bytes pro Zeiger plus 16 Bytes für selbst das kleinste Python-Objekt (4 für Typzeiger, 4 für Referenzanzahl, 4 für Wert - und die Speicherzuordnungen aufrunden auf 16). Ein NumPy-Array ist ein Array einheitlicher Werte. Zahlen mit einfacher Genauigkeit benötigen jeweils 4 Byte, Zahlen mit doppelter Genauigkeit 8 Byte. Weniger flexibel, aber Sie zahlen erheblich für die Flexibilität von Standard-Python-Listen!

Alex Martelli
quelle
Ich habe versucht, "sys.getsizeof ()" zu verwenden, um die Größe von Python-Listen und NumPy-Arrays mit der gleichen Anzahl von Elementen zu vergleichen, und es scheint nicht darauf hinzudeuten, dass die NumPy-Arrays so viel kleiner waren. Ist dies der Fall oder hat sys.getsizeof () Probleme, herauszufinden, wie groß ein NumPy-Array ist?
Jack Simpson
3
@ JackSimpson getsizeofist nicht zuverlässig. In der Dokumentation heißt es eindeutig: Es wird nur der direkt dem Objekt zugeordnete Speicherverbrauch berücksichtigt, nicht der Speicherverbrauch der Objekte, auf die es sich bezieht. Dies bedeutet, dass bei verschachtelten Python-Listen die Größe der Elemente nicht berücksichtigt wird.
Bakuriu
4
getsizeofIn einer Liste wird nur angegeben, wie viel RAM das Listenobjekt selbst und der von den Zeigern in seinem Datenarray verbrauchte RAM verbraucht. Es wird nicht angegeben, wie viel RAM von den Objekten verbraucht wird, auf die sich diese Zeiger beziehen.
PM 2Ring
@AlexMartelli, können Sie mir bitte mitteilen, woher Sie diese Nummern beziehen?
lmiguelvargasf
Nur ein Kopf hoch, Ihre Schätzung der Größe der entsprechenden Python-Liste der Listen ist nicht korrekt. Das 4-GB-Numpy-Array von Cs float(4 Bytes) würde zu etwas führen, das näher an 32 GB von lists und Pythons float(die tatsächlich Cs sind double) liegt, nicht zu 12 GB; Jedes float64-Bit-Python belegt ~ 24 Bytes (vorausgesetzt, es liegen keine Ausrichtungsverluste im Allokator vor), plus weitere 8 Bytes im list, um die Referenz zu speichern (und dies ignoriert die Gesamtzuordnung und die Objekt-Header für das lists selbst, wodurch abhängig davon möglicherweise weitere GB hinzugefügt werden genau, wie viel Gesamtzuordnung auftritt).
ShadowRanger
232

NumPy ist nicht nur effizienter. es ist auch bequemer. Sie erhalten viele kostenlose Vektor- und Matrixoperationen, mit denen Sie manchmal unnötige Arbeit vermeiden können. Und sie werden auch effizient umgesetzt.

Sie können Ihren Cube beispielsweise direkt aus einer Datei in ein Array lesen:

x = numpy.fromfile(file=open("data"), dtype=float).reshape((100, 100, 100))

Summe entlang der zweiten Dimension:

s = x.sum(axis=1)

Finden Sie heraus, welche Zellen über einem Schwellenwert liegen:

(x > 0.5).nonzero()

Entfernen Sie jede gerade indizierte Scheibe entlang der dritten Dimension:

x[:, :, ::2]

Viele nützliche Bibliotheken arbeiten auch mit NumPy-Arrays. Zum Beispiel statistische Analyse- und Visualisierungsbibliotheken.

Auch wenn Sie keine Leistungsprobleme haben, lohnt sich das Erlernen von NumPy.

Roberto Bonvallet
quelle
Vielen Dank - Sie haben in Ihrem dritten Beispiel einen weiteren guten Grund angegeben, da ich in der Tat die Matrix nach Zellen über dem Schwellenwert durchsuchen werde. Außerdem habe ich von sqlLite geladen. Der Dateiansatz wird viel effizienter sein.
Thomas Browne
112

Alex erwähnte die Speichereffizienz und Roberto erwähnte die Bequemlichkeit, und dies sind beide gute Punkte. Für ein paar weitere Ideen werde ich Geschwindigkeit und Funktionalität erwähnen .

Funktionalität: Mit NumPy, FFTs, Faltungen, schneller Suche, grundlegenden Statistiken, linearer Algebra, Histogrammen usw. ist viel integriert. Und wer kann wirklich ohne FFTs leben?

Geschwindigkeit: Hier ist ein Test zum Ausführen einer Summe über eine Liste und ein NumPy-Array, der zeigt, dass die Summe im NumPy-Array 10x schneller ist (in diesem Test kann der Kilometerstand variieren).

from numpy import arange
from timeit import Timer

Nelements = 10000
Ntimeits = 10000

x = arange(Nelements)
y = range(Nelements)

t_numpy = Timer("x.sum()", "from __main__ import x")
t_list = Timer("sum(y)", "from __main__ import y")
print("numpy: %.3e" % (t_numpy.timeit(Ntimeits)/Ntimeits,))
print("list:  %.3e" % (t_list.timeit(Ntimeits)/Ntimeits,))

was auf meinen Systemen (während ich ein Backup ausführe) ergibt:

numpy: 3.004e-05
list:  5.363e-04
tom10
quelle
44

Hier ist eine nette Antwort aus den FAQ auf der scipy.org-Website :

Welche Vorteile bieten NumPy-Arrays gegenüber (verschachtelten) Python-Listen?

Pythons Listen sind effiziente Allzweckcontainer. Sie unterstützen (ziemlich) effizientes Einfügen, Löschen, Anhängen und Verketten, und Pythons Listenverständnis erleichtert das Erstellen und Bearbeiten. Sie haben jedoch bestimmte Einschränkungen: Sie unterstützen keine "vektorisierten" Operationen wie elementweise Addition und Multiplikation. Die Tatsache, dass sie Objekte unterschiedlichen Typs enthalten können, bedeutet, dass Python Typinformationen für jedes Element speichern und Typverteilungscode ausführen muss bei der Arbeit an jedem Element. Dies bedeutet auch, dass nur sehr wenige Listenoperationen von effizienten C-Schleifen ausgeführt werden können - jede Iteration würde Typprüfungen und andere Python-API-Buchhaltung erfordern.

Elieser
quelle
9

Alle haben fast alle wesentlichen Unterschiede zwischen Numpy-Array und Python-Liste hervorgehoben. Ich werde sie hier nur kurz erläutern:

  1. Numpy Arrays haben bei der Erstellung eine feste Größe, im Gegensatz zu Python-Listen (die dynamisch wachsen können). Durch Ändern der Größe von ndarray wird ein neues Array erstellt und das Original gelöscht.

  2. Die Elemente in einem Numpy-Array müssen alle denselben Datentyp haben (wir können auch den heterogenen Typ haben, aber das erlaubt Ihnen keine mathematischen Operationen) und haben daher dieselbe Größe im Speicher

  3. Numpy Arrays werden erleichtert, um mathematische und andere Arten von Operationen mit einer großen Anzahl von Daten voranzutreiben. Typischerweise werden solche Operationen effizienter und mit weniger Code ausgeführt, als dies mit in Sequenzen eingebauten Pythons möglich ist

Parvez Khan
quelle