1513 lines
201 KiB
Plaintext
1513 lines
201 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e3354581",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- HTML file automatically generated from DocOnce source (https://github.com/doconce/doconce/)\n",
|
|
"doconce format html exercisesweek41.do.txt -->\n",
|
|
"<!-- dom:TITLE: Exercises week 41 -->"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "8d5fc499",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"# Exercises week 41\n",
|
|
"**October 9-13, 2023**\n",
|
|
"\n",
|
|
"Date: **Deadline is Sunday October 15 at midnight**"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d3ef3596",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"# Overarching aims of the exercises this week\n",
|
|
"\n",
|
|
"The aim of the exercises this week is to get started with implementing\n",
|
|
"gradient methods of relevance for project 2. This exercise will also\n",
|
|
"be continued next week with the addition of automatic differentation.\n",
|
|
"Everything you develop here will be used in project 2. \n",
|
|
"\n",
|
|
"In order to get started, we will now replace in our standard ordinary\n",
|
|
"least squares (OLS) and Ridge regression codes (from project 1) the\n",
|
|
"matrix inversion algorithm with our own gradient descent (GD) and SGD\n",
|
|
"codes. You can use the Franke function or the terrain data from\n",
|
|
"project 1. **However, we recommend using a simpler function like**\n",
|
|
"$f(x)=a_0+a_1x+a_2x^2$ or higher-order one-dimensional polynomials.\n",
|
|
"You can obviously test your final codes against for example the Franke\n",
|
|
"function. Automatic differentiation will be discussed next week.\n",
|
|
"\n",
|
|
"You should include in your analysis of the GD and SGD codes the following elements\n",
|
|
"1. A plain gradient descent with a fixed learning rate (you will need to tune it) using the analytical expression of the gradients\n",
|
|
"\n",
|
|
"2. Add momentum to the plain GD code and compare convergence with a fixed learning rate (you may need to tune the learning rate), again using the analytical expression of the gradients.\n",
|
|
"\n",
|
|
"3. Repeat these steps for stochastic gradient descent with mini batches and a given number of epochs. Use a tunable learning rate as discussed in the lectures from week 39. Discuss the results as functions of the various parameters (size of batches, number of epochs etc)\n",
|
|
"\n",
|
|
"4. Implement the Adagrad method in order to tune the learning rate. Do this with and without momentum for plain gradient descent and SGD.\n",
|
|
"\n",
|
|
"5. Add RMSprop and Adam to your library of methods for tuning the learning rate.\n",
|
|
"\n",
|
|
"The lecture notes from weeks 39 and 40 contain more information and code examples. Feel free to use these examples.\n",
|
|
"\n",
|
|
"In summary, you should \n",
|
|
"perform an analysis of the results for OLS and Ridge regression as\n",
|
|
"function of the chosen learning rates, the number of mini-batches and\n",
|
|
"epochs as well as algorithm for scaling the learning rate. You can\n",
|
|
"also compare your own results with those that can be obtained using\n",
|
|
"for example **Scikit-Learn**'s various SGD options. Discuss your\n",
|
|
"results. For Ridge regression you need now to study the results as functions of the hyper-parameter $\\lambda$ and \n",
|
|
"the learning rate $\\eta$. Discuss your results.\n",
|
|
"\n",
|
|
"You will need your SGD code for the setup of the Neural Network and\n",
|
|
"Logistic Regression codes. You will find the Python [Seaborn\n",
|
|
"package](https://seaborn.pydata.org/generated/seaborn.heatmap.html)\n",
|
|
"useful when plotting the results as function of the learning rate\n",
|
|
"$\\eta$ and the hyper-parameter $\\lambda$ when you use Ridge\n",
|
|
"regression.\n",
|
|
"\n",
|
|
"We recommend reading chapter 8 on optimization from the textbook of [Goodfellow, Bengio and Courville](https://www.deeplearningbook.org/). This chapter contains many useful insights and discussions on the optimization part of machine learning."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "9940e21b",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"# Code examples from week 39 and 40"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6559d6d2",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Code with a Number of Minibatches which varies, analytical gradient\n",
|
|
"\n",
|
|
"In the code here we vary the number of mini-batches."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "021b66d2",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Own inversion\n",
|
|
"[[4.16422434]\n",
|
|
" [2.90414392]]\n",
|
|
"Eigenvalues of Hessian Matrix:[0.29405153 4.56291744]\n",
|
|
"theta from own gd\n",
|
|
"[[4.16422434]\n",
|
|
" [2.90414392]]\n",
|
|
"theta from own sdg\n",
|
|
"[[4.13747168]\n",
|
|
" [2.89670222]]\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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inbt2pnyhupy33334auvvsI777yD4uJixMTE4PHHH8err77qlPMi8kaSEEK4uxBERERE7sKcISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKqminGGKisrcf78eQQHB1sczp6IiIiURwiBGzduIDo6Gj4+zqu/UUUwdP78ecTFxbm7GEREROSAvLw8xMbGOm3/qgiGgoODARguZpMmTdxcGiIiIrKFTqdDXFyc6TnuLKoIhoxNY02aNGEwRERE5GGcneLCBGoiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNbcHQ9u2bcPo0aMRHR0NSZKwdu1aq9s+/fTTkCQJixcvdln5iIiIyLu5PRgqKirCvffei6VLl9a63dq1a/H9998jOjraRSUjIiIiNfBzdwFSUlKQkpJS6zbnzp3D9OnTsWHDBowcOdJFJSMiIiI1cHvNUF0qKysxceJE/OEPf0DHjh3dXRwiIiLyMm6vGarLm2++CT8/P8ycOdPm95SWlqK0tNT0WqfTOaNoRERE5AUUXTP0448/YsmSJVixYgUkSbL5fQsXLkRISIjpLy4uzomlJCIiIk+m6GBo+/btKCgoQMuWLeHn5wc/Pz+cPn0aL7zwAlq3bm31fXPmzEFhYaHpLy8vz3WFJiIiIo+i6GayiRMn4v777zdbNnz4cEycOBFTpkyx+r6AgAAEBAQ4u3hERETkBdweDN28eRMnTpwwvc7NzcWBAwcQGhqKli1bIiwszGz7Bg0aIDIyEu3bt3d1UYmIiMgLuT0Y2rt3LwYPHmx6PXv2bADApEmTsGLFCjeVioiIiNTC7cHQoEGDIISweftTp045rzBERESkOopOoCYiIiJyNgZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERE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97Zt2zB69GhER0dDkiSsXbu2zvd4w/1t73l7y/1t73l7y/1t73l7y/29cOFC9OjRA8HBwQgPD8fYsWNx9OjROt/ninvc44KhVatWYdasWXj11Vexf/9+JCcnIyUlBWfOnLG4fW5uLjQaDZKTk7F//3788Y9/xMyZM5Genm7aZteuXXjooYcwceJE/PTTT5g4cSImTJiA77//3lWnVSd7z3vbtm0YOnQotFotfvzxRwwePBijR4/G/v37zbZr0qQJLly4YPYXGBjoilOyib3nbXT06FGzc2rXrp1pnTd+3kuWLDE737y8PISGhuLBBx80207pn3dRURHuvfdeLF261KbtveX+tve8veX+tve8jTz9/rb3vL3l/t66dSumTZuG3bt3Y+PGjaioqMCwYcNQVFRk9T0uu8eFh+nZs6d45plnzJZ16NBBvPLKKxa3f+mll0SHDh3Mlj399NOid+/eptcTJkwQI0aMMNtm+PDh4uGHH5ap1PVn73lbkpiYKObPn296vXz5chESEiJXEZ3C3vPOysoSAMS1a9es7lMNn/eaNWuEJEni1KlTpmWe8HlXBUCsWbOm1m285f6uypbztsQT7++qbDlvb7m/q3Lk8/aG+1sIIQoKCgQAsXXrVqvbuOoe96iaobKyMvz4448YNmyY2fJhw4Zh586dFt+za9euGtsPHz4ce/fuRXl5ea3bWNunqzly3tVVVlbixo0bNSa7u3nzJlq1aoXY2FiMGjWqxi9Ld6rPeXfp0gVRUVEYMmQIsrKyzNap4fP+6KOPcP/999cYpV3Jn7cjvOH+loMn3t/14cn3txy85f4uLCwEgFonYXXVPe5RwdDly5eh1+trzFYfERFRY1Z7o/z8fIvbV1RU4PLly7VuY22frubIeVf397//HUVFRZgwYYJpWYcOHbBixQp89dVXWLlyJQIDA9GvXz8cP35c1vI7ypHzjoqKwocffoj09HRkZGSgffv2GDJkCLZt22baxts/7wsXLiAzMxNPPvmk2XKlf96O8Ib7Ww6eeH87whvu7/rylvtbCIHZs2ejf//+SEpKsrqdq+5xj5mOoypJksxeCyFqLKtr++rL7d2nOzhaxpUrV2LevHlYt24dwsPDTct79+6N3r17m17369cPXbt2xXvvvYd3331XvoLXkz3n3b59e7Rv3970uk+fPsjLy8Nbb72FAQMGOLRPd3G0jCtWrEDTpk0xduxYs+We8nnby1vub0d5+v1tD2+6vx3lLff39OnT8fPPP+O7776rc1tX3OMeVTPUvHlz+Pr61oj2CgoKakSFRpGRkRa39/PzQ1hYWK3bWNunqzly3karVq3CE088gS+++AL3339/rdv6+PigR48eivklUZ/zrqp3795m5+TNn7cQAh9//DEmTpwIf3//WrdV2uftCG+4v+vDk+9vuXja/V0f3nJ/z5gxA1999RWysrIQGxtb67auusc9Khjy9/dHt27dsHHjRrPlGzduRN++fS2+p0+fPjW2//bbb9G9e3c0aNCg1m2s7dPVHDlvwPCLcfLkyUhLS8PIkSPrPI4QAgcOHEBUVFS9yywHR8+7uv3795udk7d+3oCht8aJEyfwxBNP1HkcpX3ejvCG+9tRnn5/y8XT7u/68PT7WwiB6dOnIyMjA1u2bEF8fHyd73HZPW5zqrVCfP7556JBgwbio48+EocOHRKzZs0SjRo1MmXVv/LKK2LixImm7X/99VcRFBQknn/+eXHo0CHx0UcfiQYNGojVq1ebttmxY4fw9fUVf/3rX8Xhw4fFX//6V+Hn5yd2797t8vOzxt7zTktLE35+fuL9998XFy5cMP1dv37dtM28efPE+vXrxcmTJ8X+/fvFlClThJ+fn/j+++9dfn7W2Hve77zzjlizZo04duyYOHjwoHjllVcEAJGenm7axhs/b6PHHntM9OrVy+I+PeHzvnHjhti/f7/Yv3+/ACDefvttsX//fnH69GkhhPfe3/aet7fc3/aet7fc3/aet5Gn39/PPvusCAkJEdnZ2Wbf2+LiYtM27rrHPS4YEkKI999/X7Rq1Ur4+/uLrl27mnXLmzRpkhg4cKDZ9tnZ2aJLly7C399ftG7dWvzjH/+osc8vv/xStG/fXjRo0EB06NDB7OZSCnvOe+DAgQJAjb9JkyaZtpk1a5Zo2bKl8Pf3Fy1atBDDhg0TO3fudOEZ2cae837zzTdF27ZtRWBgoGjWrJno37+/+Oabb2rs09s+byGEuH79umjYsKH48MMPLe7PEz5vY9dpa99bb72/7T1vb7m/7T1vb7m/Hfmee8P9bemcAYjly5ebtnHXPS7dLiARERGRKnlUzhARERGR3BgMERERkaoxGCIiIiJVYzBEREREqsZgiIiIiFSNwRARERGpGoMhIiIiUjUGQ0RERKRqDIaIiIhI1RgMERERkaoxGCIij7Ry5UoEBgbi3LlzpmVPPvkkOnXqhMLCQjeWjIg8DecmIyKPJIRA586dkZycjKVLl2L+/Pn497//jd27dyMmJsbdxSMiD+Ln7gIQETlCkiQsWLAA48ePR3R0NJYsWYLt27czECIiu7FmiIg8WteuXZGTk4Nvv/0WAwcOdHdxiMgDMWeIiDzWhg0bcOTIEej1ekRERLi7OETkoVgzREQead++fRg0aBDef/99fP755wgKCsKXX37p7mIRkQdizhAReZxTp05h5MiReOWVVzBx4kQkJiaiR48e+PHHH9GtWzd3F4+IPAxrhojIo1y9ehX9+vXDgAED8M9//tO0fMyYMSgtLcX69evdWDoi8kQMhoiIiEjVmEBNREREqsZgiIiIiFSNwRARERGpGoMhIiIiUjUGQ0RERKRqDIaIiIhI1RgMERERkaoxGCIiIiJVYzBEREREqsZgiIiIiFSNwRARERGpGoMhIiIiUrX/B4F06cthMb/4AAAAAElFTkSuQmCC\n",
|
|
"text/plain": [
|
|
"<Figure size 640x480 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {
|
|
"filenames": {
|
|
"image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/exercisesweek41_5_1.png"
|
|
}
|
|
},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"%matplotlib inline\n",
|
|
"\n",
|
|
"# Importing various packages\n",
|
|
"from math import exp, sqrt\n",
|
|
"from random import random, seed\n",
|
|
"import numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"\n",
|
|
"n = 100\n",
|
|
"x = 2*np.random.rand(n,1)\n",
|
|
"y = 4+3*x+np.random.randn(n,1)\n",
|
|
"\n",
|
|
"X = np.c_[np.ones((n,1)), x]\n",
|
|
"XT_X = X.T @ X\n",
|
|
"theta_linreg = np.linalg.inv(X.T @ X) @ (X.T @ y)\n",
|
|
"print(\"Own inversion\")\n",
|
|
"print(theta_linreg)\n",
|
|
"# Hessian matrix\n",
|
|
"H = (2.0/n)* XT_X\n",
|
|
"EigValues, EigVectors = np.linalg.eig(H)\n",
|
|
"print(f\"Eigenvalues of Hessian Matrix:{EigValues}\")\n",
|
|
"\n",
|
|
"theta = np.random.randn(2,1)\n",
|
|
"eta = 1.0/np.max(EigValues)\n",
|
|
"Niterations = 1000\n",
|
|
"\n",
|
|
"\n",
|
|
"for iter in range(Niterations):\n",
|
|
" gradients = 2.0/n*X.T @ ((X @ theta)-y)\n",
|
|
" theta -= eta*gradients\n",
|
|
"print(\"theta from own gd\")\n",
|
|
"print(theta)\n",
|
|
"\n",
|
|
"xnew = np.array([[0],[2]])\n",
|
|
"Xnew = np.c_[np.ones((2,1)), xnew]\n",
|
|
"ypredict = Xnew.dot(theta)\n",
|
|
"ypredict2 = Xnew.dot(theta_linreg)\n",
|
|
"\n",
|
|
"n_epochs = 50\n",
|
|
"M = 5 #size of each minibatch\n",
|
|
"m = int(n/M) #number of minibatches\n",
|
|
"t0, t1 = 5, 50\n",
|
|
"\n",
|
|
"def learning_schedule(t):\n",
|
|
" return t0/(t+t1)\n",
|
|
"\n",
|
|
"theta = np.random.randn(2,1)\n",
|
|
"\n",
|
|
"for epoch in range(n_epochs):\n",
|
|
"# Can you figure out a better way of setting up the contributions to each batch?\n",
|
|
" for i in range(m):\n",
|
|
" random_index = M*np.random.randint(m)\n",
|
|
" xi = X[random_index:random_index+M]\n",
|
|
" yi = y[random_index:random_index+M]\n",
|
|
" gradients = (2.0/M)* xi.T @ ((xi @ theta)-yi)\n",
|
|
" eta = learning_schedule(epoch*m+i)\n",
|
|
" theta = theta - eta*gradients\n",
|
|
"print(\"theta from own sdg\")\n",
|
|
"print(theta)\n",
|
|
"\n",
|
|
"plt.plot(xnew, ypredict, \"r-\")\n",
|
|
"plt.plot(xnew, ypredict2, \"b-\")\n",
|
|
"plt.plot(x, y ,'ro')\n",
|
|
"plt.axis([0,2.0,0, 15.0])\n",
|
|
"plt.xlabel(r'$x$')\n",
|
|
"plt.ylabel(r'$y$')\n",
|
|
"plt.title(r'Random numbers ')\n",
|
|
"plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d8e7110b",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"In the above code, we have use replacement in setting up the\n",
|
|
"mini-batches. The discussion\n",
|
|
"[here](https://sebastianraschka.com/faq/docs/sgd-methods.html) may be\n",
|
|
"useful."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "74a7859a",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Momentum based GD\n",
|
|
"\n",
|
|
"The stochastic gradient descent (SGD) is almost always used with a\n",
|
|
"*momentum* or inertia term that serves as a memory of the direction we\n",
|
|
"are moving in parameter space. This is typically implemented as\n",
|
|
"follows"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "619df8e8",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"$$\n",
|
|
"\\mathbf{v}_{t}=\\gamma \\mathbf{v}_{t-1}+\\eta_{t}\\nabla_\\theta E(\\boldsymbol{\\theta}_t) \\nonumber\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c759cfc4",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"<!-- Equation labels as ordinary links -->\n",
|
|
"<div id=\"_auto1\"></div>\n",
|
|
"\n",
|
|
"$$\n",
|
|
"\\begin{equation} \n",
|
|
"\\boldsymbol{\\theta}_{t+1}= \\boldsymbol{\\theta}_t -\\mathbf{v}_{t},\n",
|
|
"\\label{_auto1} \\tag{1}\n",
|
|
"\\end{equation}\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0a4571f9",
|
|
"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",
|
|
"indicate the gradient is to be taken over a different mini-batch at\n",
|
|
"each step. We call this algorithm gradient descent with momentum\n",
|
|
"(GDM). From these equations, it is clear that $\\mathbf{v}_t$ is a\n",
|
|
"running average of recently encountered gradients and\n",
|
|
"$(1-\\gamma)^{-1}$ sets the characteristic time scale for the memory\n",
|
|
"used in the averaging procedure. Consistent with this, when\n",
|
|
"$\\gamma=0$, this just reduces down to ordinary SGD as discussed\n",
|
|
"earlier. An equivalent way of writing the updates is"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "9bebfdd9",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"$$\n",
|
|
"\\Delta \\boldsymbol{\\theta}_{t+1} = \\gamma \\Delta \\boldsymbol{\\theta}_t -\\ \\eta_{t}\\nabla_\\theta E(\\boldsymbol{\\theta}_t),\n",
|
|
"$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c9e635e8",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"where we have defined $\\Delta \\boldsymbol{\\theta}_{t}= \\boldsymbol{\\theta}_t-\\boldsymbol{\\theta}_{t-1}$."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "eb544f8b",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Algorithms and codes for Adagrad, RMSprop and Adam\n",
|
|
"\n",
|
|
"The algorithms we have implemented are well described in the text by [Goodfellow, Bengio and Courville, chapter 8](https://www.deeplearningbook.org/contents/optimization.html).\n",
|
|
"\n",
|
|
"The codes which implement these algorithms are discussed after our presentation of automatic differentiation."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d088ad85",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Practical tips\n",
|
|
"\n",
|
|
"* **Randomize the data when making mini-batches**. It is always important to randomly shuffle the data when forming mini-batches. Otherwise, the gradient descent method can fit spurious correlations resulting from the order in which data is presented.\n",
|
|
"\n",
|
|
"* **Transform your inputs**. Learning becomes difficult when our landscape has a mixture of steep and flat directions. One simple trick for minimizing these situations is to standardize the data by subtracting the mean and normalizing the variance of input variables. Whenever possible, also decorrelate the inputs. To understand why this is helpful, consider the case of linear regression. It is easy to show that for the squared error cost function, the Hessian of the cost function is just the correlation matrix between the inputs. Thus, by standardizing the inputs, we are ensuring that the landscape looks homogeneous in all directions in parameter space. Since most deep networks can be viewed as linear transformations followed by a non-linearity at each layer, we expect this intuition to hold beyond the linear case.\n",
|
|
"\n",
|
|
"* **Monitor the out-of-sample performance.** Always monitor the performance of your model on a validation set (a small portion of the training data that is held out of the training process to serve as a proxy for the test set. If the validation error starts increasing, then the model is beginning to overfit. Terminate the learning process. This *early stopping* significantly improves performance in many settings.\n",
|
|
"\n",
|
|
"* **Adaptive optimization methods don't always have good generalization.** Recent studies have shown that adaptive methods such as ADAM, RMSPorp, and AdaGrad tend to have poor generalization compared to SGD or SGD with momentum, particularly in the high-dimensional limit (i.e. the number of parameters exceeds the number of data points). Although it is not clear at this stage why these methods perform so well in training deep neural networks, simpler procedures like properly-tuned SGD may work as well or better in these applications.\n",
|
|
"\n",
|
|
"Geron's text, see chapter 11, has several interesting discussions."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "937063d3",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Using Automatic differentation with OLS\n",
|
|
"\n",
|
|
"We conclude the part on optmization by showing how we can make codes\n",
|
|
"for linear regression and logistic regression using **autograd**. The\n",
|
|
"first example shows results with ordinary leats squares."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "e08215a6",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Own inversion\n",
|
|
"[[3.6398684 ]\n",
|
|
" [3.27790702]]\n",
|
|
"Eigenvalues of Hessian Matrix:[0.35845332 4.35403494]\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"theta from own gd\n",
|
|
"[[3.6398684 ]\n",
|
|
" [3.27790702]]\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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/AMrVqzAu+++i2vXriEqKgoPPfQQXn75ZaecF5EnUgkhhLsLQUREROQu7DNEREREisZgiIiIiBSNwRAREREpGoMhIiIiUjQGQ0RERKRoDIaIiIhI0RSRZ6iqqgqnT59Go0aNjKazJyIiIukRQuDKlSuIjIyEl5fz6m8UEQydPn0aMTEx7i4GERER2SA/Px/R0dFOO74igqFGjRoB0L6ZgYGBbi4NERERWaK4uBgxMTH6+7izKCIY0jWNBQYGMhgiIiKSGWd3cWEHaiIiIlI0BkNERESkaAyGiIiISNEYDBEREZGiMRgiIiIiRWMwRERERIrGYIiIiIgUjcEQERERKRqDISIiIlI0BkNERESkaAyGiIiISNEYDBEREZGiMRgiIiIiRWMwRERERIrGYIiIiIgUjcEQERERKRqDISIiIlI0twdD69evx7BhwxAZGQmVSoVly5aZ3PaJJ56ASqXCggULXFY+IiIi8mxuD4ZKSkrQsWNHLFy4sM7tli1bhj/++AORkZEuKhkREREpgY+7C3DXXXfhrrvuqnObU6dOYeLEiVi1ahWGDBniopIRERGREri9ZsicqqoqjB07FlOnTkW7du3cXRwiIiLyMG6vGTJn7ty58PHxwTPPPGPxPmVlZSgrK9M/Ly4udkbRiIiIyANIumZo27ZteO+997B48WKoVCqL90tPT0dQUJD+ERMT48RSEhERkZxJOhjKzc1FYWEhmjdvDh8fH/j4+OD48eN4/vnn0aJFC5P7zZgxA0VFRfpHfn6+6wpNREREsiLpZrKxY8diwIABBssGDx6MsWPHYvz48Sb38/f3h7+/v7OLR0RERB7A7cHQ1atXceTIEf3zvLw87Ny5E8HBwWjevDlCQkIMtvf19UV4eDhat27t6qISERGRB3J7MLR161YkJyfrn0+ZMgUA8PDDD2Px4sVuKhUREREphduDoaSkJAghLN7+2LFjzisMERERKY6kO1ATERERORuDISIiIlI0BkNERESkaAyGiIiISNEYDBEREZGiMRgiIiIiRWMwRERERIrGYIiIiIgUjcEQERERKRqDISIiIlI0BkNERESkaAyGiIiISNEYDBEREZGiMRgiIiIiRWMwRERERIrGYIiIiIgUjcEQERERKRqDISIiIlI0BkNERESkaAyGiIiISNEYDBEREZGiMRgiIiIiRWMwRERERIrG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0jq38ZTruzpLztsYOV7f1Vly3p5yfVdny+ftCde3EEIUFhYKAGLdunUmt3HVNS6rmqHy8nJs27YNgwYNMlg+aNAgbNy40eg+mzZtqrX94MGDsXXrVlRUVNS5jaljupot511TVVUVrly5Umuyu6tXryI2NhbR0dEYOnRorV+W7mTPeXfu3BkRERHo378/srOzDdYp4fP+7LPPMGDAgFpZ2qX8edvCE65vR5Dj9W0POV/fjuAp13dRUREA1DkJq6uucVkFQ+fPn4dGo6k1W31YWFitWe11CgoKjG5fWVmJ8+fP17mNqWO6mi3nXdM777yDkpISjBo1Sr+sTZs2WLx4MVasWIElS5YgICAAffr0weHDhx1aflvZct4RERH49NNPoVarkZWVhdatW6N///5Yv369fhtP/7zPnDmDn3/+GY899pjBcql/3rbwhOvbEeR4fdvCE65ve3nK9S2EwJQpU3DHHXegffv2Jrdz1TUum+k4qlOpVAbPhRC1lpnbvuZya4/pDraWccmSJZg1axaWL1+O0NBQ/fKePXuiZ8+e+ud9+vTB7bffjg8++ADvv/++4wpuJ2vOu3Xr1mjdurX+ea9evZCfn4+3334bffv2temY7mJrGRcvXozGjRtjxIgRBsvl8nlby1Oub1vJ/fq2hidd37bylOt74sSJ2L17NzZs2GB2W1dc47KqGWratCm8vb1rRXuFhYW1okKd8PBwo9v7+PggJCSkzm1MHdPVbDlvnW+//RaPPvoovvvuOwwYMKDObb28vNCtWzfJ/JKw57yr69mzp8E5efLnLYTA559/jrFjx8LPz6/ObaX2edvCE65ve8j5+nYUuV3f9vCU63vSpElYsWIFsrOzER0dXee2rrrGZRUM+fn5oUuXLli9erXB8tWrV6N3795G9+nVq1et7X/99Vd07doVvr6+dW5j6piuZst5A9pfjOPGjUNGRgaGDBli9nWEENi5cyciIiLsLrMj2HreNe3YscPgnDz18wa0ozWOHDmCRx991OzrSO3ztoUnXN+2kvv17Shyu77tIffrWwiBiRMnIisrC2vXrkVcXJzZfVx2jVvc1VoivvnmG+Hr6ys+++wzsW/fPjF58mTRoEEDfa/66dOni7Fjx+q3//vvv0X9+vXFc889J/bt2yc+++wz4evrKzIzM/Xb/P7778Lb21u89dZbYv/+/eKtt94SPj4+YvPmzS4/P1OsPe+MjAzh4+MjPvzwQ3HmzBn94/Lly/ptZs2aJX755Rdx9OhRsWPHDjF+/Hjh4+Mj/vjjD5efnynWnve7774rli5dKg4dOiT27t0rpk+fLgAItVqt38YTP2+dBx98UPTo0cPoMeXweV+5ckXs2LFD7NixQwAQ8+fPFzt27BDHjx8XQnju9W3teXvK9W3teXvK9W3teevI/fp+6qmnRFBQkMjJyTH43l67dk2/jbuucdkFQ0II8eGHH4rY2Fjh5+cnbr/9doNheQ8//LDo16+fwfY5OTmic+fOws/PT7Ro0UJ8/PHHtY75/fffi9atWwtfX1/Rpk0bg4tLKqw57379+gkAtR4PP/ywfpvJkyeL5s2bCz8/P9GsWTMxaNAgsXHjRheekWWsOe+5c+eKli1bioCAANGkSRNxxx13iB9//LHWMT3t8xZCiMuXL4t69eqJTz/91Ojx5PB564ZOm/reeur1be15e8r1be15e8r1bcv33BOub2PnDEAsWrRIv427rnHVjQISERERKZKs+gwRERERORqDISIiIlI0BkNERESkaAyGiIiISNEYDBEREZGiMRgiIiIiRWMwRERERIrGYIiIiIgUjcEQERERKRqDISIiIlI0BkNEJEtLlixBQEAATp06pV/22GOPISEhAUVFRW4sGRHJDecmIyJZEkKgU6dOSExMxMKFCzF79mz873//w+bNmxEVFeXu4hGRjPi4uwBERLZQqVSYM2cO0tLSEBkZiffeew+5ubkMhIjIaqwZIiJZu/322/HXX3/h119/Rb9+/dxdHCKSIfYZIiLZWrVqFQ4cOACNRoOwsDB3F4eIZIo1Q0QkS9u3b0dSUhI+/PBDfPPNN6hfvz6+//57dxeLiGSIfYaISHaOHTuGIUOGYPr06Rg7dizatm2Lbt26Ydu2bejSpYu7i0dEMsOaISKSlYsXL6JPnz7o27cv/vOf/+iXDx8+HGVlZfjll1/cWDoikiMGQ0RERKRo7EBNREREisZgiIiIiBSNwRAREREpGoMhIiIiUjQGQ0RERKRoDIaIiIhI0RgMERERkaIxGCIiIiJFYzBEREREisZgiIiIiBSNwRAREREpGoMhIiIiUrT/BzXP9Rs0RHKoAAAAAElFTkSuQmCC\n",
|
|
"text/plain": [
|
|
"<Figure size 640x480 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {
|
|
"filenames": {
|
|
"image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/exercisesweek41_16_2.png"
|
|
}
|
|
},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"# Using Autograd to calculate gradients for OLS\n",
|
|
"from random import random, seed\n",
|
|
"import numpy as np\n",
|
|
"import autograd.numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"from autograd import grad\n",
|
|
"\n",
|
|
"def CostOLS(beta):\n",
|
|
" return (1.0/n)*np.sum((y-X @ beta)**2)\n",
|
|
"\n",
|
|
"n = 100\n",
|
|
"x = 2*np.random.rand(n,1)\n",
|
|
"y = 4+3*x+np.random.randn(n,1)\n",
|
|
"\n",
|
|
"X = np.c_[np.ones((n,1)), x]\n",
|
|
"XT_X = X.T @ X\n",
|
|
"theta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)\n",
|
|
"print(\"Own inversion\")\n",
|
|
"print(theta_linreg)\n",
|
|
"# Hessian matrix\n",
|
|
"H = (2.0/n)* XT_X\n",
|
|
"EigValues, EigVectors = np.linalg.eig(H)\n",
|
|
"print(f\"Eigenvalues of Hessian Matrix:{EigValues}\")\n",
|
|
"\n",
|
|
"theta = np.random.randn(2,1)\n",
|
|
"eta = 1.0/np.max(EigValues)\n",
|
|
"Niterations = 1000\n",
|
|
"# define the gradient\n",
|
|
"training_gradient = grad(CostOLS)\n",
|
|
"\n",
|
|
"for iter in range(Niterations):\n",
|
|
" gradients = training_gradient(theta)\n",
|
|
" theta -= eta*gradients\n",
|
|
"print(\"theta from own gd\")\n",
|
|
"print(theta)\n",
|
|
"\n",
|
|
"xnew = np.array([[0],[2]])\n",
|
|
"Xnew = np.c_[np.ones((2,1)), xnew]\n",
|
|
"ypredict = Xnew.dot(theta)\n",
|
|
"ypredict2 = Xnew.dot(theta_linreg)\n",
|
|
"\n",
|
|
"plt.plot(xnew, ypredict, \"r-\")\n",
|
|
"plt.plot(xnew, ypredict2, \"b-\")\n",
|
|
"plt.plot(x, y ,'ro')\n",
|
|
"plt.axis([0,2.0,0, 15.0])\n",
|
|
"plt.xlabel(r'$x$')\n",
|
|
"plt.ylabel(r'$y$')\n",
|
|
"plt.title(r'Random numbers ')\n",
|
|
"plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "623ad923",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Same code but now with momentum gradient descent"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "b7fe53c1",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Own inversion\n",
|
|
"[[4.]\n",
|
|
" [3.]]\n",
|
|
"Eigenvalues of Hessian Matrix:[0.3431178 4.16725475]\n",
|
|
"0 [-14.28194794] [-15.81268342]\n",
|
|
"1 [-0.23712617] [0.2073339]\n",
|
|
"2 [-0.21760199] [0.19026272]\n",
|
|
"3 [-0.19968537] [0.17459712]\n",
|
|
"4 [-0.18324395] [0.16022138]\n",
|
|
"5 [-0.16815626] [0.14702929]\n",
|
|
"6 [-0.15431083] [0.13492339]\n",
|
|
"7 [-0.1416054] [0.12381425]\n",
|
|
"8 [-0.12994608] [0.1136198]\n",
|
|
"9 [-0.11924676] [0.10426473]\n",
|
|
"10 [-0.10942838] [0.09567992]\n",
|
|
"11 [-0.10041841] [0.08780195]\n",
|
|
"12 [-0.0921503] [0.08057264]\n",
|
|
"13 [-0.08456295] [0.07393855]\n",
|
|
"14 [-0.07760032] [0.0678507]\n",
|
|
"15 [-0.07121097] [0.0622641]\n",
|
|
"16 [-0.0653477] [0.05713748]\n",
|
|
"17 [-0.05996719] [0.05243298]\n",
|
|
"18 [-0.05502969] [0.04811582]\n",
|
|
"19 [-0.05049873] [0.04415412]\n",
|
|
"20 [-0.04634083] [0.04051862]\n",
|
|
"21 [-0.04252528] [0.03718245]\n",
|
|
"22 [-0.03902389] [0.03412098]\n",
|
|
"23 [-0.0358108] [0.03131157]\n",
|
|
"24 [-0.03286226] [0.02873348]\n",
|
|
"25 [-0.03015649] [0.02636766]\n",
|
|
"26 [-0.0276735] [0.02419664]\n",
|
|
"27 [-0.02539496] [0.02220437]\n",
|
|
"28 [-0.02330402] [0.02037613]\n",
|
|
"29 [-0.02138525] [0.01869843]\n",
|
|
"theta from own gd\n",
|
|
"[[3.94280548]\n",
|
|
" [3.05000867]]\n",
|
|
"0 [-0.01962446] [0.01715886]\n",
|
|
"1 [-0.01800865] [0.01574606]\n",
|
|
"2 [-0.01604113] [0.01402574]\n",
|
|
"3 [-0.0141301] [0.01235481]\n",
|
|
"4 [-0.01239337] [0.01083628]\n",
|
|
"5 [-0.01085192] [0.0094885]\n",
|
|
"6 [-0.00949598] [0.00830291]\n",
|
|
"7 [-0.00830733] [0.0072636]\n",
|
|
"8 [-0.00726673] [0.00635375]\n",
|
|
"9 [-0.00635624] [0.00555765]\n",
|
|
"10 [-0.00555974] [0.00486122]\n",
|
|
"11 [-0.00486302] [0.00425203]\n",
|
|
"12 [-0.0042536] [0.00371918]\n",
|
|
"13 [-0.00372054] [0.0032531]\n",
|
|
"14 [-0.00325429] [0.00284542]\n",
|
|
"15 [-0.00284647] [0.00248884]\n",
|
|
"16 [-0.00248975] [0.00217694]\n",
|
|
"17 [-0.00217774] [0.00190413]\n",
|
|
"18 [-0.00190483] [0.00166551]\n",
|
|
"19 [-0.00166612] [0.00145679]\n",
|
|
"20 [-0.00145732] [0.00127423]\n",
|
|
"21 [-0.00127469] [0.00111454]\n",
|
|
"22 [-0.00111495] [0.00097487]\n",
|
|
"23 [-0.00097522] [0.0008527]\n",
|
|
"24 [-0.00085301] [0.00074584]\n",
|
|
"25 [-0.00074611] [0.00065237]\n",
|
|
"26 [-0.00065261] [0.00057062]\n",
|
|
"27 [-0.00057083] [0.00049911]\n",
|
|
"28 [-0.00049929] [0.00043656]\n",
|
|
"29 [-0.00043672] [0.00038185]\n",
|
|
"theta from own gd wth momentum\n",
|
|
"[[3.9988867 ]\n",
|
|
" [3.00097342]]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Using Autograd to calculate gradients for OLS\n",
|
|
"from random import random, seed\n",
|
|
"import numpy as np\n",
|
|
"import autograd.numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"from autograd import grad\n",
|
|
"\n",
|
|
"def CostOLS(beta):\n",
|
|
" return (1.0/n)*np.sum((y-X @ beta)**2)\n",
|
|
"\n",
|
|
"n = 100\n",
|
|
"x = 2*np.random.rand(n,1)\n",
|
|
"y = 4+3*x#+np.random.randn(n,1)\n",
|
|
"\n",
|
|
"X = np.c_[np.ones((n,1)), x]\n",
|
|
"XT_X = X.T @ X\n",
|
|
"theta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)\n",
|
|
"print(\"Own inversion\")\n",
|
|
"print(theta_linreg)\n",
|
|
"# Hessian matrix\n",
|
|
"H = (2.0/n)* XT_X\n",
|
|
"EigValues, EigVectors = np.linalg.eig(H)\n",
|
|
"print(f\"Eigenvalues of Hessian Matrix:{EigValues}\")\n",
|
|
"\n",
|
|
"theta = np.random.randn(2,1)\n",
|
|
"eta = 1.0/np.max(EigValues)\n",
|
|
"Niterations = 30\n",
|
|
"\n",
|
|
"# define the gradient\n",
|
|
"training_gradient = grad(CostOLS)\n",
|
|
"\n",
|
|
"for iter in range(Niterations):\n",
|
|
" gradients = training_gradient(theta)\n",
|
|
" theta -= eta*gradients\n",
|
|
" print(iter,gradients[0],gradients[1])\n",
|
|
"print(\"theta from own gd\")\n",
|
|
"print(theta)\n",
|
|
"\n",
|
|
"# Now improve with momentum gradient descent\n",
|
|
"change = 0.0\n",
|
|
"delta_momentum = 0.3\n",
|
|
"for iter in range(Niterations):\n",
|
|
" # calculate gradient\n",
|
|
" gradients = training_gradient(theta)\n",
|
|
" # calculate update\n",
|
|
" new_change = eta*gradients+delta_momentum*change\n",
|
|
" # take a step\n",
|
|
" theta -= new_change\n",
|
|
" # save the change\n",
|
|
" change = new_change\n",
|
|
" print(iter,gradients[0],gradients[1])\n",
|
|
"print(\"theta from own gd wth momentum\")\n",
|
|
"print(theta)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "749000b3",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## But noen of these can compete with Newton's method"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "e7b4abe1",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Own inversion\n",
|
|
"[[3.87043345]\n",
|
|
" [3.22475203]]\n",
|
|
"Eigenvalues of Hessian Matrix:[0.38540656 3.68548206]\n",
|
|
"0 [-12.40634991] [-11.15578306]\n",
|
|
"1 [-5.99520433e-15] [-8.10731958e-15]\n",
|
|
"2 [-2.87964097e-16] [-5.20946226e-16]\n",
|
|
"3 [4.12864187e-16] [4.15804451e-16]\n",
|
|
"4 [4.12864187e-16] [4.15804451e-16]\n",
|
|
"beta from own Newton code\n",
|
|
"[[3.87043345]\n",
|
|
" [3.22475203]]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Using Newton's method\n",
|
|
"from random import random, seed\n",
|
|
"import numpy as np\n",
|
|
"import autograd.numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"from autograd import grad\n",
|
|
"\n",
|
|
"def CostOLS(beta):\n",
|
|
" return (1.0/n)*np.sum((y-X @ beta)**2)\n",
|
|
"\n",
|
|
"n = 100\n",
|
|
"x = 2*np.random.rand(n,1)\n",
|
|
"y = 4+3*x+np.random.randn(n,1)\n",
|
|
"\n",
|
|
"X = np.c_[np.ones((n,1)), x]\n",
|
|
"XT_X = X.T @ X\n",
|
|
"beta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)\n",
|
|
"print(\"Own inversion\")\n",
|
|
"print(beta_linreg)\n",
|
|
"# Hessian matrix\n",
|
|
"H = (2.0/n)* XT_X\n",
|
|
"# Note that here the Hessian does not depend on the parameters beta\n",
|
|
"invH = np.linalg.pinv(H)\n",
|
|
"EigValues, EigVectors = np.linalg.eig(H)\n",
|
|
"print(f\"Eigenvalues of Hessian Matrix:{EigValues}\")\n",
|
|
"\n",
|
|
"beta = np.random.randn(2,1)\n",
|
|
"Niterations = 5\n",
|
|
"\n",
|
|
"# define the gradient\n",
|
|
"training_gradient = grad(CostOLS)\n",
|
|
"\n",
|
|
"for iter in range(Niterations):\n",
|
|
" gradients = training_gradient(beta)\n",
|
|
" beta -= invH @ gradients\n",
|
|
" print(iter,gradients[0],gradients[1])\n",
|
|
"print(\"beta from own Newton code\")\n",
|
|
"print(beta)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d47c2b1c",
|
|
"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**."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "e2b04ba9",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Own inversion\n",
|
|
"[[3.98225665]\n",
|
|
" [3.11495144]]\n",
|
|
"Eigenvalues of Hessian Matrix:[0.29378469 4.27347181]\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"theta from own gd\n",
|
|
"[[3.98225665]\n",
|
|
" [3.11495144]]\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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vLll3JAjd9xxB1avXo133nkH165dQ3x8PB555BG8+OKLXjkuokAkCSGEvytBRERE5C8cM0RERESaxmCIiIiINI3BEBEREWkagyEiIiLSNAZDREREpGkMhoiIiEjTNLHOkNFoxOnTp1G7dm2by9kTERGR8gghcOXKFcTFxSEoyHvtN5oIhk6fPo3ExER/V4OIiIjckJubi4SEBK/tXxPBUO3atQGYPsw6der4uTZERETkjMLCQiQmJlru496iiWDI3DVWp04dBkNEREQq4+0hLhxATURERJrGYIiIiIg0jcEQERERaRqDISIiItI0BkNERESkaQyGiIiISNMYDBEREZGmMRgiIiIiTWMwRERERJrGYIiIiIg0jcEQERERaRqDISIiItI0BkNERESkaQyGiIiISNMYDBEREZGmMRgiIiIiTWMwRERERJrm92Bo06ZNGD58OOLi4iBJEjIzM+2WHT9+PCRJwvz5831WPyIiIgpsfg+GioqK0KFDByxcuLDKcpmZmfj5558RFxfno5oRERGRFoT4uwJ333037r777irLnDp1CpMmTcJ3332HoUOH+qhmREREpAV+bxlyxGg0YsyYMZg2bRratGnj7+oQERFRgPF7y5Ajb7zxBkJCQvD00087/ZqSkhKUlJRYHhcWFnqjakRERBQAFN0y9Ouvv2LBggVYunQpJEly+nVz5sxBRESE5S8xMdGLtSQiIiI1U3QwtHnzZpw7dw6NGjVCSEgIQkJCcPz4cTz33HNo0qSJ3dfNmDEDBQUFlr/c3FzfVZqIiIhURdHdZGPGjMHAgQOttg0ZMgRjxozBY489Zvd1YWFhCAsL83b1iIiIKAD4PRi6evUqjhw5Ynmck5OD3377DZGRkWjUqBGioqKsylerVg0NGzZEixYtfF1VIiIiCkB+D4Z27NiBlJQUy+OpU6cCAMaOHYulS5f6qVZERESkFX4PhgYMGAAhhNPljx075r3KEBERkeYoegA1ERERkbcxGCIiIiJNYzBEREREmsZgiIiIiDSNwRARERFpGoMhIiIi0jQGQ0RERKRpDIaIiIhI0xgMERERkaYxGCIiIiJNYzBEREREmsZgiIiIiDSNwRARERFpGoMhIiIi0jQGQ0RERKRpDIaIiIhI0xgMERERkaYxGCIiIiJNYzBEREREmsZgiIiIiDSNwRARERFpGoMhIiIi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yMsYDJF/OJutnoiIyMvYTUb+w7FWRESkAAyGyL841oqIiPyM3WRERESkaQyGiIiISNMYDBEREZGmMRgiIiIiTWMwRERERJrGYIiIiIg0jcEQERERaRqDISIiItI0BkNERESkaQyGiIiISNOYjsNgYG4sIiIiDdN2MJSRATzzDHDy5K1tCQnAggXMmk5ERKQR2u0my8gARoywDoQA4NQp0/aMDP/Ui4iIiHxKm8GQwWBqERKi8nPmbVOmmMoRERFRQNNmMLR5c+UWofKEAHJzTeWIiIgooGkzGDpzRt5yREREpFraDIZiY+UtR0RERKql+GBozpw56NatG2rXro3o6Gikpqbi4MGDnu00Odk0a0ySbD8vSUBioqkcERERBTTFB0MbN27ExIkTsW3bNqxbtw5lZWUYPHgwioqK3N9pcLBp+jxQOSAyP54/n+sNERERaYAkhK0pVcp1/vx5REdHY+PGjejXr59TryksLERERAQKCgpQp06dW0/YWmcoMdEUCHGdISIiIr+ye/+WmeoWXSwoKAAAREZG2i1TUlKCkpISy+PCwkLbBdPSAJ2OK1ATERFpmKpahoQQ0Ol0uHTpEjZXMe191qxZmD17dqXt3o4siYiISD6+ahlSVTA0ceJErF27Fj/++CMSEhLslrPVMpSYmMhgiIiISEXYTVbB5MmTsXr1amzatKnKQAgAwsLCEBYW5qOaERERkZopPhgSQmDy5MlYtWoVsrOzkZSU5O8qERERUQBRfDA0ceJEpKenQ6/Xo3bt2sjLywMAREREoHr16n6uHREREamd4scMSXYWRlyyZAkeffRRp/bhqz5HIiIikg/HDN2k8FiNiIiIVE7xK1ATEREReRODISIiItI0BkNERESkaQyGiIiISNMYDBEREZGmMRgiIiIiTWMwRERERJrGYIiIiIg0jcEQERERaRqDISIiItI0BkNERESkaQyGiIiISNMYDBEREZGmMRgiIiIiTWMwRERERJrGYIiIiIg0jcEQERERaRqDISIiItI0BkNERESkaQyGiIiISNMYDBEREZGmMRgiIiIiTWMwRERERJrGYIiIiIg0jcEQERERaRqDISIiItI0BkNERESkaQyGiIiISNMYDBEREZGmMRgiIiIiTWMwRERERJrGYIiIiIg0jcEQERERaRqDISIiItI0BkNERESkaQyGiIiISNMY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\n",
|
|
"text/plain": [
|
|
"<Figure size 640x480 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {
|
|
"filenames": {
|
|
"image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/exercisesweek41_22_2.png"
|
|
}
|
|
},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"theta from own sdg\n",
|
|
"[[3.89184354]\n",
|
|
" [3.13010854]]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Using Autograd to calculate gradients using SGD\n",
|
|
"# OLS example\n",
|
|
"from random import random, seed\n",
|
|
"import numpy as np\n",
|
|
"import autograd.numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"from autograd import grad\n",
|
|
"\n",
|
|
"# Note change from previous example\n",
|
|
"def CostOLS(y,X,theta):\n",
|
|
" return np.sum((y-X @ theta)**2)\n",
|
|
"\n",
|
|
"n = 100\n",
|
|
"x = 2*np.random.rand(n,1)\n",
|
|
"y = 4+3*x+np.random.randn(n,1)\n",
|
|
"\n",
|
|
"X = np.c_[np.ones((n,1)), x]\n",
|
|
"XT_X = X.T @ X\n",
|
|
"theta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)\n",
|
|
"print(\"Own inversion\")\n",
|
|
"print(theta_linreg)\n",
|
|
"# Hessian matrix\n",
|
|
"H = (2.0/n)* XT_X\n",
|
|
"EigValues, EigVectors = np.linalg.eig(H)\n",
|
|
"print(f\"Eigenvalues of Hessian Matrix:{EigValues}\")\n",
|
|
"\n",
|
|
"theta = np.random.randn(2,1)\n",
|
|
"eta = 1.0/np.max(EigValues)\n",
|
|
"Niterations = 1000\n",
|
|
"\n",
|
|
"# Note that we request the derivative wrt third argument (theta, 2 here)\n",
|
|
"training_gradient = grad(CostOLS,2)\n",
|
|
"\n",
|
|
"for iter in range(Niterations):\n",
|
|
" gradients = (1.0/n)*training_gradient(y, X, theta)\n",
|
|
" theta -= eta*gradients\n",
|
|
"print(\"theta from own gd\")\n",
|
|
"print(theta)\n",
|
|
"\n",
|
|
"xnew = np.array([[0],[2]])\n",
|
|
"Xnew = np.c_[np.ones((2,1)), xnew]\n",
|
|
"ypredict = Xnew.dot(theta)\n",
|
|
"ypredict2 = Xnew.dot(theta_linreg)\n",
|
|
"\n",
|
|
"plt.plot(xnew, ypredict, \"r-\")\n",
|
|
"plt.plot(xnew, ypredict2, \"b-\")\n",
|
|
"plt.plot(x, y ,'ro')\n",
|
|
"plt.axis([0,2.0,0, 15.0])\n",
|
|
"plt.xlabel(r'$x$')\n",
|
|
"plt.ylabel(r'$y$')\n",
|
|
"plt.title(r'Random numbers ')\n",
|
|
"plt.show()\n",
|
|
"\n",
|
|
"n_epochs = 50\n",
|
|
"M = 5 #size of each minibatch\n",
|
|
"m = int(n/M) #number of minibatches\n",
|
|
"t0, t1 = 5, 50\n",
|
|
"def learning_schedule(t):\n",
|
|
" return t0/(t+t1)\n",
|
|
"\n",
|
|
"theta = np.random.randn(2,1)\n",
|
|
"\n",
|
|
"for epoch in range(n_epochs):\n",
|
|
"# Can you figure out a better way of setting up the contributions to each batch?\n",
|
|
" for i in range(m):\n",
|
|
" random_index = M*np.random.randint(m)\n",
|
|
" xi = X[random_index:random_index+M]\n",
|
|
" yi = y[random_index:random_index+M]\n",
|
|
" gradients = (1.0/M)*training_gradient(yi, xi, theta)\n",
|
|
" eta = learning_schedule(epoch*m+i)\n",
|
|
" theta = theta - eta*gradients\n",
|
|
"print(\"theta from own sdg\")\n",
|
|
"print(theta)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f6d7455a",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Same code but now with momentum gradient descent"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "40a68e4f",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Own inversion\n",
|
|
"[[4.11385399]\n",
|
|
" [2.90239437]]\n",
|
|
"Eigenvalues of Hessian Matrix:[0.2870363 4.27221341]\n",
|
|
"theta from own gd\n",
|
|
"[[4.11265847]\n",
|
|
" [2.90343239]]\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"theta from own sdg with momentum\n",
|
|
"[[4.07560398]\n",
|
|
" [2.82894312]]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Using Autograd to calculate gradients using SGD\n",
|
|
"# OLS example\n",
|
|
"from random import random, seed\n",
|
|
"import numpy as np\n",
|
|
"import autograd.numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"from autograd import grad\n",
|
|
"\n",
|
|
"# Note change from previous example\n",
|
|
"def CostOLS(y,X,theta):\n",
|
|
" return np.sum((y-X @ theta)**2)\n",
|
|
"\n",
|
|
"n = 100\n",
|
|
"x = 2*np.random.rand(n,1)\n",
|
|
"y = 4+3*x+np.random.randn(n,1)\n",
|
|
"\n",
|
|
"X = np.c_[np.ones((n,1)), x]\n",
|
|
"XT_X = X.T @ X\n",
|
|
"theta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)\n",
|
|
"print(\"Own inversion\")\n",
|
|
"print(theta_linreg)\n",
|
|
"# Hessian matrix\n",
|
|
"H = (2.0/n)* XT_X\n",
|
|
"EigValues, EigVectors = np.linalg.eig(H)\n",
|
|
"print(f\"Eigenvalues of Hessian Matrix:{EigValues}\")\n",
|
|
"\n",
|
|
"theta = np.random.randn(2,1)\n",
|
|
"eta = 1.0/np.max(EigValues)\n",
|
|
"Niterations = 100\n",
|
|
"\n",
|
|
"# Note that we request the derivative wrt third argument (theta, 2 here)\n",
|
|
"training_gradient = grad(CostOLS,2)\n",
|
|
"\n",
|
|
"for iter in range(Niterations):\n",
|
|
" gradients = (1.0/n)*training_gradient(y, X, theta)\n",
|
|
" theta -= eta*gradients\n",
|
|
"print(\"theta from own gd\")\n",
|
|
"print(theta)\n",
|
|
"\n",
|
|
"\n",
|
|
"n_epochs = 50\n",
|
|
"M = 5 #size of each minibatch\n",
|
|
"m = int(n/M) #number of minibatches\n",
|
|
"t0, t1 = 5, 50\n",
|
|
"def learning_schedule(t):\n",
|
|
" return t0/(t+t1)\n",
|
|
"\n",
|
|
"theta = np.random.randn(2,1)\n",
|
|
"\n",
|
|
"change = 0.0\n",
|
|
"delta_momentum = 0.3\n",
|
|
"\n",
|
|
"for epoch in range(n_epochs):\n",
|
|
" for i in range(m):\n",
|
|
" random_index = M*np.random.randint(m)\n",
|
|
" xi = X[random_index:random_index+M]\n",
|
|
" yi = y[random_index:random_index+M]\n",
|
|
" gradients = (1.0/M)*training_gradient(yi, xi, theta)\n",
|
|
" eta = learning_schedule(epoch*m+i)\n",
|
|
" # calculate update\n",
|
|
" new_change = eta*gradients+delta_momentum*change\n",
|
|
" # take a step\n",
|
|
" theta -= new_change\n",
|
|
" # save the change\n",
|
|
" change = new_change\n",
|
|
"print(\"theta from own sdg with momentum\")\n",
|
|
"print(theta)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d1f7f38d",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## AdaGrad algorithm, taken from [Goodfellow et al](https://www.deeplearningbook.org/contents/optimization.html)\n",
|
|
"\n",
|
|
"<!-- dom:FIGURE: [figures/adagrad.png, width=600 frac=0.8] -->\n",
|
|
"<!-- begin figure -->\n",
|
|
"\n",
|
|
"<img src=\"figures/adagrad.png\" width=\"600\"><p style=\"font-size: 0.9em\"><i>Figure 1: </i></p>\n",
|
|
"<!-- end figure -->"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b85cc96c",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Similar (second order function now) problem but now with AdaGrad"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "3ced9e13",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Own inversion\n",
|
|
"[[2.]\n",
|
|
" [3.]\n",
|
|
" [4.]]\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"theta from own AdaGrad\n",
|
|
"[[2.00036163]\n",
|
|
" [2.99784051]\n",
|
|
" [4.00208264]]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Using Autograd to calculate gradients using AdaGrad and Stochastic Gradient descent\n",
|
|
"# OLS example\n",
|
|
"from random import random, seed\n",
|
|
"import numpy as np\n",
|
|
"import autograd.numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"from autograd import grad\n",
|
|
"\n",
|
|
"# Note change from previous example\n",
|
|
"def CostOLS(y,X,theta):\n",
|
|
" return np.sum((y-X @ theta)**2)\n",
|
|
"\n",
|
|
"n = 1000\n",
|
|
"x = np.random.rand(n,1)\n",
|
|
"y = 2.0+3*x +4*x*x\n",
|
|
"\n",
|
|
"X = np.c_[np.ones((n,1)), x, x*x]\n",
|
|
"XT_X = X.T @ X\n",
|
|
"theta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)\n",
|
|
"print(\"Own inversion\")\n",
|
|
"print(theta_linreg)\n",
|
|
"\n",
|
|
"\n",
|
|
"# Note that we request the derivative wrt third argument (theta, 2 here)\n",
|
|
"training_gradient = grad(CostOLS,2)\n",
|
|
"# Define parameters for Stochastic Gradient Descent\n",
|
|
"n_epochs = 50\n",
|
|
"M = 5 #size of each minibatch\n",
|
|
"m = int(n/M) #number of minibatches\n",
|
|
"# Guess for unknown parameters theta\n",
|
|
"theta = np.random.randn(3,1)\n",
|
|
"\n",
|
|
"# Value for learning rate\n",
|
|
"eta = 0.01\n",
|
|
"# Including AdaGrad parameter to avoid possible division by zero\n",
|
|
"delta = 1e-8\n",
|
|
"for epoch in range(n_epochs):\n",
|
|
" Giter = 0.0\n",
|
|
" for i in range(m):\n",
|
|
" random_index = M*np.random.randint(m)\n",
|
|
" xi = X[random_index:random_index+M]\n",
|
|
" yi = y[random_index:random_index+M]\n",
|
|
" gradients = (1.0/M)*training_gradient(yi, xi, theta)\n",
|
|
" Giter += gradients*gradients\n",
|
|
" update = gradients*eta/(delta+np.sqrt(Giter))\n",
|
|
" theta -= update\n",
|
|
"print(\"theta from own AdaGrad\")\n",
|
|
"print(theta)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ed1fa9e4",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"Running this code we note an almost perfect agreement with the results from matrix inversion."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "787b2b5e",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## RMSProp algorithm, taken from [Goodfellow et al](https://www.deeplearningbook.org/contents/optimization.html)\n",
|
|
"\n",
|
|
"<!-- dom:FIGURE: [figures/rmsprop.png, width=600 frac=0.8] -->\n",
|
|
"<!-- begin figure -->\n",
|
|
"\n",
|
|
"<img src=\"figures/rmsprop.png\" width=\"600\"><p style=\"font-size: 0.9em\"><i>Figure 1: </i></p>\n",
|
|
"<!-- end figure -->"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ac61b6e0",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## RMSprop for adaptive learning rate with Stochastic Gradient Descent"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "5febac4f",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Own inversion\n",
|
|
"[[2.]\n",
|
|
" [3.]\n",
|
|
" [4.]]\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"theta from own RMSprop\n",
|
|
"[[1.99976935]\n",
|
|
" [2.99966842]\n",
|
|
" [4.00437973]]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Using Autograd to calculate gradients using RMSprop and Stochastic Gradient descent\n",
|
|
"# OLS example\n",
|
|
"from random import random, seed\n",
|
|
"import numpy as np\n",
|
|
"import autograd.numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"from autograd import grad\n",
|
|
"\n",
|
|
"# Note change from previous example\n",
|
|
"def CostOLS(y,X,theta):\n",
|
|
" return np.sum((y-X @ theta)**2)\n",
|
|
"\n",
|
|
"n = 1000\n",
|
|
"x = np.random.rand(n,1)\n",
|
|
"y = 2.0+3*x +4*x*x# +np.random.randn(n,1)\n",
|
|
"\n",
|
|
"X = np.c_[np.ones((n,1)), x, x*x]\n",
|
|
"XT_X = X.T @ X\n",
|
|
"theta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)\n",
|
|
"print(\"Own inversion\")\n",
|
|
"print(theta_linreg)\n",
|
|
"\n",
|
|
"\n",
|
|
"# Note that we request the derivative wrt third argument (theta, 2 here)\n",
|
|
"training_gradient = grad(CostOLS,2)\n",
|
|
"# Define parameters for Stochastic Gradient Descent\n",
|
|
"n_epochs = 50\n",
|
|
"M = 5 #size of each minibatch\n",
|
|
"m = int(n/M) #number of minibatches\n",
|
|
"# Guess for unknown parameters theta\n",
|
|
"theta = np.random.randn(3,1)\n",
|
|
"\n",
|
|
"# Value for learning rate\n",
|
|
"eta = 0.01\n",
|
|
"# Value for parameter rho\n",
|
|
"rho = 0.99\n",
|
|
"# Including AdaGrad parameter to avoid possible division by zero\n",
|
|
"delta = 1e-8\n",
|
|
"for epoch in range(n_epochs):\n",
|
|
" Giter = 0.0\n",
|
|
" for i in range(m):\n",
|
|
" random_index = M*np.random.randint(m)\n",
|
|
" xi = X[random_index:random_index+M]\n",
|
|
" yi = y[random_index:random_index+M]\n",
|
|
" gradients = (1.0/M)*training_gradient(yi, xi, theta)\n",
|
|
"\t# Accumulated gradient\n",
|
|
"\t# Scaling with rho the new and the previous results\n",
|
|
" Giter = (rho*Giter+(1-rho)*gradients*gradients)\n",
|
|
"\t# Taking the diagonal only and inverting\n",
|
|
" update = gradients*eta/(delta+np.sqrt(Giter))\n",
|
|
"\t# Hadamard product\n",
|
|
" theta -= update\n",
|
|
"print(\"theta from own RMSprop\")\n",
|
|
"print(theta)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ee8a6301",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## ADAM algorithm, taken from [Goodfellow et al](https://www.deeplearningbook.org/contents/optimization.html)\n",
|
|
"\n",
|
|
"<!-- dom:FIGURE: [figures/adam.png, width=600 frac=0.8] -->\n",
|
|
"<!-- begin figure -->\n",
|
|
"\n",
|
|
"<img src=\"figures/adam.png\" width=\"600\"><p style=\"font-size: 0.9em\"><i>Figure 1: </i></p>\n",
|
|
"<!-- end figure -->"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b2d0f16b",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## And finally [ADAM](https://arxiv.org/pdf/1412.6980.pdf)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"id": "59349e6f",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Own inversion\n",
|
|
"[[2.]\n",
|
|
" [3.]\n",
|
|
" [4.]]\n"
|
|
]
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"theta from own ADAM\n",
|
|
"[[1.99998899]\n",
|
|
" [3.00009903]\n",
|
|
" [3.99988697]]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Using Autograd to calculate gradients using RMSprop and Stochastic Gradient descent\n",
|
|
"# OLS example\n",
|
|
"from random import random, seed\n",
|
|
"import numpy as np\n",
|
|
"import autograd.numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"from autograd import grad\n",
|
|
"\n",
|
|
"# Note change from previous example\n",
|
|
"def CostOLS(y,X,theta):\n",
|
|
" return np.sum((y-X @ theta)**2)\n",
|
|
"\n",
|
|
"n = 1000\n",
|
|
"x = np.random.rand(n,1)\n",
|
|
"y = 2.0+3*x +4*x*x# +np.random.randn(n,1)\n",
|
|
"\n",
|
|
"X = np.c_[np.ones((n,1)), x, x*x]\n",
|
|
"XT_X = X.T @ X\n",
|
|
"theta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)\n",
|
|
"print(\"Own inversion\")\n",
|
|
"print(theta_linreg)\n",
|
|
"\n",
|
|
"\n",
|
|
"# Note that we request the derivative wrt third argument (theta, 2 here)\n",
|
|
"training_gradient = grad(CostOLS,2)\n",
|
|
"# Define parameters for Stochastic Gradient Descent\n",
|
|
"n_epochs = 50\n",
|
|
"M = 5 #size of each minibatch\n",
|
|
"m = int(n/M) #number of minibatches\n",
|
|
"# Guess for unknown parameters theta\n",
|
|
"theta = np.random.randn(3,1)\n",
|
|
"\n",
|
|
"# Value for learning rate\n",
|
|
"eta = 0.01\n",
|
|
"# Value for parameters beta1 and beta2, see https://arxiv.org/abs/1412.6980\n",
|
|
"beta1 = 0.9\n",
|
|
"beta2 = 0.999\n",
|
|
"# Including AdaGrad parameter to avoid possible division by zero\n",
|
|
"delta = 1e-7\n",
|
|
"iter = 0\n",
|
|
"for epoch in range(n_epochs):\n",
|
|
" first_moment = 0.0\n",
|
|
" second_moment = 0.0\n",
|
|
" iter += 1\n",
|
|
" for i in range(m):\n",
|
|
" random_index = M*np.random.randint(m)\n",
|
|
" xi = X[random_index:random_index+M]\n",
|
|
" yi = y[random_index:random_index+M]\n",
|
|
" gradients = (1.0/M)*training_gradient(yi, xi, theta)\n",
|
|
" # Computing moments first\n",
|
|
" first_moment = beta1*first_moment + (1-beta1)*gradients\n",
|
|
" second_moment = beta2*second_moment+(1-beta2)*gradients*gradients\n",
|
|
" first_term = first_moment/(1.0-beta1**iter)\n",
|
|
" second_term = second_moment/(1.0-beta2**iter)\n",
|
|
"\t# Scaling with rho the new and the previous results\n",
|
|
" update = eta*first_term/(np.sqrt(second_term)+delta)\n",
|
|
" theta -= update\n",
|
|
"print(\"theta from own ADAM\")\n",
|
|
"print(theta)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "1d490115",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"## Introducing [JAX](https://jax.readthedocs.io/en/latest/)\n",
|
|
"\n",
|
|
"Presently, instead of using **autograd**, we recommend using [JAX](https://jax.readthedocs.io/en/latest/)\n",
|
|
"\n",
|
|
"**JAX** is Autograd and [XLA (Accelerated Linear Algebra))](https://www.tensorflow.org/xla),\n",
|
|
"brought together for high-performance numerical computing and machine learning research.\n",
|
|
"It provides composable transformations of Python+NumPy programs: differentiate, vectorize, parallelize, Just-In-Time compile to GPU/TPU, and more."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "3bc7785a",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"### Getting started with Jax, note the way we import numpy"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"id": "f1090d5e",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import jax\n",
|
|
"import jax.numpy as jnp\n",
|
|
"import numpy as np\n",
|
|
"import matplotlib.pyplot as plt\n",
|
|
"\n",
|
|
"from jax import grad as jax_grad"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ac6bf976",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"### A warm-up example"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"id": "ed55121d",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"/Users/mhjensen/miniforge3/envs/myenv/lib/python3.9/site-packages/jax/_src/numpy/lax_numpy.py:173: UserWarning: Explicitly requested dtype float64 requested in asarray is not available, and will be truncated to dtype float32. To enable more dtypes, set the jax_enable_x64 configuration option or the JAX_ENABLE_X64 shell environment variable. See https://github.com/google/jax#current-gotchas for more.\n",
|
|
" return asarray(x, dtype=self.dtype)\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"[<matplotlib.lines.Line2D at 0x126f4fa00>]"
|
|
]
|
|
},
|
|
"execution_count": 11,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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\n",
|
|
"text/plain": [
|
|
"<Figure size 640x480 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {
|
|
"filenames": {
|
|
"image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/exercisesweek41_39_2.png"
|
|
}
|
|
},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"def function(x):\n",
|
|
" return x**2\n",
|
|
"\n",
|
|
"def analytical_gradient(x):\n",
|
|
" return 2*x\n",
|
|
"\n",
|
|
"def gradient_descent(starting_point, learning_rate, num_iterations, solver=\"analytical\"):\n",
|
|
" x = starting_point\n",
|
|
" trajectory_x = [x]\n",
|
|
" trajectory_y = [function(x)]\n",
|
|
"\n",
|
|
" if solver == \"analytical\":\n",
|
|
" grad = analytical_gradient \n",
|
|
" elif solver == \"jax\":\n",
|
|
" grad = jax_grad(function)\n",
|
|
" x = jnp.float64(x)\n",
|
|
" learning_rate = jnp.float64(learning_rate)\n",
|
|
"\n",
|
|
" for _ in range(num_iterations):\n",
|
|
" \n",
|
|
" x = x - learning_rate * grad(x)\n",
|
|
" trajectory_x.append(x)\n",
|
|
" trajectory_y.append(function(x))\n",
|
|
"\n",
|
|
" return trajectory_x, trajectory_y\n",
|
|
"\n",
|
|
"x = np.linspace(-5, 5, 100)\n",
|
|
"plt.plot(x, function(x), label=\"f(x)\")\n",
|
|
"\n",
|
|
"descent_x, descent_y = gradient_descent(5, 0.1, 10, solver=\"analytical\")\n",
|
|
"jax_descend_x, jax_descend_y = gradient_descent(5, 0.1, 10, solver=\"jax\")\n",
|
|
"\n",
|
|
"plt.plot(descent_x, descent_y, label=\"Gradient descent\", marker=\"o\")\n",
|
|
"plt.plot(jax_descend_x, jax_descend_y, label=\"JAX\", marker=\"x\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4a994430",
|
|
"metadata": {
|
|
"editable": true
|
|
},
|
|
"source": [
|
|
"### A more advanced example"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"id": "863db98d",
|
|
"metadata": {
|
|
"collapsed": false,
|
|
"editable": true
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"/Users/mhjensen/miniforge3/envs/myenv/lib/python3.9/site-packages/jax/_src/numpy/lax_numpy.py:173: UserWarning: Explicitly requested dtype float64 requested in asarray is not available, and will be truncated to dtype float32. To enable more dtypes, set the jax_enable_x64 configuration option or the JAX_ENABLE_X64 shell environment variable. See https://github.com/google/jax#current-gotchas for more.\n",
|
|
" return asarray(x, dtype=self.dtype)\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<matplotlib.collections.PathCollection at 0x126f922b0>"
|
|
]
|
|
},
|
|
"execution_count": 12,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
},
|
|
{
|
|
"data": {
|
|
"image/png": "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CIVCuP322xEKhbw+yryG/p7dgf6e3YH+nt2D/q7tIbVZlSAIgiCI+Q0pIgRBEARBeAYVIgRBEARBeAYVIgRBEARBeAYVIgRBEARBeAYVIhVOMpnE2rVroSgKXn75Za+PM6/Yt28frrnmGqxYsQK1tbVYtWoVbr/9dqRSKa+PNi+47777sGLFCoTDYaxbtw5/+tOfvD7SvGLz5s045ZRTEIlE0N7ejksvvRS7du3y+ljzns2bN0NRFNx0001eH6VioEKkwrnllluwePFir48xL9m5cydyuRy+/e1v4/XXX8fXvvY1fOtb38Ktt97q9dEqnsceeww33XQTbrvtNrz00ks488wzcfHFF+PAgQNeH23e8Mwzz+C6667D1q1b8dRTTyGTyeCCCy5APB73+mjzlm3btuGBBx7AiSee6PVRKgoa361gfvOb3+Dmm2/GT3/6Uxx33HF46aWXsHbtWq+PNa+56667cP/992Pv3r1eH6Wi2bBhA04++WTcf//92sdWr16NSy+9FJs3b/bwZPOXw4cPo729Hc888wzOOussr48z75icnMTJJ5+M++67D3feeSfWrl2Lr3/9614fqyIgRaRCGRgYwCc+8Ql8//vfR11dndfHqRrGx8fR0tLi9TEqmlQqhe3bt+OCCy6Y8fELLrgAzz77rEenmv+Mj48DAL1/BXHdddfhve99L84//3yvj1JxSL30jiiOqqq4+uqrce2112L9+vXYt2+f10eqCvbs2YN7770XX/nKV7w+SkUzNDSEbDaLjo6OGR/v6OhAf3+/R6ea36iqiptvvhlnnHEGjj/+eK+PM+949NFH8eKLL2Lbtm1eH6UiIUVEIu644w4oilL21wsvvIB7770XsVgMmzZt8vrIFYnZv2cjvb29uOiii3DZZZfh4x//uEcnn18oijLj96qqHvExgg/XX389duzYgUceecTro8w7enp6cOONN+Lhhx9GOBz2+jgVCXlEJGJoaAhDQ0NlP2f58uW4/PLL8atf/WrGRTubzcLv9+PKK6/EQw89JPqoFY3Zv2d2Uent7cU555yDDRs24Lvf/S58PqrfnZBKpVBXV4cf//jH+OAHP6h9/MYbb8TLL7+MZ555xsPTzT9uuOEGPP744/jjH/+IFStWeH2cecfjjz+OD37wg/D7/drHstksFEWBz+dDMpmc8WfEkVAhUoEcOHAAsVhM+31vby8uvPBC/OQnP8GGDRvQ2dnp4enmF4cOHcI555yDdevW4eGHH6YLCic2bNiAdevW4b777tM+tmbNGnzgAx8gsyonVFXFDTfcgJ///Od4+umncfTRR3t9pHnJxMQE9u/fP+NjH/vYx3Dsscfi05/+NLXCTEAekQpk6dKlM37f0NAAAFi1ahUVIRzp7e3F2WefjaVLl+Luu+/G4cOHtT9buHChhyerfG6++WZcddVVWL9+PU477TQ88MADOHDgAK699lqvjzZvuO666/DDH/4Qv/jFLxCJRDT/TWNjI2praz0+3fwhEokcUWzU19ejtbWVihCTUCFCECXYsmULdu/ejd27dx9R4JGQ6IyPfOQjGB4exhe+8AX09fXh+OOPxxNPPIFly5Z5fbR5AxuNPvvss2d8/MEHH8TVV1/t/oEIogTUmiEIgiAIwjPIdUcQBEEQhGdQIUIQBEEQhGdQIUIQBEEQhGdQIUIQBEEQhGdQIUIQBEEQhGdQIUIQBEEQhGdQIUIQBEEQhGdQIUIQBEEQhGdQIUIQBEEQhGdQIUIQBEEQhGdQIUIQBEEQhGdQIUIQBEEQhGf8P6ZyOHzGZunmAAAAAElFTkSuQmCC\n",
|
|
"text/plain": [
|
|
"<Figure size 640x480 with 1 Axes>"
|
|
]
|
|
},
|
|
"metadata": {
|
|
"filenames": {
|
|
"image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/exercisesweek41_41_2.png"
|
|
}
|
|
},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"backend = np\n",
|
|
"\n",
|
|
"def function(x):\n",
|
|
" return x*backend.sin(x**2 + 1)\n",
|
|
"\n",
|
|
"def analytical_gradient(x):\n",
|
|
" return backend.sin(x**2 + 1) + 2*x**2*backend.cos(x**2 + 1)\n",
|
|
"\n",
|
|
"\n",
|
|
"x = np.linspace(-5, 5, 100)\n",
|
|
"plt.plot(x, function(x), label=\"f(x)\")\n",
|
|
"\n",
|
|
"descent_x, descent_y = gradient_descent(1, 0.01, 300, solver=\"analytical\")\n",
|
|
"\n",
|
|
"# Change the backend to JAX\n",
|
|
"backend = jnp\n",
|
|
"jax_descend_x, jax_descend_y = gradient_descent(1, 0.01, 300, solver=\"jax\")\n",
|
|
"\n",
|
|
"plt.scatter(descent_x, descent_y, label=\"Gradient descent\", marker=\"v\", s=10, color=\"red\") \n",
|
|
"plt.scatter(jax_descend_x, jax_descend_y, label=\"JAX\", marker=\"x\", s=5, color=\"black\")"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"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.10"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
} |