{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "import numpy as np\n", "import scipy as sp\n", "import matplotlib.pyplot as plt\n", "import random\n", "from scipy import stats\n", "from scipy.optimize import fmin" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Gradient Descent" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Gradient descent, also known as steepest descent, is an optimization algorithm for finding the local minimum of a function. To find a local minimum, the function \"steps\" in the direction of the negative of the gradient. Gradient ascent is the same as gradient descent, except that it steps in the direction of the positive of the gradient and therefore finds local maximums instead of minimums. The algorithm of gradient descent can be outlined as follows:\n", "\n", "    1:   Choose initial guess $x_0$
\n", "    2:   for k = 0, 1, 2, ... do
\n", "    3:       $s_k$ = -$\\nabla f(x_k)$
\n", "    4:       choose $\\alpha_k$ to minimize $f(x_k+\\alpha_k s_k)$
\n", "    5:       $x_{k+1} = x_k + \\alpha_k s_k$
\n", "    6:   end for" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As a simple example, let's find a local minimum for the function $f(x) = x^3-2x^2+2$" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "f = lambda x: x**3-2*x**2+2" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "x = np.linspace(-1,2.5,1000)\n", "plt.plot(x,f(x))\n", "plt.xlim([-1,2.5])\n", "plt.ylim([0,3])\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see from plot above that our local minimum is gonna be near around 1.4 or 1.5 (on the x-axis), but let's pretend that we don't know that, so we set our starting point (arbitrarily, in this case) at $x_0 = 2$" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Local minimum occurs at: 1.3334253508453249\n", "Number of steps: 17\n" ] } ], "source": [ "x_old = 0\n", "x_new = 2 # The algorithm starts at x=2\n", "n_k = 0.1 # step size\n", "precision = 0.0001\n", "\n", "x_list, y_list = [x_new], [f(x_new)]\n", "\n", "# returns the value of the derivative of our function\n", "def f_prime(x):\n", " return 3*x**2-4*x\n", " \n", "while abs(x_new - x_old) > precision:\n", " x_old = x_new\n", " s_k = -f_prime(x_old)\n", " x_new = x_old + n_k * s_k\n", " x_list.append(x_new)\n", " y_list.append(f(x_new))\n", "print(\"Local minimum occurs at:\", x_new)\n", "print(\"Number of steps:\", len(x_list))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The figures below show the route that was taken to find the local minimum." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/png": "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6scf4fjjbeRg164+lULKufdeZpdrwddL9+Gii3zuMedcApo7F/7+d2jeHF5/3UZRzZ3Lusde5LL7m3DOOVYJMHUqnHde2MGWjidTUfDmm3DJJdClC3zyidVMJZr69WHkSHj+eZgwwUYWfvRR2FG5qJg1C958k9cPfYZy5eCCC8IOyDnn8vnlF7joIlt9eMgQuPpqq03v14/Pf2tEmzZWC3XHHfDZZ9CsWdgBl54nU2U0dKh9Ro49Ft57r2zTHcSaCFx1FUyaBA0awCmnwP3320zrLondfTe5Vavz+qJjOf54W37IOedC9+OPdnV34IHw7rs26/S8efDss2zaoyE33wydOlkLymef2VRRFSqEHfSu8WSqDL780j4nRxxhtT6JnEjl16oVfP21xX733da3a/XqsKNyu2TKFBg2jE+7P8uCRRlcdFHYATnn0t7MmdZO16qVjcS68UbrJ/XUU9CgAd9/bwO1nnjCWvqmToWjjgo76LLxZGoXzZ4N3brZDPbvvx//EXtlVbWq9fN67jlr7jvsMGstcknmX/+C3XdncM757LZb+IMenHNpbNo0OOcc60fy4Ydw663w22+2dEe9euTkwEMPweGH2/Jpo0fbyPNk6WReHE+mdsHatXDaadZsNno07LFH2BHtGhG45hob8bduHRx5pPX5ckniiy/go49Yf8NdDH2/IuecYwtlO+dcXE2dCt2725Dx//7XOj/99hs8/LCtn4ZVVh11FNx5p206YwacfHK4YUeTJ1OlpGqj4+bMsf5S++0XdkRld/TRMHGire938sk2UtUlOFUrlerX5906V7JhA97E55yLr8mTrYnmkENg3DjrN/Lbb/DAA3/VMmzZAvfdZ5vMm2f9z996C3bfPdzQo6182AEkm+ees350jz5qHedSRZMmVtFxzjmWLM6da9+Hcp5uJ6axY63HZr9+vDyoEgcemPx9DpxzSeLbby1DGjUKatWCe++1zuW1au2w2aRJNoXUtGnQsyf07ftXRVXK8X+VpfDtt3DTTZaI33xz2NFEX82a1szdp4/VzvbqZVcVLsHk1Uo1bcrU9n2YONH+Zj63lHMupr7+2povDj/c7j/wgM1ifvfdOyRS2dnWXerww2H5cutXPGRI6iZS4DVTEdu4ES680IadDxqUuv+4KlSAl16ySUdvvdU6CQ4blhodBFPGe+/ZJd/Agbz8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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=[10,3])\n", "plt.subplot(1,2,1)\n", "plt.scatter(x_list,y_list,c=\"r\")\n", "plt.plot(x_list,y_list,c=\"r\")\n", "plt.plot(x,f(x), c=\"b\")\n", "plt.xlim([-1,2.5])\n", "plt.ylim([0,3])\n", "plt.title(\"Gradient descent\")\n", "plt.subplot(1,2,2)\n", "plt.scatter(x_list,y_list,c=\"r\")\n", "plt.plot(x_list,y_list,c=\"r\")\n", "plt.plot(x,f(x), c=\"b\")\n", "plt.xlim([1.2,2.1])\n", "plt.ylim([0,3])\n", "plt.title(\"Gradient descent (zoomed in)\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You'll notice that the step size (also called learning rate) in the implementation above is constant, unlike the algorithm in the pseudocode. Doing this makes it easier to implement the algorithm. However, it also presents some issues: If the step size is too small, then convergence will be very slow, but if we make it too large, then the method may fail to converge at all. \n", "\n", "A solution to this is to use adaptive step sizes as the algorithm below does (using scipy's fmin function to find optimal step sizes):" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Local minimum occurs at 1.3333333284505209\n", "Number of steps: 4\n" ] } ], "source": [ "# we setup this function to pass into the fmin algorithm\n", "def f2(n,x,s):\n", " x = x + n*s\n", " return f(x)\n", "\n", "x_old = 0\n", "x_new = 2 # The algorithm starts at x=2\n", "precision = 0.0001\n", "\n", "x_list, y_list = [x_new], [f(x_new)]\n", "\n", "# returns the value of the derivative of our function\n", "def f_prime(x):\n", " return 3*x**2-4*x\n", "\n", "while abs(x_new - x_old) > precision:\n", " x_old = x_new\n", " s_k = -f_prime(x_old)\n", " \n", " # use scipy fmin function to find ideal step size.\n", " n_k = fmin(f2,0.1,(x_old,s_k), full_output = False, disp = False)\n", "\n", " x_new = x_old + n_k * s_k\n", " x_list.append(x_new)\n", " y_list.append(f(x_new))\n", " \n", "print(\"Local minimum occurs at \", float(x_new))\n", "print(\"Number of steps:\", len(x_list))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With adaptive step sizes, the algorithm converges in just 4 iterations rather than 17. Of course, it takes time to compute the appropriate step size at each iteration. Here are some plots of the path taken below. You can see that it converges very quickly to a point near the local minimum, so it's hard to even discern the dots after the first two steps until we zoom in very close in the third frame below:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=[15,3])\n", "plt.subplot(1,3,1)\n", "plt.scatter(x_list,y_list,c=\"r\")\n", "plt.plot(x_list,y_list,c=\"r\")\n", "plt.plot(x,f(x), c=\"b\")\n", "plt.xlim([-1,2.5])\n", "plt.title(\"Gradient descent\")\n", "plt.subplot(1,3,2)\n", "plt.scatter(x_list,y_list,c=\"r\")\n", "plt.plot(x_list,y_list,c=\"r\")\n", "plt.plot(x,f(x), c=\"b\")\n", "plt.xlim([1.2,2.1])\n", "plt.ylim([0,3])\n", "plt.title(\"zoomed in\")\n", "plt.subplot(1,3,3)\n", "plt.scatter(x_list,y_list,c=\"r\")\n", "plt.plot(x_list,y_list,c=\"r\")\n", "plt.plot(x,f(x), c=\"b\")\n", "plt.xlim([1.3333,1.3335])\n", "plt.ylim([0,3])\n", "plt.title(\"zoomed in more\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another approach to update the step size is choosing a decrease constant $d$ that shrinks the step size over time:\n", "$\\eta(t+1) = \\eta(t) / (1+t \\times d)$." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Local minimum occurs at: 1.3308506740900838\n", "Number of steps: 6\n" ] } ], "source": [ "x_old = 0\n", "x_new = 2 # The algorithm starts at x=2\n", "n_k = 0.17 # step size\n", "precision = 0.0001\n", "t, d = 0, 1\n", "\n", "x_list, y_list = [x_new], [f(x_new)]\n", "\n", "# returns the value of the derivative of our function\n", "def f_prime(x):\n", " return 3*x**2-4*x\n", " \n", "while abs(x_new - x_old) > precision:\n", " x_old = x_new\n", " s_k = -f_prime(x_old)\n", " x_new = x_old + n_k * s_k\n", " x_list.append(x_new)\n", " y_list.append(f(x_new))\n", " n_k = n_k / (1 + t * d)\n", " t += 1\n", "\n", "print(\"Local minimum occurs at:\", x_new)\n", "print(\"Number of steps:\", len(x_list))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's now consider an example which is a little bit more complicated. Consider a simple linear regression where we want to see how the temperature affects the noises made by crickets. We have a data set of cricket chirp rates at various temperatures. First we'll load that data set in and plot it:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "#Load the dataset\n", "data = np.loadtxt('SGD_data.txt', delimiter=',')\n", " \n", "#Plot the data\n", "plt.scatter(data[:, 0], data[:, 1], marker='o', c='b')\n", "plt.title('cricket chirps vs temperature')\n", "plt.xlabel('chirps/sec for striped ground crickets')\n", "plt.ylabel('temperature in degrees Fahrenheit')\n", "plt.xlim([13,21])\n", "plt.ylim([65,95])\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our goal is to find the equation of the straight line $h_\\theta(x) = \\theta_0 + \\theta_1 x$ that best fits our data points. The function that we are trying to minimize in this case is:\n", "\n", "$J(\\theta_0,\\theta_1) = {1 \\over 2m} \\sum\\limits_{i=1}^m (h_\\theta(x_i)-y_i)^2$\n", "\n", "In this case, our gradient will be defined in two dimensions:\n", "\n", "$\\frac{\\partial}{\\partial \\theta_0} J(\\theta_0,\\theta_1) = \\frac{1}{m} \\sum\\limits_{i=1}^m (h_\\theta(x_i)-y_i)$\n", "\n", "$\\frac{\\partial}{\\partial \\theta_1} J(\\theta_0,\\theta_1) = \\frac{1}{m} \\sum\\limits_{i=1}^m ((h_\\theta(x_i)-y_i) \\cdot x_i)$\n", "\n", "Below, we set up our function for h, J and the gradient:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "h = lambda theta_0,theta_1,x: theta_0 + theta_1*x\n", "\n", "def J(x,y,m,theta_0,theta_1):\n", " returnValue = 0\n", " for i in range(m):\n", " returnValue += (h(theta_0,theta_1,x[i])-y[i])**2\n", " returnValue = returnValue/(2*m)\n", " return returnValue\n", "\n", "def grad_J(x,y,m,theta_0,theta_1):\n", " returnValue = np.array([0.,0.])\n", " for i in range(m):\n", " returnValue[0] += (h(theta_0,theta_1,x[i])-y[i])\n", " returnValue[1] += (h(theta_0,theta_1,x[i])-y[i])*x[i]\n", " returnValue = returnValue/(m)\n", " return returnValue" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we'll load our data into the x and y variables;" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "x = data[:, 0]\n", "y = data[:, 1]\n", "m = len(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And we run our gradient descent algorithm (without adaptive step sizes in this example):" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Local minimum occurs where:\n", "theta_0 = 25.128552558595363\n", "theta_1 = 3.297264756251897\n", "This took 565859 steps to converge\n" ] } ], "source": [ "theta_old = np.array([0.,0.])\n", "theta_new = np.array([1.,1.]) # The algorithm starts at [1,1]\n", "n_k = 0.001 # step size\n", "precision = 0.001\n", "num_steps = 0\n", "s_k = float(\"inf\")\n", "\n", "while np.linalg.norm(s_k) > precision:\n", " num_steps += 1\n", " theta_old = theta_new\n", " s_k = -grad_J(x,y,m,theta_old[0],theta_old[1])\n", " theta_new = theta_old + n_k * s_k\n", "\n", "print(\"Local minimum occurs where:\")\n", "print(\"theta_0 =\", theta_new[0])\n", "print(\"theta_1 =\", theta_new[1])\n", "print(\"This took\",num_steps,\"steps to converge\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For comparison, let's get the actual values for $\\theta_0$ and $\\theta_1$:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Actual values for theta are:\n", "theta_0 = 25.232304983426026\n", "theta_1 = 3.2910945679475647\n" ] } ], "source": [ "actualvalues = sp.stats.linregress(x,y)\n", "print(\"Actual values for theta are:\")\n", "print(\"theta_0 =\", actualvalues.intercept)\n", "print(\"theta_1 =\", actualvalues.slope)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So we see that our values are relatively close to the actual values (even though our method was pretty slow). If you look at the source code of [linregress](https://github.com/scipy/scipy/blob/master/scipy/stats/_stats_mstats_common.py), it uses the convariance matrix of x and y to compute fastly. Below, you can see a plot of the line drawn with our theta values against the data:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "xx = np.linspace(0,21,1000)\n", "plt.scatter(data[:, 0], data[:, 1], marker='o', c='b')\n", "plt.plot(xx,h(theta_new[0],theta_new[1],xx))\n", "plt.xlim([13,21])\n", "plt.ylim([65,95])\n", "plt.title('cricket chirps vs temperature')\n", "plt.xlabel('chirps/sec for striped ground crickets')\n", "plt.ylabel('temperature in degrees Fahrenheit')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that in the method above we need to calculate the gradient in every step of our algorithm. In the example with the crickets, this is not a big deal since there are only 15 data points. But imagine that we had 10 million data points. If this were the case, it would certainly make the method above far less efficient.\n", "\n", "In machine learning, the algorithm above is often called batch gradient descent to contrast it with mini-batch gradient descent (which we will not go into here) and stochastic gradient descent." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Stochastic gradient descent" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we said above, in batch gradient descent, we must look at every example in the entire training set on every step (in cases where a training set is used for gradient descent). This can be quite slow if the training set is sufficiently large. In stochastic gradient descent, we update our values after looking at each item in the training set, so that we can start making progress right away. Recall the linear regression example above. In that example, we calculated the gradient for each of the two theta values as follows:\n", "\n", "$\\frac{\\partial}{\\partial \\theta_0} J(\\theta_0,\\theta_1) = \\frac{1}{m} \\sum\\limits_{i=1}^m (h_\\theta(x_i)-y_i)$\n", "\n", "$\\frac{\\partial}{\\partial \\theta_1} J(\\theta_0,\\theta_1) = \\frac{1}{m} \\sum\\limits_{i=1}^m ((h_\\theta(x_i)-y_i) \\cdot x_i)$\n", "\n", "Where $h_\\theta(x) = \\theta_0 + \\theta_1 x$\n", "\n", "Then we followed this algorithm (where $\\alpha$ was a non-adapting stepsize):\n", "\n", "    1:   Choose initial guess $x_0$
\n", "    2:   for k = 0, 1, 2, ... do
\n", "    3:       $s_k$ = -$\\nabla f(x_k)$
\n", "    4:       $x_{k+1} = x_k + \\alpha s_k$
\n", "    5:   end for\n", "\n", "When the sample data had 15 data points as in the example above, calculating the gradient was not very costly. But for very large data sets, this would not be the case. So instead, we consider a stochastic gradient descent algorithm for simple linear regression such as the following, where m is the size of the data set:\n", "\n", "    1:   Randomly shuffle the data set
\n", "    2:   for k = 0, 1, 2, ... do
\n", "    3:       for i = 1 to m do
\n", "    4:            $\\begin{bmatrix}\n", " \\theta_{1} \\\\ \n", " \\theta_2 \\\\ \n", " \\end{bmatrix}=\\begin{bmatrix}\n", " \\theta_1 \\\\ \n", " \\theta_2 \\\\ \n", " \\end{bmatrix}-\\alpha\\begin{bmatrix}\n", " 2(h_\\theta(x_i)-y_i) \\\\ \n", " 2x_i(h_\\theta(x_i)-y_i) \\\\ \n", " \\end{bmatrix}$
\n", "    5:       end for
\n", "    6:   end for\n", "\n", "Typically, with stochastic gradient descent, you will run through the entire data set 1 to 10 times (see value for k in line 2 of the pseudocode above), depending on how fast the data is converging and how large the data set is.\n", "\n", "With batch gradient descent, we must go through the entire data set before we make any progress. With this algorithm though, we can make progress right away and continue to make progress as we go through the data set. Therefore, stochastic gradient descent is often preferred when dealing with large data sets.\n", "\n", "Unlike gradient descent, stochastic gradient descent will tend to oscillate near a minimum value rather than continuously getting closer. It may never actually converge to the minimum though. One way around this is to slowly decrease the step size $\\alpha$ as the algorithm runs. However, this is less common than using a fixed $\\alpha$.\n", "\n", "Let's look at another example where we illustrate the use of stochastic gradient descent for linear regression. In the example below, we'll create a set of 500,000 points around the line $y = 2x+17+\\epsilon$, for values of x between 0 and 100:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "f = lambda x: x*2+17+np.random.randn(len(x))*10\n", "\n", "x = np.random.random(500000)*100\n", "y = f(x) \n", "m = len(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, let's randomly shuffle around our dataset. Note that in this example, this step isn't strictly necessary since the data is already in a random order. However, that obviously may not always be the case:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "from random import shuffle\n", "\n", "x_shuf = []\n", "y_shuf = []\n", "index_shuf = list(range(len(x)))\n", "shuffle(index_shuf)\n", "for i in index_shuf:\n", " x_shuf.append(x[i])\n", " y_shuf.append(y[i])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we'll setup our h function and our cost function, which we will use to check how the value is improving." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "h = lambda theta_0,theta_1,x: theta_0 + theta_1*x\n", "cost = lambda theta_0,theta_1, x_i, y_i: 0.5*(h(theta_0,theta_1,x_i)-y_i)**2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we'll run our stochastic gradient descent algorithm. To see it's progress, we'll take a cost measurement at every step. Every 10,000 steps, we'll get an average cost from the last 10,000 steps and then append that to our cost_list variable. We will run through the entire list 10 times here:" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Local minimum occurs where:\n", "theta_0 = 16.955415496837382\n", "theta_1 = 1.999169728242732\n" ] } ], "source": [ "theta_old = np.array([0.,0.])\n", "theta_new = np.array([1.,1.]) # The algorithm starts at [1,1]\n", "n_k = 0.000005 # step size\n", "\n", "iter_num = 0\n", "s_k = np.array([float(\"inf\"),float(\"inf\")])\n", "sum_cost = 0\n", "cost_list = []\n", "\n", "for j in range(10):\n", " for i in range(m):\n", " iter_num += 1\n", " theta_old = theta_new\n", " s_k[0] = (h(theta_old[0],theta_old[1],x[i])-y[i])\n", " s_k[1] = (h(theta_old[0],theta_old[1],x[i])-y[i])*x[i]\n", " s_k = (-1)*s_k\n", " theta_new = theta_old + n_k * s_k\n", " sum_cost += cost(theta_old[0],theta_old[1],x[i],y[i])\n", " if (i+1) % 10000 == 0:\n", " cost_list.append(sum_cost/10000.0)\n", " sum_cost = 0 \n", " \n", "print(\"Local minimum occurs where:\")\n", "print(\"theta_0 =\", theta_new[0])\n", "print(\"theta_1 =\", theta_new[1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you can see, our values for $\\theta_0$ and $\\theta_1$ are close to their true values of 17 and 2.\n", "\n", "Now, we plot our cost versus the number of iterations. As you can see, the cost goes down quickly at first, but starts to level off as we go through more iterations:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYYAAAEGCAYAAABhMDI9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nO3deXwU5f3A8c93s7kvEgjhJiCXgoCAKCqCR1U8qlWr9rQe1bZWrba10Nra2kttq2IPj5+2pfU+i/eFF4og4ZT7knATCIRA7uP5/TEzuzObBHYDm012v+/XK6/szM7uPE9283znOUeMMSillFIOX6wToJRSqmPRwKCUUspDA4NSSikPDQxKKaU8NDAopZTy8Mc6AeHo1q2bKSoqinUylFKqU1mwYMFuY0xBpK/rFIGhqKiI4uLiWCdDKaU6FREpacvrtClJKaWUhwYGpZRSHhoYlFJKeUQ1MIjIzSKyTESWi8iP7H35IvKOiKy1f+dFMw1KKaUiE7XAICIjgO8C44FRwPkiMgiYCswyxgwGZtnbSimlOoho1hiOBuYZY6qMMQ3Ah8DFwIXADPuYGcBFUUyDUkqpCEUzMCwDJopIVxHJAM4F+gKFxpjt9jE7gMKWXiwi14lIsYgU79q1K4rJVEop5Ra1wGCMWQncDbwNvAksBhpDjjFAi+t+G2MeMcaMM8aMKyiIeH4GAC8t2sIT89o0jFcppRJWVDufjTGPGWPGGmNOBfYCa4CdItITwP5dGq3zv7JkO8/M3xytt1dKqbgU7VFJ3e3f/bD6F54EXgautA+5EpgZrfP7RGho1BsRKaVUJKK9JMYLItIVqAduMMaUi8hdwLMicg1QAlwWrZMn+aBJ71CnlFIRiWpgMMZMbGFfGXBGNM/r8Pt8NDZpYFBKqUjE9cxnn080MCilVITiOjAkCTRqU5JSSkUkvgODz6edz0opFaE4Dwza+ayUUpGK88Dgo0H7GJRSKiJxHhigSQODUkpFJL4Dg4h2PiulVITiOzD4fDRq57NSSkUkzgODDldVSqlIxXlg0M5npZSKVJwHBu18VkqpSMV3YNDOZ6WUilh8BwafD2O01qCUUpGI88Bg/dZag1JKhS/OA4OVPV1hVSmlwhfngcH6rYFBKaXCF9eBwScCaFOSUkpFIq4Dg99nBwad/ayUUmGL68CQ5NMag1JKRSquA4PPCQzax6CUUmGL68Dg18CglFIRi+vAEOh81sCglFJhi+vA4E/SwKCUUpGK68Cgw1WVUipycR0YkrSPQSmlIhbXgUE7n5VSKnJxHRi081kppSIX14FBO5+VUipycR0YtPNZKaUiF9eBQTuflVIqchoYlFJKecR3YNDOZ6WUilh8BwatMSilVMQSIzBo57NSSoUtIQJDfUMTy7buw2iAUEqpQ0qIwHD94ws4/68fs2xrRYxTpJRSHV9CBAanolBRUx/D1CilVOcQ34HBHpXkqGtsilFKlFKq84jvwOALCQwNGhiUUupQohoYROQWEVkuIstE5CkRSRORASIyT0TWicgzIpISrfOHBoZ6rTEopdQhRS0wiEhv4CZgnDFmBJAEXAHcDdxnjBkE7AWuiVYatMaglFKRi3ZTkh9IFxE/kAFsB04HnrefnwFcFK2Ta2BQSqnIRS0wGGO2An8GNmEFhH3AAqDcGNNgH7YF6B2tNGQk+z3b2pSklFKHFs2mpDzgQmAA0AvIBM6J4PXXiUixiBTv2rWrTWnISfcGhlqtMSil1CFFsynpTOALY8wuY0w98CJwMtDFbloC6ANsbenFxphHjDHjjDHjCgoK2pQAkdDOZ535rJRShxLNwLAJOFFEMsQqoc8AVgDvA5fax1wJzIxiGjy0j0EppQ4tmn0M87A6mRcCn9vnegT4GXCriKwDugKPRSsNobSPQSmlDs1/6EPazhhzB3BHyO4NwPhonrc1OvNZKaUOLa5nPgNcffIAALJS/dqUpJRSYYj7wHD7eUez+nfnkJbs0xqDUkqFIapNSR2Bzyek+pJISfJpjUEppcIQ9zUGR7Lfp53PSikVhoQJDFpjUEqp8CRMYEhO8vHGsh0UTX2NA7UNh36BUkolqIQJDCn+YFa3l1fHMCVKKdWxJWRgqKxrjGFKlFKqY0ucwJAUzGp5VV0MU6KUUh1b4gQGvzsw1McwJUop1bElTGBITgqutLpXawxKKdWqhAkMqf6kwOO9lRoYlFKqNQkTGDJSgoFh/a5K1pXuj2FqlFKq40qYwJCWHAwMr32+nTPv/SiGqVFKqY4rYQKDu8bg0JnQSinVXEIHhtL9NTFIiVJKdWwJExjSU6yFZEf0zuGhb44BYGeFBgallAqVMIHBqTE0NUFRt0wAtu/TwKCUUqESLzAYQ4+cNAAWlOyNZZKUUqpDSpjAkG6PSmpsMuSmJzO0MJv/flrCHp3ToJRSHokTGOwaQ6MxiAjfn3wUDU2GPZW1MU6ZUkp1LAkTGJympMYmA0BWqtUZPfWFzyk7oMFBKaUcCRMY0pOtQOAEhoxUK1AUl+zlD6+vilm6lFKqo0mYwBAclWQFhkx7+CpYHdJKKaUsCRMYnGW37bhAZmpwwluST1p6iVJKJaSECQyZdp/C2P55AGS4agzuJbmVUirR+Q99SHzITU/m9ZsmMsCe3OZeIsPv8/Hs/M3UNjbxrRP7xyqJSinVISRMYAA4pldO4LG7xpDkE257YSmABgalVMI7ZFOSiMwKZ19n477Vp3Y+K6VUUKs1BhFJAzKAbiKSBzgN8TlA73ZIW7uprmuMdRKUUqrDOFhT0vXAj4BewAKCgaEC+FuU09WuquqDgcHYM6OVUipRtRoYjDHTgekicqMx5q/tmKZ2V+pafru2oclztzellEo04QxX3SEi2QAicruIvCgiY6Kcrna1rTwYGCpq6mOYEqWUir1wAsMvjTH7ReQU4EzgMeDB6Carfbzw/ZPISfOzw1Vj2F/TEMMUKaVU7IUTGJwG+POAR4wxrwEp0UtS+xnbP4/xA/ID6yeBBgallAonMGwVkYeBy4HXRSQ1zNd1CqH9Cfu1KUkpleDCKeAvA94CzjbGlAP5wE+jmqp2lN4sMGiNQSmV2A4ZGIwxVcB64GwR+SHQ3RjzdtRT1k5Cawxlekc3pVSCC2fm883AE0B3++dxEbkx2glrL7npyQBkp/lJT07ii12VMU6RUkrFVjhrJV0DnGCMqQQQkbuBT4G4mNvQq0s6YN3AZ2BBJut2HYhxipRSKrbC6WMQgiOTsB8fcmqwiAwVkcWunwoR+ZGI5IvIOyKy1v6d19bEHwk9u6QBUF3fyKDuWawv1cCglEps4QSGfwHzROTXIvJrYC7WXIaDMsasNsaMNsaMBsYCVcBLwFRgljFmMDDL3o6ZXrlWjcEY6J+fwdbyahoam2KZJKWUiqlwOp/vBa4C9tg/Vxlj7o/wPGcA640xJcCFwAx7/wzgogjf64jqZdcYAHIzrOkZB2p1ZJJSKnEdso9BRE4ElhtjFtrbOSJygjFmXgTnuQJ4yn5caIzZbj/eARS2ct7rgOsA+vXrF8GpIpOdZnU+f3Vsn0BHdEV1A10yUvjZ80sZXJjFtRMHRu38SinV0YTTlPQg4G54P0AES2KISArwZeC50OeMMQZo8WYIxphHjDHjjDHjCgoKwj1dm6z+3TncfclIctKsOOmsl/RM8WZ+99rKqJ5bKaU6mrA6n+0CHABjTBOR3fltCrDQGLPT3t4pIj0B7N+lEbxXVKT6k/D5hJxAjUFnPyulElc4gWGDiNwkIsn2z83AhgjO8TWCzUgALwNX2o+vBGZG8F5RlWM3K+kKq0qpRBZOYPgecBKwFdgCnIDd9n8oIpIJfAl40bX7LuBLIrIWa7XWuyJJcDTlpNtNSdXa+ayUSlyHbBIyxpRidR5HzJ4U1zVkXxnWKKUOJ9D5XFOP0ftAK6USVCR9BXEvM8X6cxRv3Mtf3l4T49QopVRsaGBw8fmsCd1vLt8R45QopVTsxM19FY6UKSN6xDoJSikVU+FMcLu1hd37gAXGmMVHPkmx9fuvHMsby7w1hqYmE6hNKKVUvAunxjAOa2RSb/vneuAc4P9E5LYopi0m8jKSm+2rrm9s4UillIpP4QSGPsAYY8yPjTE/xloQrztwKvCdKKYtJkSa1ww0MCilEkk4gaE7UOvarsda76g6ZH/cqq7TwKCUShzhBIYnsJbdvkNE7gA+AZ60J6+tiGrqYuRn5wzzbGuNQSmVSMJZdvu3WDOdy+2f7xlj7jTGVBpjvhHtBMbC9ycf5dnWGoNSKpGEMyrpAeBpY8z0dkhPh+H3CQ1N1uznyjpdIkMplTjCaUpaANwuIutF5M8iMi7aieoI3MNTt5fX6BIZSqmEEU5T0gxjzLnA8cBq4G57Aby45ncFhh8/t4Tps+I+y0opBUQ283kQMAzoD6yKTnI6jqSQCW3/nrMxNglRSql2dsjAICL32DWEO4FlwDhjzAVRT1mMje2f59nOTtNlpZRSiSGc0m49MMEYszvaielI/vb1MazZuZ+L/zEHgKQWJr4ppVQ8CqeP4WGgUUTGi8ipzk87pC2mslL9jOmXx7PXTyAvI5lt+2poatIOaKVU/AunKela4CPgLeA39u9fRzdZHcf4Afnc+qUh1DU0sftAQkz0VkoluHA6n2/GGpFUYow5DTgOa6JbwuiTlwHAzU8vpryqLsapUUqp6AonMNQYY2oARCTVGLMKGBrdZHUsffPTAfh0Qxn3vqN3dlNKxbdwAsMWEekC/A94R0RmAiXRTVbH0rtLRuDxF7sreXHhFu1vUErFrUOOSjLGfMV++GsReR/IBd6Maqo6mPSUpMDj2Wt3M3vtbuobm7j8+H4xTJVSSkVHRLf2NMZ8aIx52RiTcA3tQwqzPNv/W7QtRilRSqno0ns+h+ntWybx83ODy3Hv1U5opVSc0sAQgW5ZqYHH+6rrY5gSpZSKHg0MEXAHBq0xKKXilQaGCLgDQ019EzV6ZzelVBzSwBCBblkpnu3yKm1OUkrFHw0MEcjP9AYGbU5SSsUjDQwR8Cf5uOeSkfz2wuEAbNhVqc1JSqm4o4EhQpcd35ex/fMBuOHJhdz2/NIYp0gppY4sDQxtUNQtuETG659vj2FKlFLqyNPA0AYZKX7+9vXjACjMSYtxapRS6sjSwNBG54/sxU2nD2L7vmrqGppinRyllDpiNDAchv5dM2kysGJ7RayTopRSR4wGhsMweWgB+Zkp/OXt1bFOilJKHTEaGA5D16xUzh5eyIptWmNQSsUPDQyHqV9+JmWVdRyobcAYw76qejaVVbFrv94fWinVOR3yRj3q4PrlW0NXny/ezK9fWRHY7xPY8MfzYpUspZRqM60xHKb+Xa3AcP+stZ79zp0/6xubMEZvA6qU6jyiGhhEpIuIPC8iq0RkpYhMEJF8EXlHRNbav/OimYZoG1iQSXaqv9UF9cb//l2+/c/P2jlVSinVdtGuMUwH3jTGDANGASuBqcAsY8xgYJa93WllpPj5ydlDW3xuzc797K2qZ/ba3e2cKqWUaruoBQYRyQVOBR4DMMbUGWPKgQuBGfZhM4CLopWG9vKVMb1b3P/ZF3sAyE1Pbs/kKKXUYYlmjWEAsAv4l4gsEpFHRSQTKDTGOAsM7QAKW3qxiFwnIsUiUrxr164oJvPw5aQl88/vjGu2f1t5NQAZKUntnSSllGqzaAYGPzAGeNAYcxxQSUizkbF6ZVvsmTXGPGKMGWeMGVdQUBDFZB4Zpw9rHt9K9lQBoH3PSqnOJJqBYQuwxRgzz95+HitQ7BSRngD279IopiEmkpMEgE1lVmCo1ns2KKU6kagFBmPMDmCziDg9s2cAK4CXgSvtfVcCM6OVhlh54toTAdhYVglAdZ0GBqVU5xHtCW43Ak+ISAqwAbgKKxg9KyLXACXAZVFOQ7vrnZcOwP6aBgDqGptoaGzCn6TTRpRSHV9UA4MxZjHQvFfWqj3ErcLsVJJ8QmNTsHOhur6RbA0MSqlOQEuqI2hsf2uunj/JR4+QG/jc+uwSXluqd3tTSnV8ulbSEfTs9RNosocg9c5LZ2t5NSlJPuoam3hnxU7eWbGT80bq+klKqY5NawxHUJJPSLabi/rbi+t1y0o56Gu2lVdz0h9nsXF3ZdTTp5RS4dAaQ5TcePpgKusa6JefyUMfrg/sb2oy/POTL9haXs3AbpkcqG1k274anvpsE9POPTqGKVZKKYsGhijp1zWDf3xjLHM3lHkCw8Cfv+457mfnDAO8s/xqGxr5eO1uzji6xUnhSikVVdqUFGWHWg7D6ZNwL8199xuruWZGMQtK9kQ1bUop1RINDFHmDgy3nTOUWT+exKi+XQL79lVby3VXuSbBbdpj9TeUHahrp1QqpVSQBoYoy0oNrqw6qCCLowqyOKogM7Bvx74awBsERKwlNdzzIJRSqr1oYIiy7LRgN066XXvITg3u22QvtLdh94FAIPD7rMCgcUEpFQsaGKLM3ZSUnmw9dmoEACX2ekprdh7giXklAPjswNDQ1NReyVRKqQANDFHmDgJpyc07ovdW1TO0MBuADbusIJFkv6ayVhffU0q1Px2u2o6cwJCa7I3Hk4YWUNvQSFml1c+Q5HMCQ0P7JlAppdAaQ7ty+hh+MHmQZ2RS18wU8jNT2FNZC4BTyais08CglGp/GhjakdPHkJuezF++OiqwPz8zhfzMVMoO1LF5TxWzVlr3LqrS+zgopWJAA0M7SnM1IblHK3XLSqVbVgpllXWc9ucPAnMbDmhTklIqBjQwtKM0f7DzOTc9OL8h325K2rW/lgbXGNUn522iaOprnlnRSikVbRoY2pEzDBW8I5S6ZlmBoTUVNVpzUEq1Hw0M7eClH5zEtCnDmu3/0ZmDAasp6byRPVt9fWmFNTv6/L/O5qanFkUnkUopZdPA0A6O65fH9ZOOarb/5jMGs+73U0hLTqJnbjov/uCkFl+/s8IarbRsawUvL9mmTUtKqajSwBBDIoLfdR/oMf3yeOH7E5odt6OihndX7Axsr9y+v13Sp5RKTBoYOpiirpnN9r28ZBvX/qc4sL16Z8Uh36exyfDx2t1au1BKRUwDQwfjHq3UJcN6/NGaXZ5j1pUeYF3pwWsNd76ynG8+No/ikr0RnX/hpr16m1GlEpwGhg7Gn+TjhtOO4pnrTmTxr85qsVP67++v58x7P2L7vurAvqYmw4HaBl5cuAVjDDM+tRbkq7DnRITr4n/MYfKfPzisPCilOjddK6kD+unZwRFMt593NJkpSTxbvAWwluR25jrMWVfGJWP7MG9DGXe8vJxVO6xaRNes1MDrK2paDww7K2poMoaeuenRyIZSqpPSGkMH1zM3nXsuDS6fcf2kgYHVWD9etxuAyx+ZGwgKYBX4jorq1udAnPCHWUz443tHOslKqU5OA0Mn4cyNu3xcP9665VQuHduHd1bspLqF9ZTWlx4IPI60KUkppTQwdBLJ9rDWnHSr9e+SMX04UNvAm8u3Nzt2xfbgqKWyyrrA7UMB6hqa+P1rK9hTGbyVaJPdNFXfGLsbA1XXNfLykm0xO79SKkj7GDqJp647kWc+2xwYtXTCgHx6d0nn0dlfNDt2pSsw/HvORv49ZyOfTjudVTv2c9W/5gME7v0A8PyCLVx2fF+q62O3muvvX1/B43M30TM3jeOL8mOWDqWU1hg6jTH98rj70pGBO8L5fMIlY3qzfFswCKQnJ9G7Szq7D9Q1e/2cdWWBoADefojbXlhKXUMTNTFc5ntbuZWe8qr2b/o65/6PuP1/n7f7eQ/UNvBs8eaYzDVZV7qf0v01hz7wCGtobPJcuLSnbeXVgZWL21Njk2Gdq3m3M9DA0IldOravZ3vi4G6cdFTXwHZR14zA41/OXOY5NvQfZPeBWmrqg01JH6wupbyqeYAJx4KSvSzfti+i1zh3rWuMwX2uV+3Yz+NzN7X7ee98ZTm3Pb804rkmR8KZ937ESTEYeDB91lqmTJ/N6h3tP3v/pLve48x7P2z38z4way1n3vthpwoOGhg6sX5dMxjbPy+wbYBB3bMC233zg4Eh9KY/eyu9gaF0f62nKek7/5rP9f9dAMCSzeWcfNd7lB2oPWSa1pXu55IH53D1v+e3esy+6np+9PQi9rqas/x2YKhvTJyZ2qX7rb/n/oMMKY4m9xLv7WXx5nIAzxyc9rRr/6G/w0dacckeIHZ5bgsNDJ3cU989ke9OHACAMcHAkJwk5GVYS3n3yk3j0W+P49nrg+swbS23vqSPXTkOsFZwfWOZtyN72Vbrqv9fn3zB1vJq3ly+45Dp+WiNNYS2pdFSjifnbeJ/i7fxf7M3BPY5NYaaGPZztDcnGDYkUDAM1gwTJ88+u/k3FoG4rTQwdHIpfh9j+zudtYbB3a05DheO7h0YwZSZ6ufMYwoZP8DbqesTOLpnDgBz1pdx/7trPc87/Rn97PWb1rRS/V9QspcFJXvZVFbFbrtWkZHS+riGJrtN/UBtQ2BElFNgHM5d61Zur+C3r644aHB5c9kOXlsaDICxHInl5Lm9C4xYrp+VJLGpGTbFsFDujBcAGhjiwKi+uQB8bXw/+nXN4NnrJ/D7r4wgJ80awZSRErwpUHZqsMDumpVK9+xURODFhVtafO+Zi7fywCwrYCzaXM6zxZsDNYm9lXVcO6OYSx6cwyUPzuHUP70fCAwtdfI9Ma+E+95ZQ22DVRj/59MS7n93DRC8qtq8p5qFm4Jt7nUNTTSEWXhPmT6bxz7+goUHabP/3uMLuOHJhYHtI1FDOVDbwM+eX8qz8ze3esyGXQcY8os3PGtc+X3Wv1/lYQTD9bsO8MKCLQct+F5Zso2Zi7cGtt19SW3V1GSYv3GPZyh0qJr6Rv7+/jrP39gJhtX1bc/znso6lm4pP+gx8zfuYf7GPYFt5zt3OIwxrNxewb6DDJCob2zi8bklnu9skv05V9V1nhtuaWCIAz1z09l413mccXQhAOMH5JPqTyLHWZBPgneOW/DLLzFxcDcACrJS8Sf56JWb3uJd4gS4+enFge2lW/Zx2/NL+fLfPgbg4Y828O7KnZ7XOCOiquuteQkbd1dS29DItTOK+cVLy5g+ay07XYXJM8VWYeo0Lfzzky+4+B9zAgXdsF++wdcfnXfIv4G7aWJPGJ3mT86zOpvdTV4rt1e06Z/3pYVbeKZ4Mw99uL7VY15Zsp26xib++2lJIK3OHf32H8Yd+s74y4f8+LklLNrcejC88alFns/xSAxLnrlkK1996FNue2Fpq8c8PreEP721mv98ujGwz590+Hk+9Z73+fLfPmHFttZHN331oU/56kOfBraPRKH88pJtTJk+mx8/t6TVYx6fW8Lt/1vGk58FBzM4K+t3pjsxamCIY06NwT3SJ8Xvo5u9llL3HOv3U989kZ+cNaTZ61tr4mgyVkdaS80w7iGQNz21iMl//oD/zCnxBJAdrqGyhTlpQPPCylnjqcnAZ1/soSVrd+7nueLNLN5cTlllsFPR3akNVuF/2/NLAv0qAD9/6XNq6hs9550yfTa3PGMVoB+sLqVo6mueYb2t2WoPtQ2noWDGpyXc89YqAOwykjtfXUHR1NcCxzw+t4SP1+4+5HvVua6Cw+lUHTDNun+4u5AsmvoaM+ZsBKwr8Udnbwir2WXDLmsF3u3lrXeoOkOP//D6Kp62C0rn6vm3r65gwLRgnmet3BnWMNa6hqZAc+O2g5zbMf7379p5Dn7ORVNfCwSrfVX1PPXZprCa19butEYVbT3IeZ3P4Vczl/OcfdHj1Ax//fJyz+f8/upS1uzsmPdW0cAQx5w+htC2za72/aWdts9+XTP44emDm73eXWhmp/n591XH84PJ1p3oPllX1mIH4rKtFaS77mcNVs3Czf0P7fw/hjbplFXWef5ZK2rqPcuBX/7wp3zpvo/46fNLuejvn/DW8mDg2VlRy+Y9VYD1zzfyN2/xbPEWpr3onauwY19Ns9Fac9aXAdakP4DZLRTQG3dX8tPnlvDKkm2U7q9hhz3aZE9IQGpqMlzxyKdM+OMsT9Pac/aCiKHt7M7f4Pb/LeObj7VcS1q/6wCv2DPE3UGrLOTc+6rq+dojcz0FjzFWYR36t/7L26sBuPuNVfzutZXMXtdyUHpt6fZA0HXmnbR05T9z8Vb+9ckXnguHP75hBcPgLHuDMcHgds2MYqZMn93iebeWVwcCpTfP3mBYXdfItBeXegru0v21VFQ3NMuz059215srmfbi58zd0PLFx9vLdwQ+u23257yvhRrpm8t28Mz8TZ6LKSfPxr5kcP5fnDxf9a/5nHXfR63meU4rn0N70JnPcSxYY/AWQNdMHMB7q0r50jGFnv0ZKUlU1TXy0DfH8Nbynby/upR91fWBf+DJQ7tz6uACnvxsE88Vb2ZwYXBo7AWjegUKrEHds/h8a3Aew+6QYa5rSw9w0ehe7K9pYMmWfdz5yopmBfCWvdV8/f/mBt//rx9TUlbFez+exMCCLOaF1CLctYpHPtrAgx+u5/nvTfBM6gsdbrttXzVpIUHM0TvPWnF2U1kl63cdoCA7lZy0ZF7/fDs/eMLqo3huwRbyM1MYYv8d9lXX8+S8TYzqm8v+mga+8ei8wN/ePVQxy+7nCW3e2FtVd9CVbs+dPjuw3MnNTy/ir18bE3huU1kV8zfuYVz/PP789mr+/r7VrHX7/7zzV7aWVwc6/x1Ok5Zj4+5KJg0pCGx/vmUfF9jNhwC/vXB4ILiXVdayrnQ/PXLT2bi7kvveWcOsVaUAfHlUr8BrMu1+rtCaYXlVHd3tWmNLvvXYvMB345RB3bjq5KLAc9vKa1hXeoCjCjI9eQ7t99ha3rx26+S4rsH6W2zYfYAJrjlAy7bu4/y/BvN83+WjAnneXVlHSVkl3bPTWL/rAH97b11gxJ47z84FUugIvfLqOrpnt57nbz46L7BA5rAe2fzt68cxyB5U0l40MMQxp48hNDD0zE3nvZ9Mbnb8s9dP4IWFWzh7eA/OGWHdB2Ll9gqmTJ8d+Mfy+YQpI3ry1GebPIXz9acODASGMf26BALDaUMLeH/1LrplpXhmZB9VkEWjMcxaVco/P2m+rMcHq0sD97oGKCmzagD/nVvCHWwxjaIAABYUSURBVBcMb3b83A3WlX6K3xe4Ivvhk4s8x4R2iG8vrwnMJXAIVrPGwx9atZzZ63bzwHvrGNknl5d/eAqLNnnb8veErEX185esWsm5x/bw/N23uY5J8VsV9dBCcm9lPUu3BAPqPW+u4tniLbxx80QKslM9a2A1GXhpUXDAwMMfbeDhjzYwbcqwQAEJza/ot5ZX08V1Mygnz3sr6yivtj6fT9bt5tWl2zh7eA+unTiQFxd5Byb8cubywOTJ+kbDmfdaV72Xju0TCArgrRk6Abh5MKz3fAZPzCvh8bmbePq6E8lNT/ZcMHy8bncgqII1WW76rLX8+oJjPHneFXIBsLW82vM6sLrdKmrqqWloDOT5taXbOXt4D648qShQY3Tc8swS+tnzguoampj0pw/w+4SLjuvtGcbtznNqstPpHBoM6z1Nf09/tonH55XwxLVWnj921RRW7dgfaG5tT1FtShKRjSLyuYgsFpFie1++iLwjImvt33mHeh/VNtlp1j9DfZiziUf0zuWOC4YHhqkCdM2ymp3cseV3F42gdxfvle1RBcHaw0mDugUeXzymD2t+N4UHrjjOc3xhbhrDe+W2mpZFm4KjTm45cwhTRvQgO9XPnHVlLbaB79pfiwiBJcmheVvwlr3W9us3TQTgxUVbuPvNVZ5jRIRrZgRvo+qkY+mWfWzZW9ViWjeWVTX7e7z+uXfOR0lZZWBEzs6KGp76bFOz5ov5G/cEJhUC/OOD9ew+UNti4ITgnJGC7OD9N+55a7XnmNDa2uod+7nPHgnm8Ilw7gOzA81xb6/YyfyNe/ndayupqKlH8NYoADbtqfKcF/CMfALY7Pp77amq47Mv9jTL85LN5Z4r81+8tIyV2yv4Vyt5/mBNabM8//71lZ5j9oQsCbN6RwX/nbsx5J2EC/76cWDo8uuf72DOeuu+Jvtr6t3jNQK27K2iu+u8DU2mWZ6d7xhYFw3FG/c0q90u2VzOeQ8E8zz1xc9ZtrWCf38SmkZLdlpyi/ujqT36GE4zxow2xoyzt6cCs4wxg4FZ9raKAucq7XBWmeiaaf0juJfXSPIJ54fcWS4tOfhVci+Cl5XqJ8Xv46RB3Xj+e8EJdj1y0jjz6O5MmzKMr47t0+y8zgxZsIbjPvjNsVx9ygBW79zP2yuC/QnnHdsz0CTWLz8j8I/bLSuVAd0yA8HRnZ5jeuXQNTOFT9aVNTuvu0DokZPGw98ay5QRPQBYuKkcdyvMiQOD+RzZp/UgB9ZV4o2nD+Ln5w5jf01Ds/4OwFNb+M5JRYzq2wWAOet2t9ifU9fYRF5GcuBKFprXDp2Aueq355CW7OPed9Y0K5xFYLurRnPF8cGlVtwB2q3JwHF2+hyhfSY7K2q5/tSB3HDaUZRX1XPZw58SapHrcx5flB/4ns1e23Kea+qbKMhOpU9eMBCHnnfbvhpE4P2fTCbV7+PPb69pFqhFgrVQsGp4jiWbW17OpcnAcf0OnucdFTVcffIArj55AOVV9Vz60MHzPKJ3TuDzm712V7M8Oxcx7S0Wnc8XAjPsxzOAi2KQhoTQMyeNr5/Qj0e+PbbN75HkE2ZcPZ5nXLOmAb436ShG9M4JbIsID39rLD88bRB5GcErnExXFb6LPRMboEduGiLC9ZOO4sdnDT1oGpwmsdF2QfS9x4NX1QbDCLvm0TM3jTy7Yz0vI5mHvzWWv319DPddHrzRUY9cq1r+fbsTPZR7Eb+6xibOHt6D6XZt56anFrHGtd7NtClHBx6PcwXDKyf0R8RaGt2tV246pw/z9uu4uYecnjyoGzNvOJnvThzAki37eHVpcEny80b25OLjegNQ1C0zMJigT146QwqzyEnzk5wUjHCF2WmkJScxso+3UHO4y6Lu2ancdclIlvzqLMBa58fdBPefq8cHHo9xLcfirNEVWnAO6JbJucc2vz2tY5mrL+raiQP44KenceWE/iwo2esZyfblUb0CFyNFXTMCee7dJZ3eXdLJSvXj7iopzE5jQLdMRvQ+eMAGa2WAf3xjLAt/+SUAps9a48nzv686PvDYvQTNePszD83z0B5ZXDK2d6vnW+7K881nDOGj207j2xP6U1yyl3dcFz0Xje7FMb1yWnqLqIt2YDDA2yKyQESus/cVGmOcqac7gBb/U0TkOhEpFpHiXbt2RTmZ8cnnE/7wlWMP2mQTjklDCpq1c+ZlpvDqjRM58+jugaXAzx7eg5+cPdTTFJWZGuzcdQcM9/s5V/lnHVPIBz+ZzCPfGss/vzMu8HyOfdU/cXA3TgiZvd3UBEf3tJqP6hqayLcLjKw0P0MKs5k0pICvHNeHU+3O1J52YLh24kDmTjvjoPl2+iqcPgGAj9YEv4vudanGuQqMUwYX8N6PJ3PPpSP57zXBgrRnlzQGdc/izguHezpRHc4QUHeeh/WwCgb3PAQMgQIjOy050NyXk5bMfZeP5r7LR7P0jrM5xp7V3quLleffXzSCU1zNfA73aKo6uy8p1/6sFpTs5QXX5MfRrkLQXUh+88T+3HT6IB765lj+8tVgIO7VJZ3hvXL59oT+gfkzbu5BCk6TyWC7OdDdrGYgUMjnpqcEarJdMpL5w8XH8rNzhrLsN2cHmhKdPN954XBGtVCbc7fxO5PfnO/O/I17eXFhsInIHQDdef72Sf35zklF/PVrx3HvZc3z/LXxfT2LWjqWbHHn2e/Js/uiJ5aiHRhOMcaMAaYAN4jIqe4njTUescUBxMaYR4wx44wx4woKClo6RHUAj155PEvuOKvV57NCZlrfc8lIHvzGmEAwASuAzfv5GTzwteMo6pbJWcN7eK6snQLDn+TjH98IjsQBq8bg1CSuGN8vsD6UP2SkTZpduDuBAazag1OQ/Ofq8Vwypg+ZKUn0t5szahuCnYb/cl01Otwzyp2lRaz0+hnQLZMkX3C9KrAKDIBvTyji5jOaDw92c/I8oYWCxWACfTrVdQ3BYJjqZ3ivXM44upD0lCQK7XkqznkHF2bz+LUnBN5nQLfMZu/tnhtx4ehezZ53z5w/1nU1npeRwq1nDaUwJ42BBcH3dc5954Uj+Iur8Gw5z9Z7hy7dAtasYyfPB2rrA8EwK9XPpCEFfGtCERkpfgrtz9c57/Beucz84SmudDZvr3fnuaXg5c6z+yKrICuVX395OH3yMujftXme/3jxSO6/fHRYeR7Tr3ltLpYLaEQ1MBhjttq/S4GXgPHAThHpCWD/Lm39HVRnlxkyGuSy4/sypYWmhcKctGZDR4cHroq9weWaUwYEtou6ZdI9J401v5vCV8f2IT/T+sevC2n7LbILwUlDunv2P/HdE3jom2M5dUgBf7lsFMvvPIenrzsR8LYfnza0O9e6zgtW89m/rzqeqVOGeWoV7vR2cRVEvVxDUbtkpHDxmN785+rxbLzrPB6/5gQ+cI0Uc96jV5d0Ppl6uue8xsAJA/M5YUA+vzp/eODqOXQYamWtFdj6u/qHAP7+9TGM7JPLGzdP5O1bTuXmMwZzz6Ujrb+bq5C8//LRXDDKGxxEhF+dfwxfHtXL83m58+wOhu5O+YKsVIYUZnHvZaOY9/MzuO2cofzq/GMCzzsXC0MKs3n1xmBhDlYhecLAfIb1yOZn5wyjqz1JM7TwdIYkF3X1Br37Lx/NkMIsZv/sdJ69fgJXHN838HnWuoayPnrluGbDuEWEX55/DBeNDs1z8LN1BxxPnrNTGdw9i/svH83HPzuNG08fxI/ODF4UOEPKh/fK5cUfnOQ5byzX3IvacFURyQR8xpj99uOzgDuBl4Ergbvs3zOjlQYVe6HDBCMx4+rxLN5U3mxBvl+efwy/OPdoZq0qDYy3dwpmp1CqC1kb58bTB3HF8X0Z6Bo9BVYn9Tkjenj2OVfgqX7vddN1pw5k3hd7+HzrvkANYfLQ7kwe6g022aneJrNJQwq4bFxf0lO8ge/ey4JXk6eEXKnmpLkDShrH9s4NNLtcMKoXGSn+QL/Pht1Wv0foWP0px/agZE8l15wy0LP/vJE9Oc9urx9SmM2QL2Wzr6qe21jqmaAlIlw2rk9gGLLz97g6JECGprcwJ43MlCS+NaHIk2cR4e1bJgW2fzB5EGDN/AZvcBneK4fc9ORAW/9Fo3uTk5bMmz+yGh022RMYQz/nc4/tyfJtFc2a6i46rjcX2f0y4wfkM35APmUHann0Y+9EvFR/Elcc3zfQ1t/Nrplc00Ke3entkZuG3ydcdXKRJ3iICO/cGsyz05/mTLBzv8dxfbsE5hIBXDym9X6KaIvmPIZC4CW7vdkPPGmMeVNE5gPPisg1QAlwWRTToGIstHCNRLesVM48puXOWp9Pml3ZQbBQDy0ks9OSwx72l+pPYuqUYc3a47vnpPFKyJVsS9z/7MlJPma4OmwP5bZzhnLPm6vJcr2HiPC/G05m+75qeuamB4a9OpwaQ+hCcVedPIDvnFTk6fNpjTNL/vJxoTd/KuDdWyfRNTPFU/tp7fUA6SlJLP312c3S2Zqvju3Dcwu2eC4iRIS5085gxfYKT7u+w8lz6Od8w2mDuP7UgfiTDv29cy4ivhxSKzrj6EJeu+kUCnPSAsvHtMQdDDNS/Kz87TmBe7MfyoWjezFz8bZmeS6+/UyWb6uI+e1toxYYjDEbgGaNisaYMuDgvX6q0/vhaYOYMWdjWIXSkeSMfDrc5bS/N6nlUUvhyEpr+7/VDyYPClxJuyX5hD55GS28AvLs5rOW8hzu319EWP6bs1ucCe7uZG9NaM0w3KAA8MeLj2XauUc3K8zTU5JaDAoQbKILrTEAYQUFsC4uim8/01PAO8IZsBH6OYcbFAD+dOkofnFe8zxnpPhjHhRAZz6rKPnJ2UP5ydkHH4YaDU479aCCQxdm0RJJAXEkOAVb1mFOhArtD4pEuIVxa691anrhcj7nnl1aX0IkHAerEbQm1e+jtqEpouAXKsXvO+iyGLGmgUHFlYLsVGZcPb7Z2PL2MPOGkz0T89pLn7x0pk0ZFug3aE/v3jopJiuE9s3PYPoVo5k4uP1HLL576yTP5Lh4JLG8m1O4xo0bZ4qLiw99oFJKqQARWeBadSJsuuy2UkopDw0MSimlPDQwKKWU8tDAoJRSykMDg1JKKQ8NDEoppTw0MCillPLQwKCUUsqjU0xwE5FdWAvutUU3YPchj4ovmufEoHlODIeT5/7GmIinh3eKwHA4RKS4LTP/OjPNc2LQPCeGWORZm5KUUkp5aGBQSinlkQiB4ZFYJyAGNM+JQfOcGNo9z3Hfx6CUUioyiVBjUEopFQENDEoppTziOjCIyDkislpE1onI1FinpyUi8k8RKRWRZa59+SLyjoistX/n2ftFRB6w87NURMa4XnOlffxaEbnStX+siHxuv+YBsW8C3JZzHME89xWR90VkhYgsF5Gb4z3fIpImIp+JyBI7z7+x9w8QkXn2eZ8RkRR7f6q9vc5+vsj1XtPs/atF5GzX/ha/7205xxHOe5KILBKRVxMhzyKy0f7uLRaRYntf5/puG2Pi8gdIAtYDA4EUYAlwTKzT1UI6TwXGAMtc++4BptqPpwJ324/PBd4ABDgRmGfvzwc22L/z7Md59nOf2ceK/dopbTnHEc5zT2CM/TgbWAMcE8/5tt83y36cDMyzz/MscIW9/yHg+/bjHwAP2Y+vAJ6xHx9jf5dTgQH2dzzpYN/3SM8Rhc/7VuBJ4NW2pKez5RnYCHQL2depvtsxLxij9QNMAN5ybU8DpsU6Xa2ktQhvYFgN9LQf9wRW248fBr4WehzwNeBh1/6H7X09gVWu/YHjIj1HlPM/E/hSouQbyAAWAidgzWj1h35ngbeACfZjv32chH6PneNa+77br4noHEc4r32AWcDpwKttSU8nzPNGmgeGTvXdjuempN7AZtf2FntfZ1BojNluP94BFNqPW8vTwfZvaWF/W84RFXZV/jisK+i4zrfdpLIYKAXewbraLTfGNLRwzkB67Of3AV0Pks7W9ndtwzmOpPuB24Ame7st6elseTbA2yKyQESus/d1qu+2/2BPqtgzxhgRieqY4vY4R0tEJAt4AfiRMabCbipttzS1d76NMY3AaBHpArwEDGuvc8eCiJwPlBpjFojI5Finpx2dYozZKiLdgXdEZJX7yc7w3Y7nGsNWoK9ru4+9rzPYKSI9Aezfpfb+1vJ0sP19WtjflnMcUSKSjBUUnjDGvNjGNHW6fAMYY8qB97GaOLqIiHOB5j5nID3287lA2UHS2dr+sjac40g5GfiyiGwEnsZqTprehvR0pjxjjNlq/y7FugAYTyf7bsdzYJgPDLZHJ6RgdTS9HOM0hetlwBmFcCVWG7yz/9v2KIMTgX121fEt4CwRybNHIpyF1aa6HagQkRPtkQvfDnmvSM5xxNhpeQxYaYy5NxHyLSIFdk0BEUnH6lNZiRUgLm0lPU46LwXeM1YD8cvAFfbomgHAYKzOyBa/7/ZrIj3HEWGMmWaM6WOMKbLT854x5hvxnGcRyRSRbOcx1ndyGZ3tu30kO1062g9Wb/warLbcX8Q6Pa2k8SlgO1CP1fZ3DVab5yxgLfAukG8fK8Df7fx8Doxzvc/VwDr75yrX/nH2F3M98DeCs90jPscRzPMpWO2wS4HF9s+58ZxvYCSwyM7zMuBX9v6BWIXcOuA5INXen2Zvr7OfH+h6r1/Y6VyNPSLlYN/3tpwjCp/5ZIKjkuI2z/Z5l9g/y500dbbvti6JoZRSyiOem5KUUkq1gQYGpZRSHhoYlFJKeWhgUEop5aGBQSmllIcGBhX3RGSO/btIRL5+hN/75y2dS6nOTIerqoRhL8vwE2PM+RG8xm+Ca+609PwBY0zWkUifUh2F1hhU3BORA/bDu4CJYq2Tf4u9qN2fRGS+vU799fbxk0Vktoi8DKyw9/3PXhRtubMwmojcBaTb7/eE+1z2LNM/icgysdbOv9z13h+IyPMiskpEnrBnsCIid4l1j4qlIvLn9vwbKeWmi+ipRDIVV43BLuD3GWOOF5FU4BMReds+dgwwwhjzhb19tTFmj72cxXwRecEYM1VEfmiMGd3CuS4GRgOjgG72az6ynzsOGA5sAz4BThaRlcBXgGHGGOMsn6FULGiNQSWys7DWkFmMtex3V6x1eAA+cwUFgJtEZAkwF2tBssEc3CnAU8aYRmPMTuBD4HjXe28xxjRhLQdShLX8cw3wmIhcDFQddu6UaiMNDCqRCXCjMWa0/TPAGOPUGCoDB1l9E2di3eBlFNaaR2mHcd5a1+NGrBvKNGCtwvk8cD7w5mG8v1KHRQODSiT7sW4l6ngL+L5YS4AjIkPsFTFD5QJ7jTFVIjIM6/aIjnrn9SFmA5fb/RgFWLdw/ay1hIl1b4pcY8zrwC1YTVBKxYT2MahEshRotJuE/o11b4AiYKHdAbwLuKiF170JfM/uB1iN1ZzkeARYKiILjbWktOMlrPstLMFaSfY2Y8wOO7C0JBuYKSJpWDWZW9uWRaUOnw5XVUop5aFNSUoppTw0MCillPLQwKCUUspDA4NSSikPDQxKKaU8NDAopZTy0MCglFLK4/8BBp/lAr+AMhAAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "iterations = np.arange(len(cost_list))*10000\n", "plt.plot(iterations,cost_list)\n", "plt.xlabel(\"iterations\")\n", "plt.ylabel(\"avg cost\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " " ] } ], "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.6.8" } }, "nbformat": 4, "nbformat_minor": 1 }