Zurück zum Katalog
Season 34 7 Episoden 27 min 2026

NumPy

v2.4 — 2026 Edition. Ein Audiokurs zur Einführung in NumPy, der seine hohe Performance, multidimensionale Arrays und seine entscheidende Rolle im Python-Ökosystem erklärt. (v2.4, 2026 Edition)

Datenwissenschaft Python Core
NumPy
Aktuelle Wiedergabe
Click play to start
0:00
0:00
1
Die Kernidentität: ndarray
Diese Episode behandelt das ndarray-Objekt, homogene Datentypen und feste Speicherzuweisung. Du lernst, warum Standard-Python-Listen für groß angelegte Mathematik ineffizient sind und wie NumPy dieses Problem löst, indem es auf kompilierten C-Code zurückgreift.
3m 34s
2
Arrays beschwören: Erstellung & Shape
Diese Episode untersucht, wie man multidimensionale Arrays mithilfe intrinsischer Funktionen richtig erstellt. Du lernst, wie du Werkzeuge wie zeros, arange und linspace nutzt, um Datensätze in Sekundenschnelle zu generieren.
4m 08s
3
Unter der Haube: Speicher, Strides und Views
Diese Episode taucht in die interne Architektur von NumPy ein und konzentriert sich auf den Data Buffer und Strides. Du lernst, warum Operationen wie Slicing und Transponieren praktisch sofort ausgeführt werden, da sie Memory Views und keine Kopien zurückgeben.
4m 10s
4
Universal Functions: Mathematik ohne Schleifen
Diese Episode behandelt Universal Functions (ufuncs) und wie sie Operationen vektorisieren. Du lernst, Python-for-Schleifen vollständig zu eliminieren, indem du elementweise Mathematik und achsenbasierte Reduktionen anwendest.
3m 39s
5
Broadcasting: Die Magie nicht übereinstimmender Shapes
Diese Episode erklärt die genauen Regeln des Broadcasting. Du lernst, wie NumPy Arrays mit nicht übereinstimmenden Shapes konzeptionell dehnt, damit sie zusammen verarbeitet werden können, ohne Speicherplatz zu verschwenden.
4m 23s
6
Präzisionsfilterung: Boolean Masking
Diese Episode konzentriert sich auf fortgeschrittenes Boolean Masking zum Filtern komplexer Datensätze. Du lernst, wie du mit einfacher bedingter Logik hochspezifische Datenpunkte aus riesigen Arrays extrahierst.
3m 34s
7
Der universelle Übersetzer: Interoperabilität
Diese Episode enthüllt, warum NumPy das Rückgrat der Python-Data-Science bleibt. Du lernst, wie DLPack und das Array Interface ein Zero-Copy-Memory-Sharing zwischen Tools wie Pandas und PyTorch ermöglichen.
3m 53s

Episoden

1

Die Kernidentität: ndarray

3m 34s

