From d6f717a562d814341e97893b39da3a8038c28029 Mon Sep 17 00:00:00 2001 From: Anni <39795105+annigue@users.noreply.github.com> Date: Mon, 7 Apr 2025 17:26:09 +0200 Subject: [PATCH 1/2] Aufgaben begonnen --- ex1/PE1 - Linear Regression (Exercises).ipynb | 2252 +++++++++++------ 1 file changed, 1477 insertions(+), 775 deletions(-) diff --git a/ex1/PE1 - Linear Regression (Exercises).ipynb b/ex1/PE1 - Linear Regression (Exercises).ipynb index 38a0f19..6030f40 100644 --- a/ex1/PE1 - Linear Regression (Exercises).ipynb +++ b/ex1/PE1 - Linear Regression (Exercises).ipynb @@ -1,781 +1,1483 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Linear Regression\n", - "\n", - "Stanford CS229 - Machine Learning by Andrew Ng. Programming exercise 1.\n", - "\n", - "Please check out [the repository on GitHub](https://github.com/rickwierenga/CS229-Python/). If you spot any mistakes or inconcistencies, please create an issue. For questions you can find me on Twitter: [@rickwierenga](https://twitter.com/rickwierenga). Starring the project on GitHub means a ton to me!" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import pandas as pd\n", - "import matplotlib.pylab as plt\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Linear Regression with a single variable\n", - "---\n", - "In this part of this exercise, you will implement linear regression with one variable to predict profits for a food truck. Suppose you are the CEO of a restaurant franchise and are considering different cities for opening a new outlet. The chain already has trucks in various cities and you have data for profits and populations from the cities. You would like to use this data to help you select which city to expand to next. " - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
PopulationProfit
06.110117.5920
15.52779.1302
28.518613.6620
37.003211.8540
45.85986.8233
\n", - "
" + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "d6kJ-cfLedBp" + }, + "source": [ + "# Linear Regression\n", + "\n", + "Stanford CS229 - Machine Learning by Andrew Ng. Programming exercise 1.\n", + "\n", + "Please check out [the repository on GitHub](https://github.com/rickwierenga/CS229-Python/). If you spot any mistakes or inconcistencies, please create an issue. For questions you can find me on Twitter: [@rickwierenga](https://twitter.com/rickwierenga). Starring the project on GitHub means a ton to me!" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "id": "D1MDtlCBedBq" + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pylab as plt\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "PI6agDGzedBq" + }, + "source": [ + "## Linear Regression with a single variable\n", + "---\n", + "In this part of this exercise, you will implement linear regression with one variable to predict profits for a food truck. Suppose you are the CEO of a restaurant franchise and are considering different cities for opening a new outlet. The chain already has trucks in various cities and you have data for profits and populations from the cities. You would like to use this data to help you select which city to expand to next." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 417 + }, + "id": "fOqzaCGCedBq", + "outputId": "d19f3c83-31ef-446a-fa88-b5a08707a285" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "--2025-04-07 14:26:32-- https://raw.githubusercontent.com/annigue/CS229-Python/master/ex1/ex1data1.txt\n", + "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n", + "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 1359 (1.3K) [text/plain]\n", + "Saving to: ‘ex1data1.txt.1’\n", + "\n", + "\rex1data1.txt.1 0%[ ] 0 --.-KB/s \rex1data1.txt.1 100%[===================>] 1.33K --.-KB/s in 0s \n", + "\n", + "2025-04-07 14:26:33 (50.8 MB/s) - ‘ex1data1.txt.1’ saved [1359/1359]\n", + "\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " Population Profit\n", + "0 6.1101 17.5920\n", + "1 5.5277 9.1302\n", + "2 8.5186 13.6620\n", + "3 7.0032 11.8540\n", + "4 5.8598 6.8233" + ], + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
PopulationProfit
06.110117.5920
15.52779.1302
28.518613.6620
37.003211.8540
45.85986.8233
\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
\n", + "\n", + "\n", + "
\n", + " \n", + "\n", + "\n", + "\n", + " \n", + "
\n", + "\n", + "
\n", + "
\n" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "data", + "summary": "{\n \"name\": \"data\",\n \"rows\": 97,\n \"fields\": [\n {\n \"column\": \"Population\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 3.869883527882332,\n \"min\": 5.0269,\n \"max\": 22.203,\n \"num_unique_values\": 97,\n \"samples\": [\n 21.279,\n 5.4069,\n 5.3054\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Profit\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 5.510262255231544,\n \"min\": -2.6807,\n \"max\": 24.147,\n \"num_unique_values\": 97,\n \"samples\": [\n 17.929,\n 0.55657,\n 1.9869\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" + } + }, + "metadata": {}, + "execution_count": 29 + } ], - "text/plain": [ - " Population Profit\n", - "0 6.1101 17.5920\n", - "1 5.5277 9.1302\n", - "2 8.5186 13.6620\n", - "3 7.0032 11.8540\n", - "4 5.8598 6.8233" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# start by loading the data\n", - "data = pd.read_csv('ex1data1.txt', header=None, names=['Population', 'Profit'])\n", - "\n", - "# initialize some useful variables\n", - "m = len(data) # the number of training examples\n", - "X = np.append(np.ones((m, 1)), np.array(data[\"Population\"]).reshape((m,1)), axis=1) # Add x0, a vector of 1's, to X.\n", - "y = np.array(data[\"Profit\"]).reshape(m, 1)\n", - "\n", - "data.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Visualising the data\n", - "Plotting helps us get insight in the data we are working with. Using the `'bx'` option, we get blue crosses. You can read more about markers [here](https://matplotlib.org/api/markers_api.html)." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0.5, 1.0, 'Relation between profit and population')" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(data['Population'], data['Profit'], 'bx')\n", - "plt.xlabel('Population in 10,000')\n", - "plt.ylabel('Profit in $10,000')\n", - "plt.title('Relation between profit and population')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### The hypotheses function\n", - "Our hypothesis function has the general form:\n", - "$y= h_\\theta(x)= \\theta_0 + \\theta_1x$\n", - "Note that this is like the equation of a straight line. We give to $h_\\theta(x)$ values for $\\theta_0$ and $\\theta_1$ to get our estimated output y. In other words, we are trying to create a function called $h_\\theta$ that is trying to map our input data (the x's) to our output data (the y's).\n", - "\n", - "### Cost function\n", - "\n", - "The cost functions yields \"how far off\" our hypotheses $h_\\theta$ is. It takes the avarage of the distance between our hypothesis and the actual point and squares it. Formally, the cost function has the following definition:\n", - "\n", - "$J(\\theta) = \\frac{1}{2m} \\displaystyle\\sum_{i = 0}^{m}(h_θ(x^{(i)}) - y^{(i)})^2$\n", - "\n", - "#### Vectorization\n", - "Vectorizations is the act of replacing the loops in a computer program with matrix operations. If you have a good linear algebra library (like numpy), the library will optimize the code automatically for the computer the code runs on. Mathematically, the 'regular' function should mean the same as the vectorized function.\n", - "\n", - "Gradient descent vectorized:\n", - "$\\theta = \\frac{1}{2m}(X\\theta - \\vec{y})^T(X\\theta-\\vec{y})$\n", - "\n", - "**Exercise**: Implement a vectorized implementation of the cost function." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "def cost_function(X, y, theta):\n", - " \"\"\" Computes the cost of using theta as the parameter for linear gression to fit the data in X and y. \"\"\"\n", - " \n", - " return 0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "With $\\theta = \\begin{bmatrix}0 & 0\\end{bmatrix}$, $J(\\theta)$ should return 32.07." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n" - ] - } - ], - "source": [ - "initial_theta = np.zeros((2,1))\n", - "print(cost_function(X, y, initial_theta))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Gradient descent\n", - "We want are hypothesis $h_\\theta(x)$ to function as good as possibly. Therefore, we want to minimalize the cost function $J(\\theta)$. Gradient descent is an algorithm used to do that. \n", - "\n", - "The formal definition of gradient descent:\n", - "\n", - "$repeat \\ \\{ \\\\ \\enspace \\theta_j := \\theta_j - \\alpha \\frac{1}{m}\\displaystyle\\sum_{i = 1}^{m}(h_\\theta(x^{(i)})-y^{(i)})x_j^{(i)}\\\\\\}$\n", - "\n", - "An illustration of gradient descent on a single variable:\n", - "
\n", - " \n", - "
\n", - "\n", - "**Exercise**: Implement the gradient descent algorithm in Python." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "def gradient_descent(X, y, theta, alpha, iterations):\n", - " \"\"\" Performs gradient descent to learn theta. \n", - " Returns the found value for theta and the history of the cost function.\n", - " \"\"\"\n", - " J_history = []\n", - " return theta, J_history" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Gradient descent should have found approximately the following: $\\theta = \\begin{bmatrix}-3.6303\\\\1.1664\\end{bmatrix}$" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[0.],\n", - " [0.]])" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# You can change different values for these variables\n", - "alpha = 0.01\n", - "iterations = 1500\n", - "\n", - "theta, J_history = gradient_descent(X, y, initial_theta, alpha, iterations)\n", - "theta" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using the results\n", - "#### Plotting the regularization line" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(X[:,1], y, 'rx', label='Training data')\n", - "plt.plot(X[:,1], X.dot(theta), label='Linear regression')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Plotting the cost history\n", - "A plot of how $J(\\theta)$ decreases over time. This is are model learning." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(J_history)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Making a prediction using the model\n", - "The model can be used by calculating the dot product of the input and $\\theta$." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'In a city with a population of 35000, we predict a profit of $0.00'" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "prediction = np.array([1, 3.5]).dot(theta) * 10000 # don't forget to multiply the prediction by 10000\n", - "'In a city with a population of 35000, we predict a profit of $%.2f' % prediction" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "\n", - "## Multivariate Linear Regression\n", - "\n", - "---\n", - "In this part, you will implement linear regression with multiple variables to predict the prices of houses. Suppose you are selling your house and you want to know what a good market price would be. One way to do this is to first collect information on recent houses sold and make a model of housing prices." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
SizeBedroomsPrice
021043399900
116003329900
224003369000
314162232000
430004539900
\n", - "
" + "source": [ + "# start by loading the data\n", + "!wget https://raw.githubusercontent.com/annigue/CS229-Python/master/ex1/ex1data1.txt\n", + "data = pd.read_csv('ex1data1.txt', header=None, names=['Population', 'Profit'])\n", + "\n", + "# initialize some useful variables\n", + "m = len(data) # the number of training examples\n", + "X = np.append(np.ones((m, 1)), np.array(data[\"Population\"]).reshape((m,1)), axis=1) # Add x0, a vector of 1's, to X.\n", + "y = np.array(data[\"Profit\"]).reshape(m, 1)\n", + "\n", + "data.head()" + ] + }, + { + "cell_type": "code", + "source": [ + "#from google.colab import drive\n", + "#drive.mount('/content/drive')" ], - "text/plain": [ - " Size Bedrooms Price\n", - "0 2104 3 399900\n", - "1 1600 3 329900\n", - "2 2400 3 369000\n", - "3 1416 2 232000\n", - "4 3000 4 539900" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# load data\n", - "data = pd.read_csv(\"ex1data2.txt\", header = None, names=[\"Size\", \"Bedrooms\",\"Price\"])\n", - "m = len(data)\n", - "\n", - "# Initialize X, y and theta\n", - "x0 = np.ones(m)\n", - "size = np.array((data[\"Size\"]))\n", - "bedrooms = np.array((data[\"Bedrooms\"]))\n", - "X = np.array([x0, size, bedrooms]).T\n", - "y = np.array(data[\"Price\"]).reshape(len(data.index), 1)\n", - "theta_init = np.zeros((3,1))\n", - "\n", - "data.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Feature Normalization\n", - "When features differ by order of magnitude, first performing feature scaling can make gradient descent converge much more quickly. Formally:\n", - "\n", - "$x := \\frac{x - \\mu}{\\sigma}$\n", - "\n", - "Where $\\mu$ is the average and $\\sigma$ the standard deviation.\n", - "\n", - "**Important**: It is crucial to store $\\mu$ and $\\sigma$ if you want to make predictions using the model later.\n", - "\n", - "**Exercise**: Perform feature normalization on the following dataset." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[1.000e+00, 2.104e+03, 3.000e+00],\n", - " [1.000e+00, 1.600e+03, 3.000e+00],\n", - " [1.000e+00, 2.400e+03, 3.000e+00],\n", - " [1.000e+00, 1.416e+03, 2.000e+00],\n", - " [1.000e+00, 3.000e+03, 4.000e+00]])" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# perform normalization\n", - "def normalize(X):\n", - " \"\"\" Normalizes the features in X\n", - " \n", - " returns a normalized version of X where\n", - " the mean value of each feature is 0 and the standard deviation\n", - " is 1. This is often a good preprocessing step to do when\n", - " working with learning algorithms.\n", - " \"\"\"\n", - " mu = np.zeros(len(X))\n", - " sigma = np.zeros(len(X))\n", - " \n", - " return X, mu, sigma\n", - "\n", - "X, mu, sigma = normalize(X)\n", - "X[0:5]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Gradient Descent\n", - "\n", - "Remember the algorithm for gradient descent:\n", - "\n", - "$repeat \\ \\{ \\\\ \\enspace \\theta_j := \\theta_j - \\alpha \\frac{1}{m}\\displaystyle\\sum_{i = 1}^{m}(h_\\theta(x^{(i)})-y^{(i)})x_j^{(i)}\\\\\\}$\n", - "\n", - "The vectorization for multivariate gradient descent:\n", - "\n", - "$\\theta := \\theta - \\frac{\\alpha}{m}X^T(X\\theta - \\vec{y})$\n", - "\n", - "**Exercise**: Implement gradient descent for multiple features. Make sure your solution is vectorized and supports any number of features." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[0.],\n", - " [0.],\n", - " [0.]])" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "def gradient_descent_multi(X, y, theta, alpha, iterations):\n", - " J_history = []\n", - " return theta, J_history\n", - "\n", - "alpha = 0.01\n", - "iterations = 1500\n", - "initial_theta = np.zeros((3,1))\n", - "theta, J_history = gradient_descent_multi(X, y, initial_theta, alpha, iterations)\n", - "theta" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As before we see how the cost decreases over time." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Text(0, 0.5, 'cost')" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(J_history)\n", - "plt.title('J per iteration')\n", - "plt.xlabel('iteration')\n", - "plt.ylabel('cost')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If we want to make a prediction on a normalized dataset, we have to normalize our input too." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/ipykernel_launcher.py:1: RuntimeWarning: divide by zero encountered in double_scalars\n", - " \"\"\"Entry point for launching an IPython kernel.\n" - ] - }, - { - "data": { - "text/plain": [ - "'In a house of 1650 square feet with 3 rooms, we predict a price of $nan'" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "price = theta.transpose() @ np.array([1, (1650-mu[1])/sigma[1], (3-mu[2])/sigma[2]]) # normalize the input\n", - "'In a house of 1650 square feet with 3 rooms, we predict a price of $%.2f' % price" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Using normal equations\n", - "We can use normal equations to get the exact solution in only one calculation. Although using normal equations is very fast for a small datasets with a small number of features, it can be inefficient for larger datasets because the complexity of matrix multiplication is $O(n^3)$.\n", - "\n", - "The normal equation for linear regression is:\n", - "\n", - "$\\theta = 􏰅 (X^TX)^{−1}X^T\\vec{y}$\n", - "\n", - "**Exercise**: Find theta using normal equations." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[89597.9095428 ],\n", - " [ 139.21067402],\n", - " [-8738.01911233]])" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" + "metadata": { + "id": "AdZe3c6yfDkO" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "8CptRfr1edBr" + }, + "source": [ + "### Visualising the data\n", + "Plotting helps us get insight in the data we are working with. Using the `'bx'` option, we get blue crosses. You can read more about markers [here](https://matplotlib.org/api/markers_api.html)." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 489 + }, + "id": "WRB6XX7wedBr", + "outputId": "f8e579d2-4da4-4bfe-ae4e-f627e1329394" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "Text(0.5, 1.0, 'Relation between profit and population')" + ] + }, + "metadata": {}, + "execution_count": 30 + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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vYTz589jx44d6NGjh+GXuHT93n77bXTp0kW23EaNGuH69esAgN/+9rcWA5+HHnrI5Lmjr5mlieGM/3L3FDt27MCTTz6Jnj174oMPPkB0dDT8/PyQl5eHzz77rNrxzv5+uZtKpZI9F51OV+Nrp0yZgry8PEybNg3du3c3TG44cuRIr/n5p7phMEMO5+vri7lz56J37954//338dprrxlaJfz8/JCammpXeUeOHMF///tfLF26FM8995xh+4YNG6oda+ssqOHh4QgMDDR0xxg7ceIEfHx8EBsba1c9ramsrMRPP/1k+AsYAP773/8CgGEkR+vWrbFx40Y89thjNd6crZ1nUlIStm/fjvj4eHTp0gVBQUHo3LkzQkJCsG7dOhw4cACzZ882HC91bQQHB1v9bMLDwxEUFASdTmf3Z1hbp06dMml1OX36NCorK2sc/eKsz9eeWXZXrlwJf39/rF+/3qSVMi8vz+73BfTnFBAQYGhJMyZ3npZcunQJJSUlJq0z5t/FFi1a4IcffkBlZaVJy8WJEycM+43J1em///2vyefUuHFj2S4ZW7ppv/zyS4wZMwZ/+9vfDNtKS0tx69Ytk+Ps+XzsPUfybMyZIadITk5Gt27d8N5776G0tBQRERFITk7GkiVLcPny5WrHWxviLP1FZPwXkBAC8+bNq3as9Ava/JecXJl9+/bF119/bdJlUVRUhM8++wyPP/44goODrZZhr/fff9/wfyEE3n//ffj5+aFPnz4A9CN3dDodcnNzq732/v37JufUsGFDi+eYlJSEc+fO4YsvvjB0O/n4+KBHjx549913UVFRYTKSqWvXrmjdujXeeecd3Llzp1p50mfj6+uLp59+GitXrqw27Nb4OEeShtpLFixYAEA/r5E1zvp8rV13uTqoVCqTlodz585h9erVdr+vVF5aWhpWr16NCxcuGLb/+OOPWL9+vc3l3L9/32Q4d3l5OZYsWYLw8HB07doVADBgwAAUFhaajNS7f/8+FixYgEaNGqFXr14mZa5evdok523v3r3Ys2ePyefUunVrnDhxwuR7cvjwYdnh/3Lnbt4CsmDBgmqtOrb+/NfmHMmzsWWGnOYPf/gDhg0bhvz8fLzwwgtYuHAhHn/8cXTq1AnPP/88WrVqhaKiIhQUFODnn3/G4cOHZctJSEhA69atMXPmTPzyyy8IDg7GypUr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m2tCREREtpLu27asuuT1wczt27cBALGxsW6uCREREdnr9u3bCAkJsXqM1y80WVlZiUuXLiEoKAgqlcph5RYXFyM2NhYXL16stwtY8hro8Tro8TrwGkh4HfR4Hep2DYQQuH37NmJiYuDjYz0rxutbZnx8fNC8eXOnlR8cHFxvv6QSXgM9Xgc9XgdeAwmvgx6vQ+2vQU0tMhImABMREZGiMZghIiIiRWMwU0sajQZZWVnQaDTurorb8Bro8Tro8TrwGkh4HfR4HVx3Dbw+AZiIiIi8G1tmiIiISNEYzBAREZGiMZghIiIiRWMwQ0RERIrGYEZGdnY2VCqVySMhIcHqa1asWIGEhAT4+/ujU6dO+O6771xUW+dp2bJlteugUqmQkZEhe3x+fn61Y/39/V1c67rZvn07Bg0ahJiYGKhUKqxevdpkvxACs2bNQnR0NAICApCamopTp07VWO7ChQvRsmVL+Pv7IzExEXv37nXSGTiGtetQUVGBV199FZ06dULDhg0RExOD5557DpcuXbJaZm1+rtyppu9Cenp6tfPp169fjeV603cBgOzvCJVKhbfffttimUr7LsydOxePPPIIgoKCEBERgSFDhuDkyZMmx5SWliIjIwNhYWFo1KgRnn76aRQVFVktt7a/T9ylputw48YNTJkyBe3atUNAQADi4uIwdepUaLVaq+XW9mfJGIMZCzp27IjLly8bHjt37rR47H/+8x+MGjUK48ePx8GDBzFkyBAMGTIER48edWGNHe/77783uQYbNmwAAAwbNszia4KDg01ec/78eVdV1yFKSkrQuXNnLFy4UHb/W2+9hfnz52Px4sXYs2cPGjZsiLS0NJSWllos84svvsCMGTOQlZWFAwcOoHPnzkhLS8OVK1ecdRp1Zu063L17FwcOHEBmZiYOHDiAr776CidPnsSTTz5ZY7n2/Fy5W03fBQDo16+fyfn885//tFqmt30XAJic/+XLl/HRRx9BpVLh6aeftlqukr4L27ZtQ0ZGBnbv3o0NGzagoqICffv2RUlJieGY6dOn45tvvsGKFSuwbds2XLp0CUOHDrVabm1+n7hTTdfh0qVLuHTpEt555x0cPXoU+fn5WLduHcaPH19j2fb+LFUjqJqsrCzRuXNnm48fPny4GDhwoMm2xMREMXHiRAfXzL1eeukl0bp1a1FZWSm7Py8vT4SE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\n" + }, + "metadata": {} + } + ], + "source": [ + "plt.plot(data['Population'], data['Profit'], 'bx')\n", + "plt.xlabel('Population in 10,000')\n", + "plt.ylabel('Profit in $10,000')\n", + "plt.title('Relation between profit and population')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dIlGBwuAedBr" + }, + "source": [ + "### The hypotheses function\n", + "Our hypothesis function has the general form:\n", + "$y= h_\\theta(x)= \\theta_0 + \\theta_1x$\n", + "Note that this is like the equation of a straight line. We give to $h_\\theta(x)$ values for $\\theta_0$ and $\\theta_1$ to get our estimated output y. In other words, we are trying to create a function called $h_\\theta$ that is trying to map our input data (the x's) to our output data (the y's).\n", + "\n", + "### Cost function\n", + "\n", + "The cost functions yields \"how far off\" our hypotheses $h_\\theta$ is. It takes the avarage of the distance between our hypothesis and the actual point and squares it. Formally, the cost function has the following definition:\n", + "\n", + "$J(\\theta) = \\frac{1}{2m} \\displaystyle\\sum_{i = 0}^{m}(h_θ(x^{(i)}) - y^{(i)})^2$\n", + "\n", + "#### Vectorization\n", + "Vectorizations is the act of replacing the loops in a computer program with matrix operations. If you have a good linear algebra library (like numpy), the library will optimize the code automatically for the computer the code runs on. Mathematically, the 'regular' function should mean the same as the vectorized function.\n", + "\n", + "Gradient descent vectorized:\n", + "$\\theta = \\frac{1}{2m}(X\\theta - \\vec{y})^T(X\\theta-\\vec{y})$\n", + "\n", + "**Exercise**: Implement a vectorized implementation of the cost function." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "id": "RgJswa1dedBr" + }, + "outputs": [], + "source": [ + "def cost_function(X, y, theta):\n", + " \"\"\" Computes the cost of using theta as the parameter for linear gression to fit the data in X and y. \"\"\"\n", + " #m = len(y)\n", + " predictions = X @ theta # oder np.dot(X, theta)\n", + " errors = predictions - y\n", + " cost = (1 / (2 * m)) * (errors.T @ errors) # oder np.dot(errors.T, errors)\n", + " return cost\n" + ] + }, + { + "cell_type": "code", + "source": [ + "print(cost_function(X,y,theta))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "KVyFJTXzoMoM", + "outputId": "a59fe435-1615-4752-a9aa-2b3b869435ac" + }, + "execution_count": 38, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[[32.07273388 32.07273388 32.07273388 ... 32.07273388 32.07273388\n", + " 32.07273388]\n", + " [32.07273388 32.07273388 32.07273388 ... 32.07273388 32.07273388\n", + " 32.07273388]\n", + " [32.07273388 32.07273388 32.07273388 ... 32.07273388 32.07273388\n", + " 32.07273388]\n", + " ...\n", + " [32.07273388 32.07273388 32.07273388 ... 32.07273388 32.07273388\n", + " 32.07273388]\n", + " [32.07273388 32.07273388 32.07273388 ... 32.07273388 32.07273388\n", + " 32.07273388]\n", + " [32.07273388 32.07273388 32.07273388 ... 32.07273388 32.07273388\n", + " 32.07273388]]\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "uD9qXs16edBr" + }, + "source": [ + "With $\\theta = \\begin{bmatrix}0 & 0\\end{bmatrix}$, $J(\\theta)$ should return 32.07." + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "i7f54jpLedBr", + "outputId": "9023013c-9635-4188-d415-cf7916776806" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[[32.07273388]]\n" + ] + } + ], + "source": [ + "initial_theta = np.zeros((2,1))\n", + "print(cost_function(X, y, initial_theta))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dAnaDdOcedBs" + }, + "source": [ + "### Gradient descent\n", + "We want are hypothesis $h_\\theta(x)$ to function as good as possibly. Therefore, we want to minimalize the cost function $J(\\theta)$. Gradient descent is an algorithm used to do that.\n", + "\n", + "The formal definition of gradient descent:\n", + "\n", + "$repeat \\ \\{ \\\\ \\enspace \\theta_j := \\theta_j - \\alpha \\frac{1}{m}\\displaystyle\\sum_{i = 1}^{m}(h_\\theta(x^{(i)})-y^{(i)})x_j^{(i)}\\\\\\}$\n", + "\n", + "An illustration of gradient descent on a single variable:\n", + "
\n", + " \n", + "
\n", + "\n", + "**Exercise**: Implement the gradient descent algorithm in Python." + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "id": "dFtq843KedBs" + }, + "outputs": [], + "source": [ + "def gradient_descent(X, y, theta, alpha, iterations):\n", + " \"\"\" Performs gradient descent to learn theta.\n", + " Returns the found value for theta and the history of the cost function.\n", + " \"\"\"\n", + " J_history = []\n", + " for i in range(iterations):\n", + " predictions = X @ theta\n", + " errors = predictions -y\n", + " theta = theta - (alpha / m) * (X.T @ errors)\n", + " J_history.append(cost_function(X,y,theta)[0,0])\n", + " return theta, J_history" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "2S8tAHhbedBs" + }, + "source": [ + "Gradient descent should have found approximately the following: $\\theta = \\begin{bmatrix}-3.6303\\\\1.1664\\end{bmatrix}$" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "scrolled": true, + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "WX4u1MS0edBs", + "outputId": "5e474751-b68c-49c9-aedf-289772dbbfef" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([[-3.63029144],\n", + " [ 1.16636235]])" + ] + }, + "metadata": {}, + "execution_count": 45 + } + ], + "source": [ + "# You can change different values for these variables\n", + "alpha = 0.01\n", + "iterations = 1500\n", + "\n", + "theta, J_history = gradient_descent(X, y, initial_theta, alpha, iterations)\n", + "theta" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "BiBuvD-redBs" + }, + "source": [ + "### Using the results\n", + "#### Plotting the regularization line" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 447 + }, + "id": "uH_LQl1yedBs", + "outputId": "a6746e64-87d1-4008-cc64-7bd467e5eb93" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[]" + ] + }, + "metadata": {}, + "execution_count": 46 + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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li3T8OHD1bVrV40YMUJ/+ctfHGpt6pSWloYdh7y8PM2YMcNy+6VLl4Zt27VrV4db3XEbNmzQ5ZdfruLiYuXl5em5554LWm8YhiorKzVw4EB169ZNkyZN0s6dO6Pu95FHHlFpaam6du2qMWPG6NVXX03RK+i4SMfg+PHjuu+++zRixAh1795dxcXF+t73vqcDBw5E3Gcin6t0i/ZeuPHGG8Ne05QpU6LuN5PeC1L042D1eyIvL08/+9nPbPeZae+HmpoanX/++erRo4f69++v6dOna8eOHUHbHDt2TDNmzFCfPn108skn66qrrtKhQ4ci7jfR3yfpEO0YfPrpp7rzzjs1bNgwdevWTSUlJfrhD3+ohoaGiPtN9HMUKCvChySdeeaZOnjwYNvXK6+8Yrvt3//+d1133XW6+eabtW3bNk2fPl3Tp0/X9u3bHWxx8r322mtBx2D16tWSpG9/+9u2z+nZs2fQc/bu3etUc5OmublZo0aN0iOPPGK5/sEHH9SvfvUrPfbYY9q8ebO6d++uSy+9VMeOHbPd5x/+8AfNmjVL8+bN09atWzVq1Chdeuml+vDDD1P1Mjok0jE4evSotm7dqoqKCm3dulXPPvusduzYoW984xtR9xvP58oNor0XJGnKlClBr+mpp56KuM9Mey9I0Y9D4Os/ePCgFi9erLy8PF111VUR95tJ74f169drxowZ2rRpk1avXq3jx49r8uTJam5ubtvm7rvv1p///GctW7ZM69ev14EDB3TllVdG3G8iv0/SJdoxOHDggA4cOKCf//zn2r59u5YuXaoXX3xRN998c9R9x/s5CmNkgXnz5hmjRo2Kefurr77amDZtWtCyMWPGGLfddluSW5Ze//Zv/2aceuqpRmtrq+X6JUuWGIWFhc42KsUkGcuXL2973NraahQVFRk/+9nP2pYdPnzY8Hg8xlNPPWW7n9GjRxszZsxoe+zz+Yzi4mKjpqYmJe1OptBjYOXVV181JBl79+613Sbez5XbWB2HG264wbjiiivi2k8mvxcMI7b3wxVXXGGUl5dH3CbT3w8ffvihIclYv369YRj+3wNdunQxli1b1rbNP/7xD0OSsXHjRst9JPr7xC1Cj4GVZ555xigoKDCOHz9uu00in6NQWXPlY+fOnSouLtbQoUP13e9+V++//77tths3btSkSZOCll166aXauHFj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\n" + }, + "metadata": {} + } + ], + "source": [ + "plt.plot(X[:,1], y, 'rx', label='Training data')\n", + "plt.plot(X[:,1], X.dot(theta), label='Linear regression')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "okUBboOxedBs" + }, + "source": [ + "#### Plotting the cost history\n", + "A plot of how $J(\\theta)$ decreases over time. This is are model learning." + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "scrolled": true, + "colab": { + "base_uri": "https://localhost:8080/", + "height": 447 + }, + "id": "4qpmwc3bedBs", + "outputId": "19f87ec9-fba3-4bde-fa96-5f02685e097c" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[]" + ] + }, + "metadata": {}, + "execution_count": 47 + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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aunSpaZLarGZM2fqzDPPVHx8vNLS0nTZZZcpLy+vSZuqqipNnTpVycnJiouL0xVXXKHCwsImbfLz8zVhwgTFxMQoLS1Nd911l+rq6k5nV07KrFmzZFmW7rjjjuC+cOzvnj17dNVVVyk5OVnR0dEaOHCgli9fHjxu27Z+/etfKzMzU9HR0Ro3bpw2b97c5DOKi4s1efJkJSQkKCkpSddff70qKipOd1dOyO/361e/+pWys7MVHR2tM844Q/fee2+Te1uEcn8//vhj/eAHP1BWVpYsy9Ibb7zR5Hhr9e2LL77Q2WefraioKPl8Pv3+979v664d1fH6W1tbq7vvvlsDBw5UbGyssrKyNGXKFO3du7fJZ4RLf7/plltukWVZeuSRR5rsD6X+thrboebOnWtHRkbazzzzjL1+/Xr7xhtvtJOSkuzCwkLTpbXI+PHj7WeffdZet26dvXr1avviiy+2u3TpYldUVATb3HLLLbbP57MXLlxoL1++3D7rrLPs0aNHB4/X1dXZAwYMsMeNG2evWrXKfuedd+yUlBR7xowZJrrUbEuXLrW7detmDxo0yJ42bVpwf7j1t7i42O7atat97bXX2p9//rm9bds2e/78+faWLVuCbWbNmmUnJibab7zxhr1mzRr7kksusbOzs+3KyspgmwsvvNAePHiw/dlnn9mffPKJ3aNHD3vSpEkmunRcv/vd7+zk5GT73//+t719+3b71VdftePi4uxHH3002CaU+/vOO+/Yv/zlL+3XXnvNlmS//vrrTY63Rt9KS0vt9PR0e/Lkyfa6devsl19+2Y6OjrafeOKJ09XNoOP1t6SkxB43bpz997//3d64caOdm5trjxgxwh4+fHiTzwiX/h7ptddeswcPHmxnZWXZDz/8cJNjodTf1uLYMDJixAh76tSpwdd+v9/OysqyZ86cabCqU1dUVGRLshctWmTbdv0ve0REhP3qq68G23z55Ze2JDs3N9e27fpfHpfLZRcUFATbzJ49205ISLCrq6tPbweaqby83O7Zs6e9YMEC+9xzzw2GkXDs7913322PHTv2mMcDgYCdkZFhP/DAA8F9JSUlttfrtV9++WXbtm17w4YNtiR72bJlwTbvvvuubVmWvWfPnrYr/iRMmDDB/ulPf9pk3w9/+EN78uTJtm2HV3+/+WXVWn177LHH7A4dOjT593z33XfbvXv3buMeHd/xvpwbLV261JZk79y507bt8Ozv7t277U6dOtnr1q2zu3bt2iSMhHJ/T4UjL9PU1NRoxYoVGjduXHCfy+XSuHHjlJuba7CyU1daWipJ6tixoyRpxYoVqq2tbdLXPn36qEuXLsG+5ubmauDAgUpPTw+2GT9+vMrKyrR+/frTWH3zTZ06VRMmTGjSLyk8+/vWW28pJydHEydOVFpamoYOHaqnnnoqeHz79u0qKCho0ufExESNHDmySZ+TkpKUk5MTbDNu3Di5XC59/vnnp68zzTB69GgtXLhQmzZtkiStWbNGixcv1kUXXSQp/Pp7pNbqW25urs455xxFRkYG24wfP155eXk6ePDgaerNySktLZVlWUpKSpIUfv0NBAK6+uqrddddd6l///7fOh5u/W0uR4aRAwcOyO/3N/kykqT09HQVFBQYqurUBQIB3XHHHRozZowGDBggSSooKFBkZGTwF7vRkX0tKCg46n+LxmPtzdy5c7Vy5UrNnDnzW8fCsb/btm3T7Nmz1bNnT82fP1+33nqrbr/9dj333HOSvq75eP+eCwoKlJaW1uS4x+NRx44d212f//u//1s/+clP1KdPH0VERGjo0KG64447NHnyZEnh198jtVbfQu3feKOqqirdfffdmjRpUvBGceHW3/vvv18ej0e33377UY+HW3+bKyTu2ovmmTp1qtatW6fFixebLqXN7Nq1S9OmTdOCBQsUFRVlupzTIhAIKCcnR/fdd58kaejQoVq3bp0ef/xxXXPNNYara32vvPKKXnzxRb300kvq37+/Vq9erTvuuENZWVlh2V/Uq62t1ZVXXinbtjV79mzT5bSJFStW6NFHH9XKlStlWZbpctoVR54ZSUlJkdvt/tYMi8LCQmVkZBiq6tTcdttt+ve//60PP/xQnTt3Du7PyMhQTU2NSkpKmrQ/sq8ZGRlH/W/ReKw9WbFihYqKijRs2DB5PB55PB4tWrRIf/zjH+XxeJSenh5W/ZWkzMxM9evXr8m+vn37Kj8/X9LXNR/v33NGRoaKioqaHK+rq1NxcXG76/Ndd90VPDsycOBAXX311Zo+fXrwTFi49fdIrdW3UPs33hhEdu7cqQULFgTPikjh1d9PPvlERUVF6tKlS/Dv186dO3XnnXeqW7duksKrvy3hyDASGRmp4cOHa+HChcF9gUBACxcu1KhRowxW1nK2beu2227T66+/rg8++EDZ2dlNjg8fPlwRERFN+pqXl6f8/PxgX0eNGqW1a9c2+QVo/IPwzS9B0y644AKtXbtWq1evDm45OTmaPHly8Hk49VeSxowZ863p2ps2bVLXrl0lSdnZ2crIyGjS57KyMn3++edN+lxSUqIVK1YE23zwwQcKBAIaOXLkaehF8x0+fFguV9M/TW63W4FAQFL49fdIrdW3UaNG6eOPP1ZtbW2wzYIFC9S7d2916NDhNPWmeRqDyObNm/X+++8rOTm5yfFw6u/VV1+tL774osnfr6ysLN11112aP3++pPDqb4uYHkFryty5c22v12vPmTPH3rBhg33TTTfZSUlJTWZYhIJbb73VTkxMtD/66CN73759we3w4cPBNrfccovdpUsX+4MPPrCXL19ujxo1yh41alTweONU1+9973v26tWr7Xnz5tmpqantdqrrNx05m8a2w6+/S5cutT0ej/273/3O3rx5s/3iiy/aMTEx9gsvvBBsM2vWLDspKcl+88037S+++MK+9NJLjzoddOjQofbnn39uL1682O7Zs2e7mOr6Tddcc43dqVOn4NTe1157zU5JSbF/8YtfBNuEcn/Ly8vtVatW2atWrbIl2Q899JC9atWq4OyR1uhbSUmJnZ6ebl999dX2unXr7Llz59oxMTFGpn4er781NTX2JZdcYnfu3NlevXp1k79hR84UCZf+Hs03Z9PYdmj1t7U4NozYtm3/6U9/srt06WJHRkbaI0aMsD/77DPTJbWYpKNuzz77bLBNZWWl/bOf/czu0KGDHRMTY19++eX2vn37mnzOjh077IsuusiOjo62U1JS7DvvvNOura09zb05Od8MI+HY33/961/2gAEDbK/Xa/fp08d+8sknmxwPBAL2r371Kzs9Pd32er32BRdcYOfl5TVp89VXX9mTJk2y4+Li7ISEBPu6666zy8vLT2c3mqWsrMyeNm2a3aVLFzsqKsru3r27/ctf/rLJl1Mo9/fDDz886u/sNddcY9t26/VtzZo19tixY22v12t36tTJnjVr1unqYhPH6+/27duP+Tfsww8/DH5GuPT3aI4WRkKpv63Fsu0jljUEAAA4zRw5ZgQAALQfhBEAAGAUYQQAABhFGAEAAEYRRgAAgFGEEQAAYBRhBAAAGEUYAQAARhFGAACAUYQRAABgFGEEAAAYRRgBAABG/X87ggngwR2PEgAAAABJRU5ErkJggg==\n" + }, + "metadata": {} + } + ], + "source": [ + "plt.plot(J_history)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "iveY7X8TedBs" + }, + "source": [ + "#### Making a prediction using the model\n", + "The model can be used by calculating the dot product of the input and $\\theta$." + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 90 + }, + "id": "B5p6OEededBs", + "outputId": "819d12e2-9b91-4798-9e8b-80abae2749e5" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + ":2: DeprecationWarning: Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)\n", + " 'In a city with a population of 35000, we predict a profit of $%.2f' % prediction\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "'In a city with a population of 35000, we predict a profit of $4519.77'" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "string" + } + }, + "metadata": {}, + "execution_count": 48 + } + ], + "source": [ + "prediction = np.array([1, 3.5]).dot(theta) * 10000 # don't forget to multiply the prediction by 10000\n", + "'In a city with a population of 35000, we predict a profit of $%.2f' % prediction" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "W59iLif5edBs" + }, + "source": [ + "\n", + "## Multivariate Linear Regression\n", + "\n", + "---\n", + "In this part, you will implement linear regression with multiple variables to predict the prices of houses. Suppose you are selling your house and you want to know what a good market price would be. One way to do this is to first collect information on recent houses sold and make a model of housing prices." + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": { + "scrolled": true, + "colab": { + "base_uri": "https://localhost:8080/", + "height": 417 + }, + "id": "6ovhUjB3edBs", + "outputId": "fc7c581a-4c28-4d5f-f8b8-cdaa622e9533" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "--2025-04-07 14:53:25-- https://raw.githubusercontent.com/annigue/CS229-Python/master/ex1/ex1data2.txt\n", + "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n", + "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 657 [text/plain]\n", + "Saving to: ‘ex1data2.txt’\n", + "\n", + "\rex1data2.txt 0%[ ] 0 --.-KB/s \rex1data2.txt 100%[===================>] 657 --.-KB/s in 0s \n", + "\n", + "2025-04-07 14:53:25 (30.0 MB/s) - ‘ex1data2.txt’ saved [657/657]\n", + "\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " Size Bedrooms Price\n", + "0 2104 3 399900\n", + "1 1600 3 329900\n", + "2 2400 3 369000\n", + "3 1416 2 232000\n", + "4 3000 4 539900" + ], + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
SizeBedroomsPrice
021043399900
116003329900
224003369000
314162232000
430004539900
\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
\n", + "\n", + "\n", + "
\n", + " \n", + "\n", + "\n", + "\n", + " \n", + "
\n", + "\n", + "
\n", + "
\n" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "data", + "summary": "{\n \"name\": \"data\",\n \"rows\": 47,\n \"fields\": [\n {\n \"column\": \"Size\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 794,\n \"min\": 852,\n \"max\": 4478,\n \"num_unique_values\": 47,\n \"samples\": [\n 2526,\n 2162,\n 1458\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Bedrooms\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 0,\n \"min\": 1,\n \"max\": 5,\n \"num_unique_values\": 5,\n \"samples\": [\n 2,\n 1,\n 4\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Price\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 125039,\n \"min\": 169900,\n \"max\": 699900,\n \"num_unique_values\": 40,\n \"samples\": [\n 252900,\n 199900,\n 449900\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" + } + }, + "metadata": {}, + "execution_count": 54 + } + ], + "source": [ + "# load data\n", + "!wget https://raw.githubusercontent.com/annigue/CS229-Python/master/ex1/ex1data2.txt\n", + "data = pd.read_csv(\"ex1data2.txt\", header = None, names=[\"Size\", \"Bedrooms\",\"Price\"])\n", + "m = len(data)\n", + "\n", + "# Initialize X, y and theta\n", + "x0 = np.ones(m)\n", + "size = np.array((data[\"Size\"]))\n", + "bedrooms = np.array((data[\"Bedrooms\"]))\n", + "X = np.array([x0, size, bedrooms]).T\n", + "y = np.array(data[\"Price\"]).reshape(len(data.index), 1)\n", + "theta_init = np.zeros((3,1))\n", + "\n", + "data.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "15yVO3VjedBt" + }, + "source": [ + "### Feature Normalization\n", + "When features differ by order of magnitude, first performing feature scaling can make gradient descent converge much more quickly. Formally:\n", + "\n", + "$x := \\frac{x - \\mu}{\\sigma}$\n", + "\n", + "Where $\\mu$ is the average and $\\sigma$ the standard deviation.\n", + "\n", + "**Important**: It is crucial to store $\\mu$ and $\\sigma$ if you want to make predictions using the model later.\n", + "\n", + "**Exercise**: Perform feature normalization on the following dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6DCANiS5edBt", + "outputId": "f99390c9-bd53-40fb-c7eb-58df4300eec0" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([[ nan, 0.13141542, -0.22609337],\n", + " [ nan, -0.5096407 , -0.22609337],\n", + " [ nan, 0.5079087 , -0.22609337],\n", + " [ nan, -0.74367706, -1.5543919 ],\n", + " [ nan, 1.27107075, 1.10220517]])" + ] + }, + "metadata": {}, + "execution_count": 67 + } + ], + "source": [ + "# perform normalization\n", + "def normalize(X):\n", + " \"\"\" Normalizes the features in X\n", + "\n", + " returns a normalized version of X where\n", + " the mean value of each feature is 0 and the standard deviation\n", + " is 1. This is often a good preprocessing step to do when\n", + " working with learning algorithms.\n", + " \"\"\"\n", + " mu = np.mean(X, axis=0) # Mittelwert\n", + " sigma = np.std(X, axis=0) # Standardabweichung\n", + "\n", + " # Setze sigma auf 1, falls es 0 ist (um division by zero zu verhindern)\n", + " sigma[sigma == 0] = 1\n", + "\n", + " X = (X - mu) / (sigma + 1e-10)\n", + " return X, mu, sigma\n", + "\n", + "X, mu, sigma = normalize(X)\n", + "X[0:5]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "85iiGE_BedBt" + }, + "source": [ + "## Gradient Descent\n", + "\n", + "Remember the algorithm for gradient descent:\n", + "\n", + "$repeat \\ \\{ \\\\ \\enspace \\theta_j := \\theta_j - \\alpha \\frac{1}{m}\\displaystyle\\sum_{i = 1}^{m}(h_\\theta(x^{(i)})-y^{(i)})x_j^{(i)}\\\\\\}$\n", + "\n", + "The vectorization for multivariate gradient descent:\n", + "\n", + "$\\theta := \\theta - \\frac{\\alpha}{m}X^T(X\\theta - \\vec{y})$\n", + "\n", + "**Exercise**: Implement gradient descent for multiple features. Make sure your solution is vectorized and supports any number of features." + ] + }, + { + "cell_type": "code", + "source": [ + "print(\"Überprüfe X auf NaN-Werte:\")\n", + "print(np.isnan(X).sum()) # Gibt die Anzahl der NaN-Werte in X zurück\n", + "\n", + "print(\"Überprüfe y auf NaN-Werte:\")\n", + "print(np.isnan(y).sum()) # Gibt die Anzahl der NaN-Werte in y zurück" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "1jLf-WQv011l", + "outputId": "5ba5c055-9e61-4d91-ed4b-4098a2479369" + }, + "execution_count": 64, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Überprüfe X auf NaN-Werte:\n", + "47\n", + "Überprüfe y auf NaN-Werte:\n", + "0\n" + ] + } + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "wivXwqtdedBt", + "outputId": "61495a8b-e8cc-4951-f4f1-008822b6a543" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "NaN detected in cost function at iteration 0\n" + ] + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([[nan],\n", + " [nan],\n", + " [nan]])" + ] + }, + "metadata": {}, + "execution_count": 63 + } + ], + "source": [ + "def gradient_descent_multi(X, y, theta, alpha, iterations):\n", + " m = len(y)\n", + " J_history = []\n", + "\n", + " for i in range(iterations):\n", + " predictions = X @ theta\n", + " errors = predictions - y\n", + " theta = theta - (alpha / m) * (X.T @ errors)\n", + "\n", + " # Sicherstellen, dass die Kostenfunktion keine NaNs zurückgibt\n", + " cost = cost_function(X, y, theta)\n", + " if np.isnan(cost).any():\n", + " print(\"NaN detected in cost function at iteration\", i)\n", + " break\n", + "\n", + " J_history.append(cost[0, 0])\n", + "\n", + " return theta, J_history\n", + "\n", + "# Lernrate verringern und testen\n", + "alpha = 0.01\n", + "iterations = 1500\n", + "initial_theta = np.zeros((3,1))\n", + "theta, J_history = gradient_descent_multi(X, y, initial_theta, alpha, iterations)\n", + "theta" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "2SoGUsOxedBt" + }, + "source": [ + "As before we see how the cost decreases over time." + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 489 + }, + "id": "K3EOeRPXedBt", + "outputId": "17863a3a-5917-4bab-8e22-b773ee21d509" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "Text(0, 0.5, 'cost')" + ] + }, + "metadata": {}, + "execution_count": 61 + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAksAAAHHCAYAAACvJxw8AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAMD5JREFUeJzt3XtcVXW+//H3BuTiBfCCIImSZYlmWphEk6MJJyw7ZukjY8xbJl3UpiRT0yTrnCHLJnUsrTPTkKWjo1N2c+wYmqaSF8y7OObxroBmgFeu398f/djTDvyKyG3b6/l4rIft7/5+1/p81zDs92Ot7144jDFGAAAAKJdHbRcAAABQlxGWAAAALAhLAAAAFoQlAAAAC8ISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYEJYA/GqkpKTI4XDowIEDtV1Khb300ktyOBy1XQbwq0ZYAnDFSkPIpk2baruUy/b2228rJSWlVms4d+6cXnrpJX399de1WgeA8hGWAPxqDBo0SOfPn1fr1q2dbXUlLE2ZMqXcsDRp0iSdP3++5osC4ERYAnBVOXv27EXf8/T0lK+vb7Xf1ioqKlJBQUGV7MvLy0u+vr5Vsi8AlUNYAlAjSm/VrV69Wo8//riaNm0qf39/DR48WD/++GOZ/v/85z/VrVs3NWjQQI0aNVLv3r21c+dOlz5Dhw5Vw4YNtW/fPt17771q1KiRBg4ceMkaStcshYeHa+fOnVq1apUcDoccDod69Ojh7J+Tk6NnnnlGYWFh8vHx0fXXX6+pU6eqpKTE2efAgQNyOByaNm2apk+fruuuu04+Pj7atWuXCgoKNHnyZEVGRiogIEANGjRQt27dtHLlSpfxQUFBkqQpU6Y463jppZcklb9mqaioSK+88orzWOHh4XrhhReUn5/v0i88PFz33Xef1qxZo65du8rX11dt2rTR3LlzL/4/FIAyvGq7AAC/LqNGjVJgYKBeeukl7dmzR7Nnz9bBgwf19ddfO0PBBx98oCFDhiguLk5Tp07VuXPnNHv2bN1555367rvvFB4e7txfUVGR4uLidOedd2ratGmqX79+hWuZPn26Ro8erYYNG2rixImSpODgYEk/3Rrr3r27jh49qscff1ytWrXSunXrNGHCBB0/flzTp0932ddf//pXXbhwQQkJCfLx8VGTJk2Ul5enP//5z4qPj9eIESN0+vRp/eUvf1FcXJw2bNigzp07KygoSLNnz9aTTz6pBx54QA8++KAk6eabb75o3Y899pjef/999e/fX4mJiVq/fr2Sk5O1e/duffzxxy59v//+e/Xv31/Dhw/XkCFD9N5772no0KGKjIxUhw4dKnyugF81AwBX6K9//auRZDZu3HjJPpGRkaagoMDZ/tprrxlJ5pNPPjHGGHP69GkTGBhoRowY4TI+MzPTBAQEuLQPGTLESDLjx4+/rDr379/vbOvQoYPp3r17mb6vvPKKadCggfnXv/7l0j5+/Hjj6elpDh06ZIwxZv/+/UaS8ff3N9nZ2S59i4qKTH5+vkvbjz/+aIKDg82jjz7qbDtx4oSRZJKSksrUkZSUZH7+q3rLli1Gknnsscdc+j333HNGklmxYoWzrXXr1kaSWb16tbMtOzvb+Pj4mMTExDLHAlA+bsMBqFEJCQmqV6+e8/WTTz4pLy8vLV26VJK0fPly5eTkKD4+XidPnnRunp6eioqKcrmF9fN9VLVFixapW7duaty4sUsdsbGxKi4u1urVq1369+vXz3k7rZSnp6e8vb0lSSUlJTp16pSKiorUpUsXbd68uVJ1lZ6nMWPGuLQnJiZKkr744guX9vbt26tbt27O10FBQbrxxhv1f//3f5U6PvBrxG04ADWqbdu2Lq8bNmyoFi1aONcR7d27V5LUs2fPcsf7+/u7vPby8lLLli2rvM69e/dq27ZtZQJQqezsbJfX1157bbn93n//fb3xxhvKyMhQYWHhJftfysGDB+Xh4aHrr7/epT0kJESBgYE6ePCgS3urVq3K7KNx48blrhMDUD7CEoA6pXTx9AcffKCQkJAy73t5uf7a8vHxkYdH1V8kLykp0X/8x3/o+eefL/f9G264weW1n59fmT4ffvihhg4dqr59+2rs2LFq3ry5PD09lZycrH379l1RfRX9Rp+np2e57caYKzo+8GtCWAJQo/bu3au77rrL+frMmTM6fvy47r33XknSddddJ0lq3ry5YmNjq72ei4WO6667TmfOnLmiGhYvXqw2bdroo48+cjlOUlJShWooT+vWrVVSUqK9e/cqIiLC2Z6VlaWcnByXZ0gBqBqsWQJQo959912X21GzZ89WUVGR7rnnHklSXFyc/P399Yc//MGlX6kTJ05UaT0NGjRQTk5OmfaHHnpIaWlp+vLLL8u8l5OTo6Kiokvuu/Sqzs+v4qxfv15paWku/Uq/wVdeHb9UGip/+W28P/7xj5Kk3r17X3IfAC4PV5YA1KiCggLFxMTooYce0p49e/T222/rzjvvVJ8+fST9tCZp9uzZGjRokG699VY9/PDDCgoK0qFDh/TFF1/oN7/5jWbNmlVl9URGRmr27Nn6r//6L11//fVq3ry5evbsqbFjx+rTTz/Vfffd5/yq/dmzZ7V9+3YtXrxYBw4cULNmzaz7vu+++/TRRx/pgQceUO/evbV//37NmTNH7du315kzZ5z9/Pz81L59ey1cuFA33HCDmjRpoptuukk33XRTmX126tRJQ4YM0bvvvqucnBx1795dGzZs0Pvvv6++ffu6XLUDUDUISwCuWOmVk4utj/m5WbNmad68eZo8ebIKCwsVHx+vmTNnutyK+t3vfqfQ0FC9+uqrev3115Wfn69rrrlG3bp107Bhw6q09smTJ+vgwYN67bXXdPr0aXXv3l09e/ZU/fr1tWrVKv3hD3/QokWLNHfuXPn7++uGG27QlClTFBAQcMl9Dx06VJmZmXrnnXf05Zdfqn379vrwww+1aNGiMn/a5M9//rNGjx6tZ599VgUFBUpKSio3LJX2bdOmjVJSUvTxxx8rJCREEyZMKHN7D0DVcBhW+QG4QjNnztTvf/97ff/99841R7+UkpKiYcOGaePGjerSpUsNVwgAlceaJQBXbOPGjWrQoAGLiwFclbgNB6DS/vGPf+jrr7/WvHnz9Nhjj5X5Wj8AXA34zQag0p577jmdPn1aw4cP15tvvlnb5QBAtWDNEgAAgAVrlgAAACwISwAAABasWaoCJSUlOnbsmBo1anRZf7YAAADUHmOMTp8+rdDQUOvfmCQsVYFjx44pLCystssAAACVcPjwYbVs2fKi7xOWqkCjRo0k/XSy/f39a7kaAABQEXl5eQoLC3N+jl8MYakKlN568/f3JywBAOBmLrWEhgXeAAAAFoQlAAAAC8ISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYEJYAAAAsCEsAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgAVhCQAAwIKwBAAAYEFYAgAAsCAsAQAAWBCWAAAALAhLAAAAFoQlAAAAC8ISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYEJYAAAAsCEsAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgIXbhaW33npL4eHh8vX1VVRUlDZs2GDtv2jRIrVr106+vr7q2LGjli5detG+TzzxhBwOh6ZPn17FVQMAAHflVmFp4cKFGjNmjJKSkrR582Z16tRJcXFxys7OLrf/unXrFB8fr+HDh+u7775T37591bdvX+3YsaNM348//ljffvutQkNDq3saAADAjbhVWPrjH/+oESNGaNiwYWrfvr3mzJmj+vXr67333iu3/4wZM9SrVy+NHTtWEREReuWVV3Trrbdq1qxZLv2OHj2q0aNHa968eapXr15NTAUAALgJtwlLBQUFSk9PV2xsrLPNw8NDsbGxSktLK3dMWlqaS39JiouLc+lfUlKiQYMGaezYserQoUP1FA8AANyWV20XUFEnT55UcXGxgoODXdqDg4OVkZFR7pjMzMxy+2dmZjpfT506VV5eXnr66acrXEt+fr7y8/Odr/Py8io8FgAAuBe3ubJUHdLT0zVjxgylpKTI4XBUeFxycrICAgKcW1hYWDVWCQAAapPbhKVmzZrJ09NTWVlZLu1ZWVkKCQkpd0xISIi1/zfffKPs7Gy1atVKXl5e8vLy0sGDB5WYmKjw8PCL1jJhwgTl5uY6t8OHD1/Z5AAAQJ3lNmHJ29tbkZGRSk1NdbaVlJQoNTVV0dHR5Y6Jjo526S9Jy5cvd/YfNGiQtm3bpi1btji30NBQjR07Vl9++eVFa/Hx8ZG/v7/LBgAArk5us2ZJksaMGaMhQ4aoS5cu6tq1q6ZPn66zZ89q2LBhkqTBgwfrmmuuUXJysiTp97//vbp376433nhDvXv31oIFC7Rp0ya9++67kqSmTZuqadOmLseoV6+eQkJCdOONN9bs5AAAQJ3kVmFpwIABOnHihCZPnqzMzEx17txZy5Ytcy7iPnTokDw8/n2x7I477tD8+fM1adIkvfDCC2rbtq2WLFmim266qbamAAAA3IzDGGNquwh3l5eXp4CAAOXm5nJLDgAAN1HRz2+3WbMEAABQGwhLAAAAFoQlAAAAC8ISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYEJYAAAAsCEsAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgAVhCQAAwIKwBAAAYEFYAgAAsCAsAQAAWBCWAAAALAhLAAAAFoQlAAAAC8ISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYEJYAAAAsCEsAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgAVhCQAAwIKwBAAAYEFYAgAAsCAsAQAAWBCWAAAALAhLAAAAFoQlAAAAC8ISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYuF1YeuuttxQeHi5fX19FRUVpw4YN1v6LFi1Su3bt5Ovrq44dO2rp0qXO9woLCzVu3Dh17NhRDRo0UGhoqAYPHqxjx45V9zQAAICbcKuwtHDhQo0ZM0ZJSUnavHmzOnXqpLi4OGVnZ5fbf926dYqPj9fw4cP13XffqW/fvurbt6927NghSTp37pw2b96sF198UZs3b9ZHH32kPXv2qE+fPjU5LQAAUIc5jDGmtouoqKioKN12222aNWuWJKmkpERhYWEaPXq0xo8fX6b/gAEDdPbsWX3++efOtttvv12dO3fWnDlzyj3Gxo0b1bVrVx08eFCtWrWqUF15eXkKCAhQbm6u/P39KzEzAABQ0yr6+e02V5YKCgqUnp6u2NhYZ5uHh4diY2OVlpZW7pi0tDSX/pIUFxd30f6SlJubK4fDocDAwCqpGwAAuDev2i6gok6ePKni4mIFBwe7tAcHBysjI6PcMZmZmeX2z8zMLLf/hQsXNG7cOMXHx1sTZn5+vvLz852v8/LyKjoNAADgZtzmylJ1Kyws1EMPPSRjjGbPnm3tm5ycrICAAOcWFhZWQ1UCAICa5jZhqVmzZvL09FRWVpZLe1ZWlkJCQsodExISUqH+pUHp4MGDWr58+SXXHU2YMEG5ubnO7fDhw5WYEQAAcAduE5a8vb0VGRmp1NRUZ1tJSYlSU1MVHR1d7pjo6GiX/pK0fPlyl/6lQWnv3r366quv1LRp00vW4uPjI39/f5cNAABcndxmzZIkjRkzRkOGDFGXLl3UtWtXTZ8+XWfPntWwYcMkSYMHD9Y111yj5ORkSdLvf/97de/eXW+88YZ69+6tBQsWaNOmTXr33Xcl/RSU+vfvr82bN+vzzz9XcXGxcz1TkyZN5O3tXTsTBQAAdYZbhaUBAwboxIkTmjx5sjIzM9W5c2ctW7bMuYj70KFD8vD498WyO+64Q/Pnz9ekSZP0wgsvqG3btlqyZIluuukmSdLRo0f16aefSpI6d+7scqyVK1eqR48eNTIvAABQd7nVc5bqKp6zBACA+7nqnrMEAABQGwhLAAAAFoQlAAAAC8ISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYEJYAAAAsCEsAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgAVhCQAAwIKwBAAAYEFYAgAAsCAsAQAAWBCWAAAALAhLAAAAFoQlAAAAC8ISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYEJYAAAAsCEsAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgAVhCQAAwIKwBAAAYEFYAgAAsCAsAQAAWBCWAAAALCoVlubOnav8/Pwy7QUFBZo7d+4VFwUAAFBXOIwx5nIHeXp66vjx42revLlL+w8//KDmzZuruLi4ygp0B3l5eQoICFBubq78/f1ruxwAAFABFf38rtSVJWOMHA5HmfYjR44oICCgMrsEAACok7wup/Mtt9wih8Mhh8OhmJgYeXn9e3hxcbH279+vXr16VXmRAAAAteWywlLfvn0lSVu2bFFcXJwaNmzofM/b21vh4eHq169flRYIAABQmy4rLCUlJUmSwsPD9fDDD8vHx6daigIAAKgrKrVmqWfPnjpx4oTz9YYNG/TMM8/o3XffrbLCAAAA6oJKhaXf/e53WrlypSQpMzNTsbGx2rBhgyZOnKiXX365SgsEAACoTZUKSzt27FDXrl0lSX//+9/VsWNHrVu3TvPmzVNKSkpV1lfGW2+9pfDwcPn6+ioqKkobNmyw9l+0aJHatWsnX19fdezYUUuXLnV53xijyZMnq0WLFvLz81NsbKz27t1bnVMAAABupFJhqbCw0Lle6auvvlKfPn0kSe3atdPx48errrpfWLhwocaMGaOkpCRt3rxZnTp1UlxcnLKzs8vtv27dOsXHx2v48OH67rvv1LdvX/Xt21c7duxw9nnttdc0c+ZMzZkzR+vXr1eDBg0UFxenCxcuVNs8AACA+6jUQymjoqJ01113qXfv3rr77rv17bffqlOnTvr222/Vv39/HTlypDpqVVRUlG677TbNmjVLklRSUqKwsDCNHj1a48ePL9N/wIABOnv2rD7//HNn2+23367OnTtrzpw5MsYoNDRUiYmJeu655yRJubm5Cg4OVkpKih5++OEK1cVDKQEAcD/V+lDKqVOn6p133lGPHj0UHx+vTp06SZI+/fRT5+25qlZQUKD09HTFxsY62zw8PBQbG6u0tLRyx6Slpbn0l6S4uDhn//379zvXXJUKCAhQVFTURfcpSfn5+crLy3PZAADA1emyHh1QqkePHjp58qTy8vLUuHFjZ3tCQoLq169fZcX93MmTJ1VcXKzg4GCX9uDgYGVkZJQ7JjMzs9z+mZmZzvdL2y7WpzzJycmaMmXKZc8BAAC4n0pdWZJ++vtwRUVFWrNmjdasWaMTJ04oPDy8zN+LuxpNmDBBubm5zu3w4cO1XRIAAKgmlQpLZ8+e1aOPPqoWLVrot7/9rX77298qNDRUw4cP17lz56q6RklSs2bN5OnpqaysLJf2rKwshYSElDsmJCTE2r/038vZpyT5+PjI39/fZQMAAFenSoWlMWPGaNWqVfrss8+Uk5OjnJwcffLJJ1q1apUSExOrukZJP/05lcjISKWmpjrbSkpKlJqaqujo6HLHREdHu/SXpOXLlzv7X3vttQoJCXHpk5eXp/Xr1190nwAA4FfGVELTpk3NypUry7SvWLHCNGvWrDK7rJAFCxYYHx8fk5KSYnbt2mUSEhJMYGCgyczMNMYYM2jQIDN+/Hhn/7Vr1xovLy8zbdo0s3v3bpOUlGTq1atntm/f7uzz6quvmsDAQPPJJ5+Ybdu2mfvvv99ce+215vz58xWuKzc310gyubm5VTdZAABQrSr6+V2pBd7nzp0rsyhakpo3b15tt+Gknx4FcOLECU2ePFmZmZnq3Lmzli1b5qzl0KFD8vD498WyO+64Q/Pnz9ekSZP0wgsvqG3btlqyZIluuukmZ5/nn39eZ8+eVUJCgnJycnTnnXdq2bJl8vX1rbZ5AAAA91Gp5yzFxMSoadOmmjt3rjNUnD9/XkOGDNGpU6f01VdfVXmhdRnPWQIAwP1U9PO7UleWpk+frl69eqlly5bOZyxt3bpVPj4++t///d/KVQwAAFAHVerKkvTTrbh58+Y5n3EUERGhgQMHys/Pr0oLdAdcWQIAwP1U65Wl5ORkBQcHa8SIES7t7733nk6cOKFx48ZVZrcAAAB1TqUeHfDOO++oXbt2Zdo7dOigOXPmXHFRAAAAdUWlwlJmZqZatGhRpj0oKEjHjx+/4qIAAADqikqFpbCwMK1du7ZM+9q1axUaGnrFRQEAANQVlVqzNGLECD3zzDMqLCxUz549JUmpqal6/vnnq+0J3gAAALWhUmFp7Nix+uGHH/TUU0+poKBAkuTr66tx48ZpwoQJVVogAABAbar0owMk6cyZM9q9e7f8/PzUtm1b+fj4VGVtboNHBwAA4H6q9dEBpRo2bKjbbrvtSnYBAABQp1VqgTcAAMCvBWEJAADAgrAEAABgQVgCAACwICwBAABYEJYAAAAsCEsAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgAVhCQAAwIKwBAAAYEFYAgAAsCAsAQAAWBCWAAAALAhLAAAAFoQlAAAAC8ISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYEJYAAAAsCEsAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgAVhCQAAwIKwBAAAYEFYAgAAsCAsAQAAWBCWAAAALNwmLJ06dUoDBw6Uv7+/AgMDNXz4cJ05c8Y65sKFCxo5cqSaNm2qhg0bql+/fsrKynK+v3XrVsXHxyssLEx+fn6KiIjQjBkzqnsqAADAjbhNWBo4cKB27typ5cuX6/PPP9fq1auVkJBgHfPss8/qs88+06JFi7Rq1SodO3ZMDz74oPP99PR0NW/eXB9++KF27typiRMnasKECZo1a1Z1TwcAALgJhzHG1HYRl7J79261b99eGzduVJcuXSRJy5Yt07333qsjR44oNDS0zJjc3FwFBQVp/vz56t+/vyQpIyNDERERSktL0+23317usUaOHKndu3drxYoVFa4vLy9PAQEBys3Nlb+/fyVmCAAAalpFP7/d4spSWlqaAgMDnUFJkmJjY+Xh4aH169eXOyY9PV2FhYWKjY11trVr106tWrVSWlraRY+Vm5urJk2aWOvJz89XXl6eywYAAK5ObhGWMjMz1bx5c5c2Ly8vNWnSRJmZmRcd4+3trcDAQJf24ODgi45Zt26dFi5ceMnbe8nJyQoICHBuYWFhFZ8MAABwK7UalsaPHy+Hw2HdMjIyaqSWHTt26P7771dSUpLuvvtua98JEyYoNzfXuR0+fLhGagQAADXPqzYPnpiYqKFDh1r7tGnTRiEhIcrOznZpLyoq0qlTpxQSElLuuJCQEBUUFCgnJ8fl6lJWVlaZMbt27VJMTIwSEhI0adKkS9bt4+MjHx+fS/YDAADur1bDUlBQkIKCgi7ZLzo6Wjk5OUpPT1dkZKQkacWKFSopKVFUVFS5YyIjI1WvXj2lpqaqX79+kqQ9e/bo0KFDio6OdvbbuXOnevbsqSFDhui///u/q2BWAADgauIW34aTpHvuuUdZWVmaM2eOCgsLNWzYMHXp0kXz58+XJB09elQxMTGaO3euunbtKkl68skntXTpUqWkpMjf31+jR4+W9NPaJOmnW289e/ZUXFycXn/9deexPD09KxTiSvFtOAAA3E9FP79r9crS5Zg3b55GjRqlmJgYeXh4qF+/fpo5c6bz/cLCQu3Zs0fnzp1ztr355pvOvvn5+YqLi9Pbb7/tfH/x4sU6ceKEPvzwQ3344YfO9tatW+vAgQM1Mi8AAFC3uc2VpbqMK0sAALifq+o5SwAAALWFsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgAVhCQAAwIKwBAAAYEFYAgAAsCAsAQAAWBCWAAAALAhLAAAAFoQlAAAAC8ISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYEJYAAAAsCEsAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgAVhCQAAwIKwBAAAYEFYAgAAsCAsAQAAWBCWAAAALAhLAAAAFoQlAAAAC8ISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYEJYAAAAsCEsAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgIXbhKVTp05p4MCB8vf3V2BgoIYPH64zZ85Yx1y4cEEjR45U06ZN1bBhQ/Xr109ZWVnl9v3hhx/UsmVLORwO5eTkVMMMAACAO3KbsDRw4EDt3LlTy5cv1+eff67Vq1crISHBOubZZ5/VZ599pkWLFmnVqlU6duyYHnzwwXL7Dh8+XDfffHN1lA4AANyYwxhjaruIS9m9e7fat2+vjRs3qkuXLpKkZcuW6d5779WRI0cUGhpaZkxubq6CgoI0f/589e/fX5KUkZGhiIgIpaWl6fbbb3f2nT17thYuXKjJkycrJiZGP/74owIDAytcX15engICApSbmyt/f/8rmywAAKgRFf38dosrS2lpaQoMDHQGJUmKjY2Vh4eH1q9fX+6Y9PR0FRYWKjY21tnWrl07tWrVSmlpac62Xbt26eWXX9bcuXPl4VGx05Gfn6+8vDyXDQAAXJ3cIixlZmaqefPmLm1eXl5q0qSJMjMzLzrG29u7zBWi4OBg55j8/HzFx8fr9ddfV6tWrSpcT3JysgICApxbWFjY5U0IAAC4jVoNS+PHj5fD4bBuGRkZ1Xb8CRMmKCIiQo888shlj8vNzXVuhw8frqYKAQBAbfOqzYMnJiZq6NCh1j5t2rRRSEiIsrOzXdqLiop06tQphYSElDsuJCREBQUFysnJcbm6lJWV5RyzYsUKbd++XYsXL5YklS7fatasmSZOnKgpU6aUu28fHx/5+PhUZIoAAMDN1WpYCgoKUlBQ0CX7RUdHKycnR+np6YqMjJT0U9ApKSlRVFRUuWMiIyNVr149paamql+/fpKkPXv26NChQ4qOjpYk/eMf/9D58+edYzZu3KhHH31U33zzja677rornR4AALgK1GpYqqiIiAj16tVLI0aM0Jw5c1RYWKhRo0bp4Ycfdn4T7ujRo4qJidHcuXPVtWtXBQQEaPjw4RozZoyaNGkif39/jR49WtHR0c5vwv0yEJ08edJ5vMv5NhwAALh6uUVYkqR58+Zp1KhRiomJkYeHh/r166eZM2c63y8sLNSePXt07tw5Z9ubb77p7Jufn6+4uDi9/fbbtVE+AABwU27xnKW6jucsAQDgfq6q5ywBAADUFsISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYEJYAAAAsCEsAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgAVhCQAAwIKwBAAAYEFYAgAAsCAsAQAAWBCWAAAALAhLAAAAFoQlAAAAC8ISAACABWEJAADAgrAEAABgQVgCAACwICwBAABYEJYAAAAsCEsAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgAVhCQAAwMKrtgu4GhhjJEl5eXm1XAkAAKio0s/t0s/xiyEsVYHTp09LksLCwmq5EgAAcLlOnz6tgICAi77vMJeKU7ikkpISHTt2TI0aNZLD4ajtcmpVXl6ewsLCdPjwYfn7+9d2OVctznPN4VzXDM5zzeA8uzLG6PTp0woNDZWHx8VXJnFlqQp4eHioZcuWtV1GneLv78//EWsA57nmcK5rBue5ZnCe/812RakUC7wBAAAsCEsAAAAWhCVUKR8fHyUlJcnHx6e2S7mqcZ5rDue6ZnCeawbnuXJY4A0AAGDBlSUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWMJlO3XqlAYOHCh/f38FBgZq+PDhOnPmjHXMhQsXNHLkSDVt2lQNGzZUv379lJWVVW7fH374QS1btpTD4VBOTk41zMA9VMd53rp1q+Lj4xUWFiY/Pz9FRERoxowZ1T2VOuWtt95SeHi4fH19FRUVpQ0bNlj7L1q0SO3atZOvr686duyopUuXurxvjNHkyZPVokUL+fn5KTY2Vnv37q3OKbiFqjzPhYWFGjdunDp27KgGDRooNDRUgwcP1rFjx6p7GnVeVf88/9wTTzwhh8Oh6dOnV3HVbsgAl6lXr16mU6dO5ttvvzXffPONuf766018fLx1zBNPPGHCwsJMamqq2bRpk7n99tvNHXfcUW7f+++/39xzzz1Gkvnxxx+rYQbuoTrO81/+8hfz9NNPm6+//trs27fPfPDBB8bPz8/86U9/qu7p1AkLFiww3t7e5r333jM7d+40I0aMMIGBgSYrK6vc/mvXrjWenp7mtddeM7t27TKTJk0y9erVM9u3b3f2efXVV01AQIBZsmSJ2bp1q+nTp4+59tprzfnz52tqWnVOVZ/nnJwcExsbaxYuXGgyMjJMWlqa6dq1q4mMjKzJadU51fHzXOqjjz4ynTp1MqGhoebNN9+s5pnUfYQlXJZdu3YZSWbjxo3Otn/+85/G4XCYo0ePljsmJyfH1KtXzyxatMjZtnv3biPJpKWlufR9++23Tffu3U1qauqvOixV93n+uaeeesrcddddVVd8Hda1a1czcuRI5+vi4mITGhpqkpOTy+3/0EMPmd69e7u0RUVFmccff9wYY0xJSYkJCQkxr7/+uvP9nJwc4+PjY/72t79VwwzcQ1Wf5/Js2LDBSDIHDx6smqLdUHWd5yNHjphrrrnG7Nixw7Ru3ZqwZIzhNhwuS1pamgIDA9WlSxdnW2xsrDw8PLR+/fpyx6Snp6uwsFCxsbHOtnbt2qlVq1ZKS0tztu3atUsvv/yy5s6da/2Dhr8G1Xmefyk3N1dNmjSpuuLrqIKCAqWnp7ucHw8PD8XGxl70/KSlpbn0l6S4uDhn//379yszM9OlT0BAgKKioqzn/GpWHee5PLm5uXI4HAoMDKySut1NdZ3nkpISDRo0SGPHjlWHDh2qp3g39Ov+RMJly8zMVPPmzV3avLy81KRJE2VmZl50jLe3d5lfasHBwc4x+fn5io+P1+uvv65WrVpVS+3upLrO8y+tW7dOCxcuVEJCQpXUXZedPHlSxcXFCg4Odmm3nZ/MzExr/9J/L2efV7vqOM+/dOHCBY0bN07x8fG/2j8GW13neerUqfLy8tLTTz9d9UW7McISJEnjx4+Xw+GwbhkZGdV2/AkTJigiIkKPPPJItR2jLqjt8/xzO3bs0P3336+kpCTdfffdNXJM4EoVFhbqoYcekjFGs2fPru1yrirp6emaMWOGUlJS5HA4arucOsWrtgtA3ZCYmKihQ4da+7Rp00YhISHKzs52aS8qKtKpU6cUEhJS7riQkBAVFBQoJyfH5apHVlaWc8yKFSu0fft2LV68WNJP3zCSpGbNmmnixImaMmVKJWdWt9T2eS61a9cuxcTEKCEhQZMmTarUXNxNs2bN5OnpWeZbmOWdn1IhISHW/qX/ZmVlqUWLFi59OnfuXIXVu4/qOM+lSoPSwYMHtWLFil/tVSWpes7zN998o+zsbJer+8XFxUpMTNT06dN14MCBqp2EO6ntRVNwL6ULjzdt2uRs+/LLLyu08Hjx4sXOtoyMDJeFx99//73Zvn27c3vvvfeMJLNu3bqLfrPjalZd59kYY3bs2GGaN29uxo4dW30TqKO6du1qRo0a5XxdXFxsrrnmGuuC2Pvuu8+lLTo6uswC72nTpjnfz83NZYF3FZ9nY4wpKCgwffv2NR06dDDZ2dnVU7ibqerzfPLkSZffw9u3bzehoaFm3LhxJiMjo/om4gYIS7hsvXr1MrfccotZv369WbNmjWnbtq3LV9qPHDlibrzxRrN+/Xpn2xNPPGFatWplVqxYYTZt2mSio6NNdHT0RY+xcuXKX/W34YypnvO8fft2ExQUZB555BFz/Phx5/Zr+fBZsGCB8fHxMSkpKWbXrl0mISHBBAYGmszMTGOMMYMGDTLjx4939l+7dq3x8vIy06ZNM7t37zZJSUnlPjogMDDQfPLJJ2bbtm3m/vvv59EBVXyeCwoKTJ8+fUzLli3Nli1bXH528/Pza2WOdUF1/Dz/Et+G+wlhCZfthx9+MPHx8aZhw4bG39/fDBs2zJw+fdr5/v79+40ks3LlSmfb+fPnzVNPPWUaN25s6tevbx544AFz/Pjxix6DsFQ95zkpKclIKrO1bt26BmdWu/70pz+ZVq1aGW9vb9O1a1fz7bffOt/r3r27GTJkiEv/v//97+aGG24w3t7epkOHDuaLL75web+kpMS8+OKLJjg42Pj4+JiYmBizZ8+emphKnVaV57n0Z7287ec//79GVf3z/EuEpZ84jPn/i0MAAABQBt+GAwAAsCAsAQAAWBCWAAAALAhLAAAAFoQlAAAAC8ISAACABWEJAADAgrAEwK306NFDzzzzTG2X4cLhcGjJkiW1XQaAasJDKQG4lVOnTqlevXpq1KiRwsPD9cwzz9RYeHrppZe0ZMkSbdmyxaU9MzNTjRs3lo+PT43UAaBmedV2AQBwOZo0aVLl+ywoKJC3t3elx1/sr7wDuDpwGw6AWym9DdejRw8dPHhQzz77rBwOhxwOh7PPmjVr1K1bN/n5+SksLExPP/20zp4963w/PDxcr7zyigYPHix/f38lJCRIksaNG6cbbrhB9evXV5s2bfTiiy+qsLBQkpSSkqIpU6Zo69atzuOlpKRIKnsbbvv27erZs6f8/PzUtGlTJSQk6MyZM873hw4dqr59+2ratGlq0aKFmjZtqpEjRzqPBaBuISwBcEsfffSRWrZsqZdfflnHjx/X8ePHJUn79u1Tr1691K9fP23btk0LFy7UmjVrNGrUKJfx06ZNU6dOnfTdd9/pxRdflCQ1atRIKSkp2rVrl2bMmKH/+Z//0ZtvvilJGjBggBITE9WhQwfn8QYMGFCmrrNnzyouLk6NGzfWxo0btWjRIn311Vdljr9y5Urt27dPK1eu1Pvvv6+UlBRn+AJQt3AbDoBbatKkiTw9PdWoUSOX22DJyckaOHCgcx1T27ZtNXPmTHXv3l2zZ8+Wr6+vJKlnz55KTEx02eekSZOc/x0eHq7nnntOCxYs0PPPPy8/Pz81bNhQXl5e1ttu8+fP14ULFzR37lw1aNBAkjRr1iz953/+p6ZOnarg4GBJUuPGjTVr1ix5enqqXbt26t27t1JTUzVixIgqOT8Aqg5hCcBVZevWrdq2bZvmzZvnbDPGqKSkRPv371dERIQkqUuXLmXGLly4UDNnztS+fft05swZFRUVyd/f/7KOv3v3bnXq1MkZlCTpN7/5jUpKSrRnzx5nWOrQoYM8PT2dfVq0aKHt27df1rEA1AzCEoCrypkzZ/T444/r6aefLvNeq1atnP/98zAjSWlpaRo4cKCmTJmiuLg4BQQEaMGCBXrjjTeqpc569eq5vHY4HCopKamWYwG4MoQlAG7L29tbxcXFLm233nqrdu3apeuvv/6y9rVu3Tq1bt1aEydOdLYdPHjwksf7pYiICKWkpOjs2bPOQLZ27Vp5eHjoxhtvvKyaANQNLPAG4LbCw8O1evVqHT16VCdPnpT00zfa1q1bp1GjRmnLli3au3evPvnkkzILrH+pbdu2OnTokBYsWKB9+/Zp5syZ+vjjj8scb//+/dqyZYtOnjyp/Pz8MvsZOHCgfH19NWTIEO3YsUMrV67U6NGjNWjQIOctOADuhbAEwG29/PLLOnDggK677joFBQVJkm6++WatWrVK//rXv9StWzfdcsstmjx5skJDQ6376tOnj5599lmNGjVKnTt31rp165zfkivVr18/9erVS3fddZeCgoL0t7/9rcx+6tevry+//FKnTp3Sbbfdpv79+ysmJkazZs2quokDqFE8wRsAAMCCK0sAAAAWhCUAAAALwhIAAIAFYQkAAMCCsAQAAGBBWAIAALAgLAEAAFgQlgAAACwISwAAABaEJQAAAAvCEgAAgAVhCQAAwOL/ATngjBz3hQFfAAAAAElFTkSuQmCC\n" + }, + "metadata": {} + } + ], + "source": [ + "plt.plot(J_history)\n", + "plt.title('J per iteration')\n", + "plt.xlabel('iteration')\n", + "plt.ylabel('cost')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "QuQNMgKxedBt" + }, + "source": [ + "If we want to make a prediction on a normalized dataset, we have to normalize our input too." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "bZe9sGe6edBt", + "outputId": "cbc822ab-75e7-4950-82c2-dcfbdc8274d8" + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/ipykernel_launcher.py:1: RuntimeWarning: divide by zero encountered in double_scalars\n", + " \"\"\"Entry point for launching an IPython kernel.\n" + ] + }, + { + "data": { + "text/plain": [ + "'In a house of 1650 square feet with 3 rooms, we predict a price of $nan'" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "price = theta.transpose() @ np.array([1, (1650-mu[1])/sigma[1], (3-mu[2])/sigma[2]]) # normalize the input\n", + "'In a house of 1650 square feet with 3 rooms, we predict a price of $%.2f' % price" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "FFpCDOxmedBt" + }, + "source": [ + "### Using normal equations\n", + "We can use normal equations to get the exact solution in only one calculation. Although using normal equations is very fast for a small datasets with a small number of features, it can be inefficient for larger datasets because the complexity of matrix multiplication is $O(n^3)$.\n", + "\n", + "The normal equation for linear regression is:\n", + "\n", + "$\\theta = 􏰅 (X^TX)^{−1}X^T\\vec{y}$\n", + "\n", + "**Exercise**: Find theta using normal equations." + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Xz5T3k7GedBt", + "outputId": "3eb84e73-4b18-4637-8f36-f4166bfba72d" + }, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([[-3.63029144],\n", + " [ 1.16636235]])" + ] + }, + "metadata": {}, + "execution_count": 50 + } + ], + "source": [ + "theta" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 176 + }, + "id": "A6Ms5cgpedBt", + "outputId": "f5246eb3-047d-4bd3-ce8b-90cfb043264d" + }, + "outputs": [ + { + "output_type": "error", + "ename": "NameError", + "evalue": "name 'mu' is not defined", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprice\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtheta\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtranspose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m@\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m1650\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mmu\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0msigma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0mmu\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0msigma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# normalize the input\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0;34m'In a house of 1650 square feet with 3 rooms, we predict a price of $%.2f'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mprice\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mNameError\u001b[0m: name 'mu' is not defined" + ] + } + ], + "source": [ + "price = theta.transpose() @ np.array([1, (1650-mu[1])/sigma[1], (3-mu[2])/sigma[2]]) # normalize the input\n", + "'In a house of 1650 square feet with 3 rooms, we predict a price of $%.2f' % price" + ] } - ], - "source": [ - "theta" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/ipykernel_launcher.py:1: RuntimeWarning: divide by zero encountered in double_scalars\n", - " \"\"\"Entry point for launching an IPython kernel.\n" - ] - }, - { - "data": { - "text/plain": [ - "'In a house of 1650 square feet with 3 rooms, we predict a price of $nan'" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.7.1" + }, + "colab": { + "provenance": [] } - ], - "source": [ - "price = theta.transpose() @ np.array([1, (1650-mu[1])/sigma[1], (3-mu[2])/sigma[2]]) # normalize the input\n", - "'In a house of 1650 square feet with 3 rooms, we predict a price of $%.2f' % price" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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.7.1" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file From 030d3e6d45a563af9e812ead72c6c1ab7ba18293 Mon Sep 17 00:00:00 2001 From: Anni <39795105+annigue@users.noreply.github.com> Date: Wed, 9 Apr 2025 16:42:39 +0200 Subject: [PATCH 2/2] Aufgaben erledigt --- ex1/PE1 - Linear Regression (Exercises).ipynb | 364 ++++++++++-------- 1 file changed, 203 insertions(+), 161 deletions(-) diff --git a/ex1/PE1 - Linear Regression (Exercises).ipynb b/ex1/PE1 - Linear Regression (Exercises).ipynb index 6030f40..279cbb6 100644 --- a/ex1/PE1 - Linear Regression (Exercises).ipynb +++ b/ex1/PE1 - Linear Regression (Exercises).ipynb @@ -15,7 +15,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 1, "metadata": { "id": "D1MDtlCBedBq" }, @@ -40,30 +40,30 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 2, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 417 }, "id": "fOqzaCGCedBq", - "outputId": "d19f3c83-31ef-446a-fa88-b5a08707a285" + "outputId": "92dfa297-fbc7-4b3d-97f5-b0f6455d270f" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ - "--2025-04-07 14:26:32-- https://raw.githubusercontent.com/annigue/CS229-Python/master/ex1/ex1data1.txt\n", - "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n", - "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.\n", + "--2025-04-09 12:39:09-- https://raw.githubusercontent.com/annigue/CS229-Python/master/ex1/ex1data1.txt\n", + "Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.109.133, 185.199.111.133, 185.199.108.133, ...\n", + "Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.109.133|:443... connected.\n", "HTTP request sent, awaiting response... 200 OK\n", "Length: 1359 (1.3K) [text/plain]\n", - "Saving to: ‘ex1data1.txt.1’\n", + "Saving to: ‘ex1data1.txt’\n", "\n", - "\rex1data1.txt.1 0%[ ] 0 --.-KB/s \rex1data1.txt.1 100%[===================>] 1.33K --.-KB/s in 0s \n", + "\rex1data1.txt 0%[ ] 0 --.-KB/s \rex1data1.txt 100%[===================>] 1.33K --.-KB/s in 0s \n", "\n", - "2025-04-07 14:26:33 (50.8 MB/s) - ‘ex1data1.txt.1’ saved [1359/1359]\n", + "2025-04-09 12:39:09 (63.0 MB/s) - ‘ex1data1.txt’ saved [1359/1359]\n", "\n" ] }, @@ -80,7 +80,7 @@ ], "text/html": [ "\n", - "
\n", + "
\n", "
\n", "