# NumPy

NumPy ist eine Programmbibliothek für die Programmiersprache Python, die eine einfache Handhabung von Vektoren, Matrizen oder generell großen mehrdimensionalen Arrays ermöglicht. Neben den Datenstrukturen bietet NumPy auch effizient implementierte Funktionen für numerische Berechnungen an.
Der Vorgänger von NumPy, Numeric, wurde unter Leitung von Jim Hugunin entwickelt. Travis Oliphant gliederte modifizierte Funktionalitäten des Konkurrenten Numarray in Numeric ein und veröffentlichte dies 2005 als NumPy. Die Bibliothek ist quelloffen und wird von vielen Mitwirkenden weiterentwickelt.

## Merkmale

Der für Python standardmäßig installierte Interpreter CPython führt Kommandos als unoptimierten Bytecode aus. Mathematische Algorithmen sind in dieser Python-Variante oft langsamer als eine äquivalente kompilierte Umsetzung. NumPy stellt hier eine performante Alternative dar. Bestehende iterative Algorithmen müssen dazu gegebenenfalls für mehrdimensionale Array-Operationen umgeschrieben werden. NumPys Operatoren und Funktionen sind optimiert für derartige Arrays und ermöglichen so eine besonders effiziente Evaluation.
Die Handhabung von NumPy-Arrays in Python ist damit vergleichbar zu MATLAB; beide ermöglichen eine schnelle Ausführung von Algorithmen, solange diese für ganze Arrays oder Matrizen statt einzelne Skalare konzipiert sind. Die Integration von NumPy in Python ermöglicht die Verwendung und Kombination mit vielen weiteren Paketen aus dem umfangreichen Python-Umfeld. Weitere MATLAB-ähnliche Funktionen bietet die Python-Bibliothek SciPy. Auch der Funktionsumfang der Matplotlib-Bibliothek zur einfachen Erstellung von Plots in Python ist den Möglichkeiten von MATLAB sehr ähnlich. Intern verwenden sowohl MATLAB als auch NumPy die beiden Programmbibliotheken BLAS und LAPACK für eine effiziente Berechnung linearer Algebra.
Die Python-Schnittstelle des weit verbreiteten Computer-Vision-Pakets OpenCV verwendet intern NumPy-Arrays zur Verarbeitung von Daten. Bilder mit mehreren Farbkanälen werden beispielsweise mit dreidimensionalen Arrays dargestellt. Indexierung, Slicing oder Maskierung mit anderen Arrays sind daher sehr effiziente Methoden um gezielt auf bestimmte Pixel zugreifen zu können. NumPy-Arrays als universelle Datenstruktur für Bilder, extrahierte Feature-Punkte, Faltungsmatrizen und vieles mehr erleichtern die Entwicklung und das Debugging von Algorithmen zur Bildverarbeitung.

### Die ndarray-Datenstruktur

Die Kernfunktionalität von NumPy basiert auf der Datenstruktur „ndarray“ (n-dimensionales Array), die auch als „NumPy Array“ bezeichnet wird. Dessen wesentliche Bestandteile sind ein Zeiger auf einen zusammenhängenden Speicherbereich zusammen mit Metadaten, welche die darin gespeicherten Daten beschreiben:

#### Datentyp

    Anders als in Pythons eigener List-Datenstruktur sind NumPy-Arrays homogen typisiert: Alle Elemente eines Arrays müssen vom selben Datentyp sein.

#### Form (engl. shape)

    Definiert die Dimensionen in jeder Indexausprägung („Achse“) des Arrays und die Anzahl der Achsen (bzw. Indizes).

#### Schrittlängen (engl. strides)

    Die Schrittlängen beschreiben für jede Achse, wie viele Bytes man im linearen Speicher springen muss, wenn ein zu dieser Achse gehöriger Index um 1 erhöht wird, zum Beispiel um zwischen zwei Zeilen oder zwei Spalten zu springen.
Diese Arrays erlauben es außerdem, von allozierten Puffern anderer Sprachen zu lesen, ohne Daten kopieren zu müssen. Mit C/C++-, Cython- oder Fortran-Erweiterungen des CPython-Interpreters können so auch einfach weitere bestehende Numerikbibliotheken mitverwendet werden. Dieses Verhalten wird beispielsweise von SciPy genutzt, welches Wrapper für externe Bibliotheken wie BLAS oder LAPACK bereitstellt. NumPy bietet native Unterstützung für Memory Mapping der ndarrays.

### Einschränkungen