Diese Episode behandelt das ndarray-Objekt, homogene Datentypen und feste Speicherzuweisung. Du lernst, warum Standard-Python-Listen für groß angelegte Mathematik ineffizient sind und wie NumPy dieses Problem löst, indem es auf kompilierten C-Code zurückgreift.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. NumPy, Folge 1 von 7. Die Standard-Python-List ist zwar sehr flexibel, aber in dem Moment, in dem du versuchst, mit einer Million Items zu rechnen, stößt du an eine Performance-Wand. Du zahlst am Ende einen massiven Pointer-Overhead, nur um Zahlen miteinander zu multiplizieren. Die Lösung für dieses Bottleneck ist die Core-Engine des Scientific Computing in Python: das ndarray. Um zu verstehen, warum es das ndarray gibt, musst du dir ansehen, was Standard-Lists unter der Haube machen. Eine Python-List speichert keine rohen Zahlen. Sie speichert Pointer. Jeder Pointer verweist das System auf eine verstreute Stelle im Memory, wo ein komplettes Python-Object liegt. Wenn du einen Standard-Loop schreibst, um zwei Sequenzen von einer Million Zahlen zu multiplizieren, arbeitet der Python-Interpreter extrem hart. Für jedes einzelne Item holt er den Pointer, lokalisiert das Object, checkt den Data Type, um zu bestätigen, dass es wirklich eine Zahl ist, führt die Berechnung durch und speichert das neue Object. Das eine Million Mal zu machen, erzeugt massiven Overhead. Dieser Cycle aus Pointer-Chasing und Type-Checking ist der Grund, warum Standard-Loops für große mathematische Operationen einfach zu langsam sind. Das ndarray, was für N-dimensionales Array steht, opfert diese Flexibilität im Austausch für puren Speed. Der N-dimensionale Teil bedeutet, dass dieses Object eine flache Zahlen-Sequenz, ein zweidimensionales Grid oder eine komplexe multidimensionale mathematische Matrix darstellen kann. Unabhängig davon, wie viele Dimensionen du definierst, arbeitet es unter der Haube nach zwei strengen Regeln. Erstens erfordert es homogene Data Types. Jedes einzelne Element in einem ndarray muss exakt vom selben Type sein, wie zum Beispiel ein 64-Bit-Float. Zweitens nutzt es eine feste Memory-Größe. Wenn du ein ndarray erstellst, reserviert NumPy einen einzigen, zusammenhängenden Memory-Block. Es gibt keine Pointer. Die rohen Zahlen liegen dicht gepackt nebeneinander im System-Memory. Hier ist die entscheidende Erkenntnis. Weil NumPy den exakten Data Type und das exakte Memory-Layout kennt, kann es den langsamen Python-Interpreter komplett umgehen. Wenn du zwei ndarrays mit einer Million Zahlen multiplizierst, schreibst du keinen Loop. Du schreibst einfach Array A multipliziert mit Array B. Dieser Prozess wird Vectorization genannt. NumPy nimmt deinen Befehl und übergibt die eigentliche Berechnung an vorkompilierten C-Code. Der C-Code jagt mit Hardware-Geschwindigkeit durch diesen zusammenhängenden Memory-Block. Er überspringt das Type-Checking und die Pointer-Lookups für einzelne Items, weil das Memory perfekt einheitlich ist. Der Trade-off für diesen massiven Speed-Boost ist strukturelle Starrheit. Weil das Memory ein einziger zusammenhängender Block ist, kannst du nicht einfach eine neue Zahl an ein ndarray appenden, so wie du es bei einer Python-List machst. Wenn du ein größeres Array brauchst, muss NumPy in der Regel einen brandneuen Memory-Block allozieren und die alten Daten rüberkopieren. Du baust den Container in der exakten Größe, die du brauchst, und dann führst du deine Operations auf dem gesamten Block auf einmal aus. Die Standard-Python-List ist eine Sammlung isolierter Objects, die über das Memory verteilt sind. Das NumPy-ndarray ist ein dichter, einheitlicher Block aus rohen Daten, der dafür designt wurde, sofort von optimiertem C-Code verarbeitet zu werden. Wenn dir diese Episoden gefallen und du die Show unterstützen möchtest, kannst du auf Patreon nach DevStoriesEU suchen. Das war's für diese Folge. Danke fürs Zuhören und keep building!
2

Arrays beschwören: Erstellung & Shape

4m 08s

