Files
FYS-STK4155/doc/LectureNotes/_build/jupyter_execute/exercisesweek41.ipynb
T
Morten Hjorth-Jensen dbbebedb06 update
2024-10-08 17:04:26 +02:00

1408 lines
199 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "b18bcd06",
"metadata": {},
"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": "7542d6aa",
"metadata": {},
"source": [
"# Exercises week 41\n",
"**October 4-11, 2024**\n",
"\n",
"Date: **Deadline is Friday October 11 at midnight**"
]
},
{
"cell_type": "markdown",
"id": "80943a15",
"metadata": {},
"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": "2095d197",
"metadata": {},
"source": [
"# Code examples from week 39 and 40"
]
},
{
"cell_type": "markdown",
"id": "f428decb",
"metadata": {},
"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": "ba38d454",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Own inversion\n",
"[[3.96581896]\n",
" [3.03624103]]\n",
"Eigenvalues of Hessian Matrix:[0.26120167 4.71129677]\n",
"theta from own gd\n",
"[[3.96581896]\n",
" [3.03624103]]\n",
"theta from own sdg\n",
"[[3.99729015]\n",
" [3.02646648]]\n"
]
},
{
"data": {
"image/png": "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IiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNcUEQ//+97+RkpKCiIgItGvXDlu2bPF3k4iIiCgAKCIY+vzzzzFlyhS89NJL2L17N3r06IGBAwfi9OnT/m4aERERKZwkhBD+boQ9nTp1Qtu2bfHuu++at6WmpmLYsGGYO3eu3efn5+cjOjoaeXl5iIqK8mZTiYiIyEN89f0t+56h4uJi/Pbbb+jfv7/F9v79+2Pr1q1+ahUREREFihB/N8CeS5cuQa/Xo27duhbb69ati9zcXKvPKSoqQlFRkflxXl4eAGOESURERMpg+t729iCW7IMhE0mSLB4LISpsM5k7dy5mz55dYbtGo/FK24iIiMh7Ll++jOjoaK+dX/bBUO3atREcHFyhF+jChQsVeotMZsyYgWnTppkfX7t2DfXr18fp06e9+mbKTX5+PjQaDXJyclSVK8Xr5nWrAa+b160GeXl5qFevHmJiYrz6OrIPhsLCwtCuXTusX78ew4cPN29fv349hg4davU54eHhCA8Pr7A9OjpaVR8ik6ioKF63ivC61YXXrS5qve6gIO+mOMs+GAKAadOmYfTo0Wjfvj26dOmC9957D6dPn8aTTz7p76YRERGRwikiGHrooYdw+fJlvPLKKzh//jzS0tLw9ddfo379+v5uGhERESmcIoIhAHj66afx9NNPu/Tc8PBwzJw50+rQWSDjdfO61YDXzetWA163d69bEUUXiYiIiLxF9kUXiYiIiLyJwRARERGpGoMhIiIiUjUGQ0RERKRqigyG/v3vfyMlJQURERFo164dtmzZUunxmzZtQrt27RAREYEGDRpgyZIlFY5ZsWIFmjVrhvDwcDRr1gwrV670VvNd5sx1Z2Zmol+/fqhTpw6ioqLQpUsXfPfddxbHLFu2DJIkVfgpLCz09qU4xZnr3rhxo9VrOnz4sMVxgfb7Hjt2rNXrbt68ufkYJfy+N2/eDK1Wi4SEBEiShFWrVtl9TiDc385ed6Dc385ed6Dc385ed6Dc33PnzkWHDh0QGRmJ2NhYDBs2DEeOHLH7PF/c44oLhj7//HNMmTIFL730Enbv3o0ePXpg4MCBOH36tNXjs7Ozcd9996FHjx7YvXs3XnzxRUyePBkrVqwwH7Nt2zY89NBDGD16NH7//XeMHj0aDz74IH755RdfXZZdzl735s2b0a9fP3z99df47bff0KdPH2i1WuzevdviuKioKJw/f97iJyIiwheX5BBnr9vkyJEjFtfUuHFj875A/H2/+eabFtebk5ODmJgYPPDAAxbHyf33XVBQgFatWmHx4sUOHR8o97ez1x0o97ez122i9Pvb2esOlPt706ZNmDBhArZv347169ejtLQU/fv3R0FBgc3n+OweFwrTsWNH8eSTT1psa9q0qZg+fbrV4//+97+Lpk2bWmwbP3686Ny5s/nxgw8+KO69916LYwYMGCAefvhhD7Xafc5etzXNmjUTs2fPNj9eunSpiI6O9lQTvcLZ687KyhIAxNWrV22eUw2/75UrVwpJksTJkyfN25Tw+y4LgFi5cmWlxwTK/V2WI9dtjRLv77Icue5Aub/LcuX3HQj3txBCXLhwQQAQmzZtsnmMr+5xRfUMFRcX47fffkP//v0ttvfv3x9bt261+pxt27ZVOH7AgAHYuXMnSkpKKj3G1jl9zZXrLs9gMOD69esVFru7ceMG6tevj6SkJAwePLjCX5b+5M51t2nTBvHx8ejbty+ysrIs9qnh9/3BBx/gnnvuqVClXc6/b1cEwv3tCUq8v92h5PvbEwLl/s7LywOAShdh9dU9rqhg6NKlS9Dr9RVWq69bt26FVe1NcnNzrR5fWlqKS5cuVXqMrXP6mivXXd4bb7yBgoICPPjgg+ZtTZs2xbJly7BmzRosX74cERER6NatG44dO+bR9rvKleuOj4/He++9hxUrViAzMxNNmjRB3759sXnzZvMxgf77Pn/+PL755hs8/vjjFtvl/vt2RSDc356gxPvbFYFwf7srUO5vIQSmTZuG7t27Iy0tzeZxvrrHFbMcR1mSJFk8FkJU2Gbv+PLbnT2nP7jaxuXLl2PWrFlYvXo1YmNjzds7d+6Mzp07mx9369YNbdu2xdtvv4233nrLcw13kzPX3aRJEzRp0sT8uEuXLsjJycHrr7+Onj17unROf3G1jcuWLUONGjUwbNgwi+1K+X07K1Dub1cp/f52RiDd364KlPt74sSJ2Lt3L3766Se7x/riHldUz1Dt2rURHBxcIdq7cOFChajQJC4uzurxISEhqFWrVqXH2Dqnr7ly3Saff/45HnvsMXzxxRe45557Kj02KCgIHTp0kM1fEu5cd1mdO3e2uKZA/n0LIfC///0Po0ePRlhYWKXHyu337YpAuL/doeT721OUdn+7I1Du70mTJmHNmjXIyspCUlJSpcf66h5XVDAUFhaGdu3aYf369Rbb169fj65du1p9TpcuXSoc//3336N9+/YIDQ2t9Bhb5/Q1V64bMP7FOHbsWGRkZGDQoEF2X0cIgT179iA+Pt7tNnuCq9dd3u7duy2uKVB/34Bxtsbx48fx2GOP2X0duf2+XREI97erlH5/e4rS7m93KP3+FkJg4sSJyMzMxIYNG5CSkmL3OT67xx1OtZaJzz77TISGhooPPvhAHDx4UEyZMkVUq1bNnFU/ffp0MXr0aPPxf/zxh6hataqYOnWqOHjwoPjggw9EaGio+Oqrr8zH/PzzzyI4OFj861//EocOHRL/+te/REhIiNi+fbvPr88WZ687IyNDhISEiHfeeUecP3/e/HPt2jXzMbNmzRLffvutOHHihNi9e7cYN26cCAkJEb/88ovPr88WZ6974cKFYuXKleLo0aNi//79Yvr06QKAWLFihfmYQPx9mzzyyCOiU6dOVs+phN/39evXxe7du8Xu3bsFALFgwQKxe/ducerUKSFE4N7fzl53oNzfzl53oNzfzl63idLv76eeekpER0eLjRs3Wnxub968aT7GX/e44oIhIYR45513RP369UVYWJho27atxbS8MWPGiF69elkcv3HjRtGmTRsRFhYmkpOTxbvvvlvhnF9++aVo0qSJCA0NFU2bNrW4ueTCmevu1auXAFDhZ8yYMeZjpkyZIurVqyfCwsJEnTp1RP/+/cXWrVt9eEWOcea6582bJxo2bCgiIiJEzZo1Rffu3cW6desqnDPQft9CCHHt2jVRpUoV8d5771k9nxJ+36ap07Y+t4F6fzt73YFyfzt73YFyf7vyOQ+E+9vaNQMQS5cuNR/jr3tcut1AIiIiIlVSVM4QERERkacxGCIiIiJVYzBEREREqsZgiIiIiFSNwRARERGpGoMhIiIiUjUGQ0RERKRqDIaIiIhI1RgMERERkaoxGCIiIiJVYzBERIq0fPlyRERE4OzZs+Ztjz/+OFq2bIm8vDw/toyIlIZrkxGRIgkh0Lp1a/To0QOLFy/G7Nmz8f7772P79u1ITEz0d/OISEFC/N0AIiJXSJKEOXPmYMSIEUhISMCbb76JLVu2MBAiIqexZ4iIFK1t27Y4cOAAvv/+e/Tq1cvfzSEiBWLOEBEp1nfffYfDhw9Dr9ejbt26/m4OESkUe4aISJF27dqF3r1745133sFnn32GqlWr4ssvv/R3s4hIgZgzRESKc/LkSQwaNAjTp0/H6NGj0axZM3To0AG//fYb2rVr5+/mEZHCsGeIiBTlypUr6NatG3r27In//Oc/5u1Dhw5FUVERvv32Wz+2joiUiMEQERERqRoTqImIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESq9v8BAPFOpB6joZUAAAAASUVORK5CYII=",
"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": "de04b41a",
"metadata": {},
"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": "77fc1cca",
"metadata": {},
"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": "441d1f36",
"metadata": {},
"source": [
"$$\n",
"\\mathbf{v}_{t}=\\gamma \\mathbf{v}_{t-1}+\\eta_{t}\\nabla_\\theta E(\\boldsymbol{\\theta}_t) \\nonumber\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "47434945",
"metadata": {},
"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": "f3ea5060",
"metadata": {},
"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": "923628c8",
"metadata": {},
"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": "5c94031c",
"metadata": {},
"source": [
"where we have defined $\\Delta \\boldsymbol{\\theta}_{t}= \\boldsymbol{\\theta}_t-\\boldsymbol{\\theta}_{t-1}$."
]
},
{
"cell_type": "markdown",
"id": "f3f0e9c9",
"metadata": {},
"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": "92253eff",
"metadata": {},
"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": "08209015",
"metadata": {},
"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": "f1f7d4aa",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Own inversion\n",
"[[4.03656288]\n",
" [2.95497813]]\n",
"Eigenvalues of Hessian Matrix:[0.29560433 4.58257727]\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"theta from own gd\n",
"[[4.03656288]\n",
" [2.95497813]]\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAkMAAAHFCAYAAADxOP3DAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAABVR0lEQVR4nO3deXxU1fk/8M/NNiFAAgEC2SABIavsq+yyM6FgiigoAi51QSGirfC1FmhFKr9WgaKlthasCC4Q0DIosiSAApZV2UEMEJYYwjKBhIRk5vz+GDMwyUxmySz3zv28X695ae69c+fcGSb3yTnPeY4khBAgIiIiUqkAXzeAiIiIyJcYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBHJ0PLlyyFJkvkRFBSE6OhoPPzwwzh16pTP2jVnzhxIkuSz11eCM2fOQJIk/OUvf/F1U4jIQUG+bgAR2bZs2TIkJyejrKwM3377LebNm4ecnBwcP34cjRs39nXziIj8AoMhIhlLT09H165dAQADBgyAwWDA7NmzsW7dOkyZMsXHrSNfqqioMPcaElHdcJiMSEGqAqOff/7ZvK2srAwvvfQSOnbsiIiICERGRqJXr174/PPPazxfkiQ8//zz+PDDD5GSkoKwsDB06NAB69evr3GsTqdDx44dodFokJiYaHPYp6ysDLNmzUJiYiJCQkIQGxuLqVOn4vr16xbHJSQkICMjA+vXr0enTp1Qr149pKSkmF97+fLlSElJQf369dG9e3fs3bvX7vtRNZyYk5ODZ599Fk2bNkWTJk2QmZmJixcv1rj2OXPm1DhHQkICJk+eXOOcW7duxVNPPYUmTZogPDwcjz32GEpKSlBQUIBx48ahUaNGiI6Oxssvv4yKiooa5zUajZg3bx5atmyJ0NBQdO3aFVu2bKlx3KlTpzBhwgRERUVBo9EgJSUF77zzjsUxubm5kCQJH374IV566SXExsZCo9Hgxx9/RGlpKV5++WUkJiYiNDQUkZGR6Nq1K1atWmX3/SMiE/5JQaQgeXl5AIB27dqZt5WXl+Pq1at4+eWXERsbi9u3b2Pz5s3IzMzEsmXL8Nhjj1mcQ6fTYc+ePfjjH/+IBg0aYMGCBXjggQdw4sQJtG7dGgCwZcsWjB49Gr169cLHH38Mg8GABQsWWARhACCEwJgxY7BlyxbMmjULffv2xQ8//IDZs2dj165d2LVrFzQajfn477//HrNmzcKrr76KiIgIzJ07F5mZmZg1axa2bNmCN954A5Ik4ZVXXkFGRgby8vJQr149u+/Lk08+Ca1Wi5UrVyI/Px+//e1v8eijj2Lr1q0uv9dPPvkkMjMz8fHHH+PAgQP4v//7P1RWVuLEiRPIzMzEb37zG2zevBlvvvkmYmJiMGPGDIvnL1myBK1atcLChQthNBqxYMECjBgxAtu2bUOvXr0AAEePHsV9992Hli1b4q9//StatGiBjRs3Ytq0aSgqKsLs2bMtzjlr1iz06tULS5cuRUBAAKKiojBjxgx8+OGHeP3119GpUyeUlJTg8OHDuHLlisvXTqQ6gohkZ9myZQKA2L17t6ioqBA3btwQX331lWjRooXo16+fqKiosPncyspKUVFRIZ544gnRqVMni30ARPPmzUVxcbF5W0FBgQgICBDz5883b+vRo4eIiYkRt27dMm8rLi4WkZGR4u5fG1999ZUAIBYsWGDxOp988okAIN577z3ztlatWol69eqJ8+fPm7cdPHhQABDR0dGipKTEvH3dunUCgPjiiy8cep+ee+45i+0LFiwQAMSlS5csrn327Nk1ztGqVSsxadKkGud84YUXLI4bM2aMACDeeusti+0dO3YUnTt3Nv+cl5cnANh8/wYPHmzeNmzYMBEXFyf0er3FOZ9//nkRGhoqrl69KoQQIicnRwAQ/fr1q9H+9PR0MWbMmBrbichxHCYjkrGePXsiODgYDRs2xPDhw9G4cWN8/vnnNfJEPvvsM/Tu3RsNGjRAUFAQgoOD8f777+PYsWM1zjlw4EA0bNjQ/HPz5s0RFRWFs2fPAgBKSkqwZ88eZGZmIjQ01Hxcw4YNMWrUKItzVfW83D3MBAAPPvgg6tevX2NYqGPHjoiNjTX/nJKSAsCUDxUWFlZje1Wb7PnVr35l8XP79u2der41GRkZFj9XtUmr1dbYbu11bL1/27dvh8FgQFlZGbZs2YIHHngAYWFhqKysND9GjhyJsrIy7N692+Kcv/71r2u8Tvfu3fHll19i5syZyM3Nxa1bt1y+ZiK1YjBEJGP/+c9/sGfPHmzduhVPP/00jh07hvHjx1sck52djXHjxiE2NhYrVqzArl27sGfPHjz++OMoKyurcc4mTZrU2KbRaMw30WvXrsFoNKJFixY1jqu+7cqVKwgKCkKzZs0stkuShBYtWtQYqomMjLT4OSQkpNbt1tpvTfVrqhqaq0tg4ExbrbXT1vt3+/Zt3Lx5E1euXEFlZSX+9re/ITg42OIxcuRIAEBRUZHF86Ojo2ucc/HixXjllVewbt06DBw4EJGRkRgzZoxPSzAQKQ1zhohkLCUlxZw0PXDgQBgMBvzrX//C6tWrMXbsWADAihUrkJiYiE8++cSiBlB5eblLr9m4cWNIkoSCgoIa+6pva9KkCSorK3H58mWLgEgIgYKCAnTr1s2lNniCRqOx+p54KrfG1vsXEhKCBg0aIDg4GIGBgZg4cSKmTp1q9RyJiYkWP1ur8VS/fn3MnTsXc+fOxc8//2zuJRo1ahSOHz/unosh8nPsGSJSkAULFqBx48b4wx/+AKPRCMB0gwwJCbG4URYUFFidTeaIqtlc2dnZFj0eN27cwH//+1+LYwcNGgTAFJDdbc2aNSgpKTHvl4OEhAT88MMPFtu2bt2KmzdveuT1bL1/ffv2RWBgIMLCwjBw4EAcOHAA7du3R9euXWs8rPXi1aZ58+aYPHkyxo8fjxMnTqC0tNTdl0Xkl9gzRKQgjRs3xqxZs/C73/0OK1euxKOPPoqMjAxkZ2fjueeew9ixY5Gfn48//elPiI6Odnmo5E9/+hOGDx+OIUOG4KWXXoLBYMCbb76J+vXr4+rVq+bjhgwZgmHDhuGVV15BcXExevfubZ5N1qlTJ0ycONFdl15nEydOxGuvvYY//OEP6N+/P44ePYolS5YgIiLCI68XGBiIIUOGYMaMGTAajXjzzTdRXFyMuXPnmo9ZtGgR+vTpg759++LZZ59FQkICbty4gR9//BH//e9/HZoN16NHD2RkZKB9+/Zo3Lgxjh07hg8//BC9evWyyMMiItsYDBEpzAsvvIAlS5bgj3/8I8aPH48pU6agsLAQS5cuxb///W+0bt0aM2fOxPnz5y1uvM4YMmQI1q1bh9///vd46KGH0KJFCzz33HO4deuWxTklScK6deswZ84cLFu2DPPmzUPTpk0xceJEvPHGGxbT6n3tt7/9LYqLi7F8+XL85S9/Qffu3fHpp59i9OjRHnm9559/HmVlZZg2bRoKCwuRlpYGnU6H3r17m49JTU3F/v378ac//Qm///3vUVhYiEaNGqFt27bmvCF77r//fnzxxRd4++23UVpaitjYWDz22GN49dVXPXJdRP5IEkIIXzeCiIiIyFeYM0RERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVVFFnyGg04uLFi2jYsKHVcvZEREQkP0II3LhxAzExMQgI8Fz/jSqCoYsXLyI+Pt7XzSAiIiIX5OfnIy4uzmPnV0Uw1LBhQwCmNzM8PNzHrSEiIiJHFBcXIz4+3nwf9xRVBENVQ2Ph4eEMhoiIiBTG0ykuTKAmIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVfN5MLR9+3aMGjUKMTExkCQJ69ats3ns008/DUmSsHDhQq+1j4iIiPybz4OhkpISdOjQAUuWLKn1uHXr1uG7775DTEyMl1pGREREahDk6waMGDECI0aMqPWYCxcu4Pnnn8fGjRuh1Wq91DIiIiJSA5/3DNljNBoxceJE/Pa3v0VaWpqvm0NERER+xuc9Q/a8+eabCAoKwrRp0xx+Tnl5OcrLy80/FxcXe6JpRERE5Adk3TO0b98+LFq0CMuXL4ckSQ4/b/78+YiIiDA/4uPjPdhKIiIiUjJZB0M7duxAYWEhWrZsiaCgIAQFBeHs2bN46aWXkJCQYPN5s2bNgl6vNz/y8/O912giIiJSFFkPk02cOBGDBw+22DZs2DBMnDgRU6ZMsfk8jUYDjUbj6eYRERGRH/B5MHTz5k38+OOP5p/z8vJw8OBBREZGomXLlmjSpInF8cHBwWjRogWSkpK83VQiIiLyQz4Phvbu3YuBAweaf54xYwYAYNKkSVi+fLmPWkVERERq4fNgaMCAARBCOHz8mTNnPNcYIiIiUh1ZJ1ATEREReRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrm82Bo+/btGDVqFGJiYiBJEtatW2feV1FRgVdeeQX33nsv6tevj5iYGDz22GO4ePGi7xpMREREfsXnwVBJSQk6dOiAJUuW1NhXWlqK/fv347XXXsP+/fuRnZ2NkydP4le/+pUPWkpERET+SBJCCF83oookSVi7di3GjBlj85g9e/age/fuOHv2LFq2bOnQeYuLixEREQG9Xo/w8HA3tZaIiIg8yVv37yCPndlD9Ho9JElCo0aNbB5TXl6O8vJy88/FxcVeaBkREREpkc+HyZxRVlaGmTNnYsKECbVGiPPnz0dERIT5ER8f78VWEhERkZIoJhiqqKjAww8/DKPRiHfffbfWY2fNmgW9Xm9+5Ofne6mVREREZJXBAOTmAqtWmf5rMPi6RWaKGCarqKjAuHHjkJeXh61bt9odN9RoNNBoNF5qHREREdUqOxuYPh04f/7Otrg4YNEiIDPTd+36hex7hqoCoVOnTmHz5s1o0qSJr5tEREREjsrOBsaOtQyEAODCBdP27GzftOsuPu8ZunnzJn788Ufzz3l5eTh48CAiIyMRExODsWPHYv/+/Vi/fj0MBgMKCgoAAJGRkQgJCfFVs4mIiMgeg8HUI2Rt4roQgCQBWVnA6NFAYKDXm1fF51Prc3NzMXDgwBrbJ02ahDlz5iAxMdHq83JycjBgwACHXoNT64mIiHwgNxewco+vIScHsHJPV83U+gEDBqC2eExGZZCIiIjIGZcuufc4D5F9zhAREREpVHS0e4/zEJ/3DBEREZFCGQzAjh2mnp3oaKBvX8vcn759TbPGLlywnjckSab9fft6r81WsGeIiIiInJedDSQkmHKCJkww/TchwXJ2WGCgafo8YAp87lb188KFPk2eBhgMERERkbOcmS6fmQmsXg3ExloeGxdn2i6DOkM+n03mDZxNRkRE5CYGg6kHqHogVKVq6Csvz7LHx96QmhWqmU1GRERECrJjh+1ACDDlBuXnm467e7p8YKDV6fNywGEyIiIicpxCpss7g8EQEREROU4h0+Wd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Z0LJsdJzZiYwerT82kVERLLBYEiOlDgTSs5LiXiqJAIREfkFDpPJkdJmQrHSMxERKRiDITlS0kwoLiVCREQKx2BIjpQ0E8qZSs9EREQyxGBIrpQyE0qJ+U1ERER3YQK1nClhJpTS8puIiIiqYTAkd3KfCWVvKZGq1eHlkN9ERERkBYfJqG6UlN9ERERkBYMhXzEYgNxcYNUq03+VPNtKKflNREREVnCYzBfkXKDQVUrIbyIiIrJCEsJaood/KS4uRkREBPR6PcLDw33bmKoChdXf9qohJfakEBERAfDe/ZvDZN7EAoVERESyw2DIm1igkIiISHYYDHkTCxQSERHJDoMhb2KBQiIiItlhMORNSlqAlYiISCUYDHkTCxQSERHJDoMhb2OBQiIiIllh0UVfYIFCIiIi2WAw5CtyX4CViIhIJThMRkRERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVZN9MDR//nx069YNDRs2RFRUFMaMGYMTJ074ullERETkJ2QfDG3btg1Tp07F7t27sWnTJlRWVmLo0KEoKSnxddOIiIjID0hCCOHrRjjj8uXLiIqKwrZt29CvXz+HnlNcXIyIiAjo9XqEh4d7uIVERETkDt66fwd57MweotfrAQCRkZE2jykvL0d5ebn55+LiYo+3i4iIiJRJ9sNkdxNCYMaMGejTpw/S09NtHjd//nxERESYH/Hx8V5sJRERESmJoobJpk6dCp1Oh2+++QZxcXE2j7PWMxQfH89hMiIiIgXhMFk1L7zwAr744gts37691kAIADQaDTQajZdaRkREREom+2BICIEXXngBa9euRW5uLhITE33dJCIiIvIjsg+Gpk6dipUrV+Lzzz9Hw4YNUVBQAACIiIhAvXr1fNw6IiIiUjrZ5wxJkmR1+7JlyzB58mSHzsGp9URERMrDnKFfyDxWIyIiIoVT1NR6IiIiIndjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGqKCYbeffddJCYmIjQ0FF26dMGOHTt83SQiIiLyA4oIhj755BNkZWXh1VdfxYEDB9C3b1+MGDEC586d83XTiIiISOEkIYTwdSPs6dGjBzp37oy///3v5m0pKSkYM2YM5s+fb/f5xcXFiIiIgF6vR3h4uCebSkRERG7irfu37HuGbt++jX379mHo0KEW24cOHYqdO3f6qFVERETkL4J83QB7ioqKYDAY0Lx5c4vtzZs3R0FBgdXnlJeXo7y83PyzXq8HYIowiYiISBmq7tueHsSSfTBURZIki5+FEDW2VZk/fz7mzp1bY3t8fLxH2kZERESec+XKFURERHjs/LIPhpo2bYrAwMAavUCFhYU1eouqzJo1CzNmzDD/fP36dbRq1Qrnzp3z6JspN8XFxYiPj0d+fr6qcqV43bxuNeB187rVQK/Xo2XLloiMjPTo68g+GAoJCUGXLl2wadMmPPDAA+btmzZtwujRo60+R6PRQKPR1NgeERGhqn9EVcLDw3ndKsLrVhdet7qo9boDAjyb4iz7YAgAZsyYgYkTJ6Jr167o1asX3nvvPZw7dw7PPPOMr5tGRERECqeIYOihhx7ClStX8Mc//hGXLl1Ceno6NmzYgFatWvm6aURERKRwigiGAOC5557Dc88959JzNRoNZs+ebXXozJ/xunndasDr5nWrAa/bs9etiKKLRERERJ4i+6KLRERERJ7EYIiIiIhUjcEQERERqRqDISIiIlI1RQZD7777LhITExEaGoouXbpgx44dtR6/bds2dOnSBaGhoWjdujWWLl1a45g1a9YgNTUVGo0GqampWLt2raea7zJnrjs7OxtDhgxBs2bNEB4ejl69emHjxo0WxyxfvhySJNV4lJWVefpSnOLMdefm5lq9puPHj1sc52+f9+TJk61ed1pamvkYJXze27dvx6hRoxATEwNJkrBu3Tq7z/GH77ez1+0v329nr9tfvt/OXre/fL/nz5+Pbt26oWHDhoiKisKYMWNw4sQJu8/zxndcccHQJ598gqysLLz66qs4cOAA+vbtixEjRuDcuXNWj8/Ly8PIkSPRt29fHDhwAP/3f/+HadOmYc2aNeZjdu3ahYceeggTJ07E999/j4kTJ2LcuHH47rvvvHVZdjl73du3b8eQIUOwYcMG7Nu3DwMHDsSoUaNw4MABi+PCw8Nx6dIli0doaKg3Lskhzl53lRMnTlhcU9u2bc37/PHzXrRokcX15ufnIzIyEg8++KDFcXL/vEtKStChQwcsWbLEoeP95fvt7HX7y/fb2euuovTvt7PX7S/f723btmHq1KnYvXs3Nm3ahMrKSgwdOhQlJSU2n+O177hQmO7du4tnnnnGYltycrKYOXOm1eN/97vfieTkZIttTz/9tOjZs6f553Hjxonhw4dbHDNs2DDx8MMPu6nVdefsdVuTmpoq5s6da/552bJlIiIiwl1N9AhnrzsnJ0cAENeuXbN5TjV83mvXrhWSJIkzZ86Ytynh874bALF27dpaj/GX7/fdHLlua5T4/b6bI9ftL9/vu7nyefvD91sIIQoLCwUAsW3bNpvHeOs7rqieodu3b2Pfvn0YOnSoxfahQ4di586dVp+za9euGscPGzYMe/fuRUVFRa3H2Dqnt7ly3dUZjUbcuHGjxmJ3N2/eRKtWrRAXF4eMjIwaf1n6Ul2uu1OnToiOjsagQYOQk5NjsU8Nn/f777+PwYMH16jSLufP2xX+8P12ByV+v+tCyd9vd/CX77derweAWhdh9dZ3XFHBUFFREQwGQ43V6ps3b15jVfsqBQUFVo+vrKxEUVFRrcfYOqe3uXLd1f31r39FSUkJxo0bZ96WnJyM5cuX44svvsCqVasQGhqK3r1749SpU25tv6tcue7o6Gi89957WLNmDbKzs5GUlIRBgwZh+/bt5mP8/fO+dOkSvvzySzz55JMW2+X+ebvCH77f7qDE77cr/OH7XVf+8v0WQmDGjBno06cP0tPTbR7nre+4YpbjuJskSRY/CyFqbLN3fPXtzp7TF1xt46pVqzBnzhx8/vnniIqKMm/v2bMnevbsaf65d+/e6Ny5M/72t79h8eLF7mt4HTlz3UlJSUhKSjL/3KtXL+Tn5+Mvf/kL+vXr59I5fcXVNi5fvhyNGjXCmDFjLLYr5fN2lr98v12l9O+3M/zp++0qf/l+P//88/jhhx/wzTff2D3WG99xRfUMNW3aFIGBgTWivcLCwhpRYZUWLVpYPT4oKAhNmjSp9Rhb5/Q2V667yieffIInnngCn376KQYPHlzrsQEBAejWrZts/pKoy3XfrWfPnhbX5M+ftxAC//73vzFx4kSEhITUeqzcPm9X+MP3uy6U/P12F6V9v+vCX77fL7zwAr744gvk5OQgLi6u1mO99R1XVDAUEhKCLl26YNOmTRbbN23ahPvuu8/qc3r16lXj+K+//hpdu3ZFcHBwrcfYOqe3uXLdgOkvxsmTJ2PlypXQarV2X0cIgYMHDyI6OrrObXYHV6+7ugMHDlhck79+3oBptsaPP/6IJ554wu7ryO3zdoU/fL9dpfTvt7so7ftdF0r/fgsh8PzzzyM7Oxtbt25FYmKi3ed47TvucKq1THz88cciODhYvP/+++Lo0aMiKytL1K9f35xVP3PmTDFx4kTz8T/99JMICwsTL774ojh69Kh4//33RXBwsFi9erX5mG+//VYEBgaKP//5z+LYsWPiz3/+swgKChK7d+/2+vXZ4ux1r1y5UgQFBYl33nlHXLp0yfy4fv26+Zg5c+aIr776Spw+fVocOHBATJkyRQQFBYnvvvvO69dni7PX/fbbb4u1a9eKkydPisOHD4uZM2cKAGLNmjXmY/zx867y6KOPih49elg9pxI+7xs3bogDBw6IAwcOCADirbfeEgcOHBBnz54VQvjv99vZ6/aX77ez1+0v329nr7uK0r/fzz77rIiIiBC5ubkW/25LS0vNx/jqO664YEgIId555x3RqlUrERISIjp37mwxLW/SpEmif//+Fsfn5uaKTp06iZCQEJGQkCD+/ve/1zjnZ599JpKSkkRwcLBITk62+HLJhTPX3b9/fwGgxmPSpEnmY7KyskTLli1FSEiIaNasmRg6dKjYuXOnF6/IMc5c95tvvinatGkjQkNDRePGjUWfPn2ETqercU5/+7yFEOL69euiXr164r333rN6PiV83lVTp239u/XX77ez1+0v329nr9tfvt+u/Dv3h++3tWsGIJYtW2Y+xlffcemXBhIRERGpkqJyhoiIiIjcjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISJSpFWrViE0NBQXLlwwb3vyySfRvn176PV6H7aMiJSGa5MRkSIJIdCxY0f07dsXS5Yswdy5c/Gvf/0Lu3fvRmxsrK+bR0QKEuTrBhARuUKSJMybNw9jx45FTEwMFi1ahB07djAQIiKnsWeIiBStc+fOOHLkCL7++mv079/f180hIgVizhARKdbGjRtx/PhxGAwGNG/e3NfNISKFYs8QESnS/v37MWDAALzzzjv4+OOPERYWhs8++8zXzSIiBWLOEBEpzpkzZ6DVajFz5kxMnDgRqamp6NatG/bt24cuXbr4unlEpDDsGSIiRbl69Sp69+6Nfv364R//+Id5++jRo1FeXo6vvvrKh60jIiViMERERESqxgRqIiIiUjUGQ0RERKRqDIaIiIhI1RgMERERkaoxGCIiIiJVYzBEREREqsZgiIiIiFSNwRARERGpGoMhIiIiUjUGQ0RERKRqDIaIiIhI1RgMERERkar9fyG0bL25DTIKAAAAAElFTkSuQmCC",
"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": "1bc83f33",
"metadata": {},
"source": [
"## Same code but now with momentum gradient descent"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "dc2a3f65",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Own inversion\n",
"[[4.]\n",
" [3.]]\n",
"Eigenvalues of Hessian Matrix:[0.27750534 4.13217667]\n",
"0 [-10.24816468] [-11.05638246]\n",
"1 [-0.1602625] [0.14404536]\n",
"2 [-0.14949972] [0.13437168]\n",
"3 [-0.13945974] [0.12534765]\n",
"4 [-0.13009402] [0.11692966]\n",
"5 [-0.12135727] [0.10907699]\n",
"6 [-0.11320726] [0.10175169]\n",
"7 [-0.10560458] [0.09491833]\n",
"8 [-0.09851247] [0.08854388]\n",
"9 [-0.09189665] [0.08259753]\n",
"10 [-0.08572513] [0.07705051]\n",
"11 [-0.07996807] [0.07187601]\n",
"12 [-0.07459764] [0.06704902]\n",
"13 [-0.06958788] [0.0625462]\n",
"14 [-0.06491455] [0.05834577]\n",
"15 [-0.06055507] [0.05442743]\n",
"16 [-0.05648836] [0.05077224]\n",
"17 [-0.05269476] [0.04736252]\n",
"18 [-0.04915593] [0.04418179]\n",
"19 [-0.04585476] [0.04121466]\n",
"20 [-0.04277528] [0.0384468]\n",
"21 [-0.03990261] [0.03586482]\n",
"22 [-0.03722287] [0.03345624]\n",
"23 [-0.03472308] [0.03120942]\n",
"24 [-0.03239118] [0.02911348]\n",
"25 [-0.03021588] [0.0271583]\n",
"26 [-0.02818667] [0.02533443]\n",
"27 [-0.02629373] [0.02363304]\n",
"28 [-0.02452792] [0.02204591]\n",
"29 [-0.02288069] [0.02056537]\n",
"theta from own gd\n",
"[[3.92308585]\n",
" [3.06913112]]\n",
"0 [-0.02134409] [0.01918426]\n",
"1 [-0.01991068] [0.01789589]\n",
"2 [-0.01814351] [0.01630755]\n",
"3 [-0.01639489] [0.01473588]\n",
"4 [-0.01476927] [0.01327475]\n",
"5 [-0.01328972] [0.01194492]\n",
"6 [-0.01195336] [0.01074379]\n",
"7 [-0.0107497] [0.00966192]\n",
"8 [-0.00966668] [0.0086885]\n",
"9 [-0.00869259] [0.00781297]\n",
"10 [-0.00781659] [0.00702562]\n",
"11 [-0.00702885] [0.00631759]\n",
"12 [-0.00632049] [0.00568091]\n",
"13 [-0.00568352] [0.00510839]\n",
"14 [-0.00511073] [0.00459357]\n",
"15 [-0.00459568] [0.00413064]\n",
"16 [-0.00413253] [0.00371435]\n",
"17 [-0.00371605] [0.00334002]\n",
"18 [-0.00334155] [0.00300342]\n",
"19 [-0.00300479] [0.00270073]\n",
"20 [-0.00270197] [0.00242856]\n",
"21 [-0.00242967] [0.00218381]\n",
"22 [-0.00218481] [0.00196372]\n",
"23 [-0.00196462] [0.00176582]\n",
"24 [-0.00176663] [0.00158786]\n",
"25 [-0.00158859] [0.00142784]\n",
"26 [-0.00142849] [0.00128394]\n",
"27 [-0.00128453] [0.00115455]\n",
"28 [-0.00115508] [0.00103819]\n",
"29 [-0.00103867] [0.00093356]\n",
"theta from own gd wth momentum\n",
"[[3.99663433]\n",
" [3.00302509]]\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": "0ef007d0",
"metadata": {},
"source": [
"## But noen of these can compete with Newton's method"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "0e498aa4",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Own inversion\n",
"[[3.81924504]\n",
" [3.09224244]]\n",
"Eigenvalues of Hessian Matrix:[0.31096156 4.57735536]\n",
"0 [-15.77829399] [-18.53684024]\n",
"1 [-3.15242624e-15] [-1.65243388e-16]\n",
"2 [3.85975973e-17] [5.35468713e-17]\n",
"3 [3.85975973e-17] [5.35468713e-17]\n",
"4 [3.85975973e-17] [5.35468713e-17]\n",
"beta from own Newton code\n",
"[[3.81924504]\n",
" [3.09224244]]\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": "40292cf3",
"metadata": {},
"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": "fa819b9d",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Own inversion\n",
"[[3.84019294]\n",
" [3.22756518]]\n",
"Eigenvalues of Hessian Matrix:[0.2729933 4.56108455]\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"theta from own gd\n",
"[[3.84019294]\n",
" [3.22756518]]\n"
]
},
{
"data": {
"image/png": "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jcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrmNcHQO++8g4SEBISEhKBjx47YunWrp4tEREREPsArgqHVq1dj2rRpeP7557Fr1y706tULAwcOxIkTJzxdNCIiIvJykhBCeLoQtnTp0gUdOnTAu+++a1qWmJiIYcOGYf78+Tb3LyoqQlhYGAoLCxEaGurKohIREZFM3PX8VnzN0PXr1/H777+jf//+Zsv79++PX375xUOlIiIiIl8R4OkC2HLu3DnodDpERUWZLY+KikJ+fr7FfUpLS1FaWmp6XVhYCMAQYRIREZF3MD63Xd2IpfhgyEiSJLPXQogqy4zmz5+PuXPnVlkeHx/vkrIRERGR65w/fx5hYWEuO77ig6GGDRvC39+/Si1QQUFBldoio1mzZiEtLc30+tKlS2jatClOnDjh0jdTaYqKihAfH4/c3FxV9ZXidfO61YDXzetWg8LCQjRp0gTh4eEuPY/ig6GgoCB07NgRGzZswPDhw03LN2zYgNTUVIv7BAcHIzg4uMrysLAwVX2JjEJDQ3ndKsLrVhdet7qo9br9/FzbxVnxwRAApKWlYezYsejUqRO6deuGZcuW4cSJE/jHP/7h6aIRERGRl/OKYOj+++/H+fPn8eKLLyIvLw9JSUn49ttv0bRpU08XjYiIiLycVwRDADBx4kRMnDjRqX2Dg4Mxe/Zsi01nvozXzetWA143r1sNeN2uvW6vmHSRiIiIyFUUP+kiERERkSsxGCIiIiJVYzBEREREqsZgiIiIiFTNK4Ohd955BwkJCQgJCUHHjh2xdevWarffvHkzOnbsiJCQENxyyy147733qmyTnp6OVq1aITg4GK1atcKaNWtcVXynOXLdWq0Wd999Nxo1aoTQ0FB069YNP/zwg9k2y5cvhyRJVX5KSkpcfSkOceS6MzMzLV7TwYMHzbbztc97woQJFq+7devWpm284fPesmULhg4dipiYGEiShLVr19rcxxfub0ev21fub0ev21fub0ev21fu7/nz5+OOO+5AvXr1EBkZiWHDhuHQoUM293PHPe51wdDq1asxbdo0PP/889i1axd69eqFgQMH4sSJExa3z8nJwaBBg9CrVy/s2rULzz33HKZOnYr09HTTNtu3b8f999+PsWPHYs+ePRg7dixGjRqFX3/9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",
"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.85298956]\n",
" [3.28358004]]\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": "2ca466b4",
"metadata": {},
"source": [
"## Same code but now with momentum gradient descent"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "0d44a49c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Own inversion\n",
"[[4.1356995 ]\n",
" [3.09209032]]\n",
"Eigenvalues of Hessian Matrix:[0.31362428 4.21949761]\n",
"theta from own gd\n",
"[[4.13531906]\n",
" [3.09242193]]\n",
"theta from own sdg with momentum\n",
"[[4.25003261]\n",
" [3.05169046]]\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": "b82627f6",
"metadata": {},
"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": "00d3aff0",
"metadata": {},
"source": [
"## Similar (second order function now) problem but now with AdaGrad"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "6b85aacc",
"metadata": {},
"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.00006114]\n",
" [2.99959609]\n",
" [4.00040218]]\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": "d8ddde38",
"metadata": {},
"source": [
"Running this code we note an almost perfect agreement with the results from matrix inversion."
]
},
{
"cell_type": "markdown",
"id": "ff15b503",
"metadata": {},
"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": "66f96d12",
"metadata": {},
"source": [
"## RMSprop for adaptive learning rate with Stochastic Gradient Descent"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "888f1b4e",
"metadata": {},
"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.99952851]\n",
" [3.00380258]\n",
" [3.995522 ]]\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": "2e0860f7",
"metadata": {},
"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": "ab4a9859",
"metadata": {},
"source": [
"## And finally [ADAM](https://arxiv.org/pdf/1412.6980.pdf)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "ccdd4d77",
"metadata": {},
"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.99984836]\n",
" [3.00097416]\n",
" [3.99895448]]\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": "25ac988c",
"metadata": {},
"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": "37d556d0",
"metadata": {},
"source": [
"### Getting started with Jax, note the way we import numpy"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "5b81d6e4",
"metadata": {},
"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": "c42db672",
"metadata": {},
"source": [
"### A warm-up example"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "98eb2f26",
"metadata": {},
"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 0x145270160>]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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",
"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": "8a5f19b5",
"metadata": {},
"source": [
"### A more advanced example"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "d8f5eb38",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.collections.PathCollection at 0x1452d6eb0>"
]
},
"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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {
"filenames": {
"image/png": "/Users/mhjensen/Teaching/MachineLearning/doc/LectureNotes/_build/jupyter_execute/exercisesweek41_41_1.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": {
"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"
}
},
"nbformat": 4,
"nbformat_minor": 5
}