Tatsächliches Einfügen oder Anhängen von Array-Einträgen wie bei Pythons Listen ist nicht möglich. Die Funktion np.pad, mit der Arrays erweitert werden können, legt neue Arrays gewünschter Größe an, kopiert bestehende hinein und liefert dies zurück. Auch bei der Aneinanderreihung zweier Arrays mit np.concatenate([a1,a2]) werden die Arrays nicht wirklich verkettet, sondern ein neues zusammenhängendes Array zurückgegeben. Bei NumPys Funktion np.reshape ist eine Umformung auch nur möglich, wenn sich die Anzahl der Array-Einträge nicht ändert. Diese Einschränkungen sind darauf zurückzuführen, dass NumPy-Arrays im Speicher als zusammenhängender Bereich angelegt werden müssen. Das Blaze-Framework bietet hier eine Alternative, welches diese Einschränkung beheben soll.
Die Verwendung von NumPy-Arrays allein gegenüber Python-Listen bringt noch keinen Geschwindigkeitsvorteil mit sich. Entsprechende Algorithmen müssen zunächst in eine vektortaugliche Form umgeschrieben werden. Dies kann von Nachteil sein, da eventuell temporäre Arrays in Größe der Eingabe angelegt werden müssen und sich damit die Speicherkomplexität von konstant zu linear vergrößert. Eine Laufzeitkompilation wurde schon in einigen Paketen implementiert, um diese Probleme zu vermeiden. Open-Source-Lösungen, die mit NumPy interagieren können, sind unter anderem numexpr und Numba. Außerdem gibt es mit Cython noch eine statisch kompilierbare Alternative.
NumPy Arrays werden den Anforderungen bei der Verarbeitung großer Datenmengen und denen des Deep Learnings oftmals nicht gerecht. Zum Beispiel lädt NumPy die in den Arrays enthaltenen Daten komplett in den Arbeitsspeicher eines Computers, dessen Kapazität von wissenschaftlichen Datensätzen aber oft überschritten wird. Viele Deep Learning-Anwendungen wurden erst dadurch ermöglicht, dass die dafür notwendigen Operationen der linearen Algebra auf Rechnerverbünden mit spezieller, hochparalleler Hardware wie Grafikkarten und Tensor-Prozessoren verlagert wurden, NumPy aber für die Berechnung auf dem Prozessor und auf einzelnen Computer konzipiert wurde. Um diese Herausforderungen zu meistern, sind viele alternative Array-Implementierungen für Python erschienen, wie zum Beispiel Dask zum parallelen Rechnen auf Rechnerverbünden und TensorFlow und JAX für Berechnungen auf Grafikkarten. Der Einfluss NumPys wird daran deutlich, dass diese Bibliotheken meistens eine NumPy-ähnliche Programmierschnittstelle oder eine Untermenge davon zur Verfügung stellen, um Anfängern den Umstieg zu erleichtern und eine Änderung der Array-Implementierung mit nur minimalen Änderungen am Programmquelltext zu ermöglichen.

## Geschichte

Die Programmiersprache Python war ursprünglich nicht für numerische Berechnungen optimiert, erlangte aber schnell große Bekanntheit im Anwendungsbereich des Wissenschaftlichen Rechnens. So wurde 1995 die Interessengemeinschaft matrix-sig gegründet, die das Ziel verfolgte, ein einheitliches Paket zur Array-Handhabung zu definieren. Eines der Mitglieder war Python-Autor Guido van Rossum, welcher Syntaxerweiterungen, besonders die Indexierung, direkt in Python einpflegte, um die Verwendung von Arrays zu vereinfachen. Die erste Implementierung eines Matrizenpakets wurde von Jim Fulton entwickelt, die später von Jim Hugunin generalisiert und als Numeric (teilweise auch Numerical Python Extensions) bekannt wurde, dem Vorläufer von NumPy. Hugunin war damals Student am MIT,$^{:10}$, verließ das Projekt aber 1997 um weiter an JPython zu arbeiten. Paul Dubois vom LLNL übernahm die Leitung des Projekts.$^{:10}$ Weitere Beitragende der ersten Stunde waren außerdem David Ascher, Konrad Hinsen und Travis Oliphant.$^{:10}$
Das Paket Numarray wurde als Alternative zu Numeric entwickelt, die mehr Flexibilität bieten sollte. Beide Pakete gelten inzwischen als veraltet und werden nicht mehr weiterentwickelt. Numarray and Numeric hatten jeweils ihre Stärken und Schwächen und wurden eine Zeit lang noch parallel für unterschiedliche Anwendungsbereiche eingesetzt. Die letzte Version (v24.2) von Numeric erschien am 11. November 2005, die letzte (v1.5.2) von Numarray am 24. August 2006.
Anfang 2005 begann Travis Oliphant den Funktionsumfang von Numarray in Numeric zu übertragen, um die Entwicklergemeinschaft auf ein vereinigtes Projekt zu konzentrieren; das Ergebnis wurde 2005 als NumPy 1.0 veröffentlicht. Dieses neue Projekt war außerdem Teil von SciPy, wurde aber auch separat als NumPy angeboten um zu vermeiden, dass das große SciPy-Paket installiert werden muss nur, um mit Array-Objekten arbeiten zu können. Von Version 1.5.0 an kann NumPy auch mit Python 3 verwendet werden.
2011 begann die Entwicklung einer NumPy-API für PyPy. Bislang wird allerdings noch nicht der gesamte NumPy-Funktionsumfang unterstützt.
Am 15. November 2017 gab das Team rund um NumPy bekannt, ab dem 1. Januar 2019 neue Funktionen nur noch für Python 3 bereitstellen zu wollen, während für Python 2 nur noch Fehlerbereinigungen erscheinen werden. Ab dem 1. Januar 2020 würden dann keine weiteren Aktualisierungen mehr für Python 2 folgen.