Diese Episode untersucht, wie man multidimensionale Arrays mithilfe intrinsischer Funktionen richtig erstellt. Du lernst, wie du Werkzeuge wie zeros, arange und linspace nutzt, um Datensätze in Sekundenschnelle zu generieren.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. NumPy, Folge 2 von 7. In Data Science tippst du Daten selten von Hand ein. Stattdessen musst du mit einem einzigen Befehl riesige leere Grids und Zahlenbereiche erzeugen. Lass uns über die Built-in-Funktionen sprechen, mit denen du Arrays von Grund auf neu erstellen und ihre Struktur steuern kannst. Zuerst eine kurze Korrektur zur manuellen Erstellung. Wenn du eine Standard-Python-Liste mit der grundlegenden array-Funktion in ein Array umwandelst, ist ein häufiger Fehler, mehrere separate Argumente zu übergeben, um mehrere Dimensionen zu erzeugen. Die Funktion erwartet eine einzige Sequence. Um ein zweidimensionales Array zu erstellen, übergibst du eine Liste, die andere Listen enthält, und nicht zwei separate Listen. Jedes Array, das du erstellst, enthält strukturelle Metadaten. Zwei Properties sind hier besonders wichtig. Die erste ist ndim, die dir die Anzahl der Achsen oder Dimensionen des Arrays angibt. Eine flache Sequence hat ein ndim von eins, während ein flaches Grid ein ndim von zwei hat. Die zweite Property ist shape. Shape ist ein Tuple von Integern, das die genaue Größe des Arrays entlang jeder Dimension angibt. Wenn du eine Matrix mit zwei Zeilen und drei Spalten hast, ist ihre shape zwei mal drei. Die Länge des shape-Tuples entspricht immer dem ndim-Wert. Arrays aus bestehenden Listen zu erstellen, ist für kleine Tests völlig in Ordnung, aber für echte Arbeit musst du Arrays programmatisch generieren. Wenn du einen Placeholder brauchst, den du später mit Daten füllen willst, nutzt du die zeros- oder ones-Funktionen. Du übergibst diesen Funktionen einfach ein shape-Tuple, und sie geben ein Array mit genau dieser Struktur zurück, das komplett mit Nullen oder Einsen gefüllt ist. Standardmäßig erzeugen diese Funktionen Floating-Point-Zahlen, aber du kannst das überschreiben, indem du einen anderen Datentyp angibst. Wenn du eine Sequence von Zahlen brauchst, bietet NumPy zwei Hauptwerkzeuge. Das erste ist arange, das sehr ähnlich wie das Standard-Python range funktioniert. Du gibst ihm einen Startwert, einen Stopwert und eine Schrittweite. Es generiert ein Array von Zahlen, die genau diesen Abstand haben. Während arange super für Integer ist, kann die Verwendung mit Floating-Point-Schritten zu unvorhersehbaren Ergebnissen führen, weil Computer mit Dezimalgenauigkeit speziell umgehen. Die Anzahl der Elemente, die du zurückbekommst, kann aufgrund winziger Rundungsfehler leicht variieren. Das bringt uns zu linspace, was das Problem der Floating-Point-Genauigkeit löst. Anstatt die Schrittweite zu definieren, gibst du die exakte Anzahl der gewünschten Elemente an. Du übergibst linspace einen Startwert, einen Stopwert und die Gesamtanzahl der Punkte. NumPy berechnet dann den exakten Abstand für dich. Stell dir ein Szenario vor, in dem du eine mathematische Funktion über ein bestimmtes Intervall auswertest. Du möchtest die Funktion über ein gleichmäßiges Grid von Koordinaten zwischen null und eins berechnen. Mit linspace kannst du genau hundert gleichmäßig verteilte Koordinaten über dieses Intervall generieren. Du erhältst ein perfekt verteiltes eindimensionales Array, das garantiert, dass sowohl die Start- als auch die Endgrenze enthalten sind. Hier wird es interessant. Der Unterschied zwischen diesen beiden Sequence-Generatoren bestimmt deinen Workflow. Nutze arange, wenn die exakte Schrittweite wichtig ist, wie zum Beispiel beim Zählen von Integern in Zweierschritten. Aber nutze immer linspace, wenn du mit Floats und Intervallen arbeitest, damit du garantieren kannst, wie viele Datenpunkte du genau bekommst und deine Grenzen präzise triffst. Danke fürs Zuhören – bis zum nächsten Mal.
3

Unter der Haube: Speicher, Strides und Views

4m 10s

