diff --git a/doc/pub/week40/ipynb/ipynb-week40-src.tar.gz b/doc/pub/week40/ipynb/ipynb-week40-src.tar.gz index 648f68866..24e932b68 100644 Binary files a/doc/pub/week40/ipynb/ipynb-week40-src.tar.gz and b/doc/pub/week40/ipynb/ipynb-week40-src.tar.gz differ diff --git a/doc/pub/week40/ipynb/week40.ipynb b/doc/pub/week40/ipynb/week40.ipynb index c457584b6..78bc0e838 100644 --- a/doc/pub/week40/ipynb/week40.ipynb +++ b/doc/pub/week40/ipynb/week40.ipynb @@ -2,8 +2,10 @@ "cells": [ { "cell_type": "markdown", - "id": "4687f345", - "metadata": {}, + "id": "54c44098", + "metadata": { + "editable": true + }, "source": [ "\n", @@ -12,8 +14,10 @@ }, { "cell_type": "markdown", - "id": "3da2749d", - "metadata": {}, + "id": "f64073c9", + "metadata": { + "editable": true + }, "source": [ "# Week 40: Gradient descent methods (continued) and start Neural networks\n", "**Morten Hjorth-Jensen**, Department of Physics, University of Oslo, Norway and Department of Physics and Astronomy and Facility for Rare Ion Beams, Michigan State University, USA\n", @@ -23,16 +27,20 @@ }, { "cell_type": "markdown", - "id": "55819acc", - "metadata": {}, + "id": "d2d0f844", + "metadata": { + "editable": true + }, "source": [ "## Plans for week 40" ] }, { "cell_type": "markdown", - "id": "e1252272", - "metadata": {}, + "id": "c9630d37", + "metadata": { + "editable": true + }, "source": [ "## Lecture Monday September 30, 2024\n", "1. Stochastic Gradient descent with examples and automatic differentiation\n", @@ -44,8 +52,10 @@ }, { "cell_type": "markdown", - "id": "5684fcf4", - "metadata": {}, + "id": "4b447216", + "metadata": { + "editable": true + }, "source": [ "## Suggested readings and videos\n", "**Readings and Videos:**\n", @@ -67,8 +77,10 @@ }, { "cell_type": "markdown", - "id": "db5aaeaa", - "metadata": {}, + "id": "8fb799c1", + "metadata": { + "editable": true + }, "source": [ "## Lab sessions Tuesday and Wednesday\n", "**Material for the active learning sessions on Tuesday and Wednesday.**\n", @@ -84,8 +96,10 @@ }, { "cell_type": "markdown", - "id": "358e1ba3", - "metadata": {}, + "id": "3a202eb3", + "metadata": { + "editable": true + }, "source": [ "## Summary from last week, using gradient descent methods, limitations\n", "\n", @@ -104,8 +118,10 @@ }, { "cell_type": "markdown", - "id": "5f980026", - "metadata": {}, + "id": "f0b36267", + "metadata": { + "editable": true + }, "source": [ "## Simple implementation of GD for OLS, Ridge and Lasso\n", "\n", @@ -116,28 +132,12 @@ { "cell_type": "code", "execution_count": 1, - "id": "1e1a0f93", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Parameters for OLS using gradient descent\n", - "[[3.3082004 ]\n", - " [4.71564952]\n", - " [4.19643278]]\n", - "Parameters for Ridge using gradient descent\n", - "[[3.87100077]\n", - " [3.28108241]\n", - " [4.85556155]]\n", - "Parameters for Lasso using gradient descent\n", - "[[3.36052886]\n", - " [4.56274245]\n", - " [4.2705634 ]]\n" - ] - } - ], + "id": "2d9d73e5", + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], "source": [ "from random import random, seed\n", "import numpy as np\n", @@ -186,8 +186,10 @@ }, { "cell_type": "markdown", - "id": "fa35be2d", - "metadata": {}, + "id": "fcf0f686", + "metadata": { + "editable": true + }, "source": [ "## But none of these can compete with Newton's method\n", "\n", @@ -197,29 +199,12 @@ { "cell_type": "code", "execution_count": 2, - "id": "a07b46f9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Own inversion\n", - "[[4.]\n", - " [3.]\n", - " [5.]]\n", - "0 [-26.4958444] [-31.6102394]\n", - "1 [-5.24202903e-14] [-5.76114373e-14]\n", - "2 [-1.17239551e-15] [-1.43203537e-15]\n", - "3 [-1.17239551e-15] [-1.43203537e-15]\n", - "4 [-1.17239551e-15] [-1.43203537e-15]\n", - "beta from own Newton code\n", - "[[4.]\n", - " [3.]\n", - " [5.]]\n" - ] - } - ], + "id": "1550b223", + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], "source": [ "# Using Newton's method\n", "from random import random, seed\n", @@ -258,8 +243,10 @@ }, { "cell_type": "markdown", - "id": "ad8a1ec1", - "metadata": {}, + "id": "1777d437", + "metadata": { + "editable": true + }, "source": [ "## Gradient descent and Logistic regression\n", "\n", @@ -271,17 +258,12 @@ { "cell_type": "code", "execution_count": 3, - "id": "442155a9", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Predictions: [1, 1, 1, 1]\n" - ] - } - ], + "id": "94a3c22b", + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], "source": [ "import numpy as np\n", "class LogisticRegression:\n", @@ -318,8 +300,10 @@ }, { "cell_type": "markdown", - "id": "6906a7b0", - "metadata": {}, + "id": "5d9bd47b", + "metadata": { + "editable": true + }, "source": [ "## Overview video on Stochastic Gradient Descent\n", "\n", @@ -335,8 +319,10 @@ }, { "cell_type": "markdown", - "id": "0d1b86f0", - "metadata": {}, + "id": "0107149a", + "metadata": { + "editable": true + }, "source": [ "## Batches and mini-batches\n", "\n", @@ -354,8 +340,10 @@ }, { "cell_type": "markdown", - "id": "de264c3b", - "metadata": {}, + "id": "acb322f8", + "metadata": { + "editable": true + }, "source": [ "## Stochastic Gradient Descent (SGD)\n", "\n", @@ -384,8 +372,10 @@ }, { "cell_type": "markdown", - "id": "89be850a", - "metadata": {}, + "id": "9073ab44", + "metadata": { + "editable": true + }, "source": [ "## Stochastic Gradient Descent\n", "\n", @@ -399,8 +389,10 @@ }, { "cell_type": "markdown", - "id": "97f3f2d2", - "metadata": {}, + "id": "0a457a90", + "metadata": { + "editable": true + }, "source": [ "$$\n", "C(\\mathbf{\\beta}) = \\sum_{i=1}^n c_i(\\mathbf{x}_i,\n", @@ -410,8 +402,10 @@ }, { "cell_type": "markdown", - "id": "c5756174", - "metadata": {}, + "id": "be758e1d", + "metadata": { + "editable": true + }, "source": [ "## Computation of gradients\n", "\n", @@ -421,8 +415,10 @@ }, { "cell_type": "markdown", - "id": "9491611c", - "metadata": {}, + "id": "411db876", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\nabla_\\beta C(\\mathbf{\\beta}) = \\sum_i^n \\nabla_\\beta c_i(\\mathbf{x}_i,\n", @@ -432,8 +428,10 @@ }, { "cell_type": "markdown", - "id": "c5aa3260", - "metadata": {}, + "id": "c23bb658", + "metadata": { + "editable": true + }, "source": [ "Stochasticity/randomness is introduced by only taking the\n", "gradient on a subset of the data called minibatches. If there are $n$\n", @@ -444,8 +442,10 @@ }, { "cell_type": "markdown", - "id": "14db2504", - "metadata": {}, + "id": "adea87fe", + "metadata": { + "editable": true + }, "source": [ "## SGD example\n", "As an example, suppose we have $10$ data points $(\\mathbf{x}_1,\\cdots, \\mathbf{x}_{10})$ \n", @@ -464,8 +464,10 @@ }, { "cell_type": "markdown", - "id": "7246951f", - "metadata": {}, + "id": "5e5dee91", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\nabla_{\\beta}\n", @@ -477,8 +479,10 @@ }, { "cell_type": "markdown", - "id": "1662a436", - "metadata": {}, + "id": "97047a5f", + "metadata": { + "editable": true + }, "source": [ "## The gradient step\n", "\n", @@ -487,8 +491,10 @@ }, { "cell_type": "markdown", - "id": "af377a66", - "metadata": {}, + "id": "d9a59d5c", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\beta_{j+1} = \\beta_j - \\gamma_j \\sum_{i \\in B_k}^n \\nabla_\\beta c_i(\\mathbf{x}_i,\n", @@ -498,8 +504,10 @@ }, { "cell_type": "markdown", - "id": "87fd2445", - "metadata": {}, + "id": "a9b20c1c", + "metadata": { + "editable": true + }, "source": [ "where $k$ is picked at random with equal\n", "probability from $[1,n/M]$. An iteration over the number of\n", @@ -510,8 +518,10 @@ }, { "cell_type": "markdown", - "id": "e962547b", - "metadata": {}, + "id": "3867a529", + "metadata": { + "editable": true + }, "source": [ "## Simple example code" ] @@ -519,8 +529,11 @@ { "cell_type": "code", "execution_count": 4, - "id": "53e4501a", - "metadata": {}, + "id": "e5f4f9a8", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "import numpy as np \n", @@ -541,8 +554,10 @@ }, { "cell_type": "markdown", - "id": "46109bad", - "metadata": {}, + "id": "786c5900", + "metadata": { + "editable": true + }, "source": [ "Taking the gradient only on a subset of the data has two important\n", "benefits. First, it introduces randomness which decreases the chance\n", @@ -555,8 +570,10 @@ }, { "cell_type": "markdown", - "id": "539812ca", - "metadata": {}, + "id": "5f510fcf", + "metadata": { + "editable": true + }, "source": [ "## When do we stop?\n", "\n", @@ -574,8 +591,10 @@ }, { "cell_type": "markdown", - "id": "bdfb3ce0", - "metadata": {}, + "id": "1f0043c6", + "metadata": { + "editable": true + }, "source": [ "## Slightly different approach\n", "\n", @@ -592,8 +611,10 @@ }, { "cell_type": "markdown", - "id": "93825012", - "metadata": {}, + "id": "fbc5d941", + "metadata": { + "editable": true + }, "source": [ "## Time decay rate\n", "\n", @@ -609,17 +630,12 @@ { "cell_type": "code", "execution_count": 5, - "id": "17635e19", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "gamma_j after 500 epochs: 9.97108e-05\n" - ] - } - ], + "id": "f96c423d", + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], "source": [ "import numpy as np \n", "\n", @@ -649,8 +665,10 @@ }, { "cell_type": "markdown", - "id": "e9af4782", - "metadata": {}, + "id": "cdf1efeb", + "metadata": { + "editable": true + }, "source": [ "## Code with a Number of Minibatches which varies\n", "\n", @@ -660,36 +678,12 @@ { "cell_type": "code", "execution_count": 6, - "id": "a21b3bf0", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Own inversion\n", - "[[4.00444539]\n", - " [3.05946757]]\n", - "Eigenvalues of Hessian Matrix:[0.33390381 4.08547851]\n", - "theta from own gd\n", - "[[4.00444539]\n", - " [3.05946757]]\n", - "theta from own sdg\n", - "[[3.93407215]\n", - " [3.12257566]]\n" - ] - }, - { - "data": { - "image/png": "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akyjsbxfo6m+IK2bMAwRERGR5/n6GobPA9UDkfHnf/3LI0VhGCIiIiJppKQA33xTvQYoJsawXav1SDE4zxARERFJJyUFGDnS8gzURUUeKQLDEBEREUnL1xfo31+yl2cYIiIiohskXidMCgxDREREZFDTOmEpKdKVy83YgZqIiIhurBN266zQxnXC0tOlKZcHMAwRERGpnT3rhE2fbjjOCzEMERERqZ0964Tl5BiO80IMQ0RERGpn7zphMlpPzJUYhoiIiNTO3nXCZLSemCsxDBEREamdPeuExcYajvNCDENERERqZ886YYsWee18QwxDREREZHudMC+eZ4iTLhIREZFBTeuEeTGGISIi8l4qXFqi1iReJ0wKDENEROSdVLq0BDmOfYaIiMj7qHhpCXIcwxAREXkXlS8tQY5jGCIiIu+i8qUlyHHsM0RERN5F5UtLyILCOq4zDBERkXdR+dISklNgx3U2kxERkXdR+dISklJox3WGISIi8i4qX1pCMgruuM4wRERE3se4tERUlPn26GivX1pCMvPnK7bjOvsMERGRsjjSOddaU5mSybFzcno68NJL9h0rw47rrBkiIiLlSE8H4uKAAQOAsWMN/8bFVe+LotC+KzbZe/2uptcDWVnAihWGf29u6jI2j9lLhh3XJQ9DmzZtQnJyMqKioqDRaLBmzRqz/UIIzJ07F1FRUahTpw769++PAwcOSFNYIiKSjr0BR8F9V2okVcCzFcBszet0Mzs7rl85VYiV07bgr4nbnC62IyQPQyUlJejYsSMWL15scf+CBQvwxhtvYPHixdi+fTuaNm2KQYMG4erVqx4uKRERScaRgOONky5KFfDsCWCONHs99JDVJr3sTTl4K2UjBobuQpO4uhjzzh34JqdXLQpvP8n7DA0dOhRDhw61uE8IgUWLFmHOnDlI+V9nt08++QQRERFIS0vDE0884cmiEhGRVBwJON446aIj1++qFedtBTCNxhDAli2z/5yvvw706gWkpKCqsgrbPzkI3ccF0O2Mxv6yVgBiTYe2DTyOwYlHsGhnra/EJsnDUE2ys7ORl5eHwYMHm7YFBgaiX79+2LJli9UwVFZWhrKyMtPPRUVFbi8rERG5kSMBxxsnXczNte84VwY8ewMYYJjXKTfXcnC6+SkArk+chKdnhSLjRFucr0o07fNFJZIa7oO2XyGSp8bj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NHz77bdo0KAB8vLyAAAhISGoU6eOxKUjIiIipZN9nyGNRmNx+7JlyzBhwgS7zsGh9URERMrDPkP/I/OsRkRERAqnqKH1RERERK7GMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMERERESqppgw9N577yE+Ph5BQUHo2rUrNm/eLHWRiIiIyAsoIgx9+eWXmD59OubMmYPdu3cjKSkJQ4cOxenTp6UuGhERESmcRgghpC6ELT179kSXLl3w/vvvm7a1adMGo0aNQmpqqs3nFxUVISQkBIWFhQgODnZnUYmIiMhFPPX9LfuaofLycuzcuRODBw822z548GBs2bJFolIRERGRt/CTugC2FBQUQK/XIyIiwmx7REQE8vLyLD6nrKwMZWVlpp8LCwsBGBImERERKYPxe9vdjViyD0NGGo3G7GchRLVtRqmpqZg3b1617bGxsW4pGxEREbnPxYsXERIS4rbzyz4MNW7cGL6+vtVqgfLz86vVFhnNnj0bM2bMMP185coVNG/eHKdPn3brmyk3RUVFiI2NRU5Ojqr6SvG6ed1qwOvmdatBYWEhmjVrhtDQULe+juzDUEBAALp27Yr169fj3nvvNW1fv349Ro4cafE5gYGBCAwMrLY9JCREVb9ERsHBwbxuFeF1qwuvW13Uet0+Pu7t4iz7MAQAM2bMwLhx49CtWzf07t0bS5cuxenTp/Hkk09KXTQiIiJSOEWEoQcffBAXL17Eyy+/jHPnziExMRHff/89mjdvLnXRiIiISOEUEYYAYNKkSZg0aZJTzw0MDMRLL71ksenMm/G6ed1qwOvmdasBr9u9162ISReJiIiI3EX2ky4SERERuRPDEBEREakawxARERGpGsMQERERqZoiw9B7772H+Ph4BAUFoWvXrti8eXONx2/cuBFdu3ZFUFAQWrRogSVLllQ7ZtWqVWjbti0CAwPRtm1brF692l3Fd5oj152eno5BgwahSZMmCA4ORu/evfHjjz+aHbN8+XJoNJpqj9LSUndfikMcue6srCyL13T48GGz47zt854wYYLF627Xrp3pGCV83ps2bUJycjKioqKg0WiwZs0am8/xhvvb0ev2lvvb0ev2lvvb0ev2lvs7NTUV3bt3R4MGDRAeHo5Ro0bhyJEjNp/niXtccWHoyy+/xPTp0zFnzhzs3r0bSUlJGDp0KE6fPm3x+OzsbAwbNgxJSUnYvXs3/v73v2PatGlYtWqV6ZitW7fiwQcfxLhx4/DHH39g3LhxeOCBB/D777976rJscvS6N23ahEGDBuH777/Hzp07MWDAACQnJ2P37t1mxwUHB+PcuXNmj6CgIE9ckl0cvW6jI0eOmF1Tq1atTPu88fN+6623zK43JycHoaGhuP/++82Ok/vnXVJSgo4dO2Lx4sV2He8t97ej1+0t97ej122k9Pvb0ev2lvt748aNmDx5MrZt24b169ejsrISgwcPRklJidXneOweFwrTo0cP8eSTT5ptS0hIELNmzbJ4/HPPPScSEhLMtj3xxBOiV69epp8feOABcc8995gdM2TIEPHQQw+5qNS15+h1W9K2bVsxb94808/Lli0TISEhriqiWzh63ZmZmQKAuHz5stVzquHzXr16tdBoNOLkyZOmbUr4vG8GQKxevbrGY7zl/r6ZPddtiRLv75vZc93ecn/fzJnP2xvubyGEyM/PFwDExo0brR7jqXtcUTVD5eXl2LlzJwYPHmy2ffDgwdiyZYvF52zdurXa8UOGDMGOHTtQUVFR4zHWzulpzlz3raqqqnD16tVqi90VFxejefPmiImJwYgRI6r9ZSml2lx3586dERkZibvvvhuZmZlm+9TweX/00UcYOHBgtVna5fx5O8Mb7m9XUOL9XRtKvr9dwVvu78LCQgCocRFWT93jigpDBQUF0Ov11Varj4iIqLaqvVFeXp7F4ysrK1FQUFDjMdbO6WnOXPetFi5ciJKSEjzwwAOmbQkJCVi+fDl0Oh1WrFiBoKAg9OnTB8eOHXNp+Z3lzHVHRkZi6dKlWLVqFdLT09G6dWvcfffd2LRpk+kYb/+8z507hx9++AGPPfaY2Xa5f97O8Ib72xWUeH87wxvu79rylvtbCIEZM2agb9++SExMtHqcp+5xxSzHcTONRmP2sxCi2jZbx9+63dFzSsHZMq5YsQJz587Ft99+i/DwcNP2Xr16oVevXqaf+/Tpgy5duuCdd97B22+/7bqC15Ij1926dWu0bt3a9HPv3r2Rk5OD119/HXfeeadT55SKs2Vcvnw5GjZsiFGjRpltV8rn7Shvub+dpfT72xHedH87y1vu7ylTpmDv3r349ddfbR7riXtcUTVDjRs3hq+vb7W0l5+fXy0VGjVt2tTi8X5+fggLC6vxGGvn9DRnrtvoyy+/xF//+ld89dVXGDhwYI3H+vj4oHv37rL5S6I2132zXr16mV2TN3/eQgh8/PHHGDduHAICAmo8Vm6ftzO84f6uDSXf366itPu7Nrzl/p46dSp0Oh0yMzMRExNT47GeuscVFYYCAgLQtWtXrF+/3mz7+vXrcccdd1h8Tu/evasd/9NPP6Fbt27w9/ev8Rhr5/Q0Z64bMPzFOGHCBKSlpWH48OE2X0cIgT179iAyMrLWZXYFZ6/7Vrt37za7Jm/9vAHDaI3jx4/jr3/9q83Xkdvn7QxvuL+dpfT721WUdn/XhtLvbyEEpkyZgvT0dGzYsAHx8fE2n+Oxe9zurtYysXLlSuHv7y8++ugjcfDgQTF9+nRRr149U6/6WbNmiXHjxpmO//PPP0XdunXFM888Iw4ePCg++ugj4e/vL7755hvTMb/99pvw9fUV//rXv8ShQ4fEv/71L+Hn5ye2bdvm8euzxtHrTktLE35+fuLdd98V586dMz2uXLliOmbu3Lli3bp14sSJE2L37t1i4sSJws/PT/z+++8evz5rHL3uN998U6xevVocPXpU7N+/X8yaNUsAEKtWrTId442ft9EjjzwievbsafGcSvi8r169Knbv3i12794tAIg33nhD7N69W5w6dUoI4b33t6PX7S33t6PX7S33t6PXbaT0+/upp54SISEhIisry+z39tq1a6ZjpLrHFReGhBDi3XffFc2bNxcBAQGiS5cuZsPyxo8fL/r162d2fFZWlujcubMICAgQcXFx4v333692zq+//lq0bt1a+Pv7i4SEBLObSy4cue5+/foJANUe48ePNx0zffp00axZMxEQECCaNGkiBg8eLLZs2eLBK7KPI9f92muviZYtW4qgoCDRqFEj0bdvX/Hdd99VO6e3fd5CCHHlyhVRp04dsXTpUovnU8LnbRw6be331lvvb0ev21vub0ev21vub2d+z73h/rZ0zQDEsmXLTMdIdY9r/ldAIiIiIlVSVJ8hIiIiIldjGCIiIiJVYxgiIiIiVWMYIiIiIlVjGCIiIiJVYxgiIiIiVWMYIiIiIlVjGCIiIiJVYxgiIiIiVWMYIiIiIlVjGCIiRVqxYgWCgoKQm5tr2vbYY4+hQ4cOKCwslLBkRKQ0XJuMiBRJCIFOnTohKSkJixcvxrx58/Dhhx9i27ZtiI6Olrp4RKQgflIXgIjIGRqNBvPnz8fo0aMRFRWFt956C5s3b2YQIiKHsWaIiBStS5cuOHDgAH766Sf069dP6uIQkQKxzxARKdaPP/6Iw4cPQ6/XIyIiQuriEJFCsWaIiBRp165d6N+/P959912sXLkSdevWxddffy11sYhIgdhniIgU5+TJkxg+fDhmzZqFcePGoW3btujevTt27tyJrl27Sl08IlIY1gwRkaJcunQJffr0wZ133on//Oc/pu0jR45EWVkZ1q1bJ2HpiEiJGIaIiIhI1diBmoiIiFSNYYiIiIhUjWGIiIiIVI1hiIiIiFSNYYiIiIhUjWGIiIiIVI1hiIiIiFSNYYiIiIhUjWGIiIiIVI1hiIiIiFSNYYiIiIhUjWGIiIiIVO3/ATyZ5axZC3zBAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "id": "e221b4f3", + "metadata": { + "collapsed": false, + "editable": true + }, + "outputs": [], "source": [ "%matplotlib inline\n", "\n", @@ -763,8 +757,10 @@ }, { "cell_type": "markdown", - "id": "5649ec2a", - "metadata": {}, + "id": "7e858f37", + "metadata": { + "editable": true + }, "source": [ "## Replace or not\n", "\n", @@ -776,8 +772,10 @@ }, { "cell_type": "markdown", - "id": "302f4f77", - "metadata": {}, + "id": "7dace8c0", + "metadata": { + "editable": true + }, "source": [ "## Momentum based GD\n", "\n", @@ -789,8 +787,10 @@ }, { "cell_type": "markdown", - "id": "0c094b0b", - "metadata": {}, + "id": "3cd079d0", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\mathbf{v}_{t}=\\gamma \\mathbf{v}_{t-1}+\\eta_{t}\\nabla_\\theta E(\\boldsymbol{\\theta}_t) \\nonumber\n", @@ -799,8 +799,10 @@ }, { "cell_type": "markdown", - "id": "750579fd", - "metadata": {}, + "id": "305a75c3", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -815,8 +817,10 @@ }, { "cell_type": "markdown", - "id": "1d55fdab", - "metadata": {}, + "id": "026d8598", + "metadata": { + "editable": true + }, "source": [ "where we have introduced a momentum parameter $\\gamma$, with\n", "$0\\le\\gamma\\le 1$, and for brevity we dropped the explicit notation to\n", @@ -832,8 +836,10 @@ }, { "cell_type": "markdown", - "id": "c78ccbf6", - "metadata": {}, + "id": "80e73593", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\Delta \\boldsymbol{\\theta}_{t+1} = \\gamma \\Delta \\boldsymbol{\\theta}_t -\\ \\eta_{t}\\nabla_\\theta E(\\boldsymbol{\\theta}_t),\n", @@ -842,16 +848,20 @@ }, { "cell_type": "markdown", - "id": "73bf75c1", - "metadata": {}, + "id": "4a5b87d4", + "metadata": { + "editable": true + }, "source": [ "where we have defined $\\Delta \\boldsymbol{\\theta}_{t}= \\boldsymbol{\\theta}_t-\\boldsymbol{\\theta}_{t-1}$." ] }, { "cell_type": "markdown", - "id": "24406ec7", - "metadata": {}, + "id": "f9bbf0cd", + "metadata": { + "editable": true + }, "source": [ "## More on momentum based approaches\n", "\n", @@ -864,8 +874,10 @@ }, { "cell_type": "markdown", - "id": "ff0a7cdb", - "metadata": {}, + "id": "9e7986cc", + "metadata": { + "editable": true + }, "source": [ "$$\n", "m {d^2 \\mathbf{w} \\over dt^2} + \\mu {d \\mathbf{w} \\over dt }= -\\nabla_w E(\\mathbf{w}).\n", @@ -874,16 +886,20 @@ }, { "cell_type": "markdown", - "id": "5881f048", - "metadata": {}, + "id": "50d69000", + "metadata": { + "editable": true + }, "source": [ "We can discretize this equation in the usual way to get" ] }, { "cell_type": "markdown", - "id": "ceb5d976", - "metadata": {}, + "id": "e7d9df0a", + "metadata": { + "editable": true + }, "source": [ "$$\n", "m { \\mathbf{w}_{t+\\Delta t}-2 \\mathbf{w}_{t} +\\mathbf{w}_{t-\\Delta t} \\over (\\Delta t)^2}+\\mu {\\mathbf{w}_{t+\\Delta t}- \\mathbf{w}_{t} \\over \\Delta t} = -\\nabla_w E(\\mathbf{w}).\n", @@ -892,16 +908,20 @@ }, { "cell_type": "markdown", - "id": "4e997304", - "metadata": {}, + "id": "e6f67ad8", + "metadata": { + "editable": true + }, "source": [ "Rearranging this equation, we can rewrite this as" ] }, { "cell_type": "markdown", - "id": "db031583", - "metadata": {}, + "id": "443f0b02", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\Delta \\mathbf{w}_{t +\\Delta t}= - { (\\Delta t)^2 \\over m +\\mu \\Delta t} \\nabla_w E(\\mathbf{w})+ {m \\over m +\\mu \\Delta t} \\Delta \\mathbf{w}_t.\n", @@ -910,8 +930,10 @@ }, { "cell_type": "markdown", - "id": "cf54750e", - "metadata": {}, + "id": "d89ab74d", + "metadata": { + "editable": true + }, "source": [ "## Momentum parameter\n", "\n", @@ -924,8 +946,10 @@ }, { "cell_type": "markdown", - "id": "6424326d", - "metadata": {}, + "id": "3401047f", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\gamma= {m \\over m +\\mu \\Delta t }, \\qquad \\eta = {(\\Delta t)^2 \\over m +\\mu \\Delta t}.\n", @@ -934,8 +958,10 @@ }, { "cell_type": "markdown", - "id": "4c52261d", - "metadata": {}, + "id": "c7c24040", + "metadata": { + "editable": true + }, "source": [ "Thus, as the name suggests, the momentum parameter is proportional to\n", "the mass of the particle and effectively provides inertia.\n", @@ -965,8 +991,10 @@ }, { "cell_type": "markdown", - "id": "e6351f61", - "metadata": {}, + "id": "22e04f6c", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\mathbf{v}_{t}=\\gamma \\mathbf{v}_{t-1}+\\eta_{t}\\nabla_\\theta E(\\boldsymbol{\\theta}_t +\\gamma \\mathbf{v}_{t-1}) \\nonumber\n", @@ -975,8 +1003,10 @@ }, { "cell_type": "markdown", - "id": "c0feb3d3", - "metadata": {}, + "id": "65b1fa09", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -991,16 +1021,20 @@ }, { "cell_type": "markdown", - "id": "932dfc89", - "metadata": {}, + "id": "7acccb8b", + "metadata": { + "editable": true + }, "source": [ "One of the major advantages of NAG is that it allows for the use of a larger learning rate than GDM for the same choice of $\\gamma$." ] }, { "cell_type": "markdown", - "id": "d403c5d0", - "metadata": {}, + "id": "795e6ab5", + "metadata": { + "editable": true + }, "source": [ "## Second moment of the gradient\n", "\n", @@ -1028,8 +1062,10 @@ }, { "cell_type": "markdown", - "id": "3ecb97e6", - "metadata": {}, + "id": "dec5061d", + "metadata": { + "editable": true + }, "source": [ "## RMS prop\n", "\n", @@ -1041,8 +1077,10 @@ }, { "cell_type": "markdown", - "id": "fabedf61", - "metadata": {}, + "id": "3dfb0934", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -1057,8 +1095,10 @@ }, { "cell_type": "markdown", - "id": "e0a1b163", - "metadata": {}, + "id": "bf4b7a89", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\mathbf{s}_t =\\beta \\mathbf{s}_{t-1} +(1-\\beta)\\mathbf{g}_t^2 \\nonumber\n", @@ -1067,8 +1107,10 @@ }, { "cell_type": "markdown", - "id": "60639b97", - "metadata": {}, + "id": "510c8591", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\boldsymbol{\\theta}_{t+1}=\\boldsymbol{\\theta}_t - \\eta_t { \\mathbf{g}_t \\over \\sqrt{\\mathbf{s}_t +\\epsilon}}, \\nonumber\n", @@ -1077,8 +1119,10 @@ }, { "cell_type": "markdown", - "id": "f3af4ae4", - "metadata": {}, + "id": "1a0e569f", + "metadata": { + "editable": true + }, "source": [ "where $\\beta$ controls the averaging time of the second moment and is\n", "typically taken to be about $\\beta=0.9$, $\\eta_t$ is a learning rate\n", @@ -1093,8 +1137,10 @@ }, { "cell_type": "markdown", - "id": "936f4678", - "metadata": {}, + "id": "977c9c79", + "metadata": { + "editable": true + }, "source": [ "## [ADAM optimizer](https://arxiv.org/abs/1412.6980)\n", "\n", @@ -1120,8 +1166,10 @@ }, { "cell_type": "markdown", - "id": "9614f73b", - "metadata": {}, + "id": "d188330b", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -1136,8 +1184,10 @@ }, { "cell_type": "markdown", - "id": "2440882c", - "metadata": {}, + "id": "776b649a", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\mathbf{m}_t = \\beta_1 \\mathbf{m}_{t-1} + (1-\\beta_1) \\mathbf{g}_t \\nonumber\n", @@ -1146,8 +1196,10 @@ }, { "cell_type": "markdown", - "id": "a585a1e4", - "metadata": {}, + "id": "6f8a0d72", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\mathbf{s}_t =\\beta_2 \\mathbf{s}_{t-1} +(1-\\beta_2)\\mathbf{g}_t^2 \\nonumber\n", @@ -1156,8 +1208,10 @@ }, { "cell_type": "markdown", - "id": "c6a8e863", - "metadata": {}, + "id": "53f1a2ce", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\boldsymbol{\\mathbf{m}}_t={\\mathbf{m}_t \\over 1-\\beta_1^t} \\nonumber\n", @@ -1166,8 +1220,10 @@ }, { "cell_type": "markdown", - "id": "1978dbb2", - "metadata": {}, + "id": "cc7cd55a", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\boldsymbol{\\mathbf{s}}_t ={\\mathbf{s}_t \\over1-\\beta_2^t} \\nonumber\n", @@ -1176,8 +1232,10 @@ }, { "cell_type": "markdown", - "id": "0b153be5", - "metadata": {}, + "id": "6bd6e651", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\boldsymbol{\\theta}_{t+1}=\\boldsymbol{\\theta}_t - \\eta_t { \\boldsymbol{\\mathbf{m}}_t \\over \\sqrt{\\boldsymbol{\\mathbf{s}}_t} +\\epsilon}, \\nonumber\n", @@ -1186,8 +1244,10 @@ }, { "cell_type": "markdown", - "id": "2659e6e6", - "metadata": {}, + "id": "677f1aef", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -1201,8 +1261,10 @@ }, { "cell_type": "markdown", - "id": "fe39f4bd", - "metadata": {}, + "id": "4bb1d86d", + "metadata": { + "editable": true + }, "source": [ "where $\\beta_1$ and $\\beta_2$ set the memory lifetime of the first and\n", "second moment and are typically taken to be $0.9$ and $0.99$\n", @@ -1218,8 +1280,10 @@ }, { "cell_type": "markdown", - "id": "45c3b53e", - "metadata": {}, + "id": "812cca90", + "metadata": { + "editable": true + }, "source": [ "$$\n", "\\Delta \\theta_{t+1}= -\\eta_t { \\boldsymbol{m}_t \\over \\sqrt{\\sigma_t^2 + m_t^2 }+\\epsilon}.\n", @@ -1228,8 +1292,10 @@ }, { "cell_type": "markdown", - "id": "0e1d1ab6", - "metadata": {}, + "id": "51ddf251", + "metadata": { + "editable": true + }, "source": [ "## Algorithms and codes for Adagrad, RMSprop and Adam\n", "\n", @@ -1240,8 +1306,10 @@ }, { "cell_type": "markdown", - "id": "650e1cd6", - "metadata": {}, + "id": "676bc1af", + "metadata": { + "editable": true + }, "source": [ "## AdaGrad algorithm, taken from [Goodfellow et al](https://www.deeplearningbook.org/contents/optimization.html)\n", "\n", @@ -1254,8 +1322,10 @@ }, { "cell_type": "markdown", - "id": "36fcf928", - "metadata": {}, + "id": "5e0a4bd5", + "metadata": { + "editable": true + }, "source": [ "## RMSProp algorithm, taken from [Goodfellow et al](https://www.deeplearningbook.org/contents/optimization.html)\n", "\n", @@ -1268,8 +1338,10 @@ }, { "cell_type": "markdown", - "id": "f68ae4d9", - "metadata": {}, + "id": "d9eccc07", + "metadata": { + "editable": true + }, "source": [ "## ADAM algorithm, taken from [Goodfellow et al](https://www.deeplearningbook.org/contents/optimization.html)\n", "\n", @@ -1282,8 +1354,10 @@ }, { "cell_type": "markdown", - "id": "8eb914ed", - "metadata": {}, + "id": "b81a38cf", + "metadata": { + "editable": true + }, "source": [ "## Practical tips\n", "\n", @@ -1300,8 +1374,10 @@ }, { "cell_type": "markdown", - "id": "5e2981dc", - "metadata": {}, + "id": "2be4b8ad", + "metadata": { + "editable": true + }, "source": [ "## Automatic differentiation\n", "\n", @@ -1336,8 +1412,10 @@ }, { "cell_type": "markdown", - "id": "b81eabd7", - "metadata": {}, + "id": "78ce59cc", + "metadata": { + "editable": true + }, "source": [ "$$\n", "f(x) = \\sin\\left(2\\pi x + x^2\\right)\n", @@ -1346,16 +1424,20 @@ }, { "cell_type": "markdown", - "id": "664845f7", - "metadata": {}, + "id": "a1de3aaf", + "metadata": { + "editable": true + }, "source": [ "which has the following derivative" ] }, { "cell_type": "markdown", - "id": "a2a77f69", - "metadata": {}, + "id": "99aa41ec", + "metadata": { + "editable": true + }, "source": [ "$$\n", "f'(x) = \\cos\\left(2\\pi x + x^2\\right)\\left(2\\pi + 2x\\right)\n", @@ -1364,8 +1446,10 @@ }, { "cell_type": "markdown", - "id": "34f3786a", - "metadata": {}, + "id": "76989f22", + "metadata": { + "editable": true + }, "source": [ "Using **autograd** we have" ] @@ -1373,8 +1457,11 @@ { "cell_type": "code", "execution_count": 7, - "id": "6f76195d", - "metadata": {}, + "id": "b9cd37f2", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "import autograd.numpy as np\n", @@ -1415,8 +1502,10 @@ }, { "cell_type": "markdown", - "id": "d2d23a0d", - "metadata": {}, + "id": "7f495197", + "metadata": { + "editable": true + }, "source": [ "## Using autograd\n", "\n", @@ -1430,8 +1519,11 @@ { "cell_type": "code", "execution_count": 8, - "id": "c51dc30f", - "metadata": {}, + "id": "3e79535c", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "import autograd.numpy as np\n", @@ -1455,8 +1547,10 @@ }, { "cell_type": "markdown", - "id": "c0b62f5e", - "metadata": {}, + "id": "9d764d7c", + "metadata": { + "editable": true + }, "source": [ "## Autograd with more complicated functions\n", "\n", @@ -1468,8 +1562,11 @@ { "cell_type": "code", "execution_count": 9, - "id": "52904dfe", - "metadata": {}, + "id": "b171c0bc", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "import autograd.numpy as np\n", @@ -1509,16 +1606,20 @@ }, { "cell_type": "markdown", - "id": "86e0ebe1", - "metadata": {}, + "id": "65098808", + "metadata": { + "editable": true + }, "source": [ "Note that the grad function will not produce the true gradient of the function. The true gradient of a function with two or more variables will produce a vector, where each element is the function differentiated w.r.t a variable." ] }, { "cell_type": "markdown", - "id": "634ceac6", - "metadata": {}, + "id": "5d60df18", + "metadata": { + "editable": true + }, "source": [ "## More complicated functions using the elements of their arguments directly" ] @@ -1526,8 +1627,11 @@ { "cell_type": "code", "execution_count": 10, - "id": "2bea8a29", - "metadata": {}, + "id": "cc4cc7eb", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "import autograd.numpy as np\n", @@ -1551,8 +1655,10 @@ }, { "cell_type": "markdown", - "id": "6275cbc4", - "metadata": {}, + "id": "d71a9a54", + "metadata": { + "editable": true + }, "source": [ "Note that in this case, when sending an array as input argument, the\n", "output from Autograd is another array. This is the true gradient of\n", @@ -1564,8 +1670,10 @@ }, { "cell_type": "markdown", - "id": "0068cd3c", - "metadata": {}, + "id": "290988a2", + "metadata": { + "editable": true + }, "source": [ "## Functions using mathematical functions from Numpy" ] @@ -1573,8 +1681,11 @@ { "cell_type": "code", "execution_count": 11, - "id": "efa2537a", - "metadata": {}, + "id": "4afa9fe3", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "import autograd.numpy as np\n", @@ -1598,8 +1709,10 @@ }, { "cell_type": "markdown", - "id": "0e26d1c9", - "metadata": {}, + "id": "ec23dce0", + "metadata": { + "editable": true + }, "source": [ "## More autograd" ] @@ -1607,8 +1720,11 @@ { "cell_type": "code", "execution_count": 12, - "id": "a5630d31", - "metadata": {}, + "id": "be794060", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "import autograd.numpy as np\n", @@ -1629,8 +1745,10 @@ }, { "cell_type": "markdown", - "id": "b110f814", - "metadata": {}, + "id": "1d8e15c2", + "metadata": { + "editable": true + }, "source": [ "## And with loops" ] @@ -1638,8 +1756,11 @@ { "cell_type": "code", "execution_count": 13, - "id": "a6ebc226", - "metadata": {}, + "id": "d696c96c", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "import autograd.numpy as np\n", @@ -1671,8 +1792,11 @@ { "cell_type": "code", "execution_count": 14, - "id": "c38d8cd5", - "metadata": {}, + "id": "5cdbff7d", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "import autograd.numpy as np\n", @@ -1688,8 +1812,10 @@ }, { "cell_type": "markdown", - "id": "a85b9833", - "metadata": {}, + "id": "ec95c41c", + "metadata": { + "editable": true + }, "source": [ "## Using recursion" ] @@ -1697,8 +1823,11 @@ { "cell_type": "code", "execution_count": 15, - "id": "cc00d05b", - "metadata": {}, + "id": "06c8423e", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "import autograd.numpy as np\n", @@ -1732,16 +1861,20 @@ }, { "cell_type": "markdown", - "id": "2b8de443", - "metadata": {}, + "id": "4675445a", + "metadata": { + "editable": true + }, "source": [ "Note that if n is equal to zero or one, Autograd will give an error message. This message appears when the output is independent on input." ] }, { "cell_type": "markdown", - "id": "7cd545c2", - "metadata": {}, + "id": "3ea2267f", + "metadata": { + "editable": true + }, "source": [ "## Using Autograd with OLS\n", "\n", @@ -1753,8 +1886,11 @@ { "cell_type": "code", "execution_count": 16, - "id": "4bd975ee", - "metadata": {}, + "id": "49c5a124", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "# Using Autograd to calculate gradients for OLS\n", @@ -1810,8 +1946,10 @@ }, { "cell_type": "markdown", - "id": "f442d7c8", - "metadata": {}, + "id": "f952160a", + "metadata": { + "editable": true + }, "source": [ "## Same code but now with momentum gradient descent" ] @@ -1819,8 +1957,11 @@ { "cell_type": "code", "execution_count": 17, - "id": "26b37007", - "metadata": {}, + "id": "b0595e43", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "# Using Autograd to calculate gradients for OLS\n", @@ -1880,8 +2021,10 @@ }, { "cell_type": "markdown", - "id": "acb26c62", - "metadata": {}, + "id": "43200e36", + "metadata": { + "editable": true + }, "source": [ "## Including Stochastic Gradient Descent with Autograd\n", "In this code we include the stochastic gradient descent approach discussed above. Note here that we specify which argument we are taking the derivative with respect to when using **autograd**." @@ -1890,8 +2033,11 @@ { "cell_type": "code", "execution_count": 18, - "id": "9d6704a9", - "metadata": {}, + "id": "b369d846", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "# Using Autograd to calculate gradients using SGD\n", @@ -1971,8 +2117,10 @@ }, { "cell_type": "markdown", - "id": "dd2d9f35", - "metadata": {}, + "id": "1caa8279", + "metadata": { + "editable": true + }, "source": [ "## Same code but now with momentum gradient descent" ] @@ -1980,8 +2128,11 @@ { "cell_type": "code", "execution_count": 19, - "id": "85731b81", - "metadata": {}, + "id": "a9695688", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "# Using Autograd to calculate gradients using SGD\n", @@ -2055,8 +2206,10 @@ }, { "cell_type": "markdown", - "id": "99fcedcf", - "metadata": {}, + "id": "7e8ab93f", + "metadata": { + "editable": true + }, "source": [ "## Similar (second order function now) problem but now with AdaGrad" ] @@ -2064,8 +2217,11 @@ { "cell_type": "code", "execution_count": 20, - "id": "1bbef9b5", - "metadata": {}, + "id": "be9894c6", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "# Using Autograd to calculate gradients using AdaGrad and Stochastic Gradient descent\n", @@ -2120,16 +2276,20 @@ }, { "cell_type": "markdown", - "id": "6f14b9e9", - "metadata": {}, + "id": "f9c181ef", + "metadata": { + "editable": true + }, "source": [ "Running this code we note an almost perfect agreement with the results from matrix inversion." ] }, { "cell_type": "markdown", - "id": "420764bb", - "metadata": {}, + "id": "3f40101d", + "metadata": { + "editable": true + }, "source": [ "## RMSprop for adaptive learning rate with Stochastic Gradient Descent" ] @@ -2137,8 +2297,11 @@ { "cell_type": "code", "execution_count": 21, - "id": "1ea8deac", - "metadata": {}, + "id": "da9f2895", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "# Using Autograd to calculate gradients using RMSprop and Stochastic Gradient descent\n", @@ -2199,8 +2362,10 @@ }, { "cell_type": "markdown", - "id": "7476e8fa", - "metadata": {}, + "id": "2075df0a", + "metadata": { + "editable": true + }, "source": [ "## And finally [ADAM](https://arxiv.org/pdf/1412.6980.pdf)" ] @@ -2208,8 +2373,11 @@ { "cell_type": "code", "execution_count": 22, - "id": "dd54ee0d", - "metadata": {}, + "id": "b9e0fd59", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "# Using Autograd to calculate gradients using RMSprop and Stochastic Gradient descent\n", @@ -2275,8 +2443,10 @@ }, { "cell_type": "markdown", - "id": "8bff90bf", - "metadata": {}, + "id": "3186664b", + "metadata": { + "editable": true + }, "source": [ "## And Logistic Regression" ] @@ -2284,8 +2454,11 @@ { "cell_type": "code", "execution_count": 23, - "id": "4d6f38aa", - "metadata": {}, + "id": "c4119a68", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "import autograd.numpy as np\n", @@ -2325,8 +2498,10 @@ }, { "cell_type": "markdown", - "id": "be009d46", - "metadata": {}, + "id": "55e182eb", + "metadata": { + "editable": true + }, "source": [ "## Introducing [JAX](https://jax.readthedocs.io/en/latest/)\n", "\n", @@ -2339,8 +2514,10 @@ }, { "cell_type": "markdown", - "id": "8c42305d", - "metadata": {}, + "id": "ae059fd0", + "metadata": { + "editable": true + }, "source": [ "### Getting started with Jax, note the way we import numpy" ] @@ -2348,8 +2525,11 @@ { "cell_type": "code", "execution_count": 24, - "id": "ee92fe44", - "metadata": {}, + "id": "1ad5b0d3", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "import jax\n", @@ -2362,8 +2542,10 @@ }, { "cell_type": "markdown", - "id": "7b2c5c5d", - "metadata": {}, + "id": "bc8fd16c", + "metadata": { + "editable": true + }, "source": [ "### A warm-up example" ] @@ -2371,8 +2553,11 @@ { "cell_type": "code", "execution_count": 25, - "id": "a9f25005", - "metadata": {}, + "id": "443386ca", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "def function(x):\n", @@ -2413,8 +2598,10 @@ }, { "cell_type": "markdown", - "id": "6734e909", - "metadata": {}, + "id": "b313e4d6", + "metadata": { + "editable": true + }, "source": [ "### A more advanced example" ] @@ -2422,8 +2609,11 @@ { "cell_type": "code", "execution_count": 26, - "id": "cc5b54ed", - "metadata": {}, + "id": "7ff7b64d", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "backend = np\n", @@ -2450,8 +2640,10 @@ }, { "cell_type": "markdown", - "id": "d0ff0a0e", - "metadata": {}, + "id": "b913d744", + "metadata": { + "editable": true + }, "source": [ "## Introduction to Neural networks\n", "\n", @@ -2466,8 +2658,10 @@ }, { "cell_type": "markdown", - "id": "624b7343", - "metadata": {}, + "id": "04b70882", + "metadata": { + "editable": true + }, "source": [ "## Artificial neurons\n", "\n", @@ -2488,8 +2682,10 @@ }, { "cell_type": "markdown", - "id": "b6ab860b", - "metadata": {}, + "id": "44405ff2", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -2504,8 +2700,10 @@ }, { "cell_type": "markdown", - "id": "fdab69ac", - "metadata": {}, + "id": "b39653f7", + "metadata": { + "editable": true + }, "source": [ "Here, the output $y$ of the neuron is the value of its activation function, which have as input\n", "a weighted sum of signals $x_i, \\dots ,x_n$ received by $n$ other neurons.\n", @@ -2542,8 +2740,10 @@ }, { "cell_type": "markdown", - "id": "6466c987", - "metadata": {}, + "id": "4db5fb89", + "metadata": { + "editable": true + }, "source": [ "## Neural network types\n", "\n", @@ -2569,8 +2769,10 @@ }, { "cell_type": "markdown", - "id": "8a9c8edb", - "metadata": {}, + "id": "400c590f", + "metadata": { + "editable": true + }, "source": [ "## Feed-forward neural networks\n", "\n", @@ -2588,8 +2790,10 @@ }, { "cell_type": "markdown", - "id": "ca6a908c", - "metadata": {}, + "id": "1536d443", + "metadata": { + "editable": true + }, "source": [ "## Convolutional Neural Network\n", "\n", @@ -2615,8 +2819,10 @@ }, { "cell_type": "markdown", - "id": "7f1f4f38", - "metadata": {}, + "id": "0ce4aacc", + "metadata": { + "editable": true + }, "source": [ "## Recurrent neural networks\n", "\n", @@ -2634,8 +2840,10 @@ }, { "cell_type": "markdown", - "id": "ced07fa5", - "metadata": {}, + "id": "c187a3e9", + "metadata": { + "editable": true + }, "source": [ "## Other types of networks\n", "\n", @@ -2653,8 +2861,10 @@ }, { "cell_type": "markdown", - "id": "5421341a", - "metadata": {}, + "id": "7a5d9c4f", + "metadata": { + "editable": true + }, "source": [ "## Multilayer perceptrons\n", "\n", @@ -2668,8 +2878,10 @@ }, { "cell_type": "markdown", - "id": "e5ae78f7", - "metadata": {}, + "id": "2abe1a3e", + "metadata": { + "editable": true + }, "source": [ "## Why multilayer perceptrons?\n", "\n", @@ -2687,8 +2899,10 @@ }, { "cell_type": "markdown", - "id": "40adefcc", - "metadata": {}, + "id": "187cb30d", + "metadata": { + "editable": true + }, "source": [ "## Illustration of a single perceptron model and a multi-perceptron model\n", "\n", @@ -2701,8 +2915,10 @@ }, { "cell_type": "markdown", - "id": "31608ee5", - "metadata": {}, + "id": "6269f804", + "metadata": { + "editable": true + }, "source": [ "## Examples of XOR, OR and AND gates\n", "\n", @@ -2716,8 +2932,11 @@ { "cell_type": "code", "execution_count": 27, - "id": "0529c3e9", - "metadata": {}, + "id": "1ad6269c", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "\"\"\"\n", @@ -2754,16 +2973,20 @@ }, { "cell_type": "markdown", - "id": "844f16f8", - "metadata": {}, + "id": "a4ac557d", + "metadata": { + "editable": true + }, "source": [ "What is happening here?" ] }, { "cell_type": "markdown", - "id": "750cf959", - "metadata": {}, + "id": "6c5b5b78", + "metadata": { + "editable": true + }, "source": [ "## Does Logistic Regression do a better Job?" ] @@ -2771,8 +2994,11 @@ { "cell_type": "code", "execution_count": 28, - "id": "68870b7b", - "metadata": {}, + "id": "78d9fe1b", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "\"\"\"\n", @@ -2828,16 +3054,20 @@ }, { "cell_type": "markdown", - "id": "78424809", - "metadata": {}, + "id": "522ea0b9", + "metadata": { + "editable": true + }, "source": [ "Not exactly impressive, but somewhat better." ] }, { "cell_type": "markdown", - "id": "51a551b4", - "metadata": {}, + "id": "633277bf", + "metadata": { + "editable": true + }, "source": [ "## Adding Neural Networks" ] @@ -2845,8 +3075,11 @@ { "cell_type": "code", "execution_count": 29, - "id": "390527c4", - "metadata": {}, + "id": "55106a0e", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "\n", @@ -2862,8 +3095,10 @@ }, { "cell_type": "markdown", - "id": "3fc8196f", - "metadata": {}, + "id": "6933a546", + "metadata": { + "editable": true + }, "source": [ "## Mathematical model\n", "\n", @@ -2872,8 +3107,10 @@ }, { "cell_type": "markdown", - "id": "f75b24d9", - "metadata": {}, + "id": "a392cc52", + "metadata": { + "editable": true + }, "source": [ "$$\n", "y = f\\left(\\sum_{i=1}^n w_ix_i + b_i\\right) = f(z),\n", @@ -2882,8 +3119,10 @@ }, { "cell_type": "markdown", - "id": "3a468c58", - "metadata": {}, + "id": "bc1e3563", + "metadata": { + "editable": true + }, "source": [ "This function receives $x_i$ as inputs.\n", "Here the activation $z=(\\sum_{i=1}^n w_ix_i+b_i)$. \n", @@ -2895,8 +3134,10 @@ }, { "cell_type": "markdown", - "id": "bf8973da", - "metadata": {}, + "id": "947e6060", + "metadata": { + "editable": true + }, "source": [ "## Mathematical model\n", "\n", @@ -2905,8 +3146,10 @@ }, { "cell_type": "markdown", - "id": "5e0da5ad", - "metadata": {}, + "id": "190e7764", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -2920,8 +3163,10 @@ }, { "cell_type": "markdown", - "id": "64d27300", - "metadata": {}, + "id": "9d4df41f", + "metadata": { + "editable": true + }, "source": [ "Here $b_i$ is the so-called bias which is normally needed in\n", "case of zero activation weights or inputs. How to fix the biases and\n", @@ -2933,8 +3178,10 @@ }, { "cell_type": "markdown", - "id": "9e29b76e", - "metadata": {}, + "id": "e8c69c2e", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -2949,8 +3196,10 @@ }, { "cell_type": "markdown", - "id": "b1da5364", - "metadata": {}, + "id": "80a632b1", + "metadata": { + "editable": true + }, "source": [ "where we assume that all nodes in the same layer have identical\n", "activation functions, hence the notation $f$. In general, we could assume in the more general case that different layers have different activation functions.\n", @@ -2959,8 +3208,10 @@ }, { "cell_type": "markdown", - "id": "6ed696f9", - "metadata": {}, + "id": "20de39bb", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -2975,8 +3226,10 @@ }, { "cell_type": "markdown", - "id": "a4148a64", - "metadata": {}, + "id": "01031b37", + "metadata": { + "editable": true + }, "source": [ "where $N_l$ is the number of nodes in layer $l$. When the output of\n", "all the nodes in the first hidden layer are computed, the values of\n", @@ -2986,8 +3239,10 @@ }, { "cell_type": "markdown", - "id": "da587faa", - "metadata": {}, + "id": "9560b5e1", + "metadata": { + "editable": true + }, "source": [ "## Mathematical model\n", "\n", @@ -2996,8 +3251,10 @@ }, { "cell_type": "markdown", - "id": "73eefe7b", - "metadata": {}, + "id": "baaac514", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -3012,8 +3269,10 @@ }, { "cell_type": "markdown", - "id": "9c00114f", - "metadata": {}, + "id": "f2a439d9", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -3028,16 +3287,20 @@ }, { "cell_type": "markdown", - "id": "5e51f9a8", - "metadata": {}, + "id": "9ba7b5ad", + "metadata": { + "editable": true + }, "source": [ "where we have substituted $y_k^1$ with the inputs $x_k$. Finally, the ANN output reads" ] }, { "cell_type": "markdown", - "id": "f0e1bc9b", - "metadata": {}, + "id": "bed342fd", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -3052,8 +3315,10 @@ }, { "cell_type": "markdown", - "id": "992a154d", - "metadata": {}, + "id": "d1beb8c9", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -3069,8 +3334,10 @@ }, { "cell_type": "markdown", - "id": "1ce03e37", - "metadata": {}, + "id": "a71895ad", + "metadata": { + "editable": true + }, "source": [ "## Mathematical model\n", "\n", @@ -3080,8 +3347,10 @@ }, { "cell_type": "markdown", - "id": "1d14ed5f", - "metadata": {}, + "id": "d9bd25ff", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -3096,8 +3365,10 @@ }, { "cell_type": "markdown", - "id": "5d4af831", - "metadata": {}, + "id": "e7737a5b", + "metadata": { + "editable": true + }, "source": [ "which illustrates a basic property of MLPs: The only independent\n", "variables are the input values $x_n$." @@ -3105,8 +3376,10 @@ }, { "cell_type": "markdown", - "id": "833c2044", - "metadata": {}, + "id": "384040ce", + "metadata": { + "editable": true + }, "source": [ "## Mathematical model\n", "\n", @@ -3122,8 +3395,10 @@ }, { "cell_type": "markdown", - "id": "1919c37b", - "metadata": {}, + "id": "4a27ed92", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -3138,8 +3413,10 @@ }, { "cell_type": "markdown", - "id": "034185ce", - "metadata": {}, + "id": "c71650e0", + "metadata": { + "editable": true + }, "source": [ "where the parameters $c_i$ are weights and biases. By adjusting these\n", "parameters, the activation functions can be shifted up and down or\n", @@ -3149,8 +3426,10 @@ }, { "cell_type": "markdown", - "id": "36e298b2", - "metadata": {}, + "id": "b6291c8a", + "metadata": { + "editable": true + }, "source": [ "### Matrix-vector notation\n", "\n", @@ -3167,8 +3446,10 @@ }, { "cell_type": "markdown", - "id": "b8f05873", - "metadata": {}, + "id": "da4b43f7", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -3198,8 +3479,10 @@ }, { "cell_type": "markdown", - "id": "e7a6e970", - "metadata": {}, + "id": "7fe1f511", + "metadata": { + "editable": true + }, "source": [ "### Matrix-vector notation and activation\n", "\n", @@ -3208,8 +3491,10 @@ }, { "cell_type": "markdown", - "id": "543db865", - "metadata": {}, + "id": "d53241ba", + "metadata": { + "editable": true + }, "source": [ "\n", "
\n", @@ -3225,8 +3510,10 @@ }, { "cell_type": "markdown", - "id": "59d15e0e", - "metadata": {}, + "id": "962e06e9", + "metadata": { + "editable": true + }, "source": [ "This is not just a convenient and compact notation, but also a useful\n", "and intuitive way to think about MLPs: The output is calculated by a\n", @@ -3237,8 +3524,10 @@ }, { "cell_type": "markdown", - "id": "ccf5313b", - "metadata": {}, + "id": "6446fdc6", + "metadata": { + "editable": true + }, "source": [ "### Activation functions\n", "\n", @@ -3258,8 +3547,10 @@ }, { "cell_type": "markdown", - "id": "4123228a", - "metadata": {}, + "id": "69aff123", + "metadata": { + "editable": true + }, "source": [ "### Activation functions, Logistic and Hyperbolic ones\n", "\n", @@ -3275,8 +3566,10 @@ }, { "cell_type": "markdown", - "id": "a388e95b", - "metadata": {}, + "id": "dbb74732", + "metadata": { + "editable": true + }, "source": [ "$$\n", "f(x) = \\frac{1}{1 + e^{-x}},\n", @@ -3285,16 +3578,20 @@ }, { "cell_type": "markdown", - "id": "1b615cdb", - "metadata": {}, + "id": "216973d6", + "metadata": { + "editable": true + }, "source": [ "and the *hyperbolic tangent* function" ] }, { "cell_type": "markdown", - "id": "89752e18", - "metadata": {}, + "id": "a8643aed", + "metadata": { + "editable": true + }, "source": [ "$$\n", "f(x) = \\tanh(x)\n", @@ -3303,8 +3600,10 @@ }, { "cell_type": "markdown", - "id": "b0006d32", - "metadata": {}, + "id": "b6450655", + "metadata": { + "editable": true + }, "source": [ "### Relevance\n", "\n", @@ -3318,8 +3617,11 @@ { "cell_type": "code", "execution_count": 30, - "id": "bcba3ef9", - "metadata": {}, + "id": "0565ead1", + "metadata": { + "collapsed": false, + "editable": true + }, "outputs": [], "source": [ "\"\"\"The sigmoid function (or the logistic curve) is a \n", @@ -3396,25 +3698,7 @@ ] } ], - "metadata": { - "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.9.18" - } - }, + "metadata": {}, "nbformat": 4, "nbformat_minor": 5 }