{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import pyhf\n", "pyhf.set_backend('jax')\n", "import jax\n", "import jaxlib\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import jax.numpy as jnp" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## PyHEP 2020 -- Tutorial on Automatic Differentiation\n", "\n", "\n", "### Introduction\n", "\n", "Welcome to this tutorial on automatic differentiation. Automatic Differentiation is a method to compute exact derivatives of functions implements as **programs**. It's a widely applicable method and famously is used in\n", "many Machine learning optimization problems. E.g. neural networks, which are parametrized by weights $\\text{NN}(\\text{weights})$ are trained by (stocastic) **gradient** descent to find the minimum of the loss function $L$ where \n", "\n", "\n", "$$\\text{weights}_\\text{opt} = \\text{argmin}_\\text{weights} L(\\text{weights}) \\hspace{1cm} \\nabla L(\\text{weights}) = 0$$\n", "\n", "\n", "This means that efficient algorithms to compute derivatives are crucial.\n", "\n", "Aside from ML, many other use-cases require gradients: standard statistical analysis in HEP (fitting, hypothesis testing, ...) requires gradients. Uncertainty propagation (e.g. track parameters) uses gradients, etc..\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Other approaches to differentiation\n", "\n", "Before diving into automatic differentiation, let's review how my might otherwise compute derivatives\n", "\n", "\n", "\n", "#### Finite Differences\n", "\n", "\n", "A common appraoch to approximate gradients of a black-box function is to evaluate it\n", "at close-by points $x$ and $x+Δx$ and \n", "\n", "$\\frac{\\partial f}{\\partial x} \\approx \\frac{f(x) - f(x+\\Delta x}{\\Delta x}$ if $\\Delta x$ is sufficiently small\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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lUzPPvssM2fO5Msvv6RZs2a8+OKLxeZnZ2czd+5cVq9ezcUXX1xU3QOx4R0eeeSRYmPm//73v+fss89m2rRp5OTkcNJJJ3HuueeSmppatN706dNZs2YNK1euZNeuXfTu3Zubbrqp2H7Hjx/PF198weTJkxk8eDB33XUXI0eOTDia59ixYxk7dixXX301zz77bLF5ixcvZvny5XTu3BmAadOm0aRJEwoKCjjxxBP5+c9/TigU4g9/+AOLFi0iIyODs846i+OPP75S5zVeuVlORD4DWiWY9X/GmPerLJISjDFTgakQG96huvYDsUbeybPWcFrXpozs37o6d6VU3VNGCT1ZLrnkEhwOB71792bXrl3lLj979mw++OADJk+eDMRG0ty6dWux4RC+/vprrr76apxOJ23atOHss8+uVIzz5s3jvffeA+Caa64pNhz1SSedVJT4Ida+MX36dAC2bdvGunXr2LlzJ8OGDaN58+YAXHnllUWjkVaFcpO/MebcY9huFtA+7nk7explTE+av8xcQ14wwsMX9yl3+FalVPLFV39UZHwyYwzvvPMOPXrUju7a8b845syZw2effca8efNISUlh2LBh5Q5NXRWqq5//B8BVIuIVkc5Ad2A+sADoLiKdRcRDrFH4g2qKoUzv/ZDFkIlf0GncDN5YuI0zujfTRl6l6om0tDQOHz5c9Hz48OE89dRTRV8UP/zwwxHrnHnmmbzxxhtEo1Gys7Mrfb/dU045hXfeeQeA119/vdTlDh48SOPGjUlJSWH16tV8912sxvzkk0/mq6++Yt++fYTDYd56661KxVNSZbt6Xioi24FTgRkiMgvAGLMCeJNYQ+5M4C5jTNQYEwHuBmYBq4A37WVrVKKB2+Zt0IHblKovzjrrLFauXMnAgQN54403eOihhwiHw/Tv358+ffrw0EMPHbHOpZdeSvfu3enduzc33HADp556aqVieOKJJ/jb3/5G//79Wb9+fal337rggguIRCL06tWLcePGccoppwDQunVrJkyYwKmnnsqQIUOqfJTVBjmk85CJXxRL/IXaZvr5Zlzl6vmUqg90SOfKy8/Px+/3IyK8/vrrvPbaa7z/frU1kx71kM4NsluLDtymlKpuixYt4u6778YYQ2ZmJtOmTUt2SMU0yOTfJtOfsOSvA7cpparKGWecwdKlS5MdRqka5MBudwzt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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def black_box_func(x):\n", " return x**3\n", "\n", "def true_gradient_func(x):\n", " return 3*x**2\n", "\n", "\n", "def plot_gradients(nsteps,title):\n", " xi = np.linspace(-5,5,nsteps)\n", " yi = black_box_func(xi)\n", "\n", " approx_gradient = np.gradient(yi,xi)\n", " true_gradient = true_gradient_func(xi)\n", "\n", " plt.plot(xi,yi, label = 'black-box func')\n", " plt.scatter(xi,yi)\n", "\n", " plt.plot(xi,approx_gradient, label = 'finite diff grad')\n", " plt.scatter(xi,approx_gradient)\n", "\n", " plt.plot(xi,true_gradient, label = 'true grad')\n", " plt.scatter(xi,true_gradient)\n", "\n", " plt.legend()\n", " plt.title(title)\n", " plt.show()\n", " \n", " \n", "plot_gradients(11, title = 'it is pretty bad if Δx is too large')\n", "plot_gradients(41, title = 'it gets better at the cost of many evaluations') " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

\n", "while only approximate, finite differences is *simple*. I don't need to know \n", "anything about the function beyond having the ability \n", "to *evaluate* it\n", "

\n", "

\n", "This way I can compute gradients of functions encoded as a computer\n", "program, and it works in any programming language\n", "

\n", "\n", "

\n", "For multivariate (possibly vector-valued) functions $\\vec{f}(\\vec{x}) = f_i(x_1,x_2,\\dots,x_n)$ one needs to compute a finite difference\n", "gradient for each partial derivative $\\frac{\\partial f}{\\partial x}$ in order to get the\n", "full jacobian / total derivative $df_i = J_{ik} dx_k\\; J_{ik} = \\frac{\\partial f_i}{\\partial x_k}$\n", " \n", "In high dimensions, the number of required evaluations explodes!\n", "

\n", "\n", "\n", "**Finite Differences**:\n", "\n", "* Pro: easy to to, works in any language, no \"framework needed\"\n", "* Con: inaccurate unless one does a lot of evaluations\n", "* Con does not scale to large dimensions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Symbolic Differentiation in a CAS\n", "\n", "Computer Algebra Systems (CAS), such as Mathematica (or sympy)\n", "can manipulate functional *expressions* and know about differentiation rules (and many other things)\n", "\n", "If the function / the prograrm which we want to derive is available as such an expression the \n", "symbolic differentiation can produce **exact gradients**" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle x^{3}$" ], "text/plain": [ "x**3" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import sympy\n", "\n", "def function(x):\n", " return x**3\n", "\n", "def true_deriv(x):\n", " return 3*x**2\n", "\n", "symbolic_x = sympy.symbols('x')\n", "symbolic_func = function(symbolic_x)\n", "symbolic_func" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using `lambdify` we can turn it into a normal python function we can evaluate" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "

" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "xi = np.linspace(-5,5,11)\n", "yi = sympy.lambdify(symbolic_x,symbolic_func)(xi)\n", "plt.plot(xi,yi)\n", "plt.scatter(xi,yi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`symbolic_func` is now an experssion which we can differentiate *symbolically*" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle 3 x^{2}$" ], "text/plain": [ "3*x**2" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "symbolic_deriv = symbolic_func.diff(symbolic_x)\n", "symbolic_deriv" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def plot_symbolic(nsteps,title):\n", " xi = np.linspace(-5,5,nsteps)\n", " yi = sympy.lambdify(symbolic_x,symbolic_func)(xi)\n", " plt.scatter(xi,yi)\n", " plt.plot(xi,yi, label = 'function')\n", "\n", "\n", "\n", " yi = true_deriv(xi)\n", " plt.plot(xi,yi)\n", " plt.scatter(xi,yi, label = 'true deriv')\n", "\n", " yi = sympy.lambdify(symbolic_x,symbolic_deriv)(xi)\n", " plt.plot(xi,yi)\n", " plt.scatter(xi,yi, label = 'symbolic deriv')\n", "\n", " plt.legend()\n", " plt.title(title)\n", " plt.show()\n", " \n", " \n", "plot_symbolic(11,title = 'the symbolid derivative is always exact')\n", "plot_symbolic(4, title = 'it does not matter where/how often you evaluate it') " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Chain Rule in CAS\n", "\n", "We can even handle function compositions" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle \\cos{\\left(x^{2} \\right)}$" ], "text/plain": [ "cos(x**2)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def f1(x):\n", " #standard operations are overloaded\n", " return x**2\n", "\n", "def f2(x):\n", " #note here we use a special cos function from sympy\n", " #instead of e.g. np.cos or math.cos\n", " return sympy.cos(x) \n", " \n", "\n", "composition = f2(f1(symbolic_x))\n", "\n", "composition" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle - 2 x \\sin{\\left(x^{2} \\right)}$" ], "text/plain": [ "-2*x*sin(x**2)" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "composition.diff(symbolic_x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since `sympy` knows about the chain rule it can differentiate accordingly" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Problems with Symbolic Differentiation\n", "\n", "This looks great! We get exact derivatives. However,\n", "there are drawbacks\n", "\n", "1. Need to implement it in CAS\n", "\n", "Most functions we are interested in are not implemented \n", "e.g. Mathematica. Rather we have loads of C, C++, Python\n", "code that we are interested in. \n", "\n", "But ok, `sympy` alleviates this to some degree. The functions\n", "`f1` and `f2` are fairly generic since they use operator\n", "overloading. So a symbolic program and a \"normal\" program\n", "could only differ by a few import statements\n", "\n", "\n", "\n", "```python\n", "from sympy import cos\n", "\n", "def f1(x):\n", " return x**2\n", "\n", "def f2(x):\n", " return cos(x) \n", "```\n", "\n", "versus:\n", "\n", "```python\n", "from math import cos\n", "\n", "def f1(x):\n", " return x**2\n", "\n", "def f2(x):\n", " return cos(x) \n", "```\n", "\n", "\n", "Note the code is almost exactly the same\n", "\n", "But not all our functions are so simple!\n", "\n", "\n", "**Expression swell**\n", "\n", "Let's look at a quadratic map which is applied a few times" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle 243 x^{2} + 729 x + 81 \\left(x^{2} + 3 x + 4\\right)^{2} + 27 \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 9 \\left(9 x^{2} + 27 x + 3 \\left(x^{2} + 3 x + 4\\right)^{2} + \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 52\\right)^{2} + 3 \\left(27 x^{2} + 81 x + 9 \\left(x^{2} + 3 x + 4\\right)^{2} + 3 \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + \\left(9 x^{2} + 27 x + 3 \\left(x^{2} + 3 x + 4\\right)^{2} + \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 52\\right)^{2} + 160\\right)^{2} + \\left(81 x^{2} + 243 x + 27 \\left(x^{2} + 3 x + 4\\right)^{2} + 9 \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 3 \\left(9 x^{2} + 27 x + 3 \\left(x^{2} + 3 x + 4\\right)^{2} + \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 52\\right)^{2} + \\left(27 x^{2} + 81 x + 9 \\left(x^{2} + 3 x + 4\\right)^{2} + 3 \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + \\left(9 x^{2} + 27 x + 3 \\left(x^{2} + 3 x + 4\\right)^{2} + \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 52\\right)^{2} + 160\\right)^{2} + 484\\right)^{2} + 1456$" ], "text/plain": [ "243*x**2 + 729*x + 81*(x**2 + 3*x + 4)**2 + 27*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 9*(9*x**2 + 27*x + 3*(x**2 + 3*x + 4)**2 + (3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 52)**2 + 3*(27*x**2 + 81*x + 9*(x**2 + 3*x + 4)**2 + 3*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + (9*x**2 + 27*x + 3*(x**2 + 3*x + 4)**2 + (3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 52)**2 + 160)**2 + (81*x**2 + 243*x + 27*(x**2 + 3*x + 4)**2 + 9*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 3*(9*x**2 + 27*x + 3*(x**2 + 3*x + 4)**2 + (3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 52)**2 + (27*x**2 + 81*x + 9*(x**2 + 3*x + 4)**2 + 3*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + (9*x**2 + 27*x + 3*(x**2 + 3*x + 4)**2 + (3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 52)**2 + 160)**2 + 484)**2 + 1456" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def quadmap(x):\n", " return x**2 + 3*x + 4\n", "\n", "def func(x):\n", " for i in range(6):\n", " x = quadmap(x)\n", " return x\n", "\n", "quad_6_times = func(symbolic_x)\n", "quad_6_times" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This looks pretty intimidating. What happened? \n", "Symbolic programs run through the prgram and \n", "accumulate the full program into a single expression\n", "\n", "If we would just blindly differentiate this it would look like this" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/latex": [ "$\\displaystyle 486 x + 81 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 27 \\left(12 x + 2 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 18\\right) \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right) + 9 \\left(36 x + 6 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 2 \\left(12 x + 2 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 18\\right) \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right) + 54\\right) \\left(9 x^{2} + 27 x + 3 \\left(x^{2} + 3 x + 4\\right)^{2} + \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 52\\right) + 3 \\left(108 x + 18 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 6 \\left(12 x + 2 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 18\\right) \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right) + 2 \\left(36 x + 6 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 2 \\left(12 x + 2 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 18\\right) \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right) + 54\\right) \\left(9 x^{2} + 27 x + 3 \\left(x^{2} + 3 x + 4\\right)^{2} + \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 52\\right) + 162\\right) \\left(27 x^{2} + 81 x + 9 \\left(x^{2} + 3 x + 4\\right)^{2} + 3 \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + \\left(9 x^{2} + 27 x + 3 \\left(x^{2} + 3 x + 4\\right)^{2} + \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 52\\right)^{2} + 160\\right) + \\left(324 x + 54 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 18 \\left(12 x + 2 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 18\\right) \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right) + 6 \\left(36 x + 6 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 2 \\left(12 x + 2 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 18\\right) \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right) + 54\\right) \\left(9 x^{2} + 27 x + 3 \\left(x^{2} + 3 x + 4\\right)^{2} + \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 52\\right) + 2 \\left(108 x + 18 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 6 \\left(12 x + 2 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 18\\right) \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right) + 2 \\left(36 x + 6 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 2 \\left(12 x + 2 \\left(4 x + 6\\right) \\left(x^{2} + 3 x + 4\\right) + 18\\right) \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right) + 54\\right) \\left(9 x^{2} + 27 x + 3 \\left(x^{2} + 3 x + 4\\right)^{2} + \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 52\\right) + 162\\right) \\left(27 x^{2} + 81 x + 9 \\left(x^{2} + 3 x + 4\\right)^{2} + 3 \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + \\left(9 x^{2} + 27 x + 3 \\left(x^{2} + 3 x + 4\\right)^{2} + \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 52\\right)^{2} + 160\\right) + 486\\right) \\left(81 x^{2} + 243 x + 27 \\left(x^{2} + 3 x + 4\\right)^{2} + 9 \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 3 \\left(9 x^{2} + 27 x + 3 \\left(x^{2} + 3 x + 4\\right)^{2} + \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 52\\right)^{2} + \\left(27 x^{2} + 81 x + 9 \\left(x^{2} + 3 x + 4\\right)^{2} + 3 \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + \\left(9 x^{2} + 27 x + 3 \\left(x^{2} + 3 x + 4\\right)^{2} + \\left(3 x^{2} + 9 x + \\left(x^{2} + 3 x + 4\\right)^{2} + 16\\right)^{2} + 52\\right)^{2} + 160\\right)^{2} + 484\\right) + 729$" ], "text/plain": [ "486*x + 81*(4*x + 6)*(x**2 + 3*x + 4) + 27*(12*x + 2*(4*x + 6)*(x**2 + 3*x + 4) + 18)*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16) + 9*(36*x + 6*(4*x + 6)*(x**2 + 3*x + 4) + 2*(12*x + 2*(4*x + 6)*(x**2 + 3*x + 4) + 18)*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16) + 54)*(9*x**2 + 27*x + 3*(x**2 + 3*x + 4)**2 + (3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 52) + 3*(108*x + 18*(4*x + 6)*(x**2 + 3*x + 4) + 6*(12*x + 2*(4*x + 6)*(x**2 + 3*x + 4) + 18)*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16) + 2*(36*x + 6*(4*x + 6)*(x**2 + 3*x + 4) + 2*(12*x + 2*(4*x + 6)*(x**2 + 3*x + 4) + 18)*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16) + 54)*(9*x**2 + 27*x + 3*(x**2 + 3*x + 4)**2 + (3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 52) + 162)*(27*x**2 + 81*x + 9*(x**2 + 3*x + 4)**2 + 3*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + (9*x**2 + 27*x + 3*(x**2 + 3*x + 4)**2 + (3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 52)**2 + 160) + (324*x + 54*(4*x + 6)*(x**2 + 3*x + 4) + 18*(12*x + 2*(4*x + 6)*(x**2 + 3*x + 4) + 18)*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16) + 6*(36*x + 6*(4*x + 6)*(x**2 + 3*x + 4) + 2*(12*x + 2*(4*x + 6)*(x**2 + 3*x + 4) + 18)*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16) + 54)*(9*x**2 + 27*x + 3*(x**2 + 3*x + 4)**2 + (3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 52) + 2*(108*x + 18*(4*x + 6)*(x**2 + 3*x + 4) + 6*(12*x + 2*(4*x + 6)*(x**2 + 3*x + 4) + 18)*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16) + 2*(36*x + 6*(4*x + 6)*(x**2 + 3*x + 4) + 2*(12*x + 2*(4*x + 6)*(x**2 + 3*x + 4) + 18)*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16) + 54)*(9*x**2 + 27*x + 3*(x**2 + 3*x + 4)**2 + (3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 52) + 162)*(27*x**2 + 81*x + 9*(x**2 + 3*x + 4)**2 + 3*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + (9*x**2 + 27*x + 3*(x**2 + 3*x + 4)**2 + (3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 52)**2 + 160) + 486)*(81*x**2 + 243*x + 27*(x**2 + 3*x + 4)**2 + 9*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 3*(9*x**2 + 27*x + 3*(x**2 + 3*x + 4)**2 + (3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 52)**2 + (27*x**2 + 81*x + 9*(x**2 + 3*x + 4)**2 + 3*(3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + (9*x**2 + 27*x + 3*(x**2 + 3*x + 4)**2 + (3*x**2 + 9*x + (x**2 + 3*x + 4)**2 + 16)**2 + 52)**2 + 160)**2 + 484) + 729" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "quad_6_times.diff(symbolic_x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This looks even worse!\n", "\n", "Also note that that if we just blindly substitute x for some value\n", "e.g. x=2, we would be computing a lot of the same terms\n", "manyt times. E.g. in the above expression $x^2+3x+4$ appears in a \n", "lot of places due to the \"structure' of the original progrm\n", "\n", "If you knew the structure of the program you likely could precompute\n", "some of these repeating terms. However once it got all expanded all\n", "this knowledge about the structure is gone!\n", "\n", "Modern CAS can recover some of this by finding \"common subexpressions\" (CSE)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([(x0, x**2),\n", " (x1, (3*x + x0 + 4)**2),\n", " (x2, (9*x + 3*x0 + x1 + 16)**2),\n", " (x3, (27*x + 9*x0 + 3*x1 + x2 + 52)**2),\n", " (x4, (81*x + 27*x0 + 9*x1 + 3*x2 + x3 + 160)**2)],\n", " [729*x + 243*x0 + 81*x1 + 27*x2 + 9*x3 + 3*x4 + (243*x + 81*x0 + 27*x1 + 9*x2 + 3*x3 + x4 + 484)**2 + 1456])" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sympy.cse(quad_6_times)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But it's not as automatic and may note find all relevant subexpressions. In any case it's trying hard to recover some\n", "of the structure that is already implicitly present in the prograam we want to differentiate" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Control Flow**\n", "\n", "In addition to looping constucts like above, a lot of the functions we are interested in have \n", "control flow structures like if/else statements, while loops, etc..\n", "\n", "\n", "If we try to create a symbolic expression with conditionals we fail badly\n" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "cannot determine truth value of Relational", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m \u001b[0msymbolic_result\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msymbolic_x\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m\u001b[0m in \u001b[0;36mfunc\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/Code/pyhfdev/dev/pyhfdevenv/lib/python3.7/site-packages/sympy/core/relational.py\u001b[0m in \u001b[0;36m__nonzero__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 382\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 383\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__nonzero__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 384\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"cannot determine truth value of Relational\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 385\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 386\u001b[0m \u001b[0m__bool__\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m__nonzero__\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mTypeError\u001b[0m: cannot determine truth value of Relational" ] } ], "source": [ "def func(x):\n", " if x > 2:\n", " return x**2\n", " else:\n", " return x**3\n", " \n", "symbolic_result = func(symbolic_x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That's too bad because this is a perfectly respectable functino *almost everywhere*" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "xi = np.linspace(-2,5,1001)\n", "yi = np.asarray([func(xx) for xx in xi])\n", "\n", "plt.plot(xi,yi)\n", "plt.scatter(xi,yi)\n", "plt.title(\"pretty smooth except at x=2\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we could afford finite diffences it would compute gradients *just fine*." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "g = np.gradient(yi,xi)\n", "plt.plot(xi,g)\n", "plt.scatter(xi,g)\n", "plt.ylim(-2,10)\n", "plt.title('''\\\n", "parabolesque gradient in x^3 region,\n", "linear in x^2 region as expected''');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In short: symbolic differentiation is not our saving grace.\n", "\n", "* Pro: Gradients are exact, if you can compute them\n", "* Con: Need to implement in CAS. Full-featured Cas not easily available in all languages\n", "* Con: lead to expression swell by losing any structure of the program (needs to be recovered separately0\n", "* Con: Cannot handle common control-flow structures like loops and conditionals easily" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What we need\n", "\n", "To recap: \n", "\n", "Finite differences is\n", "* easy to implement in any language\n", "* handles arbitrary (halting) programs but\n", "* is inaccurate unless we're ready to pay a large computational overhead\n", "\n", "Symbolic differentiation is:\n", "* exact to machine precision\n", "* can lead to exccessive / inefficient computation if not careful\n", "* cannot handle complex programs with control flow structures\n", "\n", "\n", "

So what we need is a third approach!

\n", "\n", "One, that is \n", "* exact\n", "* efficient\n", "* can handle arbitrayr programs\n", "* that is easy to implement in many languages\n", "\n", "\n", "This third approach is 'Automatic' differentiation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Short Interlude on Linear Transformations\n", "\n", "Before we start, let's first look at *linear transformations** from ℝᵐ → ℝⁿ:\n", "$$y(x) = Ax$$\n", "\n", "With a given basis, this is representable as a (rectangular0 matrix: \n", "$$y_i(x) = A_{ij}x_j$$\n", "\n", "\n", "For a given linear problem, there are few ways we can run this computation\n", "\n", "\n", "1. **full matrix computation**\n", "\n", " i.e. we store the full (dense) $nm$ elements of the rectangular matrix and \n", " compute an explicit matrix multiplication.\n", " \n", " The computation can be fully generic for any matrix\n", " \n", "```python\n", " def result(matrix, vector):\n", " return np.matmul(matrix,vector)\n", "```\n", "
\n", "\n", "2. **sparse matrix computation**\n", "\n", " If many $A_ij=0$, it might be wasteful to expend memory on them. We can just \n", " create a sparse matrix, by\n", " \n", " * storing only the non-zerro elements \n", " * storing a look-up table, where those elements are in the matrix\n", " \n", " The computation can be kept general\n", "\n", "```python\n", " def result(sparse_matrix, vector):\n", " return sparse_matmul(sparse_matrix,vector)\n", "```\n", "\n", "
\n", " \n", "3. **matrix-free computation**\n", "\n", " In many cases a linear program is not explicitly given by a Matrix, but it's\n", " given as *code* / a \"black-box\" function. As long as the computation in the body of \n", " keeps to (hard-coded) linear transformation the program is linear. The matrix elements\n", " are no longer explicitly enumerated and stored in a data structure\n", " but implicitly defined in the source code.\n", " \n", " This is not anymore a generic computation, but each linear transformation is its own\n", " program. At the same time this is also the most memory efficient representation. No\n", " lookup table is needed since all constants are hard-coded.\n", " \n", " \n", "```python\n", " def linear_program(vector):\n", " z1,z2 = 0,0\n", " z1 += A_11*x1\n", " z2 += A_12*x2\n", " z2 += A_22*x2\n", " return [z1,z2]\n", "```\n", "\n", "\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Recovering Matrix Elements from matrix-free computations\n", "\n", "\n", "#### Matrix-vector products\n", "\n", "In the matrix-free setting, the program does not give access to the matrix elements,\n", "but only computes \"matrix-vector\" products (MVP)\n", "\n", "We can use basis vectors to recover the matrix **one column at a time**\n", "\n", "\"A\n", "\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "M derived from matrix-vector products:\n", "[[2 0 0]\n", " [0 1 3]]\n" ] } ], "source": [ "def matrix_vector_product(x):\n", " x1,x2,x3 = x\n", " z1,z2 = 0,0\n", " z1 += 2*x1 #MVP statement 1\n", " z2 += 1*x2 #MVP statement 2\n", " z2 += 3*x3 #MVP statement 3\n", " return np.asarray([z1,z2])\n", "\n", "M = np.concatenate([\n", " matrix_vector_product(np.asarray([1,0,0])).reshape(-1,1),\n", " matrix_vector_product(np.asarray([0,1,0])).reshape(-1,1),\n", " matrix_vector_product(np.asarray([0,0,1])).reshape(-1,1),\n", "],axis=1)\n", "print(f'M derived from matrix-vector products:\\n{M}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Vector Matrix product (VMP)\n", "\n", "The same matrix induces a \"dual\" linear map: ℝⁿ → ℝᵐ \n", "$$ x_k = y_i A_{ik}$$\n", "\n", "i.e. instead of a Matrix-vector product it's now a *vector-Matrix* product (VMP)\n", "\n", "If one has access to a \"vector-Matrix\" program corresponding to a matrix $A$ one\n", "can again -- as in the MVP-case -- recover the matrix elements, by feeding in basis vectors.\n", "\n", "This time the matrix is built **one row at a time**\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"A" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "M derived from vector-matix products:\n", "[[2 0 0]\n", " [0 1 3]]\n" ] } ], "source": [ "def vector_matrix_product(z):\n", " x1,x2,x3 = 0,0,0\n", " z1,z2 = z\n", "\n", " x3 += z2*3 #VMP version of statement 3\n", " x2 += z2*1 #VMP version of statement 2\n", " x1 += z1*2 #VMP version of statement 1\n", "\n", " return np.asarray([x1,x2,x3])\n", "\n", "\n", "M = np.concatenate([\n", " vector_matrix_product(np.asarray([1,0])).reshape(1,-1),\n", " vector_matrix_product(np.asarray([0,1])).reshape(1,-1),\n", "],axis=0)\n", "print(f'M derived from vector-matix products:\\n{M}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Short Recap:\n", "\n", "For a given linear transformation, characterized by a matrix $A_{ij}$ we have a forward (matrix-vector) and backward (vector-matrix) map $$y_i = A_{ij}x_k$$ $$x_j = y_i A_{ij}$$\n", "\n", "and we can use either to recover the full matrix $A_{ij}$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Wide versus Tall Transformation\n", "\n", "If you look at the code above, you'll notice that the number of calls necessary to the MVP or VMP program\n", "is related to the dimensions of matrix itself.\n", "\n", "For a $n\\times m$ matrix (for a map: ℝᵐ → ℝⁿ), you need as $m$ calls to the \"Matrix-vector\" program to \n", "built the full matrix one-column-at-a-time. Likewise you need $n$ calls to the \"vector-Matrix\" program\n", "to build the matrix one-row-at-a-time.\n", "\n", "This becomes relevant for very asymmetric maps: e.g. scalar maps from very high-dimensional spaces\n", "$\\mathbb{R}^{10000} \\to \\mathbb{R}$ the \"vector-Matrix\" appraoch is *vastly* more efficient than the\n", "\"Matrix-vector one. There's only one row, so only one call too the VMP program is needed to construct the full matrix!\n", "\n", "Similarly, functions mapping few variables into very high dimensional spaces $\\mathbb{R} \\to \\mathbb{R}^{10000}$\n", "it's the opposite: the \"Matrix-vector\" approach is much better suited than the \"vector-Matrix\" one (this time it's a single column!).\n", "\n", "\n", "## Function Compositions\n", "\n", "Of course copositions $(f\\circ g)(x) = f(g(x))$ of linear maps are also linear, so the above applies.\n", "\n", "\"A\n", "\n", "Depending on whether the \"Matrix-vector\" or \"vector-Matrix\" appraoch is used, the data is propagated **forwards** or **backwards**." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\"A\n", "\"A\n", "\n", "### From Matrices to Graphs\n", "\n", "The \"vector-Matrix\" or \"Matrix-vector\" picture can be generalized to arrbitrary directed acyclic graphs.\n", "\n", "* In the \"Matrix-vector\" picture the node value is the edge-weighted sum of the \"upstream nodes\".\n", "* In the \"vector-Matrix\" picture the node value is the edge-weighted sum of its \"downstream nodes\".\n", "\n", "(one could in principle always recove a rectangular/matrix-like version of a DAG by inserting trivial nodes)\n", "\n", "\n", "\"A\n", "\"A\n" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "def graph_like(x):\n", " x1,x2,x3 = x\n", " y1 = 2*x1+x2\n", " z1,z2 = y1+2*x3,x3-y1 #note that we reach \"over\" the \"ys\" and diectly touch x_n\n", " return np.asarray([z1,z2])\n", "\n", "def matrix_like(x):\n", " x1,x2,x3 = x\n", " y1 = 2*x1+x2\n", " y2 = x3 #can just introduce a dummy variable to make it matrix-like\n", " z1,z2 = y1+2*x3,y2-y1\n", " return np.asarray([z1,z2])\n" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "M derived from matrix like computation:\n", "[[ 2 1 2]\n", " [-2 -1 1]]\n", "M derived from graph-like products:\n", "[[ 2 1 2]\n", " [-2 -1 1]]\n" ] } ], "source": [ "M = np.concatenate([\n", " matrix_like(np.asarray([1,0,0])).reshape(-1,1),\n", " matrix_like(np.asarray([0,1,0])).reshape(-1,1),\n", " matrix_like(np.asarray([0,0,1])).reshape(-1,1),\n", "],axis=1)\n", "print(f'M derived from matrix like computation:\\n{M}')\n", "\n", "\n", "M = np.concatenate([\n", " graph_like(np.asarray([1,0,0])).reshape(-1,1),\n", " graph_like(np.asarray([0,1,0])).reshape(-1,1),\n", " graph_like(np.asarray([0,0,1])).reshape(-1,1),\n", "],axis=1)\n", "print(f'M derived from graph-like products:\\n{M}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Derivatives\n", "\n", "\n", "Why are we talking about linear transformations? After all lot of the code we write is non-linear! However, derivatives are always linear.\n", "\n", "And derivatives (the jacobian) of a composition $f\\circ g$ is the composition of linear derivatives (the jacobians\n", "of each map) i.e. the full jacobian Matrix is the result of multipying all Jacobians of the composition.\n", "$$J = J_0 J_1 J_2 J_3 \\dots J_n $$\n", "\n", "(This is just the chain rule)\n", "$$z = f(y) = f(g(x))\\hspace{1cm} \\frac{\\partial f_i}{\\partial x_j} = \\frac{\\partial f_i}{\\partial z_j}\\frac{\\partial z_j}{\\partial x_k}$$ \n", "\n", "\n", "I.e. finding derivatives, means characterizing the jacobian matrix. From the above discussion, we can use the \"Jacobian-vector product\" (JVP, builds Jacobians column-wise) or \"vector-Jacobian product\" (builds Jacobians row-wise) approach.\n", "\n", "In the language of automatic differentiation \n", "\n", "* Jacobian-vector products (JVP) = forward mode (forward propagation)\n", "\n", "$$ Jv_n = J_0 J_1 J_3 \\dots J_n v_n = J_0 J_1 J_2 J_3 v_3 = J_0 J_1 J_2 v_2 = J_0 J_1 v_1 = J_0 v_0 = \\text{col}$$\n", "\n", "* vector-Jacobian products (VJP) = reverse mode (reverse propagation)\n", "\n", "$$ v_0 J = v_0 J_0 J_1 J_3 \\dots J_n = v_1 J_1 J_2 J_3 \\dots J_n = v_2 J_2 J_3 \\dots J_n = v_3 J_3 \\dots J_n = \\dots = v_n J_n = \\text{row}$$\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example\n", "\n", "Let's work this out on a very simple problem\n", "\n", "\n", "\"A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the forward pass we use \"Matrix-vector\" products and need to do two evaluation\n", "\n", "\"A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the backward pass we use \"vector-Matrix\" products and need to do only a single evaluation\n", "\n", "\"A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Both approaches give the same result. Since this is a map from $\\mathbb{R}^2 \\to \\mathbb{R}^1$ the backward pass is more efficient than the forward pass\n", "\n", "\n", "Let's look at a real-life example\n", "\n", "$$z(x_1,x_2) = y + x_2 = x_1x_2 + x_2$$\n", "\n", "This is easy python code" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "12\n" ] } ], "source": [ "def mul_func(x1,x2):\n", " return x1*x2\n", "\n", "def sum_func(x1,x2):\n", " return x1+x2\n", "\n", "def function(x):\n", " x1,x2 = x\n", " y = mul_func(x1,x2)\n", " z = sum_func(y,x2)\n", " return z\n", "\n", "print(function([2,4]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the forward pass, an autodiff system needs to create a JVP implementation for each elementary operation " ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "def mul_jvp(x1,dx1,x2,dx2):\n", " y = mul_func(x1,x2)\n", " dy = x1*dx2 + x2*dx1\n", " return y, dy\n", "\n", "def sum_jvp(x1,dx1,x2,dx2):\n", " return sum_func(x1,x2), dx1 + dx2\n", "\n", "def function_jvp(x,dx):\n", " x1,x2 = x\n", " dx1,dx2 = dx\n", " y, dy = mul_jvp(x1,dx1,x2,dx2)\n", " z, dz = sum_jvp(y,dy, x2, dx2)\n", " return z,dz" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since in the forward pass we build \"column-at a time\" and our final jacobian is has shape (1x2), i.e. two columns we need two forward passes to get the full Jacobian. Not that for eacch forward pass we also get the fully computed functino value delivered on top!\n", "\n", "\n", "Also note that the \"JVP\" version of the functino has the same *structure* as the original function. For each call in the original program there is an equivalent call in the JVP program. However the JVP call does always two things at once\n", "\n", "1. compute the nominal result\n", "2. compute the differentials\n", "\n", "So it has roughly 2x the run-time as the original program (depending on the complexity of the derivatives). Said another way: computing the one-pass in the derivative has the same computational complexity as the function itself." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(12, 4)\n", "(12, 3)\n" ] } ], "source": [ "print(function_jvp([2,4],[1,0]))\n", "print(function_jvp([2,4],[0,1]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the backward pass we build \"row-at-a-time'. For each elementary operation we need to build a VJP implementation" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "def mul_vjp(x1,x2,dx1,dx2,dout):\n", " dx2 += dout * x1\n", " dx1 += dout * x2\n", " return dx1,dx2\n", "\n", "def sum_vjp(x1,x2,dx1,dx2,dout):\n", " dx1 += dout * 1\n", " dx2 += dout * 1\n", " return dx1,dx2\n", "\n", "def function_vjp(x,dz):\n", " \n", " #run forward\n", " x1,x2 = x\n", " y = mul_func(x1,x2)\n", " z = sum_func(y,x2)\n", "\n", " #zero gradients\n", " dy = 0 \n", " dx1 = 0\n", " dx2 = 0\n", " \n", " #run backward\n", " dy,dx1 = sum_vjp(y,x1, dy, dx1, dz)\n", " dx1,dx2 = mul_vjp(x1,x2, dx1, dx2, dy)\n", " return z,[dx1,dx2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, we see the power of backward propagation (or the reverse mode) we get all gradients of the single row ine oone go. Since this Jacobian only has one row, we're done! And we get the function value delivered on top of the gradients as well!" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(12, [4.0, 3.0])\n" ] } ], "source": [ "print(function_vjp([2,4],1.0))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Again, let's look at the \"VJP\" code. The forward pass is *exactly* the same as the original function. This just records the final result and all intermediate values, which we will need for the backward pass.\n", "\n", "Moving on to the backward pass, we see again, as in JVP, it has the same *structure* as the forward pass. For each call to a subroutine there is an equivalent call in the backward pass to compute the VJP. \n", "\n", "\n", "As in the JVP case, the computational complexity of one backward pass is roughly the same as the forward pass. Now unlike the JVP-case we only needed a single pass for **all the gradients** of this scalar function. So obtaining the **full gradient** of a function is only as expensive as the function itself." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Recap:\n", "\n", "Above we have built a *manual* autodiff system. Let's recap what we needed to do\n", "\n", "* define a set of operations we want to be differentiable\n", "* define sub-routines for nominal operations, JVP and VJP\n", "\n", "\n", "\n", "Once given a program, we had to do the following\n", "\n", "**In the forward mode**:\n", "\n", "* just replace the nominal function with the JVP one\n", "* for each variable in the program allocate a \"differential\" variable and pass it\n", " into the JVP whereever we also pass the nominal variable\n", " \n", " \n", "**In the backward mode**:\n", "\n", "* Run the program forward, keep track of all values\n", "* keep track of the order of operations on a \"record\" of sorts\n", "* allocate \"differential\" variables for all values and initialize to zero\n", "* use the record to replay the order of operations backwards, passing along the \n", " appropriate differential values, and updating the relevant ones with the result\n", " of the VJP\n", "\n", "\n", "All of this is pretty mechanistic and hence \"automatable\". And given that it's a very narrow\n", "domain of only implementing JVP/JVP operations this is easy to do in any language.\n", "\n", "That's why it's **automatic differentiation**\n", " \n", " \n", "What we gain from this is that we get\n", "\n", "* exact derivatives (to machine precision) for arbitrary composed of the operations we define\n", "* complexity of a derivative-pass through the program is of same order of complexity as the original program\n", "* often only a single pass is necessary (e.g. scalar multi-variate functions)\n", "* unlike symbolic differrentiation, the structure of the program is preserved and allows naturally to avoid\n", " repetitive calculations of the same values\n", "* (we will see that) arbitrary control flows are handles naturally\n", "* it's something that is easy for a comoputer do and for a progarmmer to imlpement\n", "\n", "\n", "\n", "Some notes on pros and cons:\n", "\n", "**In the forward mode**:\n", "\n", "the signature of each opeartion basically extends \n", " ```c++\n", " float f(float x,float y,float z)\n", " ```\n", " to\n", " ```c++\n", " pair f(float x,float dx,float y,float float dy, float z,float dz)\n", " ```\n", " * if you use composite types (\"dual numbers\") that hold both x,dx you can basically \n", " keep the signature unchanged\n", " ```c++\n", " f(dual x, dual x, dual z)\n", " ```\n", " * together with operator overloading on these dual types e.g. `dual * dual` you can \n", " essentially keep the source code unchanged\n", " ```c++\n", " float f(float x, float y): return x*y\n", " ``` \n", " ->\n", " ```c++\n", " dual f(dual x,dual y): return x*y\n", " ```\n", " \n", "* That means it's very easy implement. And memory efficient, no superfluous values are kept when they run out of scope.\n", "* But forward more better for vector-value functions of few parameters\n", "\n", "\n", "**In the reverse mode**:\n", "\n", "* very efficient, but we need to keep track of order (need a \"tape\" of sorts)\n", "* since we need to access all intermediate varriables, we can run into memory bounds\n", "* the procedurer is a bit more complex than fwd: 1) run fwd, 2) zero grads 3) run bwd\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## I don't want to implement an autodiff system.. Aren't there libraries for this??" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Yes there are! And a lot of them in many languages. On the othe rhand, try finding CAS systems in each of those \n", "\n", "\"A\n", "\n", "This is PyHEP, so let's focus on Python. Here, basically what you think of as \"Machine Learning frameworks\" are at the core autodiff libraries\n", "\n", "* Tensorflow\n", "* PyTorch\n", "* JAX" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's focus on jax" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "import jax\n", "import jax.numpy as jnp" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "def f(x):\n", " return x**2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`jax.numpy` is almost a drop-in rerplacement for `numpy`. I do `import jax.numpy as jnp` but if you're daring you could do `import jax.numpy as np`" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/lukasheinrich/Code/pyhfdev/dev/pyhfdevenv/lib/python3.7/site-packages/jax/lib/xla_bridge.py:125: UserWarning: No GPU/TPU found, falling back to CPU.\n", " warnings.warn('No GPU/TPU found, falling back to CPU.')\n" ] } ], "source": [ "x = jnp.array([1,2,3])\n", "y = jnp.array([2,3,4])" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[3 5 7]\n", "[ 2 6 12]\n", "[0. 0.69314718 1.09861229]\n", "[ 7.3890561 20.08553692 54.59815003]\n" ] } ], "source": [ "print(x+y)\n", "print(x*y)\n", "print(jnp.log(x))\n", "print(jnp.exp(y))" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "def f(x):\n", " return x**3" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "64.0\n", "48.0\n", "24.0\n", "6.0\n", "0.0\n" ] } ], "source": [ "print(f(4.0))\n", "print(jax.grad(f)(4.0)) #boom!\n", "print(jax.grad(jax.grad(f))(4.0)) #boom!\n", "print(jax.grad(jax.grad(jax.grad(f)))(4.0)) #boom!\n", "print(jax.grad(jax.grad(jax.grad(jax.grad(f))))(4.0)) #boom!" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAX8AAAD4CAYAAAAEhuazAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAd+ElEQVR4nO3deXxU9b3/8dcnK0mAEEJYEyDsgoBgDChVrLgg1aJWLbbuIGrVqlfrtdp77a+9Vq9erW311nKRCqKidaUqKqjVqhUIO8gWIUDCkoRAIAlZJvP9/ZHBphrWZOZMZt7Px2OczJnJnPeAvv0+vufM95hzDhERiS4xXgcQEZHQU/mLiEQhlb+ISBRS+YuIRCGVv4hIFIrzOsDR6NSpk+vdu7fXMUREWpUlS5aUOucymnquVZR/7969ycvL8zqGiEirYmZbDvWcpn1ERKKQyl9EJAqp/EVEopDKX0QkCqn8RUSikMpfRCQKqfxFRKJQqzjPX0QkGr2xrAiH46KTemBmLfreGvmLiIShihofv37rS15avC0o76+Rv4hIGJr+903srqxl+vhBLT7qB438RUTCTmlFDf/3ySbGD+nKiJ5pQdmHyl9EJMw8+WE+B+rqufu8gUHbh8pfRCSMbCur4vmFW7g8J4t+ndsGbT8qfxGRMPLb+RuIMeOOswcEdT8qfxGRMLF2xz5eX17EtWN60zW1TVD3pfIXEQkTj763nnaJcdw8tm/Q96XyFxEJA4s2l/HhumJuOrMvHZITgr4/lb+IiMecczw8by1d2idy3WnZIdmnyl9ExGPzv9zF0q17uX3cAJISYkOyT5W/iIiHfPV+HnlvPX06pXB5TmbI9qvyFxHx0OwvtpBfXME94wcRFxu6Slb5i4h4pKyylsfnb2BMv3TOG9IlpPtW+YuIeOSx99dTWVvPAxcOCcribYej8hcR8cCX2/fx4qKtXDW6FwO6tAv5/lX+IiIh5pzjl39dQ2pSPHcGeRmHQ2mR8jezGWZWbGarG23raGbzzWxj4D4tsN3M7Pdmlm9mK81sZEtkEBFpLd5etYNFm8u4+7yBpCbHe5KhpUb+zwLjv7HtXuAD51x/4IPAY4Dzgf6B21Tgjy2UQUQk7B2orec3b69lcLf2TDqlp2c5WqT8nXOfAGXf2DwRmBn4eSZwUaPts1yDL4AOZtatJXKIiIS7pz/+iu3l1fzy+0OIjQntQd7Ggjnn38U5tyPw807g4HlMPYDGF6UsDGz7F2Y21czyzCyvpKQkiDFFREKjcE8VT3/8FRcM60ZudkdPs4TkgK9zzgHuGH9nmnMuxzmXk5GREaRkIiKh89A76zCD+yac4HWUoJb/roPTOYH74sD2IiCr0esyA9tERCLWpxtLeXvVDm4e24/uHZK8jhPU8p8LXBP4+RrgzUbbrw6c9TMaKG80PSQiEnEO1NZz3+ur6NMphRvH9vE6DgBxLfEmZvYicCbQycwKgQeAh4GXzWwysAW4PPDyd4AJQD5QBVzXEhlERMLVEws2sLWsijlTR9MmPjSrdh5Ji5S/c+6KQzw1ronXOuCWltiviEi4W11UzvRPNzPplCxG90n3Os7X9A1fEZEg8dX7ufe1laQlJ/Dz870/yNtYi4z8RUTk2/78WQGri/bx1I9GevZN3kPRyF9EJAi2lVXx+PwNnH1CZyYM7ep1nG9R+YuItDDnHPe9vooYg19NPDHkyzUfDZW/iEgLe2N5EX/fWMo94weFxTn9TVH5i4i0oLLKWn791lpG9OzAlaN7eR3nkFT+IiItxDnH/a+vYn91HQ9fMszThduOROUvItJCXltaxLzVO7nr3IEM7Br6q3MdC5W/iEgL2FZWxQNz15DbuyM3nB4eSzgcjspfRKSZ6v2Ou15eAcBjlw8P6+meg/QlLxGRZpr2ySYWFZTx2GXDyeqY7HWco6KRv4hIM6wuKufx+euZMLQrl4z81nWpwpbKX0TkOFXX1XPnS8tJS07gwYuGhuWXuQ5F0z4iIsfpkXfXs7G4gpnX55KWkuB1nGOikb+IyHH4dGMpMz7bzDWn9mLsgNZ3qVmVv4jIMdpZXs0dLy2jX+e23BtmSzUfLU37iIgcg7p6P7e+sJSq2npevGEkSQnhcWWuY6XyFxE5Bv89bx15W/bwu0kn0b9LeH+L93A07SMicpTeWbWD6Z82zPNPPKn1nNbZFJW/iMhR2FRSwT2vrOSkrA7c/73BXsdpNpW/iMgRVNX6uHn2UuJjjad+PJKEuNZfnZrzFxE5DOccv3h9NRuK9zPzulx6hOnFWY5V6//fl4hIEL2waCuvLSvi9nH9OaMVns9/KCp/EZFD+PyrUh54cw1jB2Tw07P6ex2nRan8RUSakF9cwU3PLSG7Uwq/v2IEMa1gmeZjofIXEfmGssparn92MfGxMcy49hRSk+K9jtTidMBXRKSRGl89U2flsXNfNXOmjm416/MfK438RUQCnHPc88pK8rbs4fHLhzOyZ5rXkYJG5S8iEvC7Dzby5vLt/Oy8gVwwrLvXcYJK5S8iAryxrIgnFmzk0pMz+cmZfb2OE3RBn/M3swJgP1AP+JxzOWbWEXgJ6A0UAJc75/YEO4uISFM+3lDCz15Zweg+HfnNxa3rilzHK1Qj/+86505yzuUEHt8LfOCc6w98EHgsIhJyCzft5sbn8ujfuR1/ujInIpZuOBpefcqJwMzAzzOBizzKISJRbMW2vUyemUePDkk8NzmX1OTIO6XzUEJR/g5438yWmNnUwLYuzrkdgZ93Al1CkENE5Gvrdu7j6hmLSEuJ5/kpo0lvm+h1pJAKxXn+33HOFZlZZ2C+ma1r/KRzzpmZ++YvBf5HMRWgZ8+eIYgpItFiU0kFV05fRFJ8LC9MGU3X1DZeRwq5oI/8nXNFgfti4HUgF9hlZt0AAvfFTfzeNOdcjnMuJyMjchZTEhFvFe6p4srpC3HOMXvKqIj9EteRBLX8zSzFzNod/Bk4F1gNzAWuCbzsGuDNYOYQEQHYUX6AH09fSEWNj1mTc+nXua3XkTwT7GmfLsDrgdOm4oAXnHPvmtli4GUzmwxsAS4Pcg4RiXKbSyu5cvpCyg/UMWtyLkO6p3odyVNBLX/n3CZgeBPbdwPjgrlvEZGD1u7Yx1XPLMLvHC/eMJqhmdFd/KCF3UQkwi3duodrZywiOSGO2VNG0a9zO68jhQWVv4hErM/yS7lhVh4Z7RKZPTl6D+42ReUvIhHp/TU7ufWFZWR3SuG5ybl0bh99p3MejspfRCLOnEVbuf+N1Qztkcqz151Ch+QEryOFHZW/iEQMX72f37yzjhmfbeaMARn8749H0jZRNdcU/amISETYV13HbS8s4+MNJVw3pjf3TziBuNjoWKTteKj8RaTVKyitZPLMxWzZXcVDlwzlilwtCXMkKn8RadU+zy/l5ueXEmMwe8ooRvdJ9zpSq6DyF5FWyTnHzM8L+K+315LdKYVnrjmFnuk6lfNoqfxFpNXZU1nLPa+uZP6Xuxg3qDNPTDqJdm2iZy3+lqDyF5FWZeGm3dzx0nJKK2r4xfdOYPJ3sqPisostTeUvIq2Cr97PHz7M5w8fbqRnx2Reu3mM1uhpBpW/iIS97XsPcMec5SwqKOOSET341UUn6vz9ZtKfnoiELb/fMWfxNh6atxa/3/H45cO5ZGSm17EigspfRMJSfnEF9722ikUFZZzaJ52HLhlK704pXseKGCp/EQkrtT4/f/zbVzz1UT5JCbE8cukwLjs5Uwd1W5jKX0TCxpItZdz76io2Fldw4fDu/OcFg8lol+h1rIik8hcRz23dXcWj76/nryu206NDEjOuzeGsQV28jhXRVP4i4pk9lbU8+VE+s/5RQGyMcdtZ/bhpbF9SdCZP0OlPWERCrrqunpmfF/DkR/lU1vi4PCeLO88ZQBddcCVkVP4iEjLVdfX8JW8bT3+8iaK9BzhrUGf+ffwgBnbVdXVDTeUvIkFXXlXHc18U8OfPCthdWcuInh149LJhnNa3k9fRopbKX0SCZte+ap75dDPPf7GFytp6zhyYwc1j+5Kb3VGnbnpM5S8iLco5xxebypizeCvzVu3E5/dz4fDu3HhGXwZ3b+91PAlQ+YtIiyjeX82rS4p4afFWCnZX0a5NHFfkZjH5O320zn4YUvmLyHGrrqvnkw0lvLq0kA/WFuPzO3J7d+Sn4/ozYWg32sTHeh1RDkHlLyLHpLLGx9/Wl/DO6h18tK6Yqtp6OqYkcP13srk8J4t+ndt6HVGOgspfRI5oZ3k1n+aX8v6anXy8oYQan5/0lAQmntSD80/syql904mPjfE6phwDlb+IfEv5gTq+2LSbz/JL+Sy/lK9KKgHo0j6RSadkMf7EbuRmdyQ2RmfstFYqf5Eo5/c7NpVWsHxbOSsL97J8215WF5Xjd5AUH0tudkd+eEoWY/p14oSu7YlR4UcElb9IFNlfXcemkkryiyvYsGs/Kwr3srpoHxU1PgBSEmI5sUcqt57VnzF90xnRM42EOE3nRCLPyt/MxgO/A2KB6c65h73KIhIpnHPsrqxl+94DbN97gKK91WwrqyK/uIL84gp27qv++rXxscbgbu25eEQPhmWmclJWB/pktNVUTpTwpPzNLBZ4CjgHKAQWm9lc59yXXuQRCUf1fkdFjY/KGh8VgVtljY+yylr2VNZSVlnL7kb3JftrKNp7gFqf/1/ep21iHH0zUjitXzp9M9rSr3PDrWfHZB2kjWJejfxzgXzn3CYAM5sDTARU/tIs1XX17Kuuo7Kmnopq37+UZ1VtPbW+emp8fmp8fmp9fmp89dTVO3x+P/V+qA/c+52j3u/wOweAC/zD4Qhs+paD2w++xjXe5hz1gfdsfPP53dc5/pmp4XF1nb/pHQWYQVpyAh1TGm6Du7fn3MFd6N4hKXBrQ48OSaQmxWspBfkWr8q/B7Ct0eNCYFTjF5jZVGAqQM+ePUOXTMKOc459B3wUBaYytpcfoGjvAXZXNB791lBWUUtlbf1Rv2+MQWJcLPGxRlxsDLExRqxZw32MEWMQYwaB3jTAzAL3Tb+nBV588PnGr4+LMWIa7SMhLoakGCMxLpbEuBgS42JIaHSfkhhH24O3NnFfP05LjictOYEOyQmaopHjFrYHfJ1z04BpADk5OYcYa0kkqajxsamk4uv56a9KKthUUsn2vQe+VeoJsTGkt/3nqDc7PZmOKYmkt02gfVI8bRNjSUloKM2DBZqUEEubuNivCzZOUx4Sxbwq/yIgq9HjzMA2iRJ7KmtZUbiXlYUNpxeu2b6PHeX/PBgZF2P0Sk+mb0ZbTu+f8fUUxsEpjfSUBJ1yKNIMXpX/YqC/mWXTUPqTgB95lEWCzDlHfnEFn+WXkrdlDysLy9laVgU0TIf06ZTCqOyO9O/S7usDkr3SdTBSJJg8KX/nnM/MbgXeo+FUzxnOuTVeZJHg2L73AJ/ll/L5Vw3fEi3eXwNA99Q2DM/qwBW5PRmelcrQHqm0axPvcVqR6OPZnL9z7h3gHa/2Ly3LOcea7ft4d/VO3l2zk/ziCgDSUxI4rV8nxvRNZ0y/TmR11NK+IuEgbA/4Svjz+x0rCvcyb/VO3l29k61lVcQYjMpOZ1JgOYCBXdppbl4kDKn85ZgV7qni5cXbeGVJIdvLq4mPNU7r24mfnNmXcwZ3Ib1totcRReQIVP5yVGp9fhas3cWcxdv4+8YSAE7vn8Fd5w7k7BO6kJqseXuR1kTlL4dVuKeK5/6xhVeWFLK7spZuqW346Vn9uSwnk8w0zd+LtFYqf2nS+p37+dPHXzF3xXYcMG5QZ67I7ckZAzL0rVKRCKDyl3+RV1DG0x9/xYK1xSQnxHL1qb2Zcno23TskeR1NRFqQyl8A+Cy/lCcWbGBxwR7SkuO58+wBXH1qL9JSEryOJiJBoPKPcmt37OPheev4eEMJ3VPb8MCFg/nhKVkkJ+hfDZFIpv/Co9SO8gM8/v4GXllaSLvEOO6fcAJXn9aLxLhYr6OJSAio/KPM/uo6nv74K575dDN+P9xweh9+cmZfOiRrekckmqj8o4Rzjnmrd/LA3DWU7K9h4kndufvcgVpuQSRKqfyjwI7yA/zHG2tYsHYXQ7q3Z/rVOQzP6uB1LBHxkMo/gvn9jtkLt/DIu+vx+f3cN2EQ14/J1kVMRETlH6k27NrPva+uZOnWvZzevxMPXjSUnuma4hGRBir/COOc49nPC3jonXWkJMby+OXDuXhED13AW0T+hco/gpRV1nLPKytYsLaYcYM688ilw7TCpog0SeUfIb7YtJs75iynrLKW/7xgMNeN6a3Rvogcksq/lfPV+/n9h/k8+eFGeqWn8No1p3Fij1SvY4lImFP5t2LF+6q59YVlLCoo4wcjM/nVxCGkJOqvVESOTE3RSq0uKueGWXnsrarjtz8czsUjMr2OJCKtiMq/FZq3agd3vrycjskJvHLzqQzprmkeETk2Kv9WxDnH7z/I57cLNjCyZwf+dFUOGe10No+IHDuVfytRXVfP3X9ZwVsrd3DJiB785pKhtInXCpwicnxU/q1A8b5qpszKY1VROf8+fhA3je2j0zhFpFlU/mFuW1kVVz6zkJL9NUy7KodzBnfxOpKIRACVfxjLL97PldMXcaCunuenjGJEzzSvI4lIhFD5h6lVheVcPWMhcbExvHTjaAZ1be91JBGJICr/MLRw024mz8wjNSme56eMonenFK8jiUiEUfmHmY/WF3PTc0vITEti9pRRdEtN8jqSiEQglX8YmbdqB7e9uIxB3dox87pcrcgpIkETtEs6mdkvzazIzJYHbhMaPfdzM8s3s/Vmdl6wMrQmH67bxW0vLmN4VgdeuGG0il9EgirYI//fOuf+p/EGMxsMTAKGAN2BBWY2wDlXH+QsYevz/FJumr2UE7q158/XnUL7NvFeRxKRCOfFxVwnAnOcczXOuc1APpDrQY6wsGTLHqbMyqN3ejKzrs9V8YtISAS7/G81s5VmNsPMDp6k3gPY1ug1hYFtUWfN9nKu/fMiOrdLZPbkUaSlJHgdSUSiRLPK38wWmNnqJm4TgT8CfYGTgB3AY8f43lPNLM/M8kpKSpoTMyzlF+/n6mcW0S4xjtlTRtG5fRuvI4lIFGnWnL9z7uyjeZ2Z/R/wVuBhEZDV6OnMwLZvvvc0YBpATk6Oa07OcLN1dxU/nr4QM+P5G0aTmZbsdSQRiTLBPNunW6OHFwOrAz/PBSaZWaKZZQP9gUXByhFuyipruWrGQmp8fmZPySVbX+ASEQ8E82yfR8zsJMABBcCNAM65NWb2MvAl4ANuiZYzfWp89UydlceO8mpevEFLNoiId4JW/s65qw7z3IPAg8HadzhyznHPKyvJ27KHJ380gpN7aZE2EfGOF6d6RqXffbCRN5dv52fnDeSCYd29jiMiUU7lHwJvLCviiQUb+cHITH5yZl+v44iIqPyDbXFBGfe8spJR2R156JKhugKXiIQFlX8QbdldydRZeWSmJfGnq04mIU5/3CISHtRGQbK/uo7rnl2MA2ZcewodkvXtXREJH1rSOQicc/zsLyvZsrtKF2MRkbCkkX8QPPPpZt5ds5N7xw9idJ90r+OIiHyLyr+FLS4o46F56xg/pCtTTs/2Oo6ISJNU/i2oZH8Ntzy/lKy0JB65bJjO7BGRsKU5/xbiq/fz0xeXsa+6jplal19EwpzKv4U8Nn8D/9i0m/+5bDgndNOaPSIS3jTt0wLmf7mLP/7tK67IzeLSkzO9jiMickQq/2baVlbFv728nBN7tOeBC4d4HUdE5Kio/Juh3u+46+UVOAd//PHJtImP9TqSiMhR0Zx/M0z7ZBOLCsp47LLhZHXU1bhEpPXQyP84rS4q5/H565kwtCuXjIzK68+LSCum8j8O1XX13PnSctKSE3jwIq3UKSKtj6Z9jsMj765nY3EFM6/PJS1FC7aJSOujkf8x+nRjKTM+28w1p/Zi7IAMr+OIiBwXlf8x2FtVy91/WUHfjBTuPf8Er+OIiBw3lf9Rcs7xizdWU1pRw+8mjSApQad1ikjrpfI/Sn9duYO3Vu7gznMGcGKPVK/jiIg0i8r/KOyprOX/zV3D8KwO3DRWF2AXkdZPZ/schf96ey3lB+p4/gdDiY3RaZ0i0vpp5H8En24s5dWlhdw4tg+Dumq1ThGJDCr/wzhQW899r68iu1MKt53V3+s4IiItRtM+h/HEBxvYWlbFizeM1qJtIhJRNPI/hNVF5Uz/+2Z+mJPFqX11EXYRiSwq/yb46v38/LVVpCUncN8EfZlLRCKPpn2a8OznBawqKufJH40gNVnX4hWRyKOR/zdsK6visfc3MG5QZ743tJvXcUREgqJZ5W9ml5nZGjPzm1nON577uZnlm9l6Mzuv0fbxgW35ZnZvc/YfDA/MXUOMwa8vOlFLNYtIxGruyH81cAnwSeONZjYYmAQMAcYD/2tmsWYWCzwFnA8MBq4IvDYsfLS+mA/XFXP72f3p3iHJ6zgiIkHTrDl/59xaoKkR8kRgjnOuBthsZvlAbuC5fOfcpsDvzQm89svm5GgJtT4/v/7rl/TplMK1p2V7HUdEJKiCNeffA9jW6HFhYNuhtn+LmU01szwzyyspKQlSzH+a+XkBm0or+Y8LBpMQp0MhIhLZjjjyN7MFQNcmnrrfOfdmy0dq4JybBkwDyMnJccHaD0DJ/hp+/8FGvjswg+8O6hzMXYmIhIUjlr9z7uzjeN8iIKvR48zANg6z3TOPvreOal89/3FB2Bx+EBEJqmDNb8wFJplZopllA/2BRcBioL+ZZZtZAg0HhecGKcNRWVm4l78sKeS6Mdn0yWjrZRQRkZBp1gFfM7sY+AOQAbxtZsudc+c559aY2cs0HMj1Abc45+oDv3Mr8B4QC8xwzq1p1idoBuccv5y7hvSURG47q59XMUREQq65Z/u8Drx+iOceBB5sYvs7wDvN2W9LeWN5EUu37uWRS4fRro2+ySsi0SNqT2uprPHx8Lx1DM9M5dKRmV7HEREJqagt/6c+ymfXvhoe+P4QYnR1LhGJMlFZ/tv3HmD6p5u5eEQPRvZM8zqOiEjIRWX5P7FgAzi469wBXkcREfFE1JX/xl37eWVJIVed2ovMtGSv44iIeCLqyv/R99aTkhDHLd/VqZ0iEr2iqvyXbNnD+1/uYuoZfeiYkuB1HBERz0RN+Tvn+O9319GpbSKTT9eqnSIS3aKm/P+2voRFm8u4fVw/khN09UoRiW5RUf5+f8Oov1d6MpNye3odR0TEc1FR/m+uKGLdzv382zkDiI+Nio8sInJYEd+ENb56Hnt/A0O6t+fCYd29jiMiEhYivvxfWLiVwj0HuGf8IC3jICISENHlX1Hj48kP8zm1Tzpn9O/kdRwRkbAR0ae9VNX4OKV3R246s29TF5kXEYlaEV3+ndu34emrTvY6hohI2InoaR8REWmayl9EJAqp/EVEopDKX0QkCqn8RUSikMpfRCQKqfxFRKKQyl9EJAqZc87rDEdkZiXAFq9zHIdOQKnXIUJMnzk66DO3Dr2ccxlNPdEqyr+1MrM851yO1zlCSZ85Ougzt36a9hERiUIqfxGRKKTyD65pXgfwgD5zdNBnbuU05y8iEoU08hcRiUIqfxGRKKTyDxEzu8vMnJlF/PUkzexRM1tnZivN7HUz6+B1pmAws/Fmtt7M8s3sXq/zBJuZZZnZR2b2pZmtMbPbvc4UKmYWa2bLzOwtr7O0FJV/CJhZFnAusNXrLCEyHzjROTcM2AD83OM8Lc7MYoGngPOBwcAVZjbY21RB5wPucs4NBkYDt0TBZz7odmCt1yFakso/NH4L3ANExdF159z7zjlf4OEXQKaXeYIkF8h3zm1yztUCc4CJHmcKKufcDufc0sDP+2kowx7epgo+M8sEvgdM9zpLS1L5B5mZTQSKnHMrvM7ikeuBeV6HCIIewLZGjwuJgiI8yMx6AyOAhd4mCYknaBi8+b0O0pIi+gLuoWJmC4CuTTx1P3AfDVM+EeVwn9k592bgNffTMFXwfCizSXCZWVvgVeAO59w+r/MEk5ldABQ755aY2Zle52lJKv8W4Jw7u6ntZjYUyAZWmBk0TH8sNbNc59zOEEZscYf6zAeZ2bXABcA4F5lfJikCsho9zgxsi2hmFk9D8T/vnHvN6zwhMAb4vplNANoA7c1stnPuSo9zNZu+5BVCZlYA5DjnWtvKgMfEzMYDjwNjnXMlXucJBjOLo+Fg9jgaSn8x8CPn3BpPgwWRNYxgZgJlzrk7vM4TaoGR/93OuQu8ztISNOcvwfAk0A6Yb2bLzexprwO1tMAB7VuB92g48PlyJBd/wBjgKuCswN/r8sCIWFohjfxFRKKQRv4iIlFI5S8iEoVU/iIiUUjlLyIShVT+IiJRSOUvIhKFVP4iIlHo/wN+8kTGzmsXWQAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "xi = jnp.linspace(-5,5)\n", "yi = f(xi)\n", "\n", "plt.plot(xi,yi)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "Gradient only defined for scalar-output functions. Output had shape: (50,).", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mjax\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgrad\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m~/Code/pyhfdev/dev/pyhfdevenv/lib/python3.7/site-packages/jax/api.py\u001b[0m in \u001b[0;36mgrad_f\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 411\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mwraps\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdocstr\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdocstr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margnums\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0margnums\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 412\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mgrad_f\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 413\u001b[0;31m \u001b[0m_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvalue_and_grad_f\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 414\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 415\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/Code/pyhfdev/dev/pyhfdevenv/lib/python3.7/site-packages/jax/api.py\u001b[0m in \u001b[0;36mvalue_and_grad_f\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 472\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 473\u001b[0m \u001b[0mans\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvjp_py\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maux\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_vjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf_partial\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0mdyn_args\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mhas_aux\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 474\u001b[0;31m \u001b[0m_check_scalar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mans\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 475\u001b[0m \u001b[0mdtype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdtypes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresult_type\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mans\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 476\u001b[0m \u001b[0mtree_map\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpartial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0m_check_output_dtype_grad\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mholomorphic\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mans\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m~/Code/pyhfdev/dev/pyhfdevenv/lib/python3.7/site-packages/jax/api.py\u001b[0m in \u001b[0;36m_check_scalar\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 493\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0maval\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mShapedArray\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 494\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0maval\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 495\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"had shape: {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0maval\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 496\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 497\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"had abstract value {}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0maval\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mTypeError\u001b[0m: Gradient only defined for scalar-output functions. Output had shape: (50,)." ] } ], "source": [ "jax.grad(f)(xi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Whoops, jax.grad defaults to reverse mode with a single backward pass, but through broadcasting we get a `vector -> vector` map. We can use some jax magic to \"unbroadcast\" the function, take the gradient and re-broadcast it" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "DeviceArray([7.50000000e+01, 6.90024990e+01, 6.32548938e+01,\n", " 5.77571845e+01, 5.25093711e+01, 4.75114536e+01,\n", " 4.27634319e+01, 3.82653061e+01, 3.40170762e+01,\n", " 3.00187422e+01, 2.62703040e+01, 2.27717618e+01,\n", " 1.95231154e+01, 1.65243648e+01, 1.37755102e+01,\n", " 1.12765514e+01, 9.02748855e+00, 7.02832153e+00,\n", " 5.27905040e+00, 3.77967514e+00, 2.53019575e+00,\n", " 1.53061224e+00, 7.80924615e-01, 2.81132861e-01,\n", " 3.12369846e-02, 3.12369846e-02, 2.81132861e-01,\n", " 7.80924615e-01, 1.53061224e+00, 2.53019575e+00,\n", " 3.77967514e+00, 5.27905040e+00, 7.02832153e+00,\n", " 9.02748855e+00, 1.12765514e+01, 1.37755102e+01,\n", " 1.65243648e+01, 1.95231154e+01, 2.27717618e+01,\n", " 2.62703040e+01, 3.00187422e+01, 3.40170762e+01,\n", " 3.82653061e+01, 4.27634319e+01, 4.75114536e+01,\n", " 5.25093711e+01, 5.77571845e+01, 6.32548938e+01,\n", " 6.90024990e+01, 7.50000000e+01], dtype=float64)" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "jax.vmap(jax.grad(f))(xi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "that looks better!\n", "\n", "`jax.grad(f)` just returns another function. Of course we can just \n", "take the gradient of that as well. And so on..." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "g1i = jax.vmap(jax.grad(f))(xi)\n", "g2i = jax.vmap(jax.grad(jax.grad(f)))(xi)\n", "g3i = jax.vmap(jax.grad(jax.grad(jax.grad(f))))(xi)\n", "plt.plot(xi,yi, label = \"f\")\n", "plt.plot(xi,g1i, label = \"f'\")\n", "plt.plot(xi,g2i, label = \"f''\")\n", "plt.plot(xi,g3i, label = \"f'''\")\n", "plt.legend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Control Flow\n", "\n", "Back when discussing symbolic differentiation we hit a snag when adding \n", "control flow through to our prorgam. In Jax this just passes through\n", "transparently. \n", "\n", "\n", "Let's compare this to finite differences. So far the only system\n", "we had to compute derivatives of control-flow-ful programs" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXAAAAD4CAYAAAD1jb0+AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nO3deVhV1f7H8fcCQRBNHFBzuFFpZk6gOKE4K86SpeVQZpmZpZWFw69s8Nq93iztWrdyqDRzCCecZ1EQMEXBIYdMswTnAUpFmdbvjwOkBgqcA/vsw/f1PDzAPufs/UXhw2LtNSitNUIIIczHyegChBBCFIwEuBBCmJQEuBBCmJQEuBBCmJQEuBBCmFSJorxYxYoVtbe3d1FeUgghTG/Pnj0XtdZedx4v0gD39vYmJiamKC8phBCmp5T6Lafj0oUihBAmJQEuhBAmJQEuhBAmVaR94EII66SmphIfH8+NGzeMLkUUAjc3N6pXr46Li0ueni8BLoSJxMfHU6ZMGby9vVFKGV2OsCGtNZcuXSI+Pp4HH3wwT6+5ZxeKUuobpdR5pdTBW45NUUodUUrtV0otV0p5WlH3XYXGJtBy8lYeHLeGlpO3EhqbUFiXEsLu3bhxgwoVKkh4OyClFBUqVMjXX1d56QOfA3S549gmoJ7WugHwMzA+z1fMh9DYBMYvO0BCYjIaSEhMZvyyAxLioliT8HZc+f2/vWeAa63Dgct3HNuotU7L/HQnUD1fV82jKRuOkpyaTvLxGJJ2LgYgOTWdKRuOFsblhBDCVGwxCuV5YF1uDyqlhimlYpRSMRcuXMjXiU8nJgNw47d9JO5YgE5Pve24EMIY/v7+RX7N0NBQDh06lK/XnDx5knr16gEQExPDqFGjALh58yYdO3bEx8eHH374gYiICOrWrYuPjw/JyebJF6sCXCn1NpAGzM/tOVrrmVprP621n5fX32aC3lVVT3cASlarA+mppJw7cdtxIeyV1ppvv/2WS5cuGV1KoYiKiiryaxYkwG/l5+fH9OnTAYiNjQUgLi6Op556ivnz5zN+/Hji4uJwdzdPvhQ4wJVSzwE9gIG6kLb1CQ6sjbuLM67VHgXgZsIR3F2cCQ6sXRiXE8JmDhw4wPPPP8+SJUsMraOwBgGULl2aq1ev0qFDBxo1akT9+vVZsWIFALt376ZBgwbcuHGDa9euUbduXQ4ePPi3cwQFBdG4cWPq1q3LzJkzbzt3liVLlvDcc88RFRXFypUrCQ4OxsfHh+PHjxMXF0fz5s1p0KABjz/+OFeuXAFgz549NGzYkIYNG/K///0v+1zbtm2jR48enD9/nkGDBrF79258fHyYMWMGISEhTJgwgYEDB9rk36eoFGgYoVKqCzAGaKO1vm7bkv4S5FsNsPSFn72vEk4XfubffepnHxfCXmW1UI0cr501CCA5NR34axAAYJOfITc3N5YvX859993HxYsXad68Ob169aJJkyb06tWLd955h+TkZAYNGpTdjXGrb775hvLly5OcnEyTJk144oknqFChQo7X8vf3p1evXvTo0YMnn3wSgAYNGvDZZ5/Rpk0b3n33XT744AM+/fRThgwZwueff07r1q0JDg7+27kqVarE7Nmz+fjjj1m9ejUA0dHRt53bLPIyjHAhEA3UVkrFK6VeAD4HygCblFJxSqmvCqvAIN9qRI5rT99u7XG/clzCW5hCVoDfvHnTsBqyBgHcypaDALTW/N///R8NGjSgY8eOJCQkcO7cOQDeffddNm3aRExMDGPGjMnx9dOnT6dhw4Y0b96cU6dOcezYsTxfOykpicTERNq0aQPA4MGDCQ8PJzExkcTERFq3bg3AM888Y+VXad/u2QLXWvfP4fDXhVDLXfn7+7No0SJOnTpFjRo1ivryQuRLdHQ0ACkpKYbVkNvNflsNApg/fz4XLlxgz549uLi44O3tnf0Xx6VLl7h69SqpqancuHEDDw+P2167bds2Nm/eTHR0NKVKlaJt27bZr711KJ3MOL0706yF0qJFC+CvHwwh7NX58+f55ZdfAGMDPLeb/bYaBJCUlESlSpVwcXEhLCyM3377a8XTl156iX/+858MHDiQsWPH5vjacuXKUapUKY4cOcLOnTuzH6tcuTKHDx8mIyOD5cuXZx8vU6YMf/75JwBly5alXLlyREREADBv3jzatGmDp6cnnp6e7NixA7D8knFkpgnwhg0b4u7uLgEu7N6t36NGBnjWIIBb2WoQgFKKgQMHEhMTQ/369fnuu+949FHLYIPvvvsOFxcXBgwYwLhx49i9ezdbt2697fVdunQhLS2NOnXqMG7cOJo3b5792OTJk+nRowf+/v7cf//92ceffvpppkyZgq+vL8ePH2fu3LkEBwfT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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def control_flow_func(x):\n", " if x > 2:\n", " return x**2\n", " else:\n", " return x**3\n", " \n", "\n", "first_gradient_of_cflow = jax.grad(control_flow_func)\n", " \n", "xi = jnp.linspace(-2,5,101)\n", "yi = np.asarray([first_gradient_of_cflow(xx) for xx in xi])\n", "plt.plot(xi,yi,c = 'k')\n", "\n", "xi = jnp.linspace(-2,5,11)\n", "yi = np.asarray([first_gradient_of_cflow(xx) for xx in xi])\n", "plt.scatter(xi,yi, label = 'jax autodiff')\n", "\n", "\n", "\n", "xi = jnp.linspace(-2,5,11)\n", "yi = np.asarray([control_flow_func(xx) for xx in xi])\n", "plt.scatter(xi,np.gradient(yi,xi), label = 'finite differences')\n", "\n", "plt.legend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can start to see the benefits autodiff. Among other things, finite differnces becomes\n", "quite sensitive to exactly where the evaluation points are (e.g. wrt to the discontinuity)\n", "\n", "\n", "As we compute higher derivatives, this error compounds badly for finite differences. But for\n", "autodiff, it's smooth sailing!" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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5JNP8Pb25sqVK7Ru3ZpOnTrRokULK6YuuYyMDBo0aMCaNWuKfYyPjw8+Pj4GpircnDlzeO6556hcufIdHT906NC878PCwnjmmWeYPHkyAJ999hlbt27Fzc3NKlltRXryObKysnj++efZvXs3S5Ys4fHHHzc7kiijcu8lEJ+Uigbik1KZGPojYYfi7/icrq6ueHt7A1C1alWaN29OfHz2+Tp06MAbb7xBmzZtaNasGbt37wYgNTWVvn370rx5c3r06EFqasEroG7cuJEHH3wQb29vQkND87ZfvXqVQYMG0aZNG7y8vFi/fj2Q3bPt1q0bTz75JB07duTs2bN5H/575JFH+M9//pN3joLePeR/t7B//37atm2Ll5cXjz76KLGx2Utxz549m0GDBgHZ90Vu2bLlLT3ws2fP0r59e7y9vfH29mbfvn23nB9g5MiRhISEMHfuXC5cuICvry++vr4AfPPNN7Rq1YqWLVvyxhtv5B2zePFimjVrRps2bdi7d2/e9mnTpjFz5kyioqKYM2cOn3/+Ob6+vgwdOpSff/4ZPz8/Zs+eXdg/Y9mktb7jP0Bv4D9AFuBz03MTgdNALNC5OOdr3bq1NsvYsWM1oD/++GPTMgjzHD9+vNj7PvrhNn3fGxG3/Hn0w21WyfLLL7/oRo0a6eTkZK211k888YR+7bXXtNZaR0ZG6o4dO2qttf7kk0/0iy++qLXW+siRI9pisegDBw7ccK7U1FTt5uamT506pbOysnTv3r11QECA1lrriRMn6qVLl2qttb58+bJu2rSpTklJ0YsXL9YNGzbUiYmJeXnc3d211lrPmjVLT506VWut9YULF3SzZs1uyb9jx468NpKTk3V6errWWustW7bonj17aq21zszM1O3bt9ehoaG6devWes+ePbec5+rVqzo1NVVrrfWpU6d0bn3If36ttR4xYoRevHix1lrr++67TyckJGittY6Pj9eNGjXSFy9e1Onp6drX11evW7dOX7hwIW/7tWvX9KOPPqpHjBihtdb6rbfe0jNmzLjl+5vPbaaCflaBGF1IXS3tcM0xoCfw//JvVEq1APoC7kADYKtSqpnWOrOU7Rli3rx5zJw5kxEjRjB27Fiz44gyrrB7BljjXgIpKSn06tWLOXPmUK1atbztPXv2BKB169acPXsWgF27duWNfXt4eODh4XHL+U6ePEmT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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "second_gradient_of_cflow = jax.grad(first_gradient_of_cflow)\n", "xi = jnp.linspace(-2,5,101)\n", "yi = np.asarray([second_gradient_of_cflow(xx) for xx in xi])\n", "plt.plot(xi,yi,c = 'k')\n", "\n", "xi = jnp.linspace(-2,5,11)\n", "yi = np.asarray([second_gradient_of_cflow(xx) for xx in xi])\n", "plt.scatter(xi,yi, label = '2nd deriv jax autodiff')\n", "\n", "xi = jnp.linspace(-2,5,11)\n", "yi = np.asarray([control_flow_func(xx) for xx in xi])\n", "plt.scatter(xi,np.gradient(np.gradient(yi),xi), label = '2nd deriv finite differences',)\n", "\n", "plt.legend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Custom Operations\n", "\n", "\n", "Not all our programs are so simple. Consider this \n", "\n", "\n", "```\n", "def func(x)\n", " y_root = solve(x^2 + y^2 == 1,x = x, y_start = 2.0)\n", " return y_root\n", " \n", "```\n", "\n", "solving this often goes through some iterative algorithm like Brent bracketing\n", "But, differentiating through the iteration is not the right solution.\n", "\n", "We can add our own custom gradients\n", "\n", "\n", "Recall the implicit function theorem\n", "$$\n", "f(x,y) = x^2 + y^2 -1 = 0\n", "$$\n", "\n", "$$\n", "df = 0 \\leftrightarrow 2x dx + 2y dy = 0\n", "$$\n", "\n", "$$\n", "dy/dx = -x/y\n", "$$\n", "\n", "\n", "How do we teach this an autodiff system:\n", "\n", "\n", "Recall: \n", "\n", "* we can choose which operations we consider \"fundamental\"\n", "* we don't need to constrain ourselves to the lowest possible representationo" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import jax\n", "from jax import core\n", "import numpy as np\n", "from jax.interpreters import ad\n", "\n", "import scipy\n", "import functools\n", "import matplotlib.pyplot as plt\n", "\n", "def findroot(f):\n", " return scipy.optimize.brentq(f,a = 0,b = 10) \n", "\n", "def func(x,y):\n", " return x**2 + y**2 - 1\n", "\n", "def y_for_x(x):\n", " return findroot(functools.partial(func,x))\n", "\n", "xi = np.linspace(-1,1)\n", "yi = np.asarray([y_for_x(xx) for xx in xi])\n", "\n", "plt.plot(xi,yi)\n", "\n", "findrootjax_p = core.Primitive('findrootjax')\n", "findrootjax_p.def_impl(lambda x: y_for_x(x))\n", "ad.defvjp(findrootjax_p, lambda g, x: - x / y_for_x(x))\n", "\n", "def findrootjax(x):\n", " return findrootjax_p.bind(x)\n", "jax.value_and_grad(findrootjax)(0.5)\n", "\n", "xi = np.linspace(-1,1,101)\n", "yi = [findrootjax(v) for v in xi]\n", "plt.plot(xi,yi)\n", "\n", "\n", "\n", "xi = np.linspace(-1,1,21)\n", "vg = np.asarray([np.asarray(jax.value_and_grad(findrootjax)(v)) for v in xi])\n", "plt.scatter(xi,vg[:,0])\n", "plt.quiver(xi,vg[:,0],np.ones_like(vg[:,0]),vg[:,1],\n", " angles = 'uv',\n", " alpha = 0.5,\n", ")\n", "plt.gcf().set_size_inches(5,2.5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## In HEP\n", "\n", "\n", "Of course we can use automatic differentiation\n", "for neural networks. But other things in HEP also \n", "can make use of gradients. A prime example where this is the \n", "case is statistical analysis\n", "\n", "For a maximum likelihood fit we want to minimize the log likelihood\n", "\n", "$\\theta^* = \\mathrm{argmin}_\\theta(\\log L)$ " ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": [ "import jax\n", "import jax.numpy as jnp\n", "import numpy as np\n", "import pyhf\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [], "source": [ "pyhf.set_backend('jax')" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "DeviceArray([-4.25748227], dtype=float64)" ] }, "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = pyhf.simplemodels.hepdata_like([5.],[10.],[3.5])\n", "pars = jnp.array(m.config.suggested_init())\n", "data = jnp.array([15.] + m.config.auxdata)\n", "m.logpdf(pars,data)" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "DeviceArray([1., 1.], dtype=float64)" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bestfit = pyhf.infer.mle.fit(data,m)\n", "bestfit" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "grid = x,y = np.mgrid[.5:1.5:101j,.5:1.5:101j]\n", "\n", "points = np.swapaxes(grid,0,-1).reshape(-1,2)\n", "v = jax.vmap(m.logpdf, in_axes = (0,None))(points,data)\n", "v = np.swapaxes(v.reshape(101,101),0,-1)\n", "plt.contourf(x,y,v, levels = 100)\n", "plt.contour(x,y,v, levels = 20, colors = 'w')\n", "\n", "\n", "\n", "grid = x,y = np.mgrid[.5:1.5:11j,.5:1.5:11j]\n", "points = np.swapaxes(grid,0,-1).reshape(-1,2)\n", "values, gradients = jax.vmap(\n", " jax.value_and_grad(\n", " lambda p,d: m.logpdf(p,d)[0]\n", " ), in_axes = (0,None)\n", ")(points,data)\n", "\n", "plt.quiver(\n", " points[:,0],\n", " points[:,1],\n", " gradients[:,0],\n", " gradients[:,1],\n", " angles = 'xy',\n", " scale = 75\n", ")\n", "plt.scatter(bestfit[0],bestfit[1], c = 'r')\n", "\n", "plt.xlim(0.5,1.5)\n", "plt.ylim(0.5,1.5)\n", "plt.gcf().set_size_inches(5,5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Thanks for joining the Tutorial!\n", "\n", "\n", "\n", "\"A\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "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.7.2" } }, "nbformat": 4, "nbformat_minor": 4 }