Diese Episode taucht in die interne Architektur von NumPy ein und konzentriert sich auf den Data Buffer und Strides. Du lernst, warum Operationen wie Slicing und Transponieren praktisch sofort ausgeführt werden, da sie Memory Views und keine Kopien zurückgeben.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. NumPy, Folge 3 von 7. Du hast eine Matrix mit einer Milliarde Pixeln und musst ihre Zeilen und Spalten vertauschen. Wenn du das in Standard-Python machst, kommt dein Rechner fast zum Stillstand, während er Gigabytes an Daten kopiert. In NumPy passiert das sofort. Beim Umordnen dieser Pixel wird tatsächlich kein einziges Byte im Memory verschoben. Das liegt daran, wie NumPy unter der Haube mit Memory, Strides und Views umgeht. Um zu verstehen, warum NumPy so schnell ist, musst du dir die interne Struktur eines Arrays ansehen. Ein NumPy-Array ist kein einzelnes, monolithisches Objekt. Es ist strikt in zwei Teile getrennt. Der erste Teil ist der Data Buffer. Das ist ein zusammenhängender, flacher Block aus Raw Memory. Es ist einfach nur eine eindimensionale Reihe von Bytes im RAM. Der Raw Buffer weiß absolut nichts über Zeilen, Spalten oder Dimensionen. Der zweite Teil sind die Metadaten. Das ist ein kleiner Header, intern als C-Struktur implementiert, der NumPy sagt, wie diese rohe Reihe von Bytes interpretiert werden soll. Die Metadaten enthalten einen Pointer auf den Anfang des Data Buffers, den Data Type, den Shape des Arrays und die Strides. Strides sind der Mechanismus, der eine flache Reihe von Memory in ein mehrdimensionales Grid verwandelt. Ein Stride ist einfach die Anzahl der Bytes, die der Computer im Memory vorwärts springen muss, um das nächste Element entlang einer bestimmten Achse zu finden. Angenommen, du hast ein zweidimensionales Array aus 64-Bit-Integern. Jeder Integer belegt acht Bytes. Um eine Spalte nach rechts zu rücken, könnte der Stride acht Bytes betragen. Aber um in die nächste Zeile zu springen, könnte der Stride achtzig Bytes sein, weil er eine komplette Datenzeile im Raw Buffer überspringen muss, um den Anfang der nächsten zu finden. Viele Entwickler nehmen an, dass das System, wenn du einen Slice von einem Array nimmst, neues Memory alloziert und die ausgewählten Daten dorthin kopiert. Das ist falsch. Wenn du einen Slice anforderst, lässt NumPy den Raw Data Buffer komplett unangetastet. Stattdessen erstellt es einen neuen Metadaten-Header. Dieser neue Header zeigt auf exakt denselben Memory-Block, aber er ändert den Start-Pointer und passt die Strides an, um die Elemente zu überspringen, die du ausgeschlossen hast. Das nennt man einen View. Hier ist die entscheidende Erkenntnis. Weil die Raw Data und die Metadaten getrennt gehalten werden, sind Operationen, die den Shape oder die Reihenfolge des Arrays ändern, fast komplett kostenlos. Denk nochmal an das Transponieren dieser riesigen Milliarden-Pixel-Matrix. NumPy nimmt die Daten nicht und ordnet sie physisch neu an. Es tauscht einfach die Stride-Werte im neuen Metadaten-Header aus. Die Anzahl der Bytes, die du vorher übersprungen hast, um die nächste Zeile zu finden, wird zu der Anzahl, die du überspringst, um die nächste Spalte zu finden. Deinem Code wird eine komplett andere Array-Struktur zurückgegeben, aber es ist nur ein View, der auf exakt dasselbe physische Memory schaut. Diese Trennung ist das Fundament von NumPys Memory-Effizienz. Du kannst ein riesiges Dataset in Dutzende überlappende Slices zerschneiden, sie an verschiedene Funktionen übergeben und verbrauchst null zusätzliches Memory für die Daten selbst. Du generierst dabei nur winzige Metadaten-Header. Das bedeutet allerdings, dass du State teilst. Wenn du einen Wert in einem Slice änderst, verändert das auch das ursprüngliche Array, weil es unter all dem nur einen einzigen wahren Data Buffer gibt. Die Trennung der Raw Bytes von den Regeln, die sie steuern, bedeutet, dass deine schwersten Data Transformations oft nur leichtgewichtige Metadaten-Swaps sind. Das war's für diese Folge. Danke fürs Zuhören, und keep building!
4

Universal Functions: Mathematik ohne Schleifen

3m 39s

