{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Numerisches Rechnen mit NumPy/SciPy\n", "\n", "Eine Variable kann als Wert mehr als nur einen Skalar beinhalten.\n", "Der Schritt zu Vektoren, Matrizen und Tensoren öffnet Tür und Tor um numerische Berechnungen ausdrücken zu können.\n", "Die Programmbibliothek [NumPy](http://docs.scipy.org/doc/numpy/user/index.html) liefert mit `numpy.ndarray` einen Rang-n Tensor,\n", "der effizientes rechnen mit Vektoren und Matritzen erlaubt.\n", "\n", "All diesen Berechnungen auf Basis dieses `np.ndarray` ist gemeinsam,\n", "dass sie dank der Vektorisierung viel effizienter ablaufen.\n", "Für performanten (und häufig auch besser lesbaren) Code ist es daher immer notwendig,\n", "auf diese Operationen zurückzugreifen -- auch wenn sie anfangs etwas verwirrend sein mögen `:-)`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die Bibliothek `numpy` wird üblicherweise immer mit dem Kurznamen Alias `np` importiert:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Vektoren und Matritzen" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Beispiel**: Die Variablen $v$ und $w$ soll hier einen Vektor aus $\\mathbb{R}^3$ repräsentieren.\n", "Die Addition und Multiplikation werden elementweise durchgeführt,\n", "während `.dot()` das Skalarprodukt (engl. dot product) durchführt.\n", "\n", "\\begin{equation}\n", "\\begin{aligned}\n", "\\texttt{v + w} &= \\left[ v_i + w_i \\right]_i \\\\\n", "\\texttt{v * w} &= \\left[ v_i \\cdot w_i \\right]_i \\\\\n", "\\texttt{v.dot(w)} &= \\sum_i v_i*w_i \\\\\n", "\\text{für} \\quad & v,\\,w\\;\\in\\;\\mathbb{R}^3\n", "\\end{aligned}\n", "\\end{equation}\n", "\n", "Jetzt definieren wir $v$ und $w$, wobei $v = (4,\\,3,\\,-1)$ sein soll und $w$ ein zufällig gewählter Vektor.\n", "Dann führen wir die Berechnungen durch. " ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [], "source": [ "v = np.array([4,3,-1])\n", "w = np.random.rand(3)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 4, 3, -1])" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 0.54487339, 0.68192372, 0.11945565])" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "w" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 4.54487339, 3.68192372, -0.88054435])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v + w" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 3.45512661, 2.31807628, -1.11945565])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v - w" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 2.17949355, 2.04577117, -0.11945565])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v * w" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Das (generalisierte) Skalarprodukt von $v$ und $w$" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "4.1058090694632829" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "v.dot(w)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Matritzen (n-dim arrays)\n", "\n", "Neben diesen Grundoperationen, werden alle NumPy-spezifischen Funktionen automatisch über tensor-wertige Argumente ausgeführt.\n", "Das heißt beispielsweise,\n", "dass die $\\sin$-Funktion über einen Vektor $x := (1,2,3)$ ergibt wieder einen Vektor,\n", "dessen Einträge die numerischen Werte von $(\\sin(1),\\,\\sin(2),\\,\\sin(3))$ beinhalten." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 0.84147098, 0.90929743, 0.14112001])" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x = np.array([1,2,3])\n", "np.sin(x)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 1, -2, 3, 8],\n", " [ 4, 6, 9, -9],\n", " [-1, 0, 5, 2],\n", " [11, 13, 15, 16]])" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = np.array([[ 1,-2, 3, 8],\n", " [ 4, 6, 9,-9],\n", " [-1, 0, 5, 2],\n", " [11,13,15,16]])\n", "m" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0.54030231, -0.41614684, -0.9899925 , -0.14550003],\n", " [-0.65364362, 0.96017029, -0.91113026, -0.91113026],\n", " [ 0.54030231, 1. , 0.28366219, -0.41614684],\n", " [ 0.0044257 , 0.90744678, -0.75968791, -0.95765948]])" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.cos(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Extrahieren einzelner Spalten/Zeilen und Elemente\n", "\n", "Der `:` steht hierbei für die gesamte Spalte, `n:m` für ein Intervall, wobei `n` oder `m` weggelassen werden kann. Negative Werte werden vom Ende weg gezählt." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 1, -2, 3, 8],\n", " [ 4, 6, 9, -9],\n", " [-1, 0, 5, 2],\n", " [11, 13, 15, 16]])" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 1, 4, -1, 11])" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m[:, 0]" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 4, 6, 9, -9])" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m[1, :]" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m[2, 2]" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 8, -9, 2, 16])" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m[:, -1]" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([-1, 5])" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m[2, [0, 2]]" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[11, 13, 15, 16]])" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m[-1:]" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 1, -2],\n", " [ 4, 6],\n", " [-1, 0]])" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m[:-1, :-2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die `.diagonal()` Funktion gibt die Diagonalelemente zurück." ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 1, 6, 5, 16])" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m.diagonal()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ein doppelter Doppelpunkt `::` gibt für ein `n:m` Intervall zusätzlich eine Schrittweite an." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 1, -2, 3, 8],\n", " [-1, 0, 5, 2]])" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m[::2, :]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Die Schrittweite kann auch negativ sein, z.B. zum Umdrehen der Richtung:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 8, 3, -2, 1],\n", " [-9, 9, 6, 4],\n", " [ 2, 5, 0, -1],\n", " [16, 15, 13, 11]])" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m[:, ::-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Transponieren" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 1, 4, -1, 11],\n", " [-2, 6, 0, 13],\n", " [ 3, 9, 5, 15],\n", " [ 8, -9, 2, 16]])" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m.T" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Skalarprodukt zweier Spalten" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "165" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m[:, 0].dot(m[:, 1])" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 1, 6, 5, 16])" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m.diagonal()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Generieren von Vektoren/Matritzen\n", "\n", "Darüber hinaus gibt es einige hilfreiche Funktionen,\n", "die das erzeugen von Punkten und eine Auswertung über einen Raster ermöglichen." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`np.arange` ist ähnlich wie Python's `range` Funktion,\n", "liefert jedoch gleich `np.ndarray` Vektoren zurück." ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.arange(1, 5, .5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "10 equally spaced points from 0 to 1" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 0. , 0.11111111, 0.22222222, 0.33333333, 0.44444444,\n", " 0.55555556, 0.66666667, 0.77777778, 0.88888889, 1. ])" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.linspace(0, 1, 10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "10 equally spaced points on a logarithmic scale from base^1 to base^2 with base = 10" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 10. , 12.91549665, 16.68100537, 21.5443469 ,\n", " 27.82559402, 35.93813664, 46.41588834, 59.94842503,\n", " 77.42636827, 100. ])" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.logspace(1, 2, 10, base=10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Koordinatenmatritzen\n", "\n", "Zur Auswertung von Funktionen über mehrere Achsen,\n", "welche aus zwei oder mehr Vektoren konstruiert werden." ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1, 2, 3],\n", " [1, 2, 3],\n", " [1, 2, 3]])" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "xx, yy = np.meshgrid([1, 2, 3], [0, 10, 20])\n", "xx" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 0, 0],\n", " [10, 10, 10],\n", " [20, 20, 20]])" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "yy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Dies ist zur Auswertung von mehrstellige Funktionen sehr praktisch:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 2, 3, 4],\n", " [22, 23, 24],\n", " [42, 43, 44]])" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "1 + xx + 2 * yy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Indexmatrix" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0, 0],\n", " [1, 1],\n", " [2, 2]])" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "xx, yy = np.indices((3, 2))\n", "xx" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0, 1],\n", " [0, 1],\n", " [0, 1]])" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "yy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Shape\n", "\n", "Die Dimensionierung lässt sich jederzeit Ändern,\n", "es muss nur die Anzahl der Elemente gleich bleiben." ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 1, 2, 3, 4],\n", " [ 5, 6, 7, 8, 9],\n", " [10, 11, 12, 13, 14],\n", " [15, 16, 17, 18, 19],\n", " [20, 21, 22, 23, 24]])" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c = np.arange(25)\n", "c.shape = (5, 5)\n", "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "oder `array.reshape((tupel))`, wobei `-1` verwendet werden kann um die Dimensionierung automatisch anzupassen." ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0, 1, 2, 3],\n", " [4, 5, 6, 7]])" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c = np.arange(8)\n", "c = c.reshape((-1, 4))\n", "c" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(2, 4)" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.shape" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[[0, 1],\n", " [2, 3]],\n", "\n", " [[4, 5],\n", " [6, 7]]])" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.shape = (2, 2, 2)\n", "c" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.ndim" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Einfügen einer neuen Achse" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[[0, 1, 2, 3]],\n", "\n", " [[4, 5, 6, 7]]])" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c = np.arange(8).reshape((2, -1))\n", "c = c[:, np.newaxis]\n", "c" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(2, 1, 4)" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.shape" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.ndim" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Zusammensetzen" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a = np.arange(10)\n", "b = np.arange(100, 110)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Zeilenweise mit `r_` (für \"row\")" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 101, 102,\n", " 103, 104, 105, 106, 107, 108, 109])" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.r_[a, b]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Spaltenweise mit `c_` (für \"column\")" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 100, 100],\n", " [ 1, 101, 101],\n", " [ 2, 102, 102],\n", " [ 3, 103, 103],\n", " [ 4, 104, 104],\n", " [ 5, 105, 105],\n", " [ 6, 106, 106],\n", " [ 7, 107, 107],\n", " [ 8, 108, 108],\n", " [ 9, 109, 109]])" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.c_[a, b, b]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Broadcasting\n", "\n", "Eine der wichtigsten (und komplexeren) Techniken ist [\"Broadcasting\"](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html).\n", "Hierbei werden Skalare, Vektoren und Matritzen in Rechenoperationen gemischt.\n", "Das funktioniert so, dass im ersten Rang,\n", "die einem der Argumente fehlt, die entsprechenden Werte mehrfach wiederholt werden, sodass die Dimensionierung in dem Rang passt.\n", "\n", "Vereinfachtes Beispiel:\n", "Eine Addition des Vektors $[1,\\,2,\\,5]$ mit dem Skalar $10$ führt dazu, dass der Skalar intern wie ein $[10,\\,10,\\,10]$ Vektor behandelt wird und daher das Ergebnis $[11,\\,12,\\,15]$ ist." ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([11, 12, 15])" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.array([1,2,5]) + 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "oder Matrix + Vektor" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0, 1, 2, 3],\n", " [ 4, 5, 6, 7],\n", " [ 8, 9, 10, 11],\n", " [12, 13, 14, 15]])" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.arange(16).reshape((4, 4))\n", "a" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ -1, 0, 10, 100])" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "b = np.array([-1, 0, 10, 100])\n", "b" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ -1, 1, 12, 103],\n", " [ 3, 5, 16, 107],\n", " [ 7, 9, 20, 111],\n", " [ 11, 13, 24, 115]])" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a + b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In Kombination mit `np.newaxis` lassen sich \"äußere\" Operationen durchführen:\n", "Hier wird ein Vektor zu einer 4x1-Matrix verändert und dann addiert." ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0],\n", " [1],\n", " [2],\n", " [3]])" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.arange(4)\n", "b = a[:, np.newaxis]\n", "b" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[0, 1, 2, 3],\n", " [1, 2, 3, 4],\n", " [2, 3, 4, 5],\n", " [3, 4, 5, 6]])" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a + b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Multiplikation eines Tensors 3-ter Stufe mit einem Vektor" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[[0, 1],\n", " [2, 3]],\n", "\n", " [[4, 5],\n", " [6, 7]]])" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.arange(8)\n", "a.shape = (2,2,2)\n", "a" ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 1, 11])" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "b = np.array([1,11])\n", "b" ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[[ 0, 11],\n", " [ 2, 33]],\n", "\n", " [[ 4, 55],\n", " [ 6, 77]]])" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a * b" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[11, 35],\n", " [59, 83]])" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.dot(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Methoden auf Arrays\n", "\n", "In der Praxis werden häufig Funktionen auf Vektoren oder Matrizen angewendet.\n", "Siehe auch [Numpy Routines](http://docs.scipy.org/doc/numpy/reference/routines.html)" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 5, 6, -1, 5],\n", " [ 1, 1, 1, 1],\n", " [ 0, -5, 10, 2]])" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = np.array([[5, 6, -1, 5],\n", " [1, 1, 1, 1],\n", " [0,-5, 10, 2]])\n", "m" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "26" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m.sum()" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 6, 2, 10, 8])" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m.sum(axis=0)" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([15, 4, 7])" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m.sum(axis=1)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "-5" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m.min()" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 5, 11, 11, 4])" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m.ptp(axis=0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Lineare Algebra\n", "\n", "Die Submodule [numpy.linalg](http://docs.scipy.org/doc/numpy/reference/routines.linalg.html) und\n", "[scipy.linalg](http://docs.scipy.org/doc/scipy/reference/tutorial/linalg.html)\n", "beinhalten diverse Routinen für lineare Algebra." ] }, { "cell_type": "code", "execution_count": 61, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import numpy.linalg as LA" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Definition der Matrix $m$" ] }, { "cell_type": "code", "execution_count": 62, "metadata": { "collapsed": false }, "outputs": [], "source": [ "m = np.array([[ 4, -1.1],\n", " [-2, 8 ]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Eigenwerte & Eigenvektoren vom $m$" ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 3.51002008 8.48997992]\n", "[[-0.91347498 0.23795303]\n", " [-0.40689491 -0.97127666]]\n" ] } ], "source": [ "eigenvalues, eigenvectors = LA.eig(m)\n", "print eigenvalues\n", "print eigenvectors" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Testen, ob der `0`-te Eigenwert/Vektor passt: beide Vektoren müssen bis auf Rundungsfehler gleich sein (das kontrolliert `np.allclose`)" ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.allclose(\n", " m.dot(eigenvectors[:,0]),\n", " eigenvalues[0] * eigenvectors[:,0]\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Determinante von $m$" ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "29.799999999999997" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "LA.det(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Invertieren der Matrix $m$" ] }, { "cell_type": "code", "execution_count": 66, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 0.26845638, 0.03691275],\n", " [ 0.06711409, 0.13422819]])" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "LA.inv(m)" ] }, { "cell_type": "code", "execution_count": 67, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 1., 0.],\n", " [ 0., 1.]])" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "LA.inv(m).dot(m)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Optimierung und Nullstellensuche mit SciPy\n", "\n", "Ein wichtiger Zweig der Numerischen Mathematik ist Optimierung.\n", "Diese besteht aus einer Sammlung standardisierter Problemstellungen,\n", "welche unter eventuell gegebenen Nebenbedingungen einen Punkt $x \\in \\mathbb{R}^n$ suchen,\n", "wo eine gegebene Zielfunktion $f: \\mathbb{R}^n \\rightarrow \\mathbb{R}$ einen minimalen oder maximalen Wert annimmt.\n", "\n", "Problemstellungen dieser Art finden sich in mannigfaltigen Anwendungsgebieten\n", "und bringen diverse Varianten dieser Fragestellung hervor.\n", "Die folgenden Beispiele zeigen exemplarisch einige Varianten vor.\n", "\n", "Link: [scipy.optimize](http://docs.scipy.org/doc/scipy-dev/reference/optimize.html)" ] }, { "cell_type": "code", "execution_count": 68, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from scipy.optimize import minimize" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$f_1(x): \\mathbb{R}^3 \\rightarrow \\mathbb{R}$ wird optimiert." ] }, { "cell_type": "code", "execution_count": 69, "metadata": { "collapsed": false }, "outputs": [], "source": [ "f1 = lambda x: (4 * x[0] - x[1])**2 + (x[1] - x[2])**2 * x[0] - x[2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$x_0$ ist der Startwert in $\\mathbb{R}^3$" ] }, { "cell_type": "code", "execution_count": 70, "metadata": { "collapsed": false }, "outputs": [], "source": [ "x0 = [1., 2., 0.]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`bounds` ist die Box der Randbedingungen an $x$:" ] }, { "cell_type": "code", "execution_count": 71, "metadata": { "collapsed": false }, "outputs": [], "source": [ "bounds = [(-10, 10), (-10, 10), (0, 1)]" ] }, { "cell_type": "code", "execution_count": 72, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ " status: 0\n", " success: True\n", " nfev: 64\n", " fun: -0.99999999999996247\n", " x: array([ 0.25 , 0.99999982, 1. ])\n", " message: 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL'\n", " jac: array([ 1.53210777e-06, -4.10782519e-07, -9.99999905e-01])\n", " nit: 13" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" } ], "source": [ "opti1 = minimize(f1, x0, bounds = bounds)\n", "opti1" ] }, { "cell_type": "code", "execution_count": 73, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 0.25 , 0.99999982, 1. ])" ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x_opti = opti1[\"x\"]\n", "x_opti" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Nullstellensuche" ] }, { "cell_type": "code", "execution_count": 74, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from scipy.optimize import fsolve" ] }, { "cell_type": "code", "execution_count": 75, "metadata": { "collapsed": false }, "outputs": [], "source": [ "f2 = lambda x : 3 * x**3 - x**2 + 1" ] }, { "cell_type": "code", "execution_count": 76, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([-0.5981935])" ] }, "execution_count": 76, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fsolve(f2, 1.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vektorwertige Funktion $f_3(x): \\mathbb{R}^2 \\rightarrow \\mathbb{R}^2$" ] }, { "cell_type": "code", "execution_count": 77, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from scipy.optimize import root" ] }, { "cell_type": "code", "execution_count": 78, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from numpy import sqrt\n", "f3 = lambda x : [(x[0] + x[1])**2 - 4, x[0] + sqrt(x[1])]" ] }, { "cell_type": "code", "execution_count": 79, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ " status: 1\n", " success: True\n", " qtf: array([ -8.12325364e-09, 1.26538374e-09])\n", " nfev: 12\n", " r: array([-4.8930465 , -3.96638873, 0.61326347])\n", " fun: array([ 2.07300843e-12, 1.27009514e-13])\n", " x: array([-2., 4.])\n", " message: 'The solution converged.'\n", " fjac: array([[-0.97680164, -0.21414609],\n", " [ 0.21414609, -0.97680164]])" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f3_root = root(f3, [2., 1.])\n", "f3_root" ] }, { "cell_type": "code", "execution_count": 80, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([-2., 4.])" ] }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f3_root.x" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.6" } }, "nbformat": 4, "nbformat_minor": 0 }