2024-heraklion-data/notebooks/020_numpy/if_time_003_vectorization.ipynb

306 lines
14 KiB
Plaintext
Raw Permalink Normal View History

2024-08-27 14:27:53 +02:00
{
"cells": [
{
"cell_type": "code",
"execution_count": 4,
"id": "807f94ad",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"id": "aa4ee33f",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Avoid for-loops (element-after-element operations)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "c4290b53",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"def compute_reciprocals(values):\n",
" output = np.empty(len(values))\n",
" for i in range(len(values)):\n",
" output[i] = 1.0 / values[i]\n",
" return output"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "b6e6dca6",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"18.4 µs ± 155 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n"
]
}
],
"source": [
"%%timeit\n",
"\n",
"np.random.seed(0)\n",
" \n",
"values = np.random.randint(1, 10, size=5)\n",
"compute_reciprocals(values)"
]
},
{
"cell_type": "markdown",
"id": "bd70d5d3",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Very slow! Each time the reciprocal is computed, Python first examines the object's **type** and does a dynamic lookup of the **correct function** to use for that type"
]
},
{
"cell_type": "markdown",
"id": "cfd3f5d5",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Basic functions\n",
"\n",
"In NumPy - convenient interface for just this kind of statically typed, compiled routine. --> vectorized operations\n",
"- performing an operation on the array, which will then be applied to each element\n",
"- pushes the loop into the compiled layer that underlies NumPy --> much faster execution\n",
"\n",
"- basic funcs quickly execute repeated operations on values in NumPy arrays --> extremely flexible"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "28eb2782",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"8.81 µs ± 173 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n"
]
}
],
"source": [
"%%timeit\n",
"values = np.random.randint(1, 10, size=5)\n",
"#compute_reciprocals(values)\n",
"1.0 / values"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "8fa81fb7",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"x = [0 1 2 3]\n",
"x + 5 = [5 6 7 8]\n",
"x - 5 = [-5 -4 -3 -2]\n",
"x * 2 = [0 2 4 6]\n"
]
}
],
"source": [
"# simple vectorized functions \n",
"x = np.arange(4)\n",
"print(\"x =\", x)\n",
"print(\"x + 5 =\", x + 5)\n",
"print(\"x - 5 =\", x - 5)\n",
"print(\"x * 2 =\", x * 2)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "84b8ac14",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"x = [1, 2, 3]\n",
"e^x = [ 2.71828183 7.3890561 20.08553692]\n",
"2^x = [2. 4. 8.]\n",
"3^x = [ 3 9 27]\n"
]
}
],
"source": [
"# exponents and logarithms\n",
"x = [1, 2, 3]\n",
"print(\"x =\", x)\n",
"print(\"e^x =\", np.exp(x))\n",
"print(\"2^x =\", np.exp2(x))\n",
"print(\"3^x =\", np.power(3, x))"
]
},
{
"cell_type": "markdown",
"id": "10ec3b82",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Mgrid"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "289495f1",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"x = np.arange(1,10) # timepoints\n",
"y = np.arange(-70, 100, 10) # voltage change\n",
"\n",
"# for loop solution\n",
"xx, yy = np.zeros((len(x), len(y))), np.zeros((len(y), len(x)))\n",
"for a, i in enumerate(x):\n",
" xx[a] = np.repeat(i, len(y))\n",
"\n",
"for b, j in enumerate(y):\n",
" yy[b] = np.repeat(j, len(x))\n",
"yy = yy.T\n",
"\n",
"# 1-line mgrid solution\n",
"# works like broadcasting\n",
"XX, YY = np.mgrid[1:10:1, -70:100:10] # two arrays with shape (9,17); (len(x), len(y))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "25bce1f0",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"fig = plt.figure()\n",
"ax = fig.add_subplot()\n",
"ax.scatter(xx, yy)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "7b8a8d1e",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Hands on exercises\n",
"\n",
"- Open notebook exercises/numpy_vectorize.ipynb\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1fb78b62",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"celltoolbar": "Slideshow",
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.11.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}