{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# NumPy Exercises\n", "\n", "Tamás Gál (tamas.gal@fau.de)\n", "\n", "The latest version of this notebook is available at [https://github.com/escape2020/school2021](https://github.com/escape2020/school2021)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Python version: 3.9.4 | packaged by conda-forge | (default, May 10 2021, 22:10:52) \n", "[Clang 11.1.0 ]\n", "NumPy version: 1.20.3\n", "Numba version: 0.53.1\n", "NumExpr version: 2.7.3\n" ] } ], "source": [ "import numpy as np\n", "import numba as nb\n", "import numexpr as ne\n", "import sys\n", "\n", "print(f\"Python version: {sys.version}\\n\"\n", " f\"NumPy version: {np.__version__}\\n\"\n", " f\"Numba version: {nb.__version__}\\n\"\n", " f\"NumExpr version: {ne.__version__}\")\n", "\n", "rng = np.random.default_rng(42) # initialise our random number generator" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "plt.rcParams['figure.figsize'] = (16, 5)\n", "plt.rcParams['figure.dpi'] = 300" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 1: Extract the integer part of a random sample\n", "\n", " rng.uniform(0, 10, 10)\n", " \n", "e.g. `[23.5, 42.0, 500.3, 123.9] -> [23, 42, 500, 123]`" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Solution:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([ 23.5, 42. , 500.3, 123.9])" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([23.5, 42.0, 500.3, 123.9])\n", "a" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([ 23., 42., 500., 123.])" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a - a%1" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([ 23., 42., 500., 123.])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.floor(a)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([ 23., 41., 500., 123.])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.ceil(a) - 1" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([ 23., 42., 500., 123.])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.trunc(a)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([ 23, 42, 500, 123])" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a.astype(int)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Further discussions" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "a = rng.uniform(0, 10, 10000)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "104 µs ± 3.75 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n" ] } ], "source": [ "%timeit a - a%1" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.45 µs ± 22.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n" ] } ], "source": [ "%timeit np.floor(a)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5.78 µs ± 35.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n" ] } ], "source": [ "%timeit np.ceil(a) - 1" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.48 µs ± 20.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n" ] } ], "source": [ "%timeit np.trunc(a)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.26 µs ± 7.76 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit a.astype(int) # the winner -> casting" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 2: Create a 5x5 matrix with 5's on its diagonal\n", "\n", "```\n", "5 0 0 0 0\n", "0 5 0 0 0\n", "0 0 5 0 0\n", "0 0 0 5 0\n", "0 0 0 0 5\n", "```" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Solution: `np.eye()`" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1., 0., 0., 0., 0.],\n", " [0., 1., 0., 0., 0.],\n", " [0., 0., 1., 0., 0.],\n", " [0., 0., 0., 1., 0.],\n", " [0., 0., 0., 0., 1.]])" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.eye(5)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([[5., 0., 0., 0., 0.],\n", " [0., 5., 0., 0., 0.],\n", " [0., 0., 5., 0., 0.],\n", " [0., 0., 0., 5., 0.],\n", " [0., 0., 0., 0., 5.]])" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.eye(5) * 5" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1., 0., 0., 0., 0.],\n", " [0., 1., 0., 0., 0.],\n", " [0., 0., 1., 0., 0.],\n", " [0., 0., 0., 1., 0.],\n", " [0., 0., 0., 0., 1.]])" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.eye(5)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Alternative solutions and further discussions" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "634 µs ± 111 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%%timeit\n", "a = np.eye(1000) * 5" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "589 µs ± 12 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%%timeit\n", "a = np.eye(1000)\n", "np.multiply(a, 5, out=a) # avoid creating a copy " ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "312 µs ± 5.57 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%%timeit\n", "a = np.zeros((1000, 1000))\n", "a[np.diag_indices_from(a)] = 5" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.zeros((10, 10))\n", "np.diag_indices_from(a)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "308 µs ± 9.53 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit np.diag(np.full(1000, 5))" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "303 µs ± 5.82 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit np.diag(np.ones(1000) * 5)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Numba?" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "@nb.njit\n", "def diag_nb(n, value):\n", " return np.diag(np.ones(n) * value)" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "298 µs ± 5.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit diag_nb(1000, 5)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "@nb.njit\n", "def diag2_nb(n, value):\n", " mat = np.zeros((n, n))\n", " for i in range(n):\n", " mat[i,i] = value\n", " return mat" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "296 µs ± 4.59 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit diag2_nb(1000, 5)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 3: Calculate `c`, with:\n", "\n", " a = rng.random(1234567)\n", " b = rng.random(1234567)\n", " \n", "so that\n", "\n", "$$\n", "c_i = \\tan(a_i) \\cdot b_i - a_i^{b_i}\n", "$$\n", "\n", "for $i \\in [0, 1234566]$" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "a = rng.random(1234567)\n", "b = rng.random(1234567)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Solution:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "def f(a, b):\n", " return np.tan(a) * b - a**b" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "17 ms ± 218 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit f(a, b)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4.1 ms ± 400 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit ne.evaluate(\"tan(a)*b - a**b\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### What about a Python loop?" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "def tanabab(a, b):\n", " c = np.empty_like(a)\n", " for i in range(len(a)):\n", " c[i] = np.tan(a[i]) * b[i] - np.power(a[i], b[i])\n", " return c" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.27 s ± 31.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] } ], "source": [ "%timeit tanabab(a, b)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Let's JIT it with `numba`!" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "@nb.jit\n", "def tanabab_nb(a, b):\n", " c = np.empty_like(a)\n", " for i in range(len(a)):\n", " c[i] = np.tan(a[i]) * b[i] - np.power(a[i], b[i])\n", " return c" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 90.5 ms, sys: 2.38 ms, total: 92.9 ms\n", "Wall time: 92.2 ms\n" ] }, { "data": { "text/plain": [ "array([-0.01106144, -0.66248701, -0.32489978, ..., -0.21608449,\n", " -0.13017545, -0.16956306])" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%time tanabab_nb(a, b) # first execution includes the compilation!" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "15.9 ms ± 328 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit tanabab_nb(a, b) # the second is pure LLVM optimised code" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "@nb.jit\n", "def tanabab_nb_mutating_a(a, b):\n", " for i in range(len(a)):\n", " a[i] = np.tan(a[i]) * b[i] - np.power(a[i], b[i])" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 56.2 ms, sys: 2.02 ms, total: 58.2 ms\n", "Wall time: 60.3 ms\n" ] } ], "source": [ "%time tanabab_nb_mutating_a(a, b); # first execution includes the compilation!" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "a = rng.random(1234567)\n", "b = rng.random(1234567)" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "7.67 ms ± 142 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit tanabab_nb_mutating_a(a, b); # the second is pure LLVM optimised code" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "Summary (your mileage may vary):\n", "- **~2200ms** (Python)\n", "- **~75ms** (reusing `a`, numba, inc. JIT comp.)\n", "- **~60ms** (numba, inc. JIT comp.)\n", "- **~17ms** (numpy)\n", "- **~16ms** (numba, JIT)\n", "- **~8ms** (reusing `a`, numba, JIT)\n", "- **~4ms** (numexpr)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 4: Given two arrays `a` anb `b`, check if they are (almost) equal\n", "\n", " a = np.random.random(1234567)\n", " b = a.copy()\n", "\n", " b[-1] = 23 # artificially make them differ at the very end ;)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "slideshow": { "slide_type": "skip" } }, "outputs": [], "source": [ "a = rng.random(1234567)\n", "b = a.copy()\n", "c = a.copy()\n", "\n", "b[-1] = 23 # make them differ at the very end ;)\n", "c[0] = 23 # make them differ at the beginning" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Solution:" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4.18 ms ± 168 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit np.allclose(a, b)" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4.16 ms ± 158 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit np.allclose(a, c)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Using numba?" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "@nb.jit\n", "def allclose(a, b, tol=0.0001):\n", " for i in range(len(a)):\n", " if np.abs(a[i] - b[i]) > tol:\n", " return False \n", " return True" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "811 µs ± 13.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit allclose(a, b)" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "265 ns ± 10.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit allclose(a, c)" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "635 µs ± 64.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit np.count_nonzero(a == b) == a.size" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 5: Create the following matrix\n", "\n", " 1 2 3 4 5 6\n", " 1 2 3 4 5 6\n", " 1 2 3 4 5 6\n", " 1 2 3 4 5 6\n", " 1 2 3 4 5 6\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Solution:" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1.],\n", " [1., 1., 1., 1., 1., 1.]])" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.ones((5, 6))" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1, 2, 3, 4, 5, 6])" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.arange(1, 7)" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([[1., 2., 3., 4., 5., 6.],\n", " [1., 2., 3., 4., 5., 6.],\n", " [1., 2., 3., 4., 5., 6.],\n", " [1., 2., 3., 4., 5., 6.],\n", " [1., 2., 3., 4., 5., 6.]])" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.ones((5, 6)) * np.arange(1, 7)" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([[1., 2., 3., 4., 5., 6.],\n", " [1., 2., 3., 4., 5., 6.],\n", " [1., 2., 3., 4., 5., 6.],\n", " [1., 2., 3., 4., 5., 6.],\n", " [1., 2., 3., 4., 5., 6.]])" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.ones(5)[:, np.newaxis] * np.arange(1, 7)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Alternative solutions and further discussions" ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5.66 µs ± 133 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n" ] } ], "source": [ "%timeit np.ones((500, 6)) * np.arange(1, 7)" ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5.62 µs ± 87.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n" ] } ], "source": [ "%%timeit\n", "a = np.ones((500, 6))\n", "np.multiply(a, np.arange(1, 7), out=a)" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1., 1., 1., 1., 1.])" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.ones(5)" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(5,)" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.ones(5).shape" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1., 2., 3., 4., 5., 6.],\n", " [1., 2., 3., 4., 5., 6.],\n", " [1., 2., 3., 4., 5., 6.],\n", " [1., 2., 3., 4., 5., 6.],\n", " [1., 2., 3., 4., 5., 6.]])" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.ones(5)[:, np.newaxis] * np.arange(1, 7)" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6.78 µs ± 88.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n" ] } ], "source": [ "%timeit np.ones(500)[:, np.newaxis] * np.arange(1, 7)" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.13 µs ± 77.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n" ] } ], "source": [ "%%timeit\n", "a = np.empty((500, 6))\n", "a[:] = np.arange(1, 7)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/plain": [ "array([1., 1., 1., 1., 1.])" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.ones(5)" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([[1.],\n", " [1.],\n", " [1.],\n", " [1.],\n", " [1.]])" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.ones(5)[:, np.newaxis] # adds a new dimension" ] }, { "cell_type": "code", "execution_count": 61, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "(5, 1)" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.ones(5)[:, np.newaxis].shape" ] }, { "cell_type": "code", "execution_count": 62, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "(6,)" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.arange(1, 7).shape" ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "(5, 6)" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# broadcasting will turn (5, 1) and (6,) into (5, 6)\n", "(np.ones(5)[:, np.newaxis] * np.arange(1, 7)).shape" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Numba?" ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "@nb.njit\n", "def grad_nb(n, m):\n", " mat = np.empty((n, m))\n", " for i in range(m):\n", " for j in range(n):\n", " mat[j,i] = i + 1\n", " return mat" ] }, { "cell_type": "code", "execution_count": 65, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.33 µs ± 15.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit grad_nb(500, 6)" ] }, { "cell_type": "code", "execution_count": 66, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "int_type = np.int32\n", "\n", "@nb.njit\n", "def grad_int_nb(n, m):\n", " mat = np.empty((n, m), dtype=int_type)\n", " for i in range(1, m):\n", " for j in range(n):\n", " mat[j,i] = i + 1\n", " return mat" ] }, { "cell_type": "code", "execution_count": 67, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.14 µs ± 6.06 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit grad_int_nb(500, 6)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 6: Roll two 6-sided dice 100 times and count each individual value" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Solution:" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "This is an ugly, hardcoded solution:" ] }, { "cell_type": "code", "execution_count": 68, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "def roll_dice(n):\n", " dice_1 = rng.integers(1, 6, n)\n", " dice_2 = rng.integers(1, 6, n)\n", " sums = dice_1 + dice_2\n", " return np.unique(sums, return_counts=True)" ] }, { "cell_type": "code", "execution_count": 69, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "(array([ 2, 3, 4, 5, 6, 7, 8, 9, 10]),\n", " array([ 6, 9, 9, 18, 18, 20, 7, 9, 4]))" ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "roll_dice(100)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 7: Roll five 12-sided dice 123456 times and count each individual value" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "If you did it right, you now only need to change 2 parameters of your previous code ;)\n", "\n", "If not, write an appropriate function.\n", "\n", "Create a histogram of the values!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Solution:" ] }, { "cell_type": "code", "execution_count": 70, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "def roll_dice(n_rolls, n_sides, n_die):\n", " rolls = np.sum(rng.integers(1, n_sides+1, n_rolls*n_die)\n", " .reshape(n_die, n_rolls), axis=0)\n", " return np.unique(rolls, return_counts=True)" ] }, { "cell_type": "code", "execution_count": 71, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "rolls = roll_dice(123456, 12, 5)" ] }, { "cell_type": "code", "execution_count": 72, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "image/png": "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AAAAAABDEksDAAAAAAAAAAAAAAAAAABDEksDAAAAAAAAAAAAAAAAAABDEksDAAAAAAAAAAAAAAAAAABDEksDAAAAAAAAAAAAAAAAAABDEksDAAAAAAAAAAAAAAAAAABDEksDAAAAAAAAAAAAAAAAAABDEksDAAAAAAAAAAAAAAAAAABDEksDAAAAAAAAAAAAAAAAAABDEksDAAAAAAAAAAAAAAAAAABDEksDAAAAAAAAAAAAAAAAAABD2rLsAwAAAAAAwDy2brt82UcAAAAAAAAAAABgRfhlaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhiaQAAAAAAAAAAAAAAAAAAYEhbln0AAAAAAAAAgAerrdsuX/YRlubGi89a9hEAAAAAAAAAeADwy9IAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQxNIAAAAAAAAAAAAAAAAAAMCQtiz7AAAAAAAAAAA8+Gzddvmyj7AUN1581rKPAAAAAAAAAPCA4pelAQAAAAAAAAAAAAAAAACAIYmlAQAAAAAAAAAAAAAAAACAIYmlAQAAAAAAAAAAAAAAAACAIYmlAQAAAAAAAAAAAAAAAACAIYmlAQAAAAAAAAAAAAAAAACAIYmlAQAAAAAAAAAAAAAAAACAIYmlAQAAAAAAAAAAAAAAAACAIYmlAQAAAAAAAAAAAAAAAACA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AAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTSAAAAAAAAAAAAAAAAAADAkMTS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SVkaAAAAAAAAAAAAAAAAAAAYkrI0AAAAAAAAAAAAAAAAAAAwJGVpAAAAAAAAAAAAAAAAAABgSMrSAAAAAAAAAAAAAAAAAADAkJSlAQAAAAAAAAAAAAAAAACAISlLAwAAAAAAAAAAAAAAAAAAQ1KWBgAAAAAAAAAAAAAAAAAAhqQsDQAAAAAAAAAAAAAAAAAADElZGgAAAAAAAAAAAAAAAAAAGJKyNAAAAAAAAAAAAAAAAAAAMCRlaQAAAAAAAAAAAAAAAAAAYEjK0gAAAAAAAAAAAAAAAAAAwJCUpQEAAAAAAAAAAAAAAAAAgCEpSwMAAAAAAAAAAAAAAAAAAENSlgYAAAAAAAAAAAAAAAAAAIakLA0AAAAAAAAAAAAAAAAAAAxJWRoAAAAAAAAAAAAAAAAAABiSsjQAAAAAAAAAAAAAAAAAADAkZWkAAAAAAAAAAAAAAAAAAGBIytIAAAAAAAAAAAAAAAAAAMCQlKUBAAAAAAAAAAAAAAAAAIAhKUsDAAAAAAAAAAAAAAAAAABDUpYGAAAAAAAAAAAAAAAAAACGpCwNAAAAAAAAAAAAAAAAAAAMSVkaAAAAAAAAAAAAAAAAAAAYkrI0AAAAAAAAAAAAAAAAAAAwJGVpAAAAAAAAAAAAAAAAAABgSMrSAAAAAAAAAAAAAAAAAADAkJSlAQAAAAAAAAAAAAAAAACAISlLAwAAAAAAAAAAAAAAAAAAQ1KWBgAAAAAAAAAAAAAAAAAAhqQsDQAAAAAAAAAAAAAAAAAADElZGgAAAAAAAAAAAAAAAAAAGJKyNAAAAAAAAAAAAAAAAAAAMCRlaQAAAAAAAAAAAAAAAAAAYEjK0gAAAAAAAAAAAAAAAAAAwJCUpQEAAAAAAAAAAAAAAAAAgCEpSwMAAAAAAAAAAAAAAAAAAENSlgYAAAAAAAAAAAAAAAAAAIakLA0AAAAAAAAAAAAAAAAAAAxJWRoAAAAAAAAAAAAAAAAAABiSsjQAAAAAAAAAAAAAAAAAADAkZWkAAAAAAAAAAAAAAAAAAGBIytIAAAAAAAAAAAAAAAAAAMCQlKUBAAAAAAAAAAAAAAAAAIAhKUsDAAAAAAAAAAAAAAAAAABDUpYGAAAAAAAAAAAAAAAAAACGpCwNAAAAAAAAAAAAAAAAAAAMSVkaAAAAAAAAAAAAAAAAAAAYkrI0AAAAAAAAAAAA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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.hist(range(len(rolls[1])), bins=rolls[0], weights=rolls[1]);" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 8: Find the value closest to a given number in an array\n", "\n", " a = rng.random(10)\n", " target = 0.23" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Solution:" ] }, { "cell_type": "code", "execution_count": 73, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([0.88422871, 0.48558074, 0.9052416 , 0.0752361 , 0.06916456,\n", " 0.05940674, 0.59183429, 0.76920539, 0.80313491, 0.91361757])" ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = rng.random(10)\n", "target = 0.23\n", "a" ] }, { "cell_type": "code", "execution_count": 74, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "0.07523610127287217" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a[np.argmin(np.abs(a - target))]" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Numba?" ] }, { "cell_type": "code", "execution_count": 75, "metadata": {}, "outputs": [], "source": [ "a = rng.random(1000)" ] }, { "cell_type": "code", "execution_count": 76, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.23 µs ± 9.72 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n" ] } ], "source": [ "%timeit a[np.argmin(np.abs(a - target))]" ] }, { "cell_type": "code", "execution_count": 77, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "@nb.jit\n", "def find_closest(arr, target):\n", " idx = 0\n", " delta = np.nan\n", " for i in range(len(arr)):\n", " _delta = abs(arr[i] - target)\n", " if _delta < delta:\n", " delta = _delta\n", " idx = i\n", " return arr[idx]" ] }, { "cell_type": "code", "execution_count": 78, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.43 µs ± 11.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit find_closest(a, 0.23)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 9: Create a random array with 10 elements and replace its largest value with 0\n", "\n", "## Bonus: Replace the second largest value with 0" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Solution:" ] }, { "cell_type": "code", "execution_count": 79, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([25, 56, 23, 62, 9, 87, 54, 75, 75, 11])" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = rng.integers(0, 100, 10)\n", "a" ] }, { "cell_type": "code", "execution_count": 80, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([25, 56, 23, 62, 9, 0, 54, 75, 75, 11])" ] }, "execution_count": 80, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.argmax(a) # gives the index of the maximum\n", "a[np.argmax(a)] = 0\n", "a" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Solution for the bonus:" ] }, { "cell_type": "code", "execution_count": 81, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([25, 28, 96, 30, 39, 38, 69, 77, 95, 53])" ] }, "execution_count": 81, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = rng.integers(0, 100, 10)\n", "a" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([25, 28, 96, 30, 39, 38, 69, 77, 0, 53])" ] }, "execution_count": 82, "metadata": {}, "output_type": "execute_result" } ], "source": [ "idx = a.argsort()[-2] # index of the second largest value\n", "a[idx] = 0\n", "a" ] }, { "cell_type": "code", "execution_count": 83, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([25, 28, 96, 30, 39, 38, 69, 0, 0, 53])" ] }, "execution_count": 83, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a[np.argpartition(a, -2)[-2]] = 0\n", "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This `np.argpartition` thing is a bit tricky, let's examine this..." ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [], "source": [ "a = np.array([5, 4, 7, 9])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`np.partition` will \"partition\" the array, so that the it guarantees that the element at the specified index will sit in the correct position **and** every element to the left is less or equal and every element to the right is greater or equal to it (in undefined order)." ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([4, 5, 7, 9])" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.partition(a, 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, you can see that if the array \"was\" sorted (it would be 4, 5, 7, 9), the `5` should sit at the position 1 (counting from 0). This can be much quicker than sorting the full array." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the solution above, we pass `-2` which means that the second last element should sit in place, so that we catch the two \"largest\" values (they are either the same or the last one is the largest)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`np.argpartition` will return the indices instead, which we can use to pick the position of the n-th largest element and set it to zero." ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1, 0, 2, 3])" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.argpartition(a, 1) # the index of five (0) is sitting on position 1" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Numba?" ] }, { "cell_type": "code", "execution_count": 87, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "a = np.random.random(10000000)" ] }, { "cell_type": "code", "execution_count": 88, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.29 ms ± 49.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit a[np.argmax(a)] = 0" ] }, { "cell_type": "code", "execution_count": 89, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "@nb.njit\n", "def zero_largest(arr):\n", " idx = 0\n", " largest = arr[0]\n", " for i in range(len(arr)):\n", " if arr[i] > largest:\n", " largest = arr[i]\n", " idx = i\n", " arr[idx] = 0.0" ] }, { "cell_type": "code", "execution_count": 90, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "42.6 ms ± 434 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" ] } ], "source": [ "%timeit zero_largest(a)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Using numba to solve the bonus exercise" ] }, { "cell_type": "code", "execution_count": 91, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "a = rng.random(10000000)" ] }, { "cell_type": "code", "execution_count": 92, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.28 s ± 42.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] } ], "source": [ "%%timeit\n", "idx = np.argsort(a)[-2]\n", "a[idx] = 0" ] }, { "cell_type": "code", "execution_count": 93, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "105 ms ± 9.28 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" ] } ], "source": [ "%%timeit \n", "a[np.argpartition(a, -2)[-2]] = 0" ] }, { "cell_type": "code", "execution_count": 94, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "@nb.njit\n", "def zero_second_largest(arr):\n", " idx_largest = 0\n", " idx_second_largest = 0\n", " largest = arr[0]\n", " second_largest = 0\n", " for i in range(len(arr)):\n", " if arr[i] > largest:\n", " second_largest, largest = largest, arr[i]\n", " idx_second_largest, idx_largest = idx_largest, i\n", " arr[idx_second_largest] = 0" ] }, { "cell_type": "code", "execution_count": 95, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "40.9 ms ± 268 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" ] } ], "source": [ "%timeit zero_second_largest(a)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 10: Create a checkerboard (8x8, 0s and 1s)\n", "\n", " 0 1 0 1 0 1 0 1\n", " 1 0 1 0 1 0 1 0\n", " 0 1 0 1 0 1 0 1\n", " 1 0 1 0 1 0 1 0\n", " 0 1 0 1 0 1 0 1\n", " 1 0 1 0 1 0 1 0\n", " 0 1 0 1 0 1 0 1\n", " 1 0 1 0 1 0 1 0" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Solution:" ] }, { "cell_type": "code", "execution_count": 96, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "array([[0, 1, 0, 1, 0, 1, 0, 1],\n", " [1, 0, 1, 0, 1, 0, 1, 0],\n", " [0, 1, 0, 1, 0, 1, 0, 1],\n", " [1, 0, 1, 0, 1, 0, 1, 0],\n", " [0, 1, 0, 1, 0, 1, 0, 1],\n", " [1, 0, 1, 0, 1, 0, 1, 0],\n", " [0, 1, 0, 1, 0, 1, 0, 1],\n", " [1, 0, 1, 0, 1, 0, 1, 0]], dtype=int32)" ] }, "execution_count": 96, "metadata": {}, "output_type": "execute_result" } ], "source": [ "checkerboard = np.zeros((8, 8), dtype='i')\n", "checkerboard[::2, 1::2] = 1\n", "checkerboard[1::2, ::2] = 1\n", "checkerboard" ] }, { "cell_type": "code", "execution_count": 97, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 97, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.imshow(checkerboard)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Numba?" ] }, { "cell_type": "code", "execution_count": 98, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "757 ns ± 6.99 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%%timeit\n", "checkerboard = np.zeros((8, 8), dtype='i')\n", "checkerboard[::2, 1::2] = 1\n", "checkerboard[1::2, ::2] = 1\n", "checkerboard" ] }, { "cell_type": "code", "execution_count": 99, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import numba as nb" ] }, { "cell_type": "code", "execution_count": 100, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "@nb.njit\n", "def checkerboard(n):\n", " board = np.zeros((n, n), dtype='i')\n", " for i in range(n):\n", " for j in range(n):\n", " k = i + j*2\n", " while k >= n:\n", " k = k - n\n", " board[k,i] = 1\n", " \n", " return board" ] }, { "cell_type": "code", "execution_count": 101, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[1, 0, 1, 0, 1, 0, 1, 0],\n", " [0, 1, 0, 1, 0, 1, 0, 1],\n", " [1, 0, 1, 0, 1, 0, 1, 0],\n", " [0, 1, 0, 1, 0, 1, 0, 1],\n", " [1, 0, 1, 0, 1, 0, 1, 0],\n", " [0, 1, 0, 1, 0, 1, 0, 1],\n", " [1, 0, 1, 0, 1, 0, 1, 0],\n", " [0, 1, 0, 1, 0, 1, 0, 1]], dtype=int32)" ] }, "execution_count": 101, "metadata": {}, "output_type": "execute_result" } ], "source": [ "checkerboard(8)" ] }, { "cell_type": "code", "execution_count": 102, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "336 ns ± 4.69 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit checkerboard(8)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Exercise 11: Calculate the diagonal of a dot product" ] }, { "cell_type": "code", "execution_count": 103, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "A = rng.random((5, 5))\n", "B = rng.random((5, 5))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Solution:" ] }, { "cell_type": "code", "execution_count": 104, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.91 µs ± 24.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit np.diag(np.dot(A, B))" ] }, { "cell_type": "code", "execution_count": 105, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.52 µs ± 44.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)\n" ] } ], "source": [ "%timeit np.sum(A * B.T, axis=1)" ] }, { "cell_type": "code", "execution_count": 106, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.18 µs ± 10.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)\n" ] } ], "source": [ "%timeit np.einsum(\"ij,ji->i\", A, B)" ] } ], "metadata": { "@webio": { "lastCommId": "6ad5f33a1af042c593030dd6c2e4c24f", "lastKernelId": "0c9e5f2e-a4fe-4694-a9fa-3f039d732689" }, "celltoolbar": "Slideshow", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.4" } }, "nbformat": 4, "nbformat_minor": 4 }