Diese Episode behandelt Universal Functions (ufuncs) und wie sie Operationen vektorisieren. Du lernst, Python-for-Schleifen vollständig zu eliminieren, indem du elementweise Mathematik und achsenbasierte Reduktionen anwendest.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. NumPy, Folge 4 von 7. Falls du jemals einen for-Loop schreibst, um Zahlen in einem Array zu multiplizieren: Hör auf damit! Dadurch zahlst du für jedes einzelne Item den Overhead des Python-Interpreters, und dein Code läuft hundertmal langsamer als nötig. Die Lösung ist, Universal Functions zu nutzen, um Mathe ohne Loops durchzuführen. Ein häufiger Fehler ist der Versuch, ein ganzes Array an eine Funktion aus Pythons Standard-math-Modul zu übergeben. Wenn du eine Million Sensor-Messwerte an math.sin übergibst, wirft Python einen Error. Das Standard-math-Modul versteht nur einzelne Scalar-Werte. Um ein Array zu verarbeiten, müsstest du normalerweise einen Loop schreiben. Aber Python ist eine dynamische Sprache. Innerhalb eines Loops evaluiert der Interpreter in jeder einzelnen Iteration den Datentyp, bevor er das Ergebnis berechnet. Wenn du riesige Datasets verarbeitest, summieren sich diese winzigen Type-Checking-Pausen zu einem signifikanten Performance-Bottleneck. Eine Universal Function, oder ufunc, löst das, indem sie automatisch Element für Element auf Arrays operiert. Wenn du eine ufunc aufrufst, pusht NumPy die Loop-Execution runter in kompilierten C-Code. Weil NumPy-Arrays einen einzigen, einheitlichen Datentyp haben, muss der C-Code nicht pausieren und Types checken. Er iteriert über zusammenhängende Memory-Blöcke und berechnet das Ergebnis so schnell, wie dein Prozessor es zulässt. Schauen wir uns ein konkretes Szenario an. Du hast ein Array mit Tausenden von Umwelt-Sensorwerten und musst auf alle gleichzeitig eine mathematische Transformation anwenden. Anstatt einen Loop zu schreiben, übergibst du einfach das komplette Array an eine Universal Function wie numpy.exp oder numpy.sin. Die ufunc nimmt dein Input-Array, führt den schnellen C-Level-Loop über jedes einzelne Element aus und gibt ein komplett neues Array mit den transformierten Werten zurück. Das ist der Teil, auf den es ankommt. Ufuncs machen mehr als nur Element-für-Element-Transformationen. Sie enthalten built-in Methods, um Daten zu reduzieren, und umgehen Python für Aggregationen komplett. Die häufigste ist die reduce-Methode. Angenommen, du hast deine mathematische Transformation angewendet und brauchst jetzt die Gesamtsumme des kompletten Arrays. Du rufst die reduce-Methode direkt auf der Addition-ufunc auf. Du schreibst numpy.add.reduce und übergibst ihr dein Array. Die reduce-Methode wendet die zugrundeliegende Addition-Operation auf die ersten beiden Elemente an. Sie nimmt diese Summe, addiert sie zum dritten Element und setzt dieses Pattern fort, bis das gesamte Array zu einem einzigen Scalar-Wert reduziert ist. Wenn deine Daten mehrere Dimensionen haben, kannst du steuern, wie dieser Collapse passiert. Wenn deine Sensorwerte ein zweidimensionales Grid bilden, in dem Rows verschiedene Sensoren und Columns einzelne Timestamps sind, zerstört das Reducen des gesamten Grids auf eine Zahl diese Struktur. Indem du ein axis Argument übergibst, steuerst du die Richtung der Operation. Wenn du der reduce-Methode sagst, entlang axis zero zu operieren, reduziert sie die Rows und du behältst ein Array, das die Summe aller Sensoren zu jedem einzelnen Timestamp enthält. Jedes Mal, wenn du eine Universal Function die Iteration nativ übernehmen lässt, tauschst du langsame Python-Loops gegen hardwareoptimierte C-Execution. Danke fürs Einschalten. Bis zum nächsten Mal!
5

Broadcasting: Die Magie nicht übereinstimmender Shapes

4m 23s

