From 1de8195b6b64a1ec781048a6b5d8df5218c46a4e Mon Sep 17 00:00:00 2001 From: Lukas Heinrich Date: Wed, 15 Jul 2020 14:21:04 +0200 Subject: [PATCH] go --- Tutorial.ipynb | 248 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 246 insertions(+), 2 deletions(-) diff --git a/Tutorial.ipynb b/Tutorial.ipynb index ba9c02e..a09e85d 100644 --- a/Tutorial.ipynb +++ b/Tutorial.ipynb @@ -1318,7 +1318,45 @@ " 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", + "\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" ] }, { @@ -1334,7 +1372,213 @@ "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" + "\"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": 171, + "metadata": {}, + "outputs": [], + "source": [ + "import jax\n", + "import jax.numpy as jnp" + ] + }, + { + "cell_type": "code", + "execution_count": 172, + "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": 191, + "metadata": {}, + "outputs": [], + "source": [ + "x = jnp.array([1,2,3])\n", + "y = jnp.array([2,3,4])" + ] + }, + { + "cell_type": "code", + "execution_count": 192, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[3 5 7]\n", + "[ 2 6 12]\n", + "[0. 0.6931472 1.0986123]\n", + "[ 7.389056 20.085537 54.598152]\n" + ] + } + ], + "source": [ + "print(x+y)\n", + "print(x*y)\n", + "print(jnp.log(x))\n", + "print(jnp.exp(y))" + ] + }, + { + "cell_type": "code", + "execution_count": 219, + "metadata": {}, + "outputs": [], + "source": [ + "def f(x):\n", + " return x**3" + ] + }, + { + "cell_type": "code", + "execution_count": 220, + "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": 221, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 221, + "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 = jnp.linspace(-5,5)\n", + "yi = f(xi)\n", + "\n", + "plt.plot(xi,yi)" + ] + }, + { + "cell_type": "code", + "execution_count": 222, + "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/pyhep2020-autodiff-tutorial/venv/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/pyhep2020-autodiff-tutorial/venv/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/pyhep2020-autodiff-tutorial/venv/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": "code", + "execution_count": 227, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 227, + "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()" ] }, {