Files
FYS-STK4155/doc/LectureNotes/_build/jupyter_execute/exercisesweek41.ipynb
T
Morten Hjorth-Jensen 3147098147 update
2024-11-17 15:55:37 +01:00

1382 lines
202 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.0010275 ]\n",
" [3.10085547]]\n",
"Eigenvalues of Hessian Matrix:[0.32462943 4.22813513]\n",
"theta from own gd\n",
"[[4.0010275 ]\n",
" [3.10085547]]\n",
"theta from own sdg\n",
"[[4.08051993]\n",
" [3.13522576]]\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAkMAAAHHCAYAAAC88FzIAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABYvklEQVR4nO3deXyM1/4H8M+TkASVkCDrIHZJLC2lVNooqmoZRau6oa1uqjdFf622qNslWlq01dJNeq+iljC6UUuCtqhWXWKJpUHEEusEIWTm/P6Yzsgks2eWZ+b5vF+vecU825wzM/J8c873nCMJIQSIiIiIFCrI1wUgIiIi8iUGQ0RERKRoDIaIiIhI0RgMERERkaIxGCIiIiJFYzBEREREisZgiIiIiBSNwRAREREpGoMhIiIiUjQGQ0TksBEjRqBx48a+Loas5eTkQJIkLF261NdFISIHMRgikqHMzExIkmR6VKtWDfHx8RgxYgQKCwt9XTwiooBSzdcFICLr/v3vfyMxMRFXr17Fli1bkJmZiV9++QW5ubkICwvzdfGIiAICgyEiGevTpw86duwIAHjyySdRr149vPvuu1i5ciUeeOABH5eOfOny5cuoVauWr4tBFBDYTUbkR1JTUwEAhw4dMm27du0aJk2ahA4dOiAiIgK1atVCamoqsrOzzc49fPgwJEnC9OnT8dlnn6Fp06YIDQ3Frbfeim3btlV6rRUrViAlJQVhYWFISUnB8uXLLZbp8uXLGDduHFQqFUJDQ9GyZUtMnz4dQgiz4yRJwvPPP48lS5YgKSkJNWrUQJcuXbBr1y4AwNy5c9GsWTOEhYUhLS0Nhw8ftvt+vPHGG5AkCQcPHsSIESNQp04dREREYOTIkSgpKalU98zMzErXkCQJb7zxRqVr7t+/H4888ggiIiJQv359TJw4EUIIFBQUQK1WIzw8HDExMXj//fctlk2n0+HVV19FTEwMatWqhQEDBqCgoKDScVu3bsU999yDiIgI1KxZE3feeSd+/fVXi/Xcs2cPHnroIdStWxfdunUDAJw8eRIjR45EQkICQkNDERsbC7Va7dD7R0QGbBki8iPGG1zdunVN24qLi/HFF19g2LBhGDVqFC5evIgvv/wSvXv3xu+//4727dubXWPBggW4ePEinn76aUiShPfeew+DBg3C33//jerVqwMAfv75ZwwePBhJSUnIyMjA2bNnTTfc8oQQGDBgALKzs/HEE0+gffv2WL16NV566SUUFhZixowZZsdv2rQJK1euxOjRowEAGRkZ6NevH/7v//4Pn3zyCZ577jmcP38e7733Hh5//HGsX7/eofflgQceQGJiIjIyMrB9+3Z88cUXaNCgAd59911n3l4zQ4cORevWrTF16lT88MMPeOuttxAZGYm5c+firrvuwrvvvotvvvkG48ePx6233oo77rjD7Py3334bkiTh5ZdfRlFREWbOnImePXtix44dqFGjBgBg/fr16NOnDzp06IDJkycjKCgI8+bNw1133YVNmzahU6dOZte8//770bx5c7zzzjumYHPw4MHYvXs3xowZg8aNG6OoqAhr1qzB0aNHmexO5ChBRLIzb948AUCsXbtWnD59WhQUFIilS5eK+vXri9DQUFFQUGA6tqysTJSWlpqdf/78eREdHS0ef/xx07b8/HwBQERFRYlz586Ztms0GgFAfPfdd6Zt7du3F7GxseLChQumbT///LMAIBo1amTatmLFCgFAvPXWW2avP2TIECFJkjh48KBpGwARGhoq8vPzTdvmzp0rAIiYmBhRXFxs2j5hwgQBwOxYSyZPniwAmNVTCCHuu+8+ERUVVanu8+bNq3QNAGLy5MmVrvnUU0+ZtpWVlYmEhAQhSZKYOnWqafv58+dFjRo1xPDhw03bsrOzBQARHx9vVqfFixcLAGLWrFlCCCH0er1o3ry56N27t9Dr9abjSkpKRGJioujVq1elMg0bNsys7OfPnxcAxLRp02y+T0RkG7vJiGSsZ8+eqF+/PlQqFYYMGYJatWph5cqVZi00wcHBCAkJAQDo9XqcO3cOZWVl6NixI7Zv317pmkOHDjVrWTJ2vf39998AgBMnTmDHjh0YPnw4IiIiTMf16tULSUlJZtf68ccfERwcjBdeeMFs+7hx4yCEwE8//WS2vUePHmatFZ07dwZgaN2oXbt2pe3GMtnzzDPPmD1PTU3F2bNnUVxc7ND5ljz55JOmfwcHB6Njx44QQuCJJ54wba9Tpw5atmxpsZyPPfaYWZ2GDBmC2NhY/PjjjwCAHTt24MCBA3jooYdw9uxZnDlzBmfOnMHly5fRo0cPbNy4EXq93mY9a9SogZCQEOTk5OD8+fMu15VI6dhNRiRjs2fPRosWLaDVavHVV19h48aNCA0N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TUJsbCxq1KiBnj174sCBA56sgkucqffnn3+O1NRU1K1bF3Xr1kXPnj0rHT9ixAhIkmT2uOeeezxdDac5U+/MzMxKdQoLCzM7JhA/77S0tEr1liQJffv2NR3jD5/3xo0b0b9/f8TFxUGSJKxYscLuOTk5ObjlllsQGhqKZs2aITMzs9Ixzv7O8DZn652VlYVevXqhfv36CA8PR5cuXbB69WqzY954441Kn3erVq08WAvnOVvvnJwci9/zkydPmh0XaJ+3pf+7kiQhOTnZdIw/fN4ZGRm49dZbUbt2bTRo0AADBw5EXl6e3fO8cQ/3u2Do22+/xdixYzF58mRs374d7dq1Q+/evVFUVGTx+N9++w3Dhg3DE088gb/++gsDBw7EwIEDkZubazrmvffew4cffog5c+Zg69atqFWrFnr37o2rV696q1p2OVvvnJwcDBs2DNnZ2di8eTNUKhXuvvtuFBYWmh13zz334MSJE6bHwoULvVEdhzlbb8AwQ2v5Oh05csRsfyB+3llZWWZ1zs3NRXBwMO6//36z4+T+eV++fBnt2rXD7NmzHTo+Pz8fffv2Rffu3bFjxw6kp6fjySefNAsMXPkOeZuz9d64cSN69eqFH3/8EX/++Se6d++O/v3746+//jI7Ljk52ezz/uWXXzxRfJc5W2+jvLw8s3o1aNDAtC8QP+9Zs2aZ1begoACRkZGV/n/L/fPesGEDRo8ejS1btmDNmjW4fv067r77bly+fNnqOV67hws/06lTJzF69GjTc51OJ+Li4kRGRobF4x944AHRt29fs22dO3cWTz/9tBBCCL1eL2JiYsS0adNM+y9cuCBCQ0PFwoULPVAD1zhb74rKyspE7dq1xddff23aNnz4cKFWq91dVLdytt7z5s0TERERVq+nlM97xowZonbt2uLSpUumbf7weZcHQCxfvtzmMf/3f/8nkpOTzbYNHTpU9O7d2/S8qu+ltzlSb0uSkpLElClTTM8nT54s2rVr576CeZgj9c7OzhYAxPnz560eo4TPe/ny5UKSJHH48GHTNn/7vIUQoqioSAAQGzZssHqMt+7hftUydO3aNfz555/o2bOnaVtQUBB69uyJzZs3Wzxn8+bNZscDQO/evU3H5+fn4+TJk2bHREREoHPnzlav6W2u1LuikpISXL9+vdJidzk5OWjQoAFatmyJZ599FmfP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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"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",
"[[3.8679219 ]\n",
" [3.12497024]]\n",
"Eigenvalues of Hessian Matrix:[0.31887646 4.68712364]\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"theta from own gd\n",
"[[3.8679219 ]\n",
" [3.12497024]]\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAkMAAAHHCAYAAAC88FzIAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABa10lEQVR4nO3deXhTVf4/8Hfa0rQsLZSlO1B2KAUEZBUoggICpoMMiIqAyjgOqB2QUfwNIN/RKZuCozi4goqgLKVFRPYW0AFEK1L2AgVKoex0YSk0Ob8/QkLTJm2S3iT35r5fz9MHeu/Nveckae4nZ/kcjRBCgIiIiEilfDxdACIiIiJPYjBEREREqsZgiIiIiFSNwRARERGpGoMhIiIiUjUGQ0RERKRqDIaIiIhI1RgMERERkaoxGCIiIiJVYzBERHYbO3YsGjdu7OliyFp6ejo0Gg1WrVrl6aIQkZ0YDBHJ0JIlS6DRaMw/fn5+iIyMxNixY5Gbm+vp4hEReRU/TxeAiGz7v//7P8TExOD27dvYvXs3lixZgp9++gkHDhxAQECAp4tHROQVGAwRydigQYPQuXNnAMALL7yAevXqYfbs2Vi7di1GjBjh4dKRJ924cQM1atTwdDGIvAK7yYgUpFevXgCAEydOmLfduXMH06dPR6dOnRAcHIwaNWqgV69eSEtLs3jsqVOnoNFoMG/ePHzyySdo2rQptFotHnzwQezdu7fctVJSUtC2bVsEBASgbdu2WLNmjdUy3bhxA5MnT0Z0dDS0Wi1atmyJefPmQQhhcZxGo8HEiROxcuVKtGnTBoGBgejevTsyMzMBAB9//DGaNWuGgIAAxMfH49SpU5U+H2+99RY0Gg2OHz+OsWPHonbt2ggODsa4ceNw8+bNcnVfsmRJuXNoNBq89dZb5c557NgxPPPMMwgODkb9+vUxbdo0CCGQk5MDnU6HoKAghIWF4d1337VaNr1ejzfffBNhYWGoUaMGHn/8ceTk5JQ7bs+ePRg4cCCCg4NRvXp19OnTBz///LPVeh46dAhPPfUU6tSpg4ceeggAkJeXh3HjxiEqKgparRbh4eHQ6XR2PX9EZMSWISIFMd3g6tSpY95WUFCAzz77DKNGjcL48eNRWFiIzz//HAMGDMAvv/yCDh06WJxj2bJlKCwsxIsvvgiNRoM5c+Zg2LBhOHnyJKpVqwYA2LRpE5544gm0adMGSUlJuHLlivmGW5oQAo8//jjS0tLw/PPPo0OHDti4cSOmTJmC3NxczJ8/3+L4nTt3Yu3atZgwYQIAICkpCUOGDME//vEPfPTRR/jb3/6Ga9euYc6cOXjuueewbds2u56XESNGICYmBklJScjIyMBnn32GBg0aYPbs2Y48vRZGjhyJ1q1bY9asWfjhhx/w9ttvIyQkBB9//DEefvhhzJ49G9988w1ee+01PPjgg+jdu7fF49955x1oNBq8/vrruHjxIhYsWID+/ftj3759CAwMBABs27YNgwYNQqdOnTBjxgz4+Phg8eLFePjhh7Fz50506dLF4px//vOf0bx5c/z73/82B5tPPPEEDh48iJdffhmNGzfGxYsXsXnzZpw5c4aD3YnsJYhIdhYvXiwAiC1btohLly6JnJwcsWrVKlG/fn2h1WpFTk6O+diSkhJRXFxs8fhr166J0NBQ8dxzz5m3ZWdnCwCibt264urVq+btqampAoD4/vvvzds6dOggwsPDxfXr183bNm3aJACIRo0ambelpKQIAOLtt9+2uP7w4cOFRqMRx48fN28DILRarcjOzjZv+/jjjwUAERYWJgoKCszbp06dKgBYHGvNjBkzBACLegohxJ/+9CdRt27dcnVfvHhxuXMAEDNmzCh3zr/85S/mbSUlJSIqKkpoNBoxa9Ys8/Zr166JwMBAMWbMGPO2tLQ0AUBERkZa1GnFihUCgHj//feFEEIYDAbRvHlzMWDAAGEwGMzH3bx5U8TExIhHHnmkXJlGjRplUfZr164JAGLu3LkVPk9EVDF2kxHJWP/+/VG/fn1ER0dj+PDhqFGjBtauXWvRQuPr6wt/f38AgMFgwNWrV1FSUoLOnTsjIyOj3DlHjhxp0bJk6no7efIkAOD8+fPYt28fxowZg+DgYPNxjzzyCNq0aWNxrvXr18PX1xevvPKKxfbJkydDCIEff/zRYnu/fv0sWiu6du0KwNi6UatWrXLbTWWqzF//+leL33v16oUrV66goKDArsdb88ILL5j/7+vri86dO0MIgeeff968vXbt2mjZsqXVcj777LMWdRo+fDjCw8Oxfv16AMC+ffuQlZWFp556CleuXMHly5dx+fJl3LhxA/369cOOHTtgMBgqrGdgYCD8/f2Rnp6Oa9euOV1XIrVjNxmRjC1cuBAtWrRAfn4+vvjiC+zYsQNarbbccV9++SXeffddHDlyBHfv3jVvj4mJKXdsw4YNLX43BUamm+np06cBAM2bNy/32JYtW1oEWKdPn0ZERITFTR8AWrdubXEuW9c2BVvR0dFWt9t7g6+oTkFBQXado7JzBgcHIyAgAPXq1Su3/cqVK+UeX/b502g0aNasmbmrMysrCwAwZswYm2XIz8+3CFzLvp5arRazZ8/G5MmTERoaim7dumHIkCF49tlnERYWVnkliQgAgyEiWevSpYt5NllCQgIeeughPPXUUzh69Chq1qwJAFi6dCnGjh2LhIQETJkyBQ0aNICvry+SkpIsBlqb+Pr6Wr2WKDPg2RVsXbuqZars8RqNxup+vV7v0DmlfO5MrT5z584tN67LxPQam5jGGpWWmJiIoUOHIiUlBRs3bsS0adOQlJSEbdu24YEHHnC4XERqxGCISCFMAU7fvn3x4Ycf4o033gAArFq1Ck2aNEFycrLFTX/GjBlOXadRo0YA7rdclHb06NFyx27ZsgWFhYUWrUNHjhyxOJenmVpXrl+/brG9bMuVlMo+f0IIHD9+HO3atQMANG3aFAAQFBSE/v37V+laTZs2xeTJkzF58mRkZWWhQ4cOePfdd7F06dIqnZdILThmiEhB4uPj0aVLFyxYsAC3b98GcL+1onTrxJ49e7Br1y6nrhEeHo4OHTrgyy+/RH5+vnn75s2bcejQIYtjH3vsMej1enz44YcW2+fPnw+NRoNBgwY5VQapBQUFoV69etixY4fF9o8++shl1/zqq69QWFho/n3VqlU4f/68+Tnp1KkTmjZtinnz5qGoqKjc4y9dulTpNW7evGl+H5g0bdoUtWrVQnFxcRVrQKQebBkiUpgpU6bgz3/+M5YsWYK//vWvGDJkCJKTk/GnP/0JgwcPRnZ2NhYtWoQ2bdpYvcnaIykpCYMHD8ZDDz2E5557DlevXsUHH3yA2NhYi3MOHToUffv2xf/7f/8Pp06dQvv27bFp0yakpqYiMTHR3PohBy+88AJmzZqFF154AZ07d8aOHTtw7Ngxl10vJCQEDz30EMaNG4cLFy5gwYIFaNasGcaPHw8A8PHxwWeffYZBgwYhNjYW48aNQ2RkJHJzc5GWloagoCB8//33FV7j2LFj6NevH0aMGIE2bdrAz88Pa9aswYULF/Dkk0+6rG5E3obBEJHCDBs2zNyiMH78eIwdOxZ5eXn4+OOPsXHjRrRp0wZLly7FypUrkZ6e7tQ1Bg4ciJUrV+Kf//wnpk6diqZNm2Lx4sVITU21OKePjw/Wrl2L6dOn47vvvsPixYvRuHFjzJ07F5MnT5amwhKZPn06Ll26hFWrVmHFihUYNGgQfvzxRzRo0MAl13vzzTexf/9+JCUlobCwEP369cNHH32E6tWrm4+Jj4/Hrl278K9//QsffvghioqKEBYWhq5du+LFF1+s9BrR0dEYNWoUtm7diq+//hp+fn5o1aoVVqxYgSeeeMIl9SLyRhrhjlGTRERERDLFMUNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUTRV5hgwGA86dO4datWrZXKOIiIiI5EUIgcLCQkRERMDHx3XtN6oIhs6dO1duVWwiIiJShpycHERFRbns/KoIhkwLSObk5CAoKMjDpSEiIiJ7FBQUIDo62mIhaFdQRTBk6hoLCgpiMERERKQwrh7iwgHUREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoeD4Z27NiBoUOHIiIiAhqNBikpKTaP/etf/wqNRoMFCxa4rXxERETk3TweDN24cQPt27fHwoULKzxuzZo12L17NyIiItxUMiIiIlIDP08XYNCgQRg0aFCFx+Tm5uLll1/Gxo0bMXjwYDeVjIiIiNTA4y1DlTEYDBg9ejSmTJmC2NhYTxeHiIiIvIzHW4YqM3v2bPj5+eGVV16x+zHFxcUoLi42/15QUOCKohEREZEXkHXL0G+//Yb3338fS5YsgUajsftxSUlJCA4ONv9ER0e7sJRERESkZLIOhnbu3ImLFy+iYcOG8PPzg5+fH06fPo3JkyejcePGNh83depU5Ofnm39ycnLcV2giIiJSFFl3k40ePRr9+/e32DZgwACMHj0a48aNs/k4rVYLrVbr6uIRERGRF/B4MFRUVITjx4+bf8/Ozsa+ffsQEhKChg0bom7duhbHV6tWDWFhYWjZsqW7i0pEREReyOPB0K+//oq+ffuaf580aRIAYMyYMViyZImHSkVERERq4fFgKD4+HkIIu48/deqU6wpDREREqiPrAdRERERErsZgiIiIiFSNwRARERGpGoMhIiIiUjUGQ0RERKRqHp9NRkRERF5Arwd27gTOnwfCw4FevQBfX0+Xyi4MhoiIiKhqkpOBV18Fzp69vy0qCnj/fWDYMM+Vy07sJiMiIiLnJScDw4dbBkIAkJtr3J6c7JlyOYDBEBERETlHrze2CFlLnmzalphoPE7GGAwRERGRc3buLN8iVJoQQE6O8TgZYzBEREREzjl/XtrjPITBEBERETknPFza4zyEwRARERE5p1cv46wxjcb6fo0GiI42HidjDIaIiIjIOb6+xunzQPmAyPT7ggWyzzfEYIiIiIicN2wYsGoVEBlpuT0qyrhdAXmGmHSRiIiIqmbYMECnYwZqIiIiUjFfXyA+3tOlcAq7yYiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREakagyEiIiJSNQZDREREpGoMhoiIiEjVGAwRERGRqjEYIiIiIlVjMERERESqxmCIiIiIVI3BEBEREamax4OhHTt2YOjQoYiIiIBGo0FKSop53927d/H6668jLi4ONWrUQEREBJ599lmcO3fOcwUmIiIir+LxYOjGjRto3749Fi5cWG7fzZs3kZGRgWnTpiEjIwPJyck4evQoHn/8cQ+UlIiIiLyRRgghPF0IE41GgzVr1iAhIcHmMXv37kWXLl1w+vRpNGzY0K7zFhQUIDg4GPn5+QgKCpKotERERORK7rp/+7nszC6Sn58PjUaD2rVr2zymuLgYxcXF5t8LCgrcUDIiIiJSIkUFQ7dv38brr7+OUaNGVRghJiUlYebMmW4sGREREUlCrwd27gTOnwfc1Jvj8TFD9rp79y5GjBgBIQT++9//Vnjs1KlTkZ+fb/7JyclxUymJiIjIacnJQOPGQN++wFNPAUOGuOWyimgZMgVCp0+fxrZt2yrtN9RqtdBqtW4qHREREVVZcjIwfDjggaHMsg+GTIFQVlYW0tLSULduXU8XiYiIiKSk1wOvvuqRQAiQQTBUVFSE48ePm3/Pzs7Gvn37EBISgvDwcAwfPhwZGRlYt24d9Ho98vLyAAAhISHw9/f3VLGJiIhIKjt3AmfPeuzyHg+Gfv31V/Tt29f8+6RJkwAAY8aMwVtvvYW1a9cCADp06GDxuLS0NMTHx7urmEREROQq58979PIeD4bi4+NRUaojGaVBIiIiIlcID/fo5RUzm4yIiIi8VK9eQFQUoNF45PIMhoiIiMizfH2B9983/t8DARGDISIiIqXS64H0dGD5cuO/er2nS+S8YcOAVauAyEi3X1pWa5O5CtcmIyIir5OcbJyOXnoWVlSUsYVl2DDPlauqSmWgLggKQvCQIS6/fzMYIiIiUhpbCQpNXUyrVik7ILrHXfdvdpMREREpSUUJCk3bEhOV3WXmZgyGiIiIlKSyBIVCADk5xuPILgyGiIiIlMTeBIUeTmSoJAyGiIiIlMTeBIUeTmSoJAyGiIiIlKSyBIUaDRAdbTyO7MJgiIiISEkqSlBo+n3BAuNxZBcGQ0REREpjK0FhVJTXTKt3J48v1EpEREROGDYM0OnMCQoRHm7sGmOLkMMYDBERESmVry8QH+/pUigeu8mIiIhI1dgyREREZEupdbLYDeW9GAwRERFZ460LoVI57CYjIiIqy7QQatllL3JzjduTkz1TLnIJrlpPRETS8JYuJb0eaNzY9vpfGo2xhSg7W5n1k7My76GC9u0RHBLi8vs3u8mIiKjqvKlLyZGFUDmTSzrW3kMREW65NLvJiIioarytS4kLobqfrffQuXNuuTyDISIicp5eb/w2b23EhWlbYqLxOKXgQqhVo9cD6enA8uXGfyt77St6D7kJgyEiInKeI11KSsGFUJ2XnGwcb9W3L/DUU8Z/GzeuuHWwsveQGzAYIiIi53ljlxIXQnWOs92lMnhvMBgiIiLneWuXEhdCdUxVuktl8N7g1HoiInKeaRp6bq71G6HSp6F7S7oAW6SqX3q6sUusMmlp5WfgVfAeKgAQDLj8/s2WISIicp63dymZFkIdNcr4r1LrYY0z43tsqUp3aUXvITdhMERERFXDLiXlkTodQlW7S229h8r+7iLsJiMiIml4e5eSt3BFhm2pukuZgZqIiBTN1KVE8uaKDNumrq7hw42BT+mAyJHu0rLvoYIC+65fRewmIyIiUhNXpUOoSnepo4kaJcaWISIiIjVxZTqEYcMAna7y7tLS3WFZWcCnn1pf165/f8fL4ASOGSIiIlITT6dDsLYgq7UyACj46isEjx7NqfVEREQkIU+mQ7A1i60sU5D2xhvSl8EKBkNERERq48j4HqnG8zi6IKsQxtYrN+CYISIiIjWyZ3yPtS4t03geR/NHyWBBVlsYDBERkXp5Y24kR+pUUToEU5dW2ZYcU2JGRxNqymBBVlvYTUZEROok5XIUciFVnaqy8Kotjs5O02jcloHa48HQjh07MHToUERERECj0SAlJcVivxAC06dPR3h4OAIDA9G/f39kZWV5prBEROQdpF6OQg6qWqfSY4M++MD+xIz26tULqFfPrkPFvUt8U+1Z+89fBR4Phm7cuIH27dtj4cKFVvfPmTMH//nPf7Bo0SLs2bMHNWrUwIABA3D79m03l5SIyMU8nHhONVzR6uFpVa1T2Ralv//dvus60vXl6wt89JFdh55DBJ7AKvztlHtmk0HICACxZs0a8+8Gg0GEhYWJuXPnmrddv35daLVasXz5crvPm5+fLwCI/Px8KYtLRCSd1auFiIoSwnjrMv5ERRm3k7TS0iyfZ1s/aWmeLqn9qlKn1auF0Gjse7wUz9GUKVbPpb/380/MFD4oEXU0V8WIRhvccv/2eMtQRbKzs5GXl4f+pTJQBgcHo2vXrti1a5fNxxUXF6OgoMDih4hItryxy0bOXLUchSc5WydHp7ubaDRAdLSx68tBJwZOwPedZ+Capo7F9rOIxks+n6CgfR9seXc/LhTVxKf7uzt8fmfIejZZXl4eACA0NNRie2hoqHmfNUlJSZg5c6ZLy0ZEJInKujc0GmP3hk6n/FlOcuHK5Sg8xdk6OTPd3cHEjMIg8NvSw0j55CJSf43EgeLmAN6CD6ahF3aie7Xf0LKNLzq8/igWjWwNjTAYy5W6CrfctGqErIMhZ02dOhWTJk0y/15QUIDo6GgPloiIyAZXrCBOFevVy5grp7LlKJxo9fAYZ+vkTOtXVJQxEKpgWv2dojtI/yATqcuKkHqoBXINbQC0AQD4ogR96uyHrm8hdJOaoVHP+PsPtGepDheQdTAUFhYGALhw4QLCS0WzFy5cQIcOHWw+TqvVQqvVurp4RERV541dNnJnWo5i+HBjkFA6eHD1chSu4myd7G1Rmj8fCA2tMG9RwdkC/Dj3AFJSgPVnYlGATuZ9NVCEgZGZSBhqwGOvtUFI047lr2Err5EbyDoYiomJQVhYGLZu3WoOfgoKCrBnzx689NJLni0cEZEUvLHLRglMy1FYy65cSauHbDlTJ3tblF5+2WoAlPvreax9Nwupm6tj25V2uIse5n2hPhfxeIsj0I0MRL/EOATUrmD8j7NjlyTi8WCoqKgIx48fN/+enZ2Nffv2ISQkBA0bNkRiYiLefvttNG/eHDExMZg2bRoiIiKQkJDguUITEUnFG7tslMKe5SiUxtE6OdiiJAwCh74/gZQPzyJ1V33svREL4H6g3tL/JBIeOAPdc3XR9blY+Pj1tq/cnl6qw6Vz1eyQlpYmcC+/UumfMWPGCCGM0+unTZsmQkNDhVarFf369RNHjx516BqcWk9Esmaa2lx2erNpG6fXk6tZS+0QHS3E6tWipLhE7Phgn5jcKU009Ttl+RaFXnSvuV/MGpgmDv9wwvnrL1tmdbp9/r2YwNX3b40QHmqTcqOCggIEBwcjPz8fQW4amU5E5BBrA0ejo5XbZUPKU2pNs+IaIdi4qxZSVuux7ngrXBL1zYf5oxj96+9HwsBbGPpaK4S1a1D1a6enGxM+llEAIBhw+f2bwRARkVx446KhpBiXj17BurmHkbreDxvPt8MtVDfvq625jiGND0D3J18MmNwWtSJqSXtxvd6YAbtMdzGDIQkxGCIiIirvZPoZpC44iZT02vgpPw4G3A++G/qehS72BBKeDUKvl9qiWvVqri2MaTYZYA6I3BUMeXwANREREbmHMAhkLDuClI8vIPXXCGTebgGgoXl/+4CjSOh6HroXw9BhZEtofKLcVzhbs+HcgC1DREREXuxO0R1s/9CUALE5zuojzPt8UYLetTOh61sA3aSmaPyQG4MfW0p1FxcEBSF4yBC2DBEREdmFY67MCs4WYMO7B5CyRmD96bbIL5MAcUDEASQMLcHgKbEIafqAB0tqha/v/WzrblpblMEQEREpn7XZeFFRxhw6KpmNdy4jD2vnHUPKpvIJEBtoLuHxFoehGxGAfolxCAzp5sGSyg+DISIiUjZbyzjk5hq3r1rllQGRMAgcXncvAeL/6uGXG20BhJn3t6iWDV2H00h4vi66jmsDX387EyCqEMcMERGRcpmmZNsacGvK4J2d7RVdZvo7euz67CBSF19Fyh+NcfxuY4v93WpmQtfzChJeaYhWjzXxTCEl5K77N1uGiIhIuSpbxkEIICfHeJxpHIrC3Lp6C1vmZyLlu2J8f7wVLol25n3+KEa/+vuR8OgtDH2tJcI7xHmwpMrFYIiIiJTr/Hlpj5OJK1lXsW7OIaT+4IeN5+NwE13M+4KRfy8Bog8GvtYWtSIe9GBJvQODISIiUo6yM8Ya2LkURHh45cd4WPaOHKTOP4mUtGDszI+DAQ+Z90X75kLX5jgSRtdC7wlxqFa9pwdL6n0YDBERkTJYmzEWGQnUrQtcvVp+ADVwf8xQr17uK6edhEHg9+X3EiDuDcf+2y0BRJv3tws4ioQu56H7SygeGNUKGp9IzxXWyzEYIiIi+bM1Y+zcufvbNBrL/RqN8d8FC2QzePruzbvGBIhLC5F6qBly9K0BtAYA+ECP3rX3QxdfAN3fmyCmd0sALT1aXrVgMERERPKm1xtbhKy1/AhhDHpCQoDAwPJ5hhYs8Pi0+sJzhdgw7wBSkg1YfyYW10VH877quIEB4ZlIGFKCwVPaoG5zmSVAVAkGQ0REJG/2zBi7cgXYssXYAuRIBmoXZa0+v+8C1s49itTNgdh6qR3uoLt5X33NJTze/AgSRmqZAFEmGAwREZG82TsT7OJFYNQo+88rYdZqYRA4sv4kUj7IQerP9bDnRlsAoeb9zatlI6HDaejGhaDb87Hw9ZffGCY1YzBERETyZu9MMEdmjEmQtVp/R4/dn99LgLivEbLuNgXQ1Ly/a40D0PW8jISXo9HqsSbQ+MTYXz5yK2agJiIi6Tnb/WTtcYAxy3RubsUzxuzNMl2FrNW3rt7C1gX3EiBmtcJlEYJe2IlwnMdl1IV/3SA8PuAOhk5ugYiOYdbPT3ZjBmoiIlImZ7ufKnrc++8bW2ykmDHmYNbqK1lX8cNcYwLEDefuJ0D8E5LxAV5GJM7df2xgFPDE+0BHL18HzEVjrTzFx9MFICIiL2LqfiobbJi6n5KTnXscYOy6iiyTaycqyvGFWO0cg/TjlG3oW+d3hLYIwphPH0LyuW64iRqI8j2HTxr+C6vxBCJKB0Kly2urnt4gOdnYsta3L/DUU8Z/GzdWdJ3ZTUZERNJwtvvJkccBVW+RSE833sArEY80bEc8ACAu4BgSHjwH3V9C0XFkc2iaxKhmcVgLtsZamVro3noLaN5cstYid92/GQwREZE07AwykJZmuWiqs49z1r3gS+TmQmPlFmiABmcRibFBKRjatxC6xCZoEt/Qc+WVi8qC1rKcnJlXGscMERGRstg7BX7rVsuWHTcutlp4rhAb3z2As8Uv4RXxTwho4IP7AZEBgAYCtf/zNra93Klq5VDY4rCVqmysVVkOzMzzNAZDREQkDXuntr/99v3/R0UB48dLe/4y8vZfxNo5R5C6KRBbzAkQu2MHWpUbAO0THQ0sWICgim7erpjqrwSOBnem7OCJiYBOJ+suQ3aTEZFnSDUbxctmtSiaqRvF1hR4a0yzw+xZbNWBMThH1p9E6gdnkPJTXewpioUoNV+oWbVTSGh/CrpxIeg+rhV89/zP8azVUk71Vwp7uwetcbLLkN1kROS9pMr86+h5GDi5lq+v7SnwtphaD0ycnDpvKDEYEyB+cQWp+xri6J0mAJqY93epcQC6HpeRMDEKrYc0hcan8f0HO3qTrqieMlwcVjK9ehn/vhwJdk3k3mUoVCA/P18AEPn5+Z4uChGtXi2ERiOE8eP0/o9GY/xZvdo151m9WoioKMtjo6Lsvx7Zz9pzbc/PzJnlHxcdbfM1unXtllg34xfxQsvtItTngsXDqqFYDKi7V/x31HZxdu8599WzgvJ6BdPfnbW/vcpeWye46/7NbjIicp8qZP61OEd6OjBihLFbxZ7zVDYdWAEDPBWndCvcoUOW44RsWbbM+LpW0Hp39cQ1/DD3IFLX+WJDbhxuoKZ5XxDyMbjRAeh0Ggya0hZBUW74vFdja6O1FtnKREUBp045/Nxwar2EGAwRyURVpyQ7+iGclma8OVU1AKOqqeLrfvrns0h97wRStgVhx/U46EuN8Ij0OQ9dm2NIeLom+kyMg39Nf+nKTbaVDgI3bQKWLKn8MU6MG+KYISLyPlWZkmyrdaey8zi49AK5QGVjTUwB6b11yIRB4I+Vx5Dy3/NI/SUM+261AhBlPrytNgsJD+ZCN74BOj3TGhofL5u1pQS+vpZ/L/YEQzIeN8RgiIjcx9kpyXq9sUXI0Ybs8HD15oSREzsGHJfMnocdC/Yj9esCpB5oitP6lgBaAgB8oMdDwZnQ9bkO3asxaPpwcwDN3V8PV1B6N5teD1y4YN+xMk41wGCIiNzHwRYCM0eTvZU+z86d9j1Gxh/UXmHYMOPYrDLdnDdr1senga9g5tOP4JqoY94eiJt4NCwTCYPvYsiU1qjXsoMHCu0ipgAoNRX45hvg0qX7+yTI2uw29nZb2/q7lhEGQ0TkPqYWgieesL5fCOtTkh1ptSk7tdnZAMwVlN4KUFXDhiEvpjt+fX0FDu0pwJaCrtha2A+GQuNzUE9zGUObHYZuuD8emRSH6vW6erjALlBZAKGUrM32dlsrJNUAgyEikj9HWm2ioowfvKYbiVxywkiVW0mBjv54LwHizrrYXRQLgVfN+5r6nUZC+2zoxtZBj7+0ha+/fFsPqsyeAMK0T85Zmx3pti779yhTnE1GRO5T1VXNK0r2FhICrFhhHNRp7QZiLRi5t/SCyz+oVTa131BiwJ4vjAkQU343JUC878EaB6HrfgkJE6PQZmhTaHw0Ns6kQLZa/xxd5BSQ70Kv9s4OnD8fePnlKgV0nE1GRN7H2Zld9rTufPop0K+f7XMPG2b8pu3ubqqKvkUraO2myty+fhvb3s9Eyre38P2xlsgzxJn3VcMd9K27HwmP3MTjk5sjsnOsB0vqQhW1/oWEOBYIAcbgX47s7bYODVXMe5rBEBG5T1VmdtkYgOtQM3zZ6cDu4MVT+69lX8cPcw4i9XsfbMhtiyI8aN4XhHw81vAgdDpg0GuxCG7Y2YMldQNbrX+mMUCvvmr9cRUpPbBaTrxwoVoGQ0TkPlX9EPVU605VeNnU/jO7cpH67nGkbKuF7dfaQY+e5n2RPufxeOssJDxdA/Evx8G/Zg8PltSN7Gn9++Ybx89bv37Vy+YKcpqUIBHZB0N6vR5vvfUWli5diry8PERERGDs2LH45z//CY3Gi/qZidRAig9RT7TuVIWnv0VXcQabMAjsX3UvAeKeUPx+qzWASPP+WG0WEjrfS4D4dCv4+CmnNUAy9rT+XboE1KsHXLlif76syMjKj/EEuUxKkJJLVz6TwDvvvCPq1q0r1q1bJ7Kzs8XKlStFzZo1xfvvv2/3ObhQK5GM2Fro0Z6FWktKhEhLE2LZMuO/JSXuKrXzSkqMi3naWthSozEu7umKuji5OO3dW3fFtnczxKsd0kUj3xyLh/ugRPQK2ifmDUkTWVtOSV9mJVq2zL7FShMT7V/k1FXvCSm5YaFad92/ZR8MDR48WDz33HMW24YNGyaefvppu8/BYIhIZpz5EFXyqvNVCQCrek1rwZeVaxaeLxSrp+wSo5vsFCGaKxYPCcBN8XjYbvHFuB3i4qFL0pdV6dLS7AuG0tKsv4+tvUZKeF8L4fIvKAyG7nnnnXdEo0aNxNGjR4UQQuzbt080aNBALF261O5zMBgikiFHPkQdvLHLkhu+RZuZWqMqutlGR4u8fefFp8/uEEMa7BFa3LI4pK7mshjbbIdY88ZuUXShSPoyehNHW/9M7/3ERCHq1XPPe0Kh3HX/ln2eIYPBgDfffBNz5syBr68v9Ho93nnnHUydOtXmY4qLi1FcXGz+vaCgANHR0cwzRKREzuYmkiN3ZaC2Mw9MX2xFOh42/97ElABxTB30GB8LvwDZDyuVD9NsMsD6GBpbuaTUnpW8EswzdM+KFSvwzTffYNmyZYiNjcW+ffuQmJiIiIgIjBkzxupjkpKSMHPmTDeXlIhcwpumprtr8LedM9PCcAGdqx+CrvtFJEyIRKyuGTQ+jVxcOC/lbOoHpU0I8FKybxmKjo7GG2+8gQkTJpi3vf3221i6dCmOHDli9TFsGSLyIsuXA089Vflxy5YBo0a5vjwKcOeHTfAfMqDS4y79dxXq/9XGOnHkHLb0SIotQ/fcvHkTPj4+Ftt8fX1hMBhsPkar1UKr1bq6aETkDp6emq4Q17KvY/1cYwLEjWe74ACiEIlc+MB2CoP64xPcXk6vx5YeRZJ9MDR06FC88847aNiwIWJjY/H777/jvffew3PPPefpohGRO3hhgjep5Ow5h9R5WUjZWgvbr8WhpFQCxJmat/CpeAECgEVGNjnlgWErCsmE7LvJCgsLMW3aNKxZswYXL15EREQERo0ahenTp8Pf39+uc3ChViKFc3ZwqpcRBoHM5CykfHQOqbtDkXGrtcX+NtrjSOh0Fgl/uZcAcW2K5xanrUxF63h5umxkyYNBq7vu37IPhqTAYIi8mlK/XTtabk+uOu9BJbdL8NOiA0j9Kh8pmU1wqiTavE8DA3oGZULX6xp0rzZG80calz+BHN8fttbxUllwqwgeDloZDEmIwRB5LaV+u3a23BXd2OV403fSjYs3sOndTKSsKsG67Da4KkLM+wJwC4+G7Ydu4B0Mea0VGsTKdP0qW7wpVYK3k0HQymBIQgyGyCvJ4IPKKa4ot1KDwlIuHryE7+ceQeoGf2y+0A63EWjeV1dzBUOaHEbCn6vhkb+3RY0GNTxY0iqyMwcS0tI4ENmTZBK0yjIYysnJQXR0dOUHygyDIfI6Mvmgcpgryq3UoBBA1oYTyJj5PQ7vK8b22w9iB/rAAGO9Y/zOIKHdSeierY2eL7b1ngSITJWgDDIJWmU5tb5Vq1aYPHky3njjDVSvXt1VZSKiyig1EaHU5dbrjS1C1r7TCWEMiBITAZ1OFkGhocSAX78+jJRPL+HG3oN4rWQWRuL+83FBE4odsX9Dq7eeRNs/NYfGp6EHS+siTJWgDHYm7rT7OJnzqfyQ+zZv3oyNGzeiefPmWLJkiYuKRESV8sQHlV5v/La4fLnxX73e8XNIXW5HgisPKS4oxoa3f8VLsTsQpb2Irs/F4siuq5hf8jIiYVn2UFzEnw++hTjNAWh87rVsSfG8y4kpVYJGY32/RmMcGK/CVAmyorKg1aFgqEePHtizZw+SkpIwbdo0dOrUCTs9+CFDpFru/qBKTjZ2b/Xta+zi6NvX+HtysmPnkbrcMv32ev10PpZN+BkjG/4P9YOLMWhaZyw61BvnDWEIwnV84vtXaCDKfwCbWrgSE41Bj1TPu5z4+hrHcgHlAyI55UBSO7UFrc6u8Hrjxg0xbdo0UaNGDfHEE0+IkydPVm3JWBfiqvXkdexclbzCleDtJeWK8Y6u7l2ZtDTbz0Hpn7Q0Z2rukDO7c8WHf04X/UN+FX64Y3H5cJ/z4sXW28WP/9oritdttK/MM2dK97zL0erV5d/DXLFdXkx/+2Xfh258D7rr/l2lYGjnzp3i1VdfFT4+PiIgIEBMmTJFFBYWSlk+STAYIq80ZUrFwZAUH1SuCLqk/ICVOrhygEFvEPtXHRX/93Ca6FT9YLlLt/Y/LqZ2TxO7P8sU+rv6+w9ctsy+YCgkxD3BrieVlBgD1WXLjP8qvT7eyMNBq7vu3w7NJlu0aBH27t2LvXv34vDhw/Dx8UHbtm3RrVs3tG/fHt9++y2OHz+O5ORkdO7c2VWNWQ7jbDLyOrZmUJlMmQLMmVP167hqRomUCRTdmJ265HYJfv74AFK/uo6U/U2QXXJ/gLMGBvSodQAJva/aToAI2P+c2oPTz8kdmIHaUnR0NLp27Ypu3bqhW7du6NSpEwIDAy2O+fe//41ly5bhwIEDkhfWWQyGyKu4c1q9K6dBS/kB68Ls1Dcv3zQmQFx5F+tOtsYVUde8T4vbeDT0D3MCxNC2diRANL1+Fa21VqcOcPVq5eeaOBF44gl5JJj0oqSXJB+yDIbsceHCBUREREAvoxkPDIbIq7gz/4crryX1zVPC8106fBnfzzmM1A3+2JRnmQAxRHMVQ2IOIWG4Hx6dHOdcAsTKWrPeeguYMcP+83k6waQXJL0keXLb/VvqfjeDwSDS09OlPm2VcMwQeRV7x5wsW1b1a7lqTI61cQhRUR4dPJu15ZSYNyRNPBS0T/igxKJojf3OiMQH0kXa/N/F3Vt3pblgRWMxKnve5TSoWsoB9q4i1dgkjnFyO9kPoFYSBkPkVdw9g0rqGSUyuXnq7+rFni8OiDd7pIlY7bFyxekYeEjM7Jsm/lh5VBj0BtcUoqKbq63nXU6Dqt05q9FZUgXeMgzg1YDBkIQYDJFX8cQMKqlmlHj45llcWCw2vL1XvBS7XUT4nLO4tB/uiH51fhMfDE8Xp/931iXXd5i1591dQbA9ZJTawCpnAm9rAapMAng1ctf920sWuyFSEVPSuuHDjWNMrI05kTpp3bBhxiUtqjomxwPLiOSfycf6uQeRmgr8mBOLAtyf6VoThRgUdQC6oQY8NiUWdWI6SnJNyZR+3levBj78sPLHuDPBpEyTXgJwbqkWa2OfIiOB27cdOw8pDoMhIiUaNsw4ZdzaoFUJZlBZ5etb9QDFTTfPs3vPY+27x5CyuSbSr8bhLnqY94X5XMDjLY4iYVQgHk5sB21Q9ypdy+VKP+/2BEPuXB5Bzks2OBp420pXkZtb8XVcEMCT+zEYIlIqqVpr3MlFN09hEDiYehwpC3ORuqsBfr3ZBsD9c7TyP4GEjjnQPV8PXca2gY9fqEPnlwXT8ggVTcmPinLv8ghyLJOJI4F3Ra1IUl+PZInBEJGSSdFa404S3jz1d/TGBIhfXkPKHzE4WdIcQHPjaWBA91oHkNDrKnSvNEKLAU0BNJW2Lu7mie5RJZbJxJHAu7JWJCmvR7Lk0EKtRERVUsVFOm9evonUN/dgXPOdCAu4hj6vtMd7v8XjZEkjaHEbQxr8gk+f3YnzmVfwc0E7TPkhHi0GxLiuPu5m6h6NjLTcHhUlaaZtxZcJcGyh0aq06njbgqUqJXnSRTli0kUimXEgY/Slw5exbu5hpP7oj015cbiF6uZ9dTTXMCTmIBKe8MOjk9qiZlhNN1WgFE9kXpZjtmc5lsnepVqcXSLFBUu+kCXFZqCWIwZDRDJUwc3zxLbTSH0/GynpdfBzQVsYcP+m2sj3LBLiTkA3OggP/bUtqlWvJtl1HSaHzMtyDELkxJ7A254lUkJCgMBAlyz5QrYxGJIQgyEieRMGgd+WHkbKJxeR+mskDhQ3t9j/QOBh6LpeQMJL4Wg3vAU0Pja6PiojZfBia/aRO1sL5BCMKYE9AaM9rUhKm7DgBRgMSYjBECmal37zv1N0B+kfZCJ1WRFSD7VAruH+AFRflKBPnf1IeLgQj/+9KRr1jKr6BaUMXuxZLLdePWD+fONYGle8ZnIIxryNCxf8JecwGJIQgyFSLC/75l9wtgA/zj2AlBRg/ZlYFCDYvK8GijAoMtOYAPG1NghpWke6C9sTvERFAdnZ9gUtjo4xkfo1k7o+dJ+XfvlQKnfdvzm1nkiuKkoCN3y4Yr755/56HmvfzULq5urYdqWdRQLEUJ+LeLzFESQ8GYiHX41DQG0XJUCUOvO1o7OPpH7NPJDJWzWUlq6CJMFgiEiOnFlKwJVlceCbsjAIHPr+BFI+PIvUXfWx90YsyiZA1D2QA91zddH1uVj4+PV2bfkB6TNfO5pTRurXTM7LYBApEIMhIjmSyzd/O7vp9Hf0+N8nB5C6xJgA8URJMwDNABgTIHareRAJva5A93JDtBzkgQSIUme+rix5pDVSvmZyXgaDSIEYDBHJkRy++VfSTVe8+BtsPNYEKSvvYN3xVrgk2psP0eI2+jfYD92A2xj6WiuEtYtzXTntIfWyERVlXq6MFK+ZnJfBIFIgBkNEcuTpb/6VdNMZAFwc+w/8CafMOYDqaK5hcOODSHjCFwMmx6FmWBfXlM0Zrlg2wtZiuZWR4jWT8zIYRArE2WREcmRPEjhXzhayc7bUSJ8VCItrAN3oIPR6yYkEiO7miqnTpjFVubnGMUGXL1s/zhWvGaeCk5fjbDIiNfPgN39hEMhe+Sua2HHst1/dhebpPpKXwWWGDZM+cV7p2UeBgRUn7pP6NXNFfYhUiMEQkVzZ6oaJipL8m/+dojvY/qEpAWJzNNV3Rrodj9NERkhWBrdx5dRpN75mZpwKTlRl7CYjkjsXJYErOFuADe8eQMoagfWn2yK/VALEWsjHSZ8WqGu4CKsLXzCpX8WYuI9IEuwmIyIjCb/5n8vIw9p5x5CyqXwCxAaaS9C1PAzdyED0S4xDwLb/urfLB5BnEOFMmdhaQ6QoDIaIvJgwCBxedy8B4v/q4ZcbbQGEmfe3qJaNhAdOI+F5KwkQ3d3lI8elR+RYJiKSHLvJiCoix5aKSujv6LHrs4NIXXwVKX80xvG7jS32d6uZiYSHjAkQWz1mxzBpdzwHclx0VIoyKfD9QyQnXKhVQgyGyCkKahW4dfUWtszPRMp3xfj+eCtcEvXN+/xRjP7190P36C0Mfa0lwjuEerCkVshx0VEpyqSg9w+RXDEYkhCDoTL4bbVycmypKONK1lWsm3MIqT/4YeP5ONxEDfO+2prrGNzoIBKG+WDA5LaoFVHLgyWthL0rwKeluW8cTlXLpID3D5EScAA1uQa/rVZOTouklpG9Iwep808iJS0YO/PjYMBD5n3RvrlIiD0O3TO10HtCHKpV7+nWsjlNDkuPOHsta8fJ+P1DRNb5eLoA9sjNzcUzzzyDunXrIjAwEHFxcfj11189XSzlMX1bLdv0f2+tKSQne6ZccuPIIqkuJgwCGd8cxvTe6WgfeBRN+kTj7yl9sD2/AwzwRfuAo5jeOx0Zy47g9J0I/OePPug3paP8M0GX5umlR6pyLWvHyej94zS93tg6tny58V+93tMlInIp2bcMXbt2DT179kTfvn3x448/on79+sjKykKdOnU8XTRlcfW3VW/qevNwS8Xdm3eNCRCXFiL1UDPk6FsDaA0A8EUJetXORELfAjye2AQxvVsCaOmScriNHBcdrUqZ5NjS5Qi2HpMKyT4Ymj17NqKjo7F48WLztpiYGA+WSKEc+bbq6LgMb/vw9EBLReG5QmyYdwApyQasPxOL66KjeV913MDAiEzoBpdg8JQ2qNv8AcmuKwtyXHS0KmWSY0uXvWyNdTK1HnOsE3krIXOtW7cWiYmJYvjw4aJ+/fqiQ4cO4pNPPqnwMbdv3xb5+fnmn5ycHAFA5Ofnu6nUMrRsmRDGj7iKf5Ytc+y8q1cLodGUP49GY/xZvdo19XGlkhIhoqKs18tUt+ho43FVcO73PLHoqe1iUP1fhD9uW1yigeaieL7FDvH9tD3i5pWbElVM5lavNj7vpZ+I6GjPvoecKZOb3j+SM5Xb1meDXMtNXi0/P98t92/ZB0NarVZotVoxdepUkZGRIT7++GMREBAglixZYvMxM2bMEADK/ag6GEpLsy8YSkuz/5ze/OFpCvLK3tCqEOQZ9AZx6Pvj4t+PpomuNTLLPV3Nq50UUx5MEz8v2i9KihX4nEmhpMT4Hly2zPivHN47zpTJBe8fl3PFZwRRFTEYuqdatWqie/fuFttefvll0a1bN5uPYcuQFa74turtH54StFSUFJeInz76Q0x5ME00r3ay3FPTtUamSBqQJg59f1wY9AYXVobcTo4tXRVxVesxURW4KxiS/Zih8PBwtGnTxmJb69atsXr1apuP0Wq10Gq1ri6asrhiXIbSB4pWZtgw44ByBweG37p6C1sX3EuAmNUKF0U78z5/FKNf/f3QPXILQye3QETHtq6uBXmKk+8fj1HyWCeiKpJ9MNSzZ08cPXrUYtuxY8fQqFEjD5VIwaRea8odH56enqVm54KbV7Ku4oe5xgSIG87F4Sa6mPcFIx+DGx1AwjAfDHytLWpFPOjCApOsKGnBVjnO6iNyE9lnoN67dy969OiBmTNnYsSIEfjll18wfvx4fPLJJ3j66aftOgczUJchVYBhWrKgsg9PZ5dRkPkstVM/nUXqeyeQkhaEndfjoC/13SLK9xwS2mRB90wt9JkYp6y8P6ReptlkgPXWY84mIzfjchylrFu3DlOnTkVWVhZiYmIwadIkjB8/3u7HMxhyIVd9eMpwOQNhENj33VGkLMpD6i/h+OO2ZX6fdgFHoXvwPBJeDMUDo1pB46Nxa/mIJGHtS0h0tHOtx0RVxGBIQgyGXEzqD08ZLdx59+Zd7Fh4LwHiwaY4o48y7/OBHr2CM5HQNx+6vzdBTO9ol5aFyG083T1NdA+DIQkxGHIDKT88PbxwZ+G5Qmx815gA8YfTsbguapv3VccNDAjPRMIQUwLEEMmvT0RERlyolZRFyoGiHpillrf/ItbOOYLUTYHYcqkd7qC7eV99zSU83vwIdCO06P/3OASGdJPsulXCb+9ERJJgMETy46YpvkfWn0TqB2eQ8lNd7CmKhUBv875m1U4hof0pJDwXgm7Px8LXX2YzaGQ+uJyISEnYTUbyo9cDjRoZZ6lZ4+SYIUOJAbs/P4jUL64gdV9DHL3TxGJ/lxoHkNDzMnQTotB6SFP5DoCW4eByIiJXYDcZqVdqKnD7tvV9FSWItNJtdLvwrjEB4re38H1WK1wwxJkPr4Y76FfvD+geuYXHX1NIAkS93tgiZO07jBDG5ycx0Zjsj11mRER2YTBE8mKr1cMkJAT45JPyLR9Wuo0u+zTAK4b3sBz381EFIx+PNTqAP+kMeOyhAtQoKTAGTu3ru6I20tu50/YsO8D4vOXkGI9TSrI/IiIPYzBE8lFRq4dJYKCx1aO05GSIJ4YDECjdsRViuISlGI0amtvQtm0G3VM10WdiHPw3XTBe5z8KHG/j7UugEBF5AIMhko/KWj0A4/6dOyF698EfK48h9aOzeHHHBDSAgE+ZQ30gIKDBJ1Ezofn93vgiWy1PZ88at0sx3saVs7y4fhQRkeTK3j+IPMfO1owvx2xDjH8uHniyJdJ2+CIMeTbfyBoIaEzdRpW1PAlhHG+j1ztVfADGYKtxY2OepKeeMv7buLFxuxRM60dpbAzu1miMCS+5fhQRkd0YDJF82NmasfjMwzitj0IgbmJo7R32nfv8eftankyBkzNMrU5lr5Gba9wuRUDk62vszgPKB0QVDS4nIiKbGAyRfNxr9RA2Wj0M0OAsItGsGZD65h5cvgRMXtPb6rHlhIfbnqpflr3HlVbZLC+g6q1OJsOGGbvzIiMtt0dFcVo9EZETOGaIPKfU2JozZwS+Sw/F1cuT8I6YDAENfHA/sBAANADCv1uAz0bE3z+HqdsoN9d6IGLKSdSrF/DBB/aV69Ilx+vi7llew4YZB5IzAzURUZUxGPImlQ3cldHyDYaVq3D3xYnQXrsAAGgI4ElE4VW8j+FYhf9q/oZQccF8vObewq++ZVs9TN1Gw4cbA5/SAVHZbqP6dk6ft/e40jwxy0vKJVCkIKP3FxGRI9QZDHnjh3ZlyzPIYPmG29dvY9v7mTj96Ua8mDsd1WDZkhOJs1iNJ3B19meoOznX/tfI1G1krX4LFtyvX9luJVvsPa40tc/yksH7i4jIWepbjmPLFu/70K5seYbXXgPmzfPI8g3Xsq/jhzkHkfq9DzbktsVNVMcpNEYkztoesBYd7fBSGwDsaxlr3Lji7qyqXLtx48q765w5t9xxeRAichF3LcehrmDo668R9Oyz3vWhXdkNXqMBfHxsD9x1wU36zK5cpL57HCnbamH7tXbQl2qAHK5ZjZVieOUnSUtzTReQ6cYNWO9Sq8p7wJXnlit73n/eGgQSkcu5KxhS12yy1193z2wfd7Jn4G5FdSo9sNdJwiDwx4qjmNk3HR2rH0ajHpF4ZXUfbLvWEXr4oa02C/+vZzr2fnkIK768Zd9JnZnRZQ9XzsRS4ywvRwaOExHJlLrGDJ07Z3ufUtd0kmpAroPnKbldgp0fZSL16wKkZDbFaX1LAC0BAD7Qo2fQASTEX4NuYkM0rZZ7r+sKwG8XKjyvmTMzuuzlyplYapvlxeVBiMgLqCsYsoeUH9ruGKgt1YBcO85TlFeETe8dQMrqEvyQ3QZXxQPmfYG4iUfDMqEbdAdDprRG/dbtjd1Gz422bDmoU8e+8jgzo8sRrpyJJbdZXq6k9oHjROQVGAyVJdWHtrtm19iTZ8eeMUM2lm+4cOASvp97BKkbtNh8sR2K0c28r57mMoY2OwzdcH88MikO1et1vf9AW4Nqr12zr17OzOiqKm+cZehqjuR5IiKSKXWNGYqIcM+aTu5YlsHEnuUZJk0y/t/O5RuObczG3MHp6Bm0H5FxtbH0Kz1qXjyBbtiNZr4nMalTOnZ88AfybtfBF8d6Qffvrqher/r989qz+nxFoqKM51i+HEhPd884LlevKeYqer3xOXLnc1UalwchIm8gVCA/P18AEPlffy2ERmP8Md6qjT+mbatXV/1iJSVCREVZnr/staKjjcdJafXq8teNjr5fpwr26+/qxe7PMsUb3dJEa//j5t1/wmpxBpaPMURFVf48paXZrr89P3XrWv5uzzWr+tyVfU9I/b5wBWuvqaufK0fKUvr9R0TkBPP9Oz/fpddR19R6W3mG7mU3tui+crbLJD3d2KpQGVdMHXcgA/WdoLrYujcIKd/dwffHWuC8Icx8mB/uYlrN+ZhW9DoA4zIYZvZME1++3Ni6IhVXTk1X6tRwOeb2YTcjEUmMeYYkVO7JrOxDuyrjfewNBJYtA0aNcq5CTrqWfR3r5xoTIP54ti2KUMu8rxYK8Fj0ASQkAIP+3grBvds7HyDYGxA6wlVBiSeDV2cpNYAjInKQu4IhdQ2g3rkTKCio+FurrW/cpvE+lX3jltnsmpw955A6LwspW2th+7U4lKCneV+Ez3noWmdBN6o64l+Ogzaoh3FHenrVFh2tbFCtM1yV+kCJU8PdvSgsEZGXU1cwNGTI/f9ba+mpaOCvEMZv3ImJxjwythZAbdDAOBPq3DmPzK4RBoHM5CykfHQOqbtDkXGrNYAI8/5YbRZ0nXKR8JcG6PR0K/j4WQnKqhogVLR4alVJHZTILHi1ixIDOCIiGVNXMFSatZYeZ75xW+tSq1v3fvBU0SrqEim5XYKfFh1A6lf5SMlsglMlLQC0MF4SBvQMykRC72vQJcagWb/mAJpXfEIpAgRbi6fWr1+1hIpSByVKnBquxACOiEjG1DVmCIBFj2PZsRWOjvepaBCrEMag6MqV+9utDdR20o2LN7Dp3UykrCrBuuw2uCpCzPsCcAuPhu2HbuAdDHmtFRrEOpjAUMpFR8uOz+rRA2ja1PEuNFeOg1HammJqXhSWiFSFY4bcoWxLjyPfuO3pUgsMBLZsAS5elGR2zcWDpgSI/th8oR1ul0qAWFdzBUObHjImQPx7W9Ro0LWCM1Wiom4uR1u3rGVjdrQLzdX5amy1YkVFSRa8SkrK14eIiFTeMmRiaulx5Bv3zp1umYWUtfkU1i44gVNpp3DlVgDOIRI70QsG+KKJ32no2mUjYWwd9BgfC78AiWNba12AUrVu2Tr3k08aW+hccc3KKG1quCtfHyIiGeDUeglVGgyVDljs7TJx0RR6Q4kBv359GCmfXkJqRhRaFu/H+3gV0bh/wyvQ1se1l6ej4ewJ0PjYyKgtFVcGCLbOrbSgxJP4XBGRF2MwJCG7xwyZ2PONW8L8NMUFxUj7TyZSl99E6pH7CRD/hGSswnBoIBxPfEhERKRwDIYkVGHL0OrV1gMKe7I529Oldvw48L//lTvP9dP5WD/nAFK/1+DHnLYoLFWyWijAY1F/4PPrT6B60SVYbfvhIFkiIvJyHEDtDjNn2m5ZsTbwt+z+ygaxPvmkceZUqRamwsD6eM93Ct4uSrRIgBjukwddq2PQjaqOvq/EQZuhB/pWMAWdifWIiIgkoe5gqHkl+XYqU9EspCefhJg3DxCWXVw1bl3GNLyOP9AUR7XtoOt4Fgnj66Pz6Nbw8bu/PhgT6xEREbmHuoMhKZLSDRtmzEh9r0tNX7cBfsqshfZThyBICPiUOdwHAgLAd/Unotr5HMC3WdXKxsR6REREVaLOYEjirMI3rxVj08ZApKyMxrqTrdFWZCIdtru4NACqXTpfcReXqzIjc/YRERGRBfUFQxIlpbt0+DK+n3MYqRv8sSmvHW7jfpLD5siy7yQVdXG5IrGetVly1tZoIyIiUpGyvTiyN2vWLGg0GiQmJjp3gqgop6ekH996Gu8OTUev4D8Q1qYOnl/SC2vzuuI2AhHjdwaJD2xH+oJ9WLSxiX0nrKyLyzQmKTKy6nUw5U8qu/aaaY225GT7z0VERORFFDW1fu/evRgxYgSCgoLQt29fLFiwwK7HmafmrVuHoIED7W5NMSVATP3sElJ/i8TBYssB1x0DDyOh+wXoXopA3LDm9xMgSr12VFW7tkzlsbUILafpqwe7SYlIQTi1voyioiI8/fTT+PTTT/H22287dxI7PvjvFN1B2vv7jQkQDzfHOUOseZ8f7iI+ZD90Dxfh8UnN0LB7awCty59E6i6uyqb5V2bnTtuBEMBp+mrBblIiIqsUEwxNmDABgwcPRv/+/SsNhoqLi1FcXGz+vaCgoMLj88/kY/3cg0hNBX7MiUUBOpv31UQhBkUdQMLjBjz2j7ao3aiTfQWW0+KfnKZPpm7Ssi2Vpm5SZjMnIhVTRDD07bffIiMjA3v37rXr+KSkJMycObPCY87uPY+17x5DyuaaSL8ah7voYd4X5nMBupZHoXsyEA8ntoM2qLtzBS8z7d5j3RKcpq9uer0xKLfWZSuEsbUyMdH4XmWXGRGpkOzHDOXk5KBz587YvHkz2rVrBwCIj49Hhw4dbI4ZstYyFB0djV1LM7BlcT5SdzXArzfbWDymtf8J6DrmIOGFenhwTBv4+ClubLltUo9hImWRcB09IiJ34pihe3777TdcvHgRHTt2NG/T6/XYsWMHPvzwQxQXF8O3zA1cq9VCq9WWO1f3Z5rCtDqZBgb0rPkHJsRuR594DcIHtvfewaSumKZPysFuUiKiCsk+GOrXrx8yMzMtto0bNw6tWrXC66+/Xi4Qqog/buPRBkeQMKgYT3Q4jtrvTgf2nAX2AJgN7x5MKqcxTORe7CYlIqqQ7LvJrKmsm6wsUzNb7rFcRDSPsD2Y1NRK4s2DSTm1Wn3YTUpECuWubjIvGhhTuZqhNSsfTAoYB5Pq9W4tm9uYpumPGmX8lzc/72fqJgXuB/wm7CYlIlJmy5CjLCLLjAwOJnUWW5WUzVqeoehodpMSkWxxALWrcDCpc5iwT/nkkuqBiEhm1BcMcTCp45iwz3tUNZs5EZEXUtWYIQDGb8JRUeXHTphoNMaug1693FsuuVL7GCsiIvJ66guGOJjUMY6sa0ZERKRA6guGgPs5dyIjLbdHRbHLpyyOsSIiIi+nvjFDJhxMah+OsSIiIi+n3mAI4GBSe5jGWFWWsI9jrIiISKHU2U1G9uMYKyIi8nIMhtRGrzeuYr58ufFfe2aBcYwVERF5MXV3k6lNVRInKnGMFTNmExGRHdS3HIcL03nLmtoWp2XGbCIixeNCrSQdtSVONAV+ZfMjmTJmJyd7plxERCRLDIbUQE2JE9UW+BERUZUxGFIDNSVOVFPgR0REkmAwpAZqSpyopsCPiIgkwWBIDdS0OK2aAj8iIpIEgyE1UFPiRDUFfkREJAkGQ2qhlsSJagr8iIhIEswzpDZqSURoLc9QdLQxEPKWwI+IyMu56/7NYIi8l1oCPyIiL+Wu+zeX4yDv5esLxMd7uhRERCRzHDNEREREqsZgiIiIiFSNwRARERGpGoMhIiIiUjUGQ0RERKRqDIaIiIhI1RgMERERkaoxGCIiIiJVYzBEREREqsZgiIiIiFSNwRARERGpGoMhIiIiUjUGQ0RERKRqDIaIiIhI1RgMERERkaoxGCIiIiJVYzBEREREqib7YCgpKQkPPvggatWqhQYNGiAhIQFHjx71dLGIiIjIS8g+GNq+fTsmTJiA3bt3Y/Pmzbh79y4effRR3Lhxw9NFIyIiIi+gEUIITxfCEZcuXUKDBg2wfft29O7d267HFBQUIDg4GPn5+QgKCnJxCYmIiEgK7rp/+7nszC6Sn58PAAgJCbF5THFxMYqLi82/FxQUuLxcREREpEyy7yYrzWAwIDExET179kTbtm1tHpeUlITg4GDzT3R0tBtLSUREREqiqG6yl156CT/++CN++uknREVF2TzOWstQdHQ0u8mIiIgUhN1kZUycOBHr1q3Djh07KgyEAECr1UKr1bqpZERERKRksg+GhBB4+eWXsWbNGqSnpyMmJsbTRSIiIiIvIvtgaMKECVi2bBlSU1NRq1Yt5OXlAQCCg4MRGBjo4dIRERGR0sl+zJBGo7G6ffHixRg7dqxd5+DUeiIiIuXhmKF7ZB6rERERkcIpamo9ERERkdQYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqRqDISIiIlI1BkNERESkagyGiIiISNUYDBEREZGqMRgiIiIiVWMwRERERKrGYIiIiIhUjcEQERERqZpigqGFCxeicePGCAgIQNeuXfHLL794ukhERETkBRQRDH333XeYNGkSZsyYgYyMDLRv3x4DBgzAxYsXPV00IiIiUjhFBEPvvfcexo8fj3HjxqFNmzZYtGgRqlevji+++MLTRSMiIiKFk30wdOfOHfz222/o37+/eZuPjw/69++PXbt2ebBkRERE5A38PF2Ayly+fBl6vR6hoaEW20NDQ3HkyBGrjykuLkZxcbH59/z8fABAQUGB6wpKREREkjLdt4UQLr2O7IMhZyQlJWHmzJnltkdHR3ugNERERFQVV65cQXBwsMvOL/tgqF69evD19cWFCxcstl+4cAFhYWFWHzN16lRMmjTJ/Pv169fRqFEjnDlzxqVPptwUFBQgOjoaOTk5CAoK8nRx3Ib1Zr3VgPVmvdUgPz8fDRs2REhIiEuvI/tgyN/fH506dcLWrVuRkJAAADAYDNi6dSsmTpxo9TFarRZarbbc9uDgYFW9iUyCgoJYbxVhvdWF9VYXtdbbx8e1Q5xlHwwBwKRJkzBmzBh07twZXbp0wYIFC3Djxg2MGzfO00UjIiIihVNEMDRy5EhcunQJ06dPR15eHjp06IANGzaUG1RNRERE5ChFBEMAMHHiRJvdYpXRarWYMWOG1a4zb8Z6s95qwHqz3mrAeru23hrh6vlqRERERDIm+6SLRERERK7EYIiIiIhUjcEQERERqRqDISIiIlI1RQZDCxcuROPGjREQEICuXbvil19+qfD4lStXolWrVggICEBcXBzWr19vsV8IgenTpyM8PByBgYHo378/srKyXFkFpzhS708//RS9evVCnTp1UKdOHfTv37/c8WPHjoVGo7H4GThwoKur4TBH6r1kyZJydQoICLA4xhtf7/j4+HL11mg0GDx4sPkYJbzeO3bswNChQxEREQGNRoOUlJRKH5Oeno6OHTtCq9WiWbNmWLJkSbljHP3McDdH652cnIxHHnkE9evXR1BQELp3746NGzdaHPPWW2+Ve71btWrlwlo4ztF6p6enW32f5+XlWRznba+3tb9djUaD2NhY8zFKeL2TkpLw4IMPolatWmjQoAESEhJw9OjRSh/njnu44oKh7777DpMmTcKMGTOQkZGB9u3bY8CAAbh48aLV4//3v/9h1KhReP755/H7778jISEBCQkJOHDggPmYOXPm4D//+Q8WLVqEPXv2oEaNGhgwYABu377trmpVytF6p6enY9SoUUhLS8OuXbsQHR2NRx99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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"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.3011187 4.49781862]\n",
"0 [-10.84111032] [-12.09572749]\n",
"1 [-0.48072858] [0.39646149]\n",
"2 [-0.4485449] [0.3699193]\n",
"3 [-0.41851584] [0.34515405]\n",
"4 [-0.39049716] [0.32204677]\n",
"5 [-0.36435426] [0.30048647]\n",
"6 [-0.33996158] [0.28036959]\n",
"7 [-0.31720192] [0.26159948]\n",
"8 [-0.29596598] [0.24408599]\n",
"9 [-0.27615173] [0.22774499]\n",
"10 [-0.257664] [0.21249799]\n",
"11 [-0.24041398] [0.19827173]\n",
"12 [-0.22431882] [0.18499789]\n",
"13 [-0.20930118] [0.1726127]\n",
"14 [-0.19528895] [0.16105668]\n",
"15 [-0.1822148] [0.1502743]\n",
"16 [-0.17001593] [0.14021378]\n",
"17 [-0.15863375] [0.13082678]\n",
"18 [-0.14801358] [0.12206823]\n",
"19 [-0.13810441] [0.11389604]\n",
"20 [-0.12885864] [0.10627096]\n",
"21 [-0.12023184] [0.09915636]\n",
"22 [-0.1121826] [0.09251807]\n",
"23 [-0.10467223] [0.08632419]\n",
"24 [-0.09766466] [0.08054499]\n",
"25 [-0.09112623] [0.07515268]\n",
"26 [-0.08502554] [0.07012138]\n",
"27 [-0.07933327] [0.06542692]\n",
"28 [-0.07402209] [0.06104673]\n",
"29 [-0.06906648] [0.05695979]\n",
"theta from own gd\n",
"[[3.78598925]\n",
" [3.17649673]]\n",
"0 [-0.06444264] [0.05314647]\n",
"1 [-0.06012835] [0.04958843]\n",
"2 [-0.05480861] [0.04520119]\n",
"3 [-0.04954337] [0.0408589]\n",
"4 [-0.04464699] [0.0368208]\n",
"5 [-0.04018906] [0.0331443]\n",
"6 [-0.03616111] [0.02982242]\n",
"7 [-0.03253183] [0.02682931]\n",
"8 [-0.02926511] [0.02413522]\n",
"9 [-0.02632586] [0.02171119]\n",
"10 [-0.02368163] [0.01953047]\n",
"11 [-0.02130293] [0.01756873]\n",
"12 [-0.01916314] [0.01580402]\n",
"13 [-0.01723827] [0.01421657]\n",
"14 [-0.01550675] [0.01278856]\n",
"15 [-0.01394915] [0.011504]\n",
"16 [-0.01254801] [0.01034846]\n",
"17 [-0.0112876] [0.009309]\n",
"18 [-0.0101538] [0.00837394]\n",
"19 [-0.00913389] [0.00753281]\n",
"20 [-0.00821642] [0.00677616]\n",
"21 [-0.00739111] [0.00609552]\n",
"22 [-0.0066487] [0.00548325]\n",
"23 [-0.00598086] [0.00493247]\n",
"24 [-0.0053801] [0.00443702]\n",
"25 [-0.00483969] [0.00399134]\n",
"26 [-0.00435356] [0.00359042]\n",
"27 [-0.00391626] [0.00322978]\n",
"28 [-0.00352289] [0.00290536]\n",
"29 [-0.00316902] [0.00261353]\n",
"theta from own gd wth momentum\n",
"[[3.99053294]\n",
" [3.00780757]]\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.1739262 ]\n",
" [2.85239235]]\n",
"Eigenvalues of Hessian Matrix:[0.27968902 4.49424386]\n",
"0 [-13.16403338] [-14.97007223]\n",
"1 [7.61543606e-16] [2.78435018e-15]\n",
"2 [-4.23272528e-16] [-4.70203152e-16]\n",
"3 [-4.23272528e-16] [-4.70203152e-16]\n",
"4 [-4.23272528e-16] [-4.70203152e-16]\n",
"beta from own Newton code\n",
"[[4.1739262 ]\n",
" [2.85239235]]\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.50455587]\n",
" [2.69978846]]\n",
"Eigenvalues of Hessian Matrix:[0.35172802 4.35427615]\n",
"theta from own gd\n",
"[[4.50455587]\n",
" [2.69978846]]\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAkMAAAHHCAYAAAC88FzIAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABWy0lEQVR4nO3deXwTZeIG8Gfa0gOkhXL0DKdQKKeAIAjSSiIiIlgQBUVAUVR0l5XFY38K4uoW1BVcRYFVQUVQhAKeYAotFARBC6tygwVKoZSzLQUKTd7fHyGhadPm6GQy6Tzfzyef0snM5J1Myjx55z0kIYQAERERkUYF+LoARERERL7EMERERESaxjBEREREmsYwRERERJrGMERERESaxjBEREREmsYwRERERJrGMERERESaxjBEREREmsYwREQuGzduHFq0aOHrYqhaZmYmJEnC8uXLfV0UInIRwxCRCi1atAiSJNkeQUFBiIuLw7hx45CXl+fr4hER1SpBvi4AEVXt1VdfRcuWLXH58mVs3boVixYtwqZNm/DHH38gNDTU18UjIqoVGIaIVGzQoEHo0aMHAGDChAlo3LgxZs2aha+//hojR470cenIl0pKSlCvXj1fF4OoVuBtMiI/0q9fPwDAoUOHbMuuXLmCadOmoXv37oiIiEC9evXQr18/ZGRk2G17+PBhSJKEt956CwsWLEDr1q0REhKCm2++Gdu3b6/0WqtWrULHjh0RGhqKjh07YuXKlQ7LVFJSgilTpkCn0yEkJAQJCQl46623IISwW0+SJDz99NP46quvkJiYiLCwMPTu3Ru///47AGD+/Pm48cYbERoaiqSkJBw+fNjp+/HKK69AkiQcPHgQ48aNQ4MGDRAREYHx48fj4sWLlY590aJFlfYhSRJeeeWVSvvcv38/HnroIURERKBJkyZ4+eWXIYRAbm4uhg4divDwcERHR+Pf//63w7KZTCb84x//QHR0NOrVq4d77rkHubm5ldb7+eefceeddyIiIgJ169ZF//79sXnzZofHuXv3bowePRoNGzZE3759AQD5+fkYP3484uPjERISgpiYGAwdOtSl94+ILFgzRORHrBe4hg0b2pYVFRXhww8/xKhRo/DYY4+huLgYH330EQYOHIht27aha9eudvtYsmQJiouLMXHiREiShDfeeAMpKSn4888/UadOHQDAjz/+iOHDhyMxMRGpqak4c+aM7YJbnhAC99xzDzIyMvDoo4+ia9euWLt2LaZOnYq8vDzMnj3bbv2srCx8/fXXmDRpEgAgNTUVd999N5577jm8//77eOqpp3Du3Dm88cYbeOSRR7B+/XqX3peRI0eiZcuWSE1NRXZ2Nj788EM0bdoUs2bNcufttXP//fejffv2mDlzJr777ju89tpriIyMxPz583H77bdj1qxZ+Pzzz/H3v/8dN998M2677Ta77V9//XVIkoTnn38eBQUFmDNnDvR6PXbu3ImwsDAAwPr16zFo0CB0794d06dPR0BAABYuXIjbb78dWVlZ6Nmzp90+77vvPrRp0wb/+te/bGFz+PDh2LVrF5555hm0aNECBQUFMBqNOHr0KBu7E7lKEJHqLFy4UAAQ6enp4tSpUyI3N1csX75cNGnSRISEhIjc3FzbumVlZaK0tNRu+3PnzomoqCjxyCOP2Jbl5OQIAKJRo0bi7NmztuWrV68WAMQ333xjW9a1a1cRExMjzp8/b1v2448/CgCiefPmtmWrVq0SAMRrr71m9/ojRowQkiSJgwcP2pYBECEhISInJ8e2bP78+QKAiI6OFkVFRbblL774ogBgt64j06dPFwDsjlMIIe69917RqFGjSse+cOHCSvsAIKZPn15pn48//rhtWVlZmYiPjxeSJImZM2falp87d06EhYWJsWPH2pZlZGQIACIuLs7umJYtWyYAiHfeeUcIIYTZbBZt2rQRAwcOFGaz2bbexYsXRcuWLYXBYKhUplGjRtmV/dy5cwKAePPNN6t9n4ioerxNRqRier0eTZo0gU6nw4gRI1CvXj18/fXXdjU0gYGBCA4OBgCYzWacPXsWZWVl6NGjB7Kzsyvt8/7777erWbLeevvzzz8BACdOnMDOnTsxduxYRERE2NYzGAxITEy029f333+PwMBA/OUvf7FbPmXKFAgh8MMPP9gtHzBggF1tRa9evQBYajfq169fabm1TM488cQTdr/369cPZ86cQVFRkUvbOzJhwgTbvwMDA9GjRw8IIfDoo4/aljdo0AAJCQkOy/nwww/bHdOIESMQExOD77//HgCwc+dOHDhwAKNHj8aZM2dw+vRpnD59GiUlJRgwYAA2btwIs9lc7XGGhYUhODgYmZmZOHfunMfHSqR1vE1GpGJz585F27ZtUVhYiI8//hgb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kpKSIIRwef3Dhw97rzBERESkOapuQE1ERETkbQxDREREpGkMQ0RERKRpDENERESkaQxDREREpGkMQ0RERKRpDENERESkaQxDREREpGkMQ0RERKRpDENERESkaQxDREREpGkMQ0RERKRpDENERESkaQxDREREpGkMQ0RERKRpDENERESkaQxDREREpGkMQ0RERKRpDENERESkaQxDREREpGkMQ0RERKRpDENERESkaQxDREREpGkMQ0RERKRpDENERESkaQxDREREpGkMQ0RERKRpDENERESkaQxDREREpGkMQ0RERKRpDENERESkaQxDREREpGlBvi4AERERaYjJBGRlASdOADExQL9+QGCgT4vEMERERETKSEsD/vpX4Nix68vi44F33gFSUnxWLN4mIyIiIu9LSwNGjLAPQgCQl2dZnpbmm3KBYYiIiIi8zWSy1AgJUfk567LJky3r+QDDEBEREXlXVlblGqHyhABycy3r+QDDEBEREXnXiRPyriczhiEiIiLyrpgYedeTmc/D0MaNGzFkyBDExsZCkiSsWrXK9tzVq1fx/PPPo1OnTqhXrx5iY2Px8MMP4/jx474rMBEREbmnXz9LrzFJcvy8JAE6nWU9H/B5GCopKUGXLl0wd+7cSs9dvHgR2dnZePnll5GdnY20tDTs27cP99xzjw9KSkRERB4JDLR0nwcqByLr73Pm+Gy8IUkIR027fUOSJKxcuRLDhg2rcp3t27ejZ8+eOHLkCJo1a+bSfouKihAREYHCwkKEh4fLVFoiIiJyi6NxhnQ6SxByMM6QUtdvvxt0sbCwEJIkoUGDBlWuU1paitLSUtvvRUVFCpSMiIiIqpWSAgwdyhGoa+Ly5ct4/vnnMWrUqGoTYmpqKmbMmKFgyYiIiMglgYFAUpKvS2HH522GXHX16lWMHDkSQgh88MEH1a774osvorCw0PbIzc1VqJRERETkb/yiZsgahI4cOYL169c7vW8YEhKCkJAQhUpHRERE/kz1YcgahA4cOICMjAw0atTI10UiIiKiWsTnYejChQs4ePCg7fecnBzs3LkTkZGRiImJwYgRI5CdnY1vv/0WJpMJ+fn5AIDIyEgEBwf7qthERERUS/i8a31mZiaSk5MrLR87dixeeeUVtGzZ0uF2GRkZSHKxARa71hMREfkfzXStT0pKQnV5TEXDIBEREVEt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iEjTGIaIiIhI0xiGiIiISNMYhoiIiEjTGIaIiIhI0xiGiIiISNMYhoiIiEjTGIaIiIhI0xiGiIiISNMYhoiIiEjTGIaIiIhI0xiGiIiISNMYhoiIiEjTVB+GUlNTcfPNN6N+/fpo2rQphg0bhn379vm6WERERFRLqD4MbdiwAZMmTcLWrVthNBpx9epV3HHHHSgpKfF10YiIiKgWkIQQwteFcMepU6fQtGlTbNiwAbfddptL2xQVFSEiIgKFhYUIDw/3cgmJiIhIDkpdv4O8tmcvKSwsBABERkZWuU5paSlKS0ttvxcVFXm9XEREROSfVH+brDyz2YzJkyfj1ltvRceOHatcLzU1FREREbaHTqdTsJRERETkT/zqNtmTTz6JH374AZs2bUJ8fHyV6zmqGdLpdLxNRkRE5Ed4m6yCp59+Gt9++y02btxYbRACgJCQEISEhChUMiIiIvJnqg9DQgg888wzWLlyJTIzM9GyZUtfF4mIiIhqEdWHoUmTJmHJkiVYvXo16tevj/z8fABAREQEwsLCfFw6IiIi8neqbzMkSZLD5QsXLsS4ceNc2ge71hMREfkfthm6RuVZjYiIiPycX3WtJyIiIpIbwxARERFpGsMQERERaRrDEBEREWkawxARERFpGsMQERERaRrDEBEREWkawxARERFpGsMQERERaRrDEBEREWkawxARERFpGsMQERERaRrDEBEREWkawxARERFpGsMQERERaRrDEBEREWkawxARERFpGsMQERERaRrDEBEREWkawxARERFpGsMQERERaRrDEBEREWkawxARERFpGsMQERERaRrDEBEREWkawxARERFpGsMQERERaRrDEBEREWkawxARERFpGsMQERERaRrDEBEREWkawxARERFpGsMQERERaRrDEBEREWkawxARERFpGsMQERERaRrDEBEREWkawxARERFpmt+Eoblz56JFixYIDQ1Fr169sG3bNl8XiYiIiGoBvwhDX375JZ599llMnz4d2dnZ6NKlCwYOHIiCggJfF42IiIj8nF+EobfffhuPPfYYxo8fj8TERMybNw9169bFxx9/7OuiERERkZ9TfRi6cuUKfv31V+j1etuygIAA6PV6bNmyxYclIyIiotogyNcFcOb06dMwmUyIioqyWx4VFYW9e/c63Ka0tBSlpaW23wsLCwEARUVF3iso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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"theta from own sdg\n",
"[[4.51550231]\n",
" [2.6728048 ]]\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.8301107 ]\n",
" [3.31610195]]\n",
"Eigenvalues of Hessian Matrix:[0.31047897 4.32701817]\n",
"theta from own gd\n",
"[[3.82958153]\n",
" [3.31655284]]\n",
"theta from own sdg with momentum\n",
"[[3.82977678]\n",
" [3.25067525]]\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.99978312]\n",
" [3.00126504]\n",
" [3.99880408]]\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.99827523]\n",
" [2.99976195]\n",
" [3.99585312]]\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",
"[[2.00000058]\n",
" [2.99998203]\n",
" [4.00001412]]\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 0x11d60e820>]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"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 0x107a83760>"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"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
}