Diese Episode erklärt die genauen Regeln des Broadcasting. Du lernst, wie NumPy Arrays mit nicht übereinstimmenden Shapes konzeptionell dehnt, damit sie zusammen verarbeitet werden können, ohne Speicherplatz zu verschwenden.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. NumPy, Folge 5 von 7. Was passiert, wenn du versuchst, eine dreidimensionale Matrix von einer Million Pixeln mit einem einzigen kleinen Array aus drei Zahlen zu multiplizieren? In vielen strikten Sprachen bekommst du einen Shape Mismatch Error. In NumPy funktioniert es einfach. Dieses Verhalten nennt man Broadcasting. Broadcasting beschreibt, wie NumPy Arrays mit unterschiedlichen Shapes bei arithmetischen Operationen behandelt. Es nimmt das kleinere Array und streckt es konzeptionell über das größere, sodass ihre Shapes perfekt übereinstimmen. Zuhörer glauben oft fälschlicherweise, dass dieses Strecken Daten physisch kopiert, um ein neues, passendes Array im Speicher zu bauen. Das tut es nicht. NumPy handhabt dieses Alignment implizit auf C-Ebene. Es iteriert mehrmals über dieselben Elemente mit Zero Memory Overhead, was Broadcasting unglaublich schnell und hocheffizient macht. Um es zu nutzen, musst du verstehen, wie NumPy entscheidet, ob zwei Arrays kompatibel sind. Es schaut sich nicht die Gesamtzahl der Elemente an. Es schaut auf die Shape-Tuples. NumPy reiht die Shapes der beiden Arrays aneinander und vergleicht sie, beginnend mit den Trailing Dimensions – also denen ganz rechts – und arbeitet sich nach links vor. Zwei Dimensionen sind kompatibel, wenn sie eine von zwei strikten Bedingungen erfüllen. Sie müssen exakt gleich sein, oder eine von ihnen muss die Zahl Eins sein. Wenn an irgendeinem Punkt während des Vergleichs keine der Bedingungen erfüllt ist, wirft NumPy einen ValueError und die Operation schlägt fehl. Lass uns das auf ein konkretes Szenario anwenden. Du arbeitest mit einem RGB-Bild. Du lädst es in ein NumPy-Array mit einem Shape von 256 mal 256 mal 3. Die 3 repräsentiert die roten, grünen und blauen Farbkanäle am Ende des Shapes. Jetzt musst du dieses Bild farbkorrigieren, indem du jeden Farbkanal unterschiedlich skalierst. Du definierst ein eindimensionales Array, das drei Color Correction Weights enthält. Der Shape dieses Arrays ist einfach 3. Wenn du das riesige Image-Array mit dem winzigen Weights-Array multiplizierst, wendet NumPy die Rechts-nach-links-Regel an. Es platziert den Image-Shape, 256 mal 256 mal 3, über den Weights-Shape, der einfach 3 ist. Ganz rechts beginnend, werden die Trailing Dimensions verglichen. Beide sind 3. Weil sie gleich sind, sind sie kompatibel. Dann bewegt sich NumPy nach links. Das Image-Array hat eine Dimension von 256, aber dem Weights-Array sind die Dimensionen komplett ausgegangen. Hier greift der zweite Teil der Regel. Wenn ein Array weniger Dimensionen hat als das andere, stellt NumPy seinem Shape implizit Einsen voran, bis sie in der Länge übereinstimmen. Der Weights-Array-Shape wird als 1 mal 1 mal 3 behandelt. Nun geht der Vergleich weiter. Das Image hat eine Dimension von 256, und das Weights-Array hat jetzt eine Dimension von 1. Weil eines davon eine 1 ist, sind sie kompatibel. Das Weights-Array wird konzeptionell über die 256 Rows gestreckt. Das passiert nochmal für die nächste Dimension. Die Shapes stimmen überein, und NumPy wendet deine drei Color Weights nahtlos auf alle 65.000 Pixel an. Das ist der Teil, auf den es ankommt. Die Regel funktioniert nur von rechts nach links. Wenn du ein zweidimensionales Array mit dem Shape 5 mal 4 hast und versuchst, ein Array mit dem Shape 5 zu addieren, denkst du vielleicht, es würde sich über die Columns strecken. Das wird es nicht. Von rechts beginnend, vergleicht NumPy 4 und 5. Sie sind nicht gleich, und keines davon ist eins. Die Operation schlägt sofort fehl. Damit es funktioniert, müsstest du das zweite Array zuerst auf 5 mal 1 reshapen. Broadcasting lässt dich sauberen, loop-freien Code schreiben, der mit Compiled Speeds ausgeführt wird. Die goldene Regel ist immer Trailing Dimensions zuerst: Sie müssen exakt übereinstimmen, oder eine von ihnen muss eine Eins sein. Danke fürs Einschalten. Bis zum nächsten Mal!
6

Präzisionsfilterung: Boolean Masking

