NumPy

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen
NumPy

NumPy logo.svg
Basisdaten

Maintainer Das NumPy-Team
Entwickler Travis Oliphant
Erscheinungsjahr 1995 (als Numeric); 2006 (als NumPy)
Aktuelle Version 1.16.2[1]
(26. Februar 2019)
Betriebssystem plattformübergreifend
Programmiersprache Python, C
Kategorie Numerische Bibliothek für wissenschaftliches Rechnen
Lizenz BSD (neu)
www.numpy.org

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[Bearbeiten | Quelltext bearbeiten]

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 compilierte 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, solang diese für ganze Arrays oder Matrizen statt einzelne Skalare konzipiert sind. MATLAB bietet große Erweiterungsmöglichkeiten mit Zusatzprodukten wie zum Beispiel Simulink. 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 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[Bearbeiten | Quelltext bearbeiten]

Die Kernfunktionalität von NumPy basiert auf der Datenstruktur „ndarray“ (n-dimensionales Array), einem zusammenhängenden Speicherbereich fester Größe.[2] Anders als in Pythons eigener List-Datenstruktur (welche konträr zu ihrem Namen eigentlich durch ein dynamisches Array verwirklicht ist) sind ndarrays homogen typisiert: Alle Elemente eines Arrays müssen vom selben Datentyp sein.

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.[2]

Einschränkungen[Bearbeiten | Quelltext bearbeiten]

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.[3]

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 scipy.weave, numexpr[4] und Numba.[5] Außerdem wäre Cython noch eine statisch kompilierbare Alternative.

Beispiele[Bearbeiten | Quelltext bearbeiten]

Array-Erzeugung
>>> import numpy as np
>>> x = np.array([1, 2, 3])
>>> x
array([1, 2, 3])
>>> y = np.arange(10) # analog zu Python's range-Funktion, nur wird ein Array statt einer Liste generiert
>>> y
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Basic operations
>>> a = np.array([1, 2, 3, 6])
>>> b = np.linspace(0, 2, 4) # erzeugt vier äquidistante Werte im Intervall [0,2]
>>> c = a - b
>>> c
array([ 1.    , 1.33333333, 1.66666667, 4.    ])
>>> a**2 # Python Operatoren können direkt auf Arrays angewandt werden
array([ 1, 4, 9, 36])
Universelle Funktionen
>>> a = np.linspace(-np.pi, np.pi, 100)
>>> b = np.sin(a)
>>> c = np.cos(a)
Lineare Algebra
>>> from numpy.random import rand
>>> from numpy.linalg import solve, inv
>>> a = np.array([[1, 2, 3], [3, 4, 6.7], [5, 9.0, 5]])
>>> a.transpose()
array([[1. , 3. , 5. ],
       [ 2. , 4. , 9. ],
       [ 3. , 6.7, 5. ]])
>>> inv(a)
array([[-2.27683616, 0.96045198, 0.07909605],
       [ 1.04519774, -0.56497175, 0.1299435 ],
       [ 0.39548023, 0.05649718, -0.11299435]])
>>> b = np.array([3, 2, 1])
>>> solve(a, b) # Löst die Gleichung ax = b
array([-4.83050847, 2.13559322, 1.18644068])
>>> c = rand(3, 3) # Erzeugt eine zufällige 3x3 Matrix mit Werten im Intervall [0,1]
>>> c
array([[0.3242542 , 0.94330798, 0.27474668],
       [0.45979412, 0.39204496, 0.58138993],
       [0.66361452, 0.90350118, 0.65898373]])
>>> np.dot(a, c) # Punkt Produkt der Matrizen
array([[ 3.23468601,  4.43790144,  3.41447772],
       [ 7.25815638, 10.45156168,  7.56499072],
       [ 9.07749071, 12.76245045,  9.9011614 ]])
>>> a @ c # Möglich ab Python 3.5 und NumPy 1.10
array([[ 3.23468601,  4.43790144,  3.41447772],
       [ 7.25815638, 10.45156168,  7.56499072],
       [ 9.07749071, 12.76245045,  9.9011614 ]])
Integration in OpenCV
>>> import numpy as np
>>> import cv2
>>> r = np.reshape(np.arange(256*256)%256,(256,256)) # 256x256 Pixel Array mit horizontalem Verlauf von 0 bis 255 für den roten Farbkanal
>>> g = np.zeros_like(r) # Array selber Größe und selbem Datentyp wie r aber gefüllt mit Nullen für den grünen Farbkanal
>>> b = r.T # Das transponierte r Array wird als vertikaler Verlauf des blauen Farbkanals verwendet.
>>> cv2.imwrite('gradients.png', np.dstack([b,g,r])) # OpenCV interpretiert Bilder in BGR, das in dritter Dimension gestapelte Array wird als 8bit RGB PNG-Datei 'gradients.png' gespeichert
True
Nächste-Nachbar-Suche - Iterativer Python-Algorithmus und vektorisierte NumPy-Alternative
>>> # # # Iterative Python Variante # # #
>>> points = [[9,2,8],[4,7,2],[3,4,4],[5,6,9],[5,0,7],[8,2,7],[0,3,2],[7,3,0],[6,1,1],[2,9,6]]
>>> qPoint = [4,5,3]
>>> minIdx = -1
>>> minDist = -1
>>> for idx, point in enumerate(points): # iteriere über alle Punkte
        dist = sum([(dp-dq)**2 for dp,dq in zip(point,qPoint)])**0.5 # berechne die Euklidische Distanz jedes Punkts zu q
        if dist < minDist or minDist < 0: # wenn nötig, aktualisiere die minimale Distanz und Index des entsprechenden Punkts
            minDist = dist
            minIdx = idx

