Spaces:
Runtime error
Runtime error
File size: 27,459 Bytes
8711bb8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "_ZCogkNcQhAB"
},
"source": [
"# Gaussian Maximum Likelihood\n",
"\n",
"## MLE of a Gaussian $p_{model}(x|w)$\n",
"\n",
"You are given an array of data points called `data`. Your course site plots the negative log-likelihood function for several candidate hypotheses. Estimate the parameters of the Gaussian $p_{model}$ by coding an implementation that estimates its optimal parameters (15 points) and explaining what it does (10 points). You are free to use any Gradient-based optimization method you like. "
]
},
{
"cell_type": "code",
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import seaborn as sns\n",
"import matplotlib.pyplot as plt\n",
"\n",
"np.random.seed(0)\n",
"sns.set_theme(style='whitegrid', palette='pastel')\n",
"\n",
"import warnings\n",
"warnings.filterwarnings('ignore')\n",
"\n",
"from sklearn.linear_model import LinearRegression"
],
"metadata": {
"id": "9tEZiMYncrvb"
},
"execution_count": 73,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"\n",
"- $lnL(\\hat \\mu,\\sigma^2|Y) = {-N \\over 2} ln(2\\pi) - [\\sum_{i=1}^N{1\\over 2}ln \\sigma ^2 - {1 \\over 2 \\sigma ^2} (Y_i - \\mu)^2]$\n",
"\n",
"- ${\\partial ln L \\over \\partial \\mu} = {1 \\over \\sigma^2} \\sum_{i=1}^N(Y_i - \\mu)$\n",
"\n",
"- ${\\partial ln L \\over \\partial \\sigma ^2} = {1 \\over 2 \\sigma ^2} (-N + {1 \\over \\sigma^2} \\sum_{n=1}^N(Y_i - \\mu)^2)$"
],
"metadata": {
"id": "6y7UTqAlYqa8"
}
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {
"id": "_fbYCmRRQhAF"
},
"outputs": [],
"source": [
"data = [4, 5, 7, 8, 8, 9, 10, 5, 2, 3, 5, 4, 8, 9]\n",
"\n",
"# This function calculates the partial derivates of a negative log-likelihood function for the mean and variance\n",
"def gradient(mean, var, x):\n",
" N = len(x)\n",
" mean_gradient = (1 / var) * np.sum(x - mean) \n",
" var_gradient = (1 / (2 * var)) * (-N + (1 / var) * np.sum(np.subtract(x, mean) ** 2))\n",
" return mean_gradient, var_gradient\n",
" \n",
"\n",
"# Performs a gradient descent using data, starting params, learning rate, and number of iterations.\n",
"# Each iteration changes theta partially based on the learning rate and eventually would converge towards\n",
"# the true params.\n",
"def gradient_descent(data, theta0, learning_rate, max_iter):\n",
" mean, var = theta0\n",
" x = np.array(data) # transform to numpy array for easier functions\n",
" for _ in range(max_iter): \n",
" g = gradient(mean, var, x)\n",
" \n",
" # update params with calculated partial derivatives\n",
" mean = mean + learning_rate * g[0] \n",
" var = var + learning_rate * g[1]\n",
" return mean, var"
]
},
{
"cell_type": "code",
"source": [
"iterations = 1000 # number of times we want to descent\n",
"theta = (0, 1) # (mean, var)\n",
"alpha = 0.01 # learning rate\n",
"\n",
"# calculate params\n",
"e_mean, e_var = gradient_descent(data, theta, alpha, iterations)\n",
"mean = np.mean(data) # true mean from data\n",
"var = np.var(data) # true variance from data\n",
"\n",
"print(f\"Estimated params: mean={e_mean} variance={e_var}\")\n",
"print(f\"True params: mean={mean} variance={var}\")"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "9-VFAZtKpwvM",
"outputId": "77594a4f-4c7d-4201-b56a-b0fda92c93c3"
},
"execution_count": 75,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Estimated params: mean=6.214285714179054 variance=5.851817293989179\n",
"True params: mean=6.214285714285714 variance=5.882653061224489\n"
]
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "SqVOZaiAQhAI"
},
"source": [
"## MLE of a conditional Gaussian $p_{model}(y|x,w)$\n",
"\n",
"You are given a problem that involves the relationship between $x$ and $y$. Estimate the parameters of a $p_{model}$ that fit the dataset (x,y) shown below. You are free to use any Gradient-based optimization method you like. \n"
]
},
{
"cell_type": "markdown",
"source": [
"$MSE = {1 \\over n} \\sum_{i=1}^n (y_i - \\hat y_i)^2$ \n",
"\n",
"- $f(m, b) = {1 \\over n} \\sum_{i=1}^n (y_i - (mx_i+b))^2$\n",
"\n",
"${\\partial f \\over \\partial m} = {1 \\over n} \\sum_{i=1}^n -2x_i(y_i - (mx_i+b))$\n",
"\n",
"${\\partial f \\over \\partial b} = {1 \\over n} \\sum_{i=1}^n -2(y_i - (mx_i+b))$\n",
"\n"
],
"metadata": {
"id": "OIdosdhMxn3D"
}
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {
"id": "4xoYaZCBQhAL"
},
"outputs": [],
"source": [
"x = np.array([8, 16, 22, 33, 50, 51])\n",
"y = np.array([5, 20, 14, 32, 42, 58])\n",
"\n",
"# The goal here is to generate a p_model that is optimized for the following \n",
"# linear regression: y = m * x + b\n",
"# Because we are provided x and y, we can use gradient descent and mean-squared\n",
"# error to optimize m and b. The code is attached below.\n",
"# An additional implementation using sklearn's Linear Regression is also included.\n",
"# y = m * x + b\n",
"\n",
"def conditional_gradient(x, y, m, b):\n",
" n = len(x)\n",
" m_gradient = -2 * np.sum(x * (y - (m * x + b))) / n\n",
" b_gradient = -2 * np.sum(y - (m * x + b)) / n\n",
" return m_gradient, b_gradient\n",
" \n",
"def conditional_gradient_descent(x, y, params, learning_rate, max_iter):\n",
" m, b = params\n",
" for _ in range(max_iter):\n",
" g = conditional_gradient(x, y, m, b)\n",
"\n",
" m = m - learning_rate * g[0]\n",
" b = b + learning_rate * g[1]\n",
" return m, b"
]
},
{
"cell_type": "code",
"source": [
"# The code below generates paramters from a self-implemented gradient descent\n",
"# as well as through `sklearn`'s LinearRegression package. It takes the calculated\n",
"# `m` and `b` and places them into the respective `estimate` and `actual` \n",
"# functions\n",
"\n",
"params = (0, 5)\n",
"iterations = 100\n",
"alpha = 0.0001\n",
"\n",
"m, b = conditional_gradient_descent(x, y, params, alpha, iterations)\n",
"\n",
"def estimate(x):\n",
" return m * x + b\n",
"\n",
"model = LinearRegression()\n",
"model.fit(x.reshape(-1, 1), y)\n",
"\n",
"def actual(x):\n",
" return model.coef_[0] * x + model.intercept_"
],
"metadata": {
"id": "Lu-6_UHKclJS"
},
"execution_count": 79,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# The code below uses the previously calculated `estimate` and `actual` functions\n",
"# to generate a graph with the original data points as well as the estimated and\n",
"# actual lines.\n",
"\n",
"sns.scatterplot(x=x, y=y)\n",
"\n",
"start = min(x)\n",
"end = max(x)\n",
"\n",
"pp1, pp2 = (start, estimate(start)), (end, estimate(end))\n",
"ap1, ap2 = (start, actual(start)), (end, actual(end))\n",
"\n",
"plt.plot([pp1[0], pp2[0]], [pp1[1], pp2[1]], label='Estimated')\n",
"plt.plot([ap1[0], ap2[0]], [ap1[1], ap2[1]], label='Actual')\n",
"plt.legend(loc=\"upper left\")\n",
"\n",
"plt.show()"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 269
},
"id": "126Kj3r-gBYL",
"outputId": "4081c5e0-2d67-46c0-ae52-4f5195fb89b5"
},
"execution_count": 80,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
],
"image/png": "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\n"
},
"metadata": {}
}
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.10.9"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "7d6993cb2f9ce9a59d5d7380609d9cb5192a9dedd2735a011418ad9e827eb538"
}
},
"colab": {
"provenance": []
}
},
"nbformat": 4,
"nbformat_minor": 0
} |