3m 34s

Diese Episode konzentriert sich auf fortgeschrittenes Boolean Masking zum Filtern komplexer Datensätze. Du lernst, wie du mit einfacher bedingter Logik hochspezifische Datenpunkte aus riesigen Arrays extrahierst.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. NumPy, Folge 6 von 7. Alle negativen Zahlen aus einem Array mit einer Milliarde Elementen zu ziehen, ist kein Suchproblem. Es sollte keine Schleife erfordern und deine Anwendung auf keinen Fall ausbremsen. Hier nutzen wir Precision Filtering: Boolean Masking. Basic Slicing holt dir saubere, vorhersehbare Datenblöcke. Aber echte Daten sind chaotisch. Du willst selten einfach nur die ersten zehn Elemente. Du brauchst bestimmte Elemente basierend auf einer logischen Bedingung, und diese Elemente könnten zufällig über dein ganzes Dataset verstreut sein. In NumPy nennt man diese Art, Daten zu holen, Advanced Indexing, und Boolean Masking ist eine der mächtigsten Formen davon. Nimm mal ein riesiges Array mit Temperaturmesswerten. Du musst nur die Werte isolieren, die unter den Gefrierpunkt fallen. Anstatt eine Schleife zu schreiben, um jeden einzelnen Wert zu checken, benutzt du eine Maske. Eine Maske ist ein Array aus Boolean-Werten, also True oder False. Das Entscheidende ist: Dieses Boolean-Array hat exakt dieselbe Shape wie dein ursprüngliches Daten-Array. Du erstellst sie, indem du eine Kleiner-als-Null-Bedingung direkt auf das Array anwendest. NumPy wertet jedes einzelne Element sofort aus. Wenn eine Temperatur unter null ist, speichert die Maske an genau dieser Position ein True. Ist die Temperatur null oder höher, speichert sie ein False. Sobald du diese Maske hast, wendest du sie wieder auf das ursprüngliche Array an, indem du sie genau dort übergibst, wo du normalerweise einen Index setzen würdest. NumPy liest die Maske, pickt sich jedes Element heraus, bei dem die Maske True ist, und verwirft den Rest. Diese Operation liefert ein brandneues, eindimensionales Array, das nichts anderes als deine Gefriertemperaturen enthält. Das passiert in einem einzigen Schritt und wird unter der Haube an hochoptimierten C-Code weitergereicht. Pass bei der nächsten Unterscheidung gut auf, denn darüber stolpern viele Entwickler. Du musst genau wissen, was NumPy dir zurückgibt, wenn du Daten filterst. Basic Slicing gibt eine View zurück. Wenn du die ersten zehn Elemente eines Arrays slicest und sie veränderst, ändert sich das ursprüngliche Array. Boolean Masking verhält sich da völlig anders. Weil Boolean Masking eine Form von Advanced Indexing ist, gibt es immer eine Copy der Daten zurück, niemals eine View. Der Grund dafür ist die Speicherarchitektur. Beim Slicen ändert NumPy einfach nur die Pointer auf einen bestehenden, zusammenhängenden Speicherblock. Aber wenn du eine Boolean Mask anwendest, sind die ausgewählten Elemente völlig beliebig. Sie liegen im Speicher nicht mehr feinsäuberlich nebeneinander. NumPy muss sie zusammensuchen und neuen Speicherplatz allokieren, um das Ergebnis zu speichern. Das bedeutet: Wenn du dein neu gefiltertes Array mit Gefriertemperaturen veränderst, bleibt dein ursprüngliches Dataset komplett unangetastet. Du kannst diese Bedingungen auch chainen. Wenn du Temperaturen brauchst, die unter dem Gefrierpunkt, aber strikt über minus zehn Grad liegen, kombinierst du die beiden logischen Bedingungen. NumPy wertet die kombinierte Logik Element für Element aus und baut eine einzige, präzise Maske. Wenn du eine Boolean Mask anwendest, tauschst du die Speichereffizienz einer View gegen absolute Filterpräzision ein. Dafür bekommst du eine makellose, unabhängige Copy von exakt den Daten, die du angefragt hast. Das war's für diese Folge. Danke fürs Zuhören und keep building!
7

Der universelle Übersetzer: Interoperabilität

3m 53s