>>> print 'Nächster Punkt zu q: ', points[minIdx]
Nächster Punkt zu q: [3, 4, 4]
>>>
>>>
>>> # # # Äquivalente NumPy Vektorisierung # # #
>>> import numpy as np
>>> points = np.array([[9,2,8],[4,7,2],[3,4,4],[5,6,9],[5,0,7],[8,2,7],[0,3,2],[7,3,0],[6,1,1],[2,9,6]])
>>> qPoint = np.array([4,5,3])
>>> minIdx = np.argmin(np.linalg.norm(points-qPoint,axis=1)) # berechne alle Euklidischen Distanzen auf einmal und bestimme den Index des kleinsten Werts
>>> print 'Nächster Punkt zu q: ', points[minIdx]
Nächster Punkt zu q: [3 4 4]

Geschichte[Bearbeiten | Quelltext bearbeiten]

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.[6] Die erste Implementierung eines Matrizenpakets wurde von Jim Fulton entwickelt, die später von Jim Hugunin generalisiert und als Numeric[6] (teilweise auch Numerical Python Extensions) bekannt wurde, dem Vorläufer von NumPy.[7][8] Hugunin war damals Student am MIT,[8]:10, verließ das Projekt aber 1997 um weiter an JPython zu arbeiten.[6] Paul Dubois vom LLNL übernahm die Leitung des Projekts.[8]:10 Weitere Beitragende der ersten Stunde waren außerdem David Ascher, Konrad Hinsen und Travis Oliphant.[8]:10

Das Paket Numarray wurde als Alternative zu Numeric entwickelt, die mehr Flexibilität bieten sollte.[2] Beide Pakete gelten inzwischen als veraltet und werden nicht mehr weiterentwickelt.[9] 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.[10]

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.[2] 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.[11]

2011 begann die Entwicklung einer NumPy-API für PyPy.[12] Bislang wird allerdings noch nicht der gesamte NumPy-Funktionsumfang unterstützt.[13]

Am 15. November 2017 wurde NumPy in die Liste der Python 3 Erklärung aufgenommen und verpflichtete sich damit dazu, Python 2 nur noch bis 2020 zu unterstützen.[14][15]

Das Team rund um NumPy gab 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.[16]

Siehe auch[Bearbeiten | Quelltext bearbeiten]

Literatur[Bearbeiten | Quelltext bearbeiten]

Weblinks[Bearbeiten | Quelltext bearbeiten]

 Commons: NumPy – Sammlung von Bildern, Videos und Audiodateien

Einzelnachweise[Bearbeiten | Quelltext bearbeiten]

  1. Release 1.16.2. 26. Februar 2019 (abgerufen am 27. Februar 2019).
  2. a b c d Stéfan van der Walt, S. Chris Colbert and Gaël Varoquaux: The NumPy array: a structure for efficient numerical computation. In: IEEE (Hrsg.): Computing in Science and Engineering. 2011. arxiv:1102.1523.
  3. Blaze Ecosystem Docs. Abgerufen am 6. Januar 2016.
  4. Francesc Alted: numexpr. Abgerufen am 8. März 2014.
  5. Numba. Abgerufen am 6. Januar 2016.
  6. a b c K. Jarrod Millman, Michael Aivazis: Python for Scientists and Engineers. In: Computing in Science and Engineering. 13, Nr. 2, 2011, S. 9–12.
  7. Travis Oliphant: Python for Scientific Computing. In: Computing in Science and Engineering. 2007.
  8. a b c d David Ascher, Paul F. Dubois, Konrad Hinsen, Jim Hugunin, Travis Oliphant: Numerical Python. 1999. Abgerufen am 6. Januar 2016.
  9. Numarray Homepage. Abgerufen am 6. Januar 2016.@1@2Vorlage:Toter Link/www.stsci.edu (Seite nicht mehr abrufbar, Suche in Webarchiven)
  10. NumPy Sourceforge Files. Abgerufen am 6. Januar 2016.
  11. NumPy 1.5.0 Release Notes. Abgerufen am 6. Januar 2016.
  12. PyPy Status Blog: Numpy funding and status update. Abgerufen am 6. Januar 2016.
  13. NumPyPy Status. Abgerufen am 6. Januar 2016.
  14. Add NumPy · python3statement/python3statement.github.io (englisch) Abgerufen am 7. Juli 2018.
  15. Moving to require Python 3 (englisch), auf python3statement.org, abgerufen am 17. Oktober 2018
  16. Plan for dropping Python 2.7 support (englisch) Archiviert vom Original am 8. Juli 2018. Abgerufen am 7. Juli 2018.