Files
FYS-STK4155/doc/LectureNotes/_build/jupyter_execute/exercisesweek41.ipynb
T
Morten Hjorth-Jensen a7012b5326 update
2024-10-14 09:13:10 +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",
"[[4.1729993]\n",
" [3.0170097]]\n",
"Eigenvalues of Hessian Matrix:[0.28192769 4.68753434]\n",
"theta from own gd\n",
"[[4.1729993]\n",
" [3.0170097]]\n",
"theta from own sdg\n",
"[[4.14043884]\n",
" [2.99071523]]\n"
]
},
{
"data": {
"image/png": "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22zbtg233XYbJk2ahJ9//hmTJk3C+PHj8f333/vqsJxy97g3b96MYcOG4bPPPsNPP/2EtLQ0GAwG7Ny502a7iIgInDx50uYVFhbmi0NyibvHbXHgwAGbY2rfvr11nT9e7yVLltgcb0FBAaKionDrrbfabKf2611WVobrrrsOS5cudWl7f/l9u3vc/vL7dve4LbT++3b3uP3l971p0yZMmzYN3333HdavX4+qqioMHz4cZWVlDj/js9+40JgbbrhB3H///TbLkpOTxZw5c+xu/49//EMkJyfbLLvvvvtE3759re/Hjx8vRo4cabPNiBEjxF//+leZSl1/7h63PZ07dxbz58+3vl++fLmIjIyUq4he4e5x5+bmCgDi/PnzDveph+u9Zs0aIUmSOHz4sHWZFq53dQDEmjVr6tzGX37f1bly3PZo8fddnSvH7S+/7+o8ud7+8PsWQoiioiIBQGzatMnhNr76jWuqZujKlSv46aefMHz4cJvlw4cPx7fffmv3M9u2bau1/YgRI/Djjz+isrKyzm0c7dPXPDnumkwmEy5evFhrsrvS0lK0bt0aCQkJSE9Pr/WXpZLqc9w9evRAbGwshgwZgtzcXJt1erjeb731FoYOHVorS7uar7cn/OH3LQct/r7rQ8u/bzn4y++7uLgYAOqchNVXv3FNBUNnzpyB0WisNVt9TExMrVntLQoLC+1uX1VVhTNnztS5jaN9+ponx13TCy+8gLKyMowfP966LDk5GStWrMCnn36KlStXIiwsDP3798fBgwdlLb+nPDnu2NhYvPHGG1i9ejWysrLQsWNHDBkyBJs3b7Zu4+/X++TJk/j8889xzz332CxX+/X2hD/8vuWgxd+3J/zh911f/vL7FkJg1qxZGDBgAFJSUhxu56vfuGam46hOkiSb90KIWsucbV9zubv7VIKnZVy5ciXmzZuHTz75BNHR0dblffv2Rd++fa3v+/fvj549e+KVV17Byy+/LF/B68md4+7YsSM6duxofd+vXz8UFBTg+eefx8CBAz3ap1I8LeOKFSvQpEkTjB071ma5Vq63u/zl9+0prf++3eFPv29P+cvve/r06fjll1/wzTffON3WF79xTdUMNW/eHIGBgbWivaKiolpRoUXLli3tbh8UFIRmzZrVuY2jffqaJ8dt8eGHH+Luu+/GRx99hKFDh9a5bUBAAK6//nrV/CVRn+Ourm/fvjbH5M/XWwiBt99+G5MmTUJISEid26rtenvCH37f9aHl37dctPb7rg9/+X3PmDEDn376KXJzc5GQkFDntr76jWsqGAoJCUGvXr2wfv16m+Xr16/HjTfeaPcz/fr1q7X9V199hd69eyM4OLjObRzt09c8OW7A/BfjlClTkJmZidGjRzv9HiEEdu3ahdjY2HqXWQ6eHndNO3futDkmf73egHm0xqFDh3D33Xc7/R61XW9P+MPv21Na/33LRWu/7/rQ+u9bCIHp06cjKysLGzduRFJSktPP+Ow37nJXa5X44IMPRHBwsHjrrbfEvn37xMyZM0XDhg2tvernzJkjJk2aZN3+jz/+EOHh4eLhhx8W+/btE2+99ZYIDg4Wq1atsm6zdetWERgYKP7zn/+IX3/9VfznP/8RQUFB4rvvvvP58Tni7nFnZmaKoKAgsWzZMnHy5Enr68KFC9Zt5s2bJ7744gvx+++/i507d4o777xTBAUFie+//97nx+eIu8f90ksviTVr1ojffvtN7NmzR8yZM0cAEKtXr7Zu44/X2+L2228Xffr0sbtPLVzvixcvip07d4qdO3cKAOLFF18UO3fuFEeOHBFC+O/v293j9pfft7vH7S+/b3eP20Lrv+8HHnhAREZGiry8PJv79tKlS9ZtlPqNay4YEkKIZcuWidatW4uQkBDRs2dPm2F5kydPFoMGDbLZPi8vT/To0UOEhISINm3aiNdee63WPj/++GPRsWNHERwcLJKTk21+XGrhznEPGjRIAKj1mjx5snWbmTNnilatWomQkBDRokULMXz4cPHtt9/68Ihc485xP/fcc6Jdu3YiLCxMNG3aVAwYMECsW7eu1j797XoLIcSFCxdEgwYNxBtvvGF3f1q43pah047uW3/9fbt73P7y+3b3uP3l9+3Jfe4Pv297xwxALF++3LqNUr9x6WoBiYiIiHRJU32GiIiIiOTGYIiIiIh0jcEQERER6RqDISIiItI1BkNERESkawyGiIiISNcYDBEREZGuMRgiIiIiXWMwRERERLrGYIiIiIh0jcEQEWnSypUrERYWhuPHj1uX3XPPPejWrRuKi4sVLBkRaQ3nJiMiTRJCoHv37khNTcXSpUsxf/58vPnmm/juu+8QHx+vdPGISEOClC4AEZEnJEnCggULMG7cOMTFxWHJkiXYsmULAyEichtrhohI03r27Im9e/fiq6++wqBBg5QuDhFpEPsMEZFmffnll9i/fz+MRiNiYmKULg4RaRRrhohIk3bs2IHBgwdj2bJl+OCDDxAeHo6PP/5Y6WIRkQaxzxARac7hw4cxevRozJkzB5MmTULnzp1x/fXX46effkKvXr2ULh4RaQxrhohIU86dO4f+/ftj4MCB+O9//2tdPmbMGFRUVOCLL75QsHREpEUMhoiIiEjX2IGaiIiIdI3BEBEREekagyEiIiLSNQZDREREpGsMhoiIiEjXGAwRERGRrjEYIiIiIl1jMERERES6xmCIiIiIdI3BEBEREekagyEiIiLSNQZDREREpGv/H5fdgFdQP4w4AAAAAElFTkSuQmCC",
"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",
"#while (iter <= Ni... or test)\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.03696458]\n",
" [3.0324793 ]]\n",
"Eigenvalues of Hessian Matrix:[0.30959659 4.4150026 ]\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"theta from own gd\n",
"[[4.03696458]\n",
" [3.0324793 ]]\n"
]
},
{
"data": {
"image/png": "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++LFizFp0iSHzsGh9URERMrDPkPXyTyrERERkcIpamg9ERERkbsxDBEREZGqMQwRERGRqjEMERERkaoxDBEREZGqMQwRERGRqjEMERERkaoxDBEREZGqMQwRERGRqjEMERERkaoxDBEREZGqMQwRERGRqjEMERERkaoxDBEREZGqMQwRERGRqjEMERERkaoxDBEREZGqMQwRERGRqjEMERERkaoxDBEREZGqMQwRERGRqjEMERERkaoxDBEREZGqMQwRERGRqjEMERERkaoxDBEREZGqMQwRERGRqjEMERERkaoxDBEREZGqMQwRERGRqjEMERERkaoxDBEREZGqMQwRERGRqjEMERERkaoxDBEREZGqMQwRERGRqjEMERERkaoxDBEREZGqKSYMvf3220hJSUFYWBh69OiBTZs2+bpIRERE5AcUEYaWLVuG7OxsPPvss9i5cycyMjIwbNgwHD9+3NdFIyIiIoWThBDC14Wwp3fv3ujevTveeecd87YOHTpg9OjRmDt3rt3Hl5aWIjIyEjqdDhEREZ4sKhEREbmJt+7fsq8ZunbtGn7++WcMGTLEYvuQIUOwZcsWH5WKiIiI/EWQrwtgz9mzZ6HX69GiRQuL7S1atEBJSYnVx1RUVKCiosL8s06nA2BMmERERKQMpvu2pxuxZB+GTCRJsvhZCFFrm8ncuXMxZ86cWtuTkpI8UjYiIiLynHPnziEyMtJj55d9GGrWrBkCAwNr1QKdPn26Vm2RyaxZszB9+nTzzxcvXkSrVq1w/Phxj76YclNaWoqkpCQUFhaqqq8Ur5vXrQa8bl63Guh0OrRs2RJRUVEefR7Zh6GQkBD06NEDa9euxV133WXevnbtWowaNcrqY0JDQxEaGlpre2RkpKp+iUwiIiJ43SrC61YXXre6qPW6AwI828VZ9mEIAKZPn44JEyagZ8+e6NOnD9577z0cP34cjz76qK+LRkRERAqniDB0zz334Ny5c/j73/+O4uJipKen48svv0SrVq18XTQiIiJSOEWEIQCYPHkyJk+e7NJjQ0ND8cILL1htOvNnvG5etxrwunndasDr9ux1K2LSRSIiIiJPkf2ki0RERESexDBEREREqsYwRERERKrGMERERESqpsgw9PbbbyMlJQVhYWHo0aMHNm3aVOfxGzZsQI8ePRAWFobWrVvj3XffrXXM8uXL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m4ZO2/q99dfPt7PX7S+fb2ev218+3678nvvD59vaNQMQixcvNh/jq8+4dL2ARERERKqkqD5DRERERO7GMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMERERESqxjBEREREqsYwRERERKrGMEREirR06VKEhYWhqKjIvO2hhx5C586dodPpfFgyIlIark1GRIokhEDXrl2RkZGBRYsWYc6cOXj//fexbds2JCQk+Lp4RKQgQb4uABGRKyRJwssvv4wxY8YgPj4eCxcuxKZNmxiEiMhprBkiIkXr3r079u7di2+//Ra33nqrr4tDRArEPkNEpFjffPMNDhw4AL1ejxYtWvi6OESkUKwZIiJF2rFjBwYOHIi33noLn3zyCcLDw/HZZ5/5ulhEpEDsM0REinP06FEMHz4cM2fOxIQJE5CWloabb74ZP//8M3r06OHr4hGRwrBmiIgU5fz58+jXrx8GDBiAf/3rX+bto0aNQkVFBb7++msflo6IlIhhiIiIiFSNHaiJiIhI1RiGiIiISNUYhoiIiEjVGIaIiIhI1RiGiIiISNUYhoiIiEjVGIaIiIhI1RiGiIiISNUYhoiIiEjVGIaIiIhI1RiGiIiISNUYhoiIiEjV/h9yWzJp60J2fAAAAABJRU5ErkJggg==",
"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.23469347 4.90407685]\n",
"0 [-18.02987043] [-22.42501752]\n",
"1 [-0.32329897] [0.25206371]\n",
"2 [-0.30782691] [0.24000075]\n",
"3 [-0.2930953] [0.22851508]\n",
"4 [-0.27906869] [0.21757908]\n",
"5 [-0.26571335] [0.20716644]\n",
"6 [-0.25299716] [0.19725211]\n",
"7 [-0.24088952] [0.18781225]\n",
"8 [-0.22936132] [0.17882416]\n",
"9 [-0.21838482] [0.17026621]\n",
"10 [-0.20793362] [0.16211781]\n",
"11 [-0.19798258] [0.15435937]\n",
"12 [-0.18850776] [0.14697222]\n",
"13 [-0.17948638] [0.1399386]\n",
"14 [-0.17089674] [0.13324158]\n",
"15 [-0.16271817] [0.12686507]\n",
"16 [-0.15493099] [0.12079371]\n",
"17 [-0.14751649] [0.11501291]\n",
"18 [-0.14045682] [0.10950876]\n",
"19 [-0.13373501] [0.10426802]\n",
"20 [-0.12733488] [0.09927808]\n",
"21 [-0.12124104] [0.09452695]\n",
"22 [-0.11543883] [0.09000319]\n",
"23 [-0.10991429] [0.08569593]\n",
"24 [-0.10465415] [0.08159479]\n",
"25 [-0.09964573] [0.07768993]\n",
"26 [-0.094877] [0.07397193]\n",
"27 [-0.09033649] [0.07043187]\n",
"28 [-0.08601328] [0.06706123]\n",
"29 [-0.08189696] [0.06385189]\n",
"theta from own gd\n",
"[[3.66774691]\n",
" [3.25904489]]\n",
"0 [-0.07797763] [0.06079614]\n",
"1 [-0.07424587] [0.05788664]\n",
"2 [-0.06957317] [0.05424351]\n",
"3 [-0.06484181] [0.05055465]\n",
"4 [-0.06031928] [0.04702861]\n",
"5 [-0.05607583] [0.04372016]\n",
"6 [-0.05211919] [0.04063532]\n",
"7 [-0.04843794] [0.03776519]\n",
"8 [-0.04501548] [0.03509683]\n",
"9 [-0.04183444] [0.0326167]\n",
"10 [-0.03887807] [0.03031173]\n",
"11 [-0.03613058] [0.02816961]\n",
"12 [-0.03357723] [0.02617887]\n",
"13 [-0.03120433] [0.02432881]\n",
"14 [-0.02899912] [0.02260949]\n",
"15 [-0.02694975] [0.02101168]\n",
"16 [-0.02504521] [0.01952679]\n",
"17 [-0.02327527] [0.01814683]\n",
"18 [-0.0216304] [0.01686439]\n",
"19 [-0.02010178] [0.01567258]\n",
"20 [-0.01868119] [0.014565]\n",
"21 [-0.01736099] [0.01353569]\n",
"22 [-0.01613409] [0.01257912]\n",
"23 [-0.01499389] [0.01169016]\n",
"24 [-0.01393427] [0.01086401]\n",
"25 [-0.01294954] [0.01009625]\n",
"26 [-0.01203439] [0.00938275]\n",
"27 [-0.01118392] [0.00871967]\n",
"28 [-0.01039355] [0.00810345]\n",
"29 [-0.00965904] [0.00753078]\n",
"theta from own gd wth momentum\n",
"[[3.96175251]\n",
" [3.02982009]]\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",
"[[4.15451852]\n",
" [2.83230774]]\n",
"Eigenvalues of Hessian Matrix:[0.30616802 4.24299211]\n",
"0 [-10.57502449] [-11.57610367]\n",
"1 [-4.47905601e-15] [-4.07372439e-16]\n",
"2 [-6.9388939e-16] [-7.21432413e-16]\n",
"3 [-6.9388939e-16] [-7.21432413e-16]\n",
"4 [-6.9388939e-16] [-7.21432413e-16]\n",
"beta from own Newton code\n",
"[[4.15451852]\n",
" [2.83230774]]\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",
"[[4.04601419]\n",
" [3.12204312]]\n",
"Eigenvalues of Hessian Matrix:[0.33604208 4.45709724]\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"theta from own gd\n",
"[[4.04601419]\n",
" [3.12204312]]\n"
]
},
{
"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_22_2.png"
}
},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"theta from own sdg\n",
"[[4.02781444]\n",
" [3.13976073]]\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",
"[[3.96417888]\n",
" [3.06634473]]\n",
"Eigenvalues of Hessian Matrix:[0.32962444 4.18715465]\n",
"theta from own gd\n",
"[[3.9639885]\n",
" [3.0665111]]\n",
"theta from own sdg with momentum\n",
"[[4.00842216]\n",
" [3.14285244]]\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",
"[[1.99969895]\n",
" [3.00167058]\n",
" [3.99835872]]\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.99852187]\n",
" [3.03868311]\n",
" [3.95744254]]\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.99996471]\n",
" [3.00026784]\n",
" [3.99973141]]\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 0x11892e7f0>]"
]
},
"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 0x118995f70>"
]
},
"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.15"
}
},
"nbformat": 4,
"nbformat_minor": 5
}