Diese Episode enthüllt, warum NumPy das Rückgrat der Python-Data-Science bleibt. Du lernst, wie DLPack und das Array Interface ein Zero-Copy-Memory-Sharing zwischen Tools wie Pandas und PyTorch ermöglichen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. NumPy, Folge 7 von 7. Da moderne GPU Frameworks das Heavy Lifting im Machine Learning übernehmen, denkst du vielleicht, NumPy wird langsam überflüssig. Du nimmst vielleicht sogar an, dass die Konvertierung eines PyTorch CPU Tensors in ein NumPy Array eine langsame Memory Copy erfordert, die deine Pipeline ausbremst. Beides ist falsch. Die Realität ist, dass NumPy als The Universal Translator fungiert: Interoperabilität, die das gesamte Python Data Ecosystem zusammenhält. Denk an eine Standard Machine Learning Pipeline. Du nutzt Pandas, um ein riesiges tabellarisches Dataset zu laden und zu bereinigen. Du extrahierst diese Werte in NumPy, um einen speziellen mathematischen Filter anzuwenden. Schließlich übergibst du diese gefilterten Daten an PyTorch, um ein Neural Network zu trainieren. Wenn jede dieser Libraries ihre Daten isolieren würde, würde der Wechsel von Schritt zu Schritt bedeuten, das gesamte Dataset immer wieder im Memory zu duplizieren. Du würdest deinen RAM ausschöpfen und Processing Time verschwenden, nur um Bytes hin und her zu schieben. Stattdessen bewegen sich die Daten durch die Magie der Interoperabilität eigentlich nie. Pandas, NumPy und PyTorch teilen sich einfach exakt denselben zugrundeliegenden Memory Pointer. Wenn PyTorch die Daten liest, schaut es auf exakt dieselben physischen Memory Adressen, die Pandas ursprünglich allocated hat. Dieses Zero Copy Sharing wird durch Standard Memory Protokolle ermöglicht. Das grundlegendste ist das Array Interface. Wenn ein Python Objekt dieses Interface exposed, übergibt es im Grunde ein kleines Dictionary mit Metadaten. Diese Metadaten sagen NumPy genau, wo die Raw Data im Memory beginnt, welche Shape sie hat und welchen Data Type sie enthält. Wenn du eine NumPy Funktion auf einem kompatiblen Objekt aufrufst, liest NumPy diese Anweisungen und legt seine eigene Array Struktur um den bestehenden Memory Block. Es erstellt kein neues Array; es erstellt einfach eine neue View auf die alten Daten. Hier ist die entscheidende Erkenntnis. Das ursprüngliche Array Interface wurde primär für Standard System Memory entwickelt. Als Data Science sich in Richtung Hardware Accelerators bewegte, brauchte das Ökosystem einen Weg, um Daten, die auf GPUs oder Custom Chips liegen, zu teilen, ohne sie zurück durch die CPU zu routen. Das führte zur Adaption von DLPack. DLPack ist ein moderner, offener Standard für das Sharing von multidimensionalen Arrays über verschiedene Frameworks hinweg. Es definiert eine stabile Struktur, die jede Library produzieren und konsumieren kann. Wenn du einen Tensor in einem Framework wie PyTorch oder JAX hast, kannst du ihn über das DLPack Protokoll exportieren. NumPy kann ihn dann nahtlos mit seiner dedizierten from dlpack Funktion einlesen. Während NumPy selbst meistens auf der CPU operiert, bedeutet sein Support für DLPack, dass es als zentraler Routing Hub fungieren kann. Du kannst ein DLPack Objekt von einem Deep Learning Framework an NumPy übergeben, oder von NumPy zurück an ein Framework, und das alles ohne teure Data Duplication. NumPy hat schon lange aufgehört, nur eine Math Library zu sein. Es ist der unsichtbare Memory Standard, der verhindert, dass das Python Data Ecosystem in isolierte, inkompatible Inseln zersplittert. Ich ermutige dich, die offizielle Documentation zu erkunden, diese Zero Copy Conversions hands-on in deinem eigenen Terminal auszuprobieren, oder devstories dot eu zu besuchen, um Themen für unsere zukünftigen Serien vorzuschlagen. Das war's für diese Folge. Danke fürs Zuhören, und keep building!