diff --git a/LogisticRegression.ipynb b/LogisticRegression.ipynb new file mode 100644 index 000000000..2d8c1ee4c --- /dev/null +++ b/LogisticRegression.ipynb @@ -0,0 +1,484 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# used for manipulating directory paths\n", + "import os\n", + "\n", + "# used for mathematical operations of elements\n", + "import math\n", + "\n", + "# Scientific and vector computation for python\n", + "import numpy as np\n", + "\n", + "# Plotting library\n", + "from matplotlib import pyplot\n", + "\n", + "# Optimization module in scipy\n", + "from scipy import optimize\n", + "\n", + "# library written for this exercise providing additional functions for assignment submission, and others\n", + "import utils\n", + "\n", + "# define the submission/grader object for this exercise\n", + "grader = utils.Grader()\n", + "\n", + "# tells matplotlib to embed plots within the notebook\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Load data\n", + "# The first two columns contains the exam scores and the third column\n", + "# contains the label.\n", + "data = np.loadtxt('ex2data1.txt', delimiter=',')\n", + "X, y = data[:, 0:2], data[:, 2]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def plotData(X, y):\n", + " \"\"\"\n", + " Plots the data points X and y into a new figure. Plots the data \n", + " points with * for the positive examples and o for the negative examples.\n", + " \n", + " Parameters\n", + " ----------\n", + " X : array_like\n", + " An Mx2 matrix representing the dataset. \n", + " \n", + " y : array_like\n", + " Label values for the dataset. A vector of size (M, ).\n", + " \n", + " Instructions\n", + " ------------\n", + " Plot the positive and negative examples on a 2D plot, using the\n", + " option 'k*' for the positive examples and 'ko' for the negative examples. \n", + " \"\"\"\n", + " # Create New Figure\n", + " fig = pyplot.figure()\n", + "\n", + " # ====================== YOUR CODE HERE ======================\n", + " # Find Indices of Positive and Negative Examples\n", + " pos = y == 1\n", + " neg = y == 0\n", + " \n", + " pyplot.plot(X[neg,0],X[neg,1],'ko', mfc='y', ms=8, mec='k', mew=1)\n", + "\n", + " pyplot.plot(X[pos,0],X[pos,1],'k*', lw=2, ms=10)\n", + "\n", + " \n", + " # ============================================================" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "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pOu7CdKgrZE6MRfM/ff748JKlc4OkgfRsgiUpaCq/6mqA1V1EDAZWKuqVwLrgC+5b5sKLMu0LGHS3sZRgjRoa6ROstkFgkZnB8mDMIO8MwRpnsL3cAad/w70AxZl8mKZzP8iIsyYMaN5fd68efzwhz9s95ja2lo2bdrU7ntGjBjBlClTEu7funUrZ511zDBMu1RWVrJ69WoA7r77bvbt29e870c/+lGnzgWwePFivv3tb3f6uM7g5Uxkw2hLZzslYXN3+qoUVHW9qk5wX/9DVT+tqkNV9QpVPZDJa2dSe/fs2ZPf/OY37N69O+ljOlIKmzdv5siRI2zYsIF//etfKcvWltmzZzdXr0qHUvCCMPujjfDT2U5J2MJvg2QpeEomtXe3bt2YNm0ad9111zH73nrrLcrLyxk+fDjl5eVs27aNZ555huXLl3PLLbcwcuRI3njjjWOO+9WvfsVVV13FxRdfzPLly5u3b9y4kREjRnD++efzP//zP83bFy9ezKRJk7jssssYPHgwP/vZz5g/fz4lJSWcd955vP/++wBcc801PProo9xzzz1s376dsrIyysrK+P73v89HH33EyJEjufLKKwH4xS9+wac//WlGjhzJN77xDQ4fdvz2Dz74IKeddhpjxozh6aefTvm+JYsN2hp+0tlOSejcnYlKsoWhxSvHuWnTpg4K0Tl0pjRnZznuuOO0oaFBTz31VK2vr9e5c+fqrFmzVFV1woQJunjxYlVVXbRokU6cOFFVVadOnaqPPPJIwnMOGzZMt27dqn/4wx/0sssua95+9tln6/r161VV9eabb9YzzzxTVVUffPBBHTJkiH744Ye6c+dOPf744/W+++5TVdXp06frXXfddcx1Tz31VN21a1erzxFj06ZNOmHCBD148KCqqt5www360EMP6fbt27W4uFh37typBw4c0M9+9rN64403xv0MyX43hhF0YqVEi4uLNC8vosXFRQnLuLZX2nfs2KhWVVV6Lj9WjvNYMq29jz/+eK6++mruueeeVtufffZZvvpVZ47eVVddxR//+McOz/Xcc89RVFTEqaeeSnl5Oc8//zwffPABDQ0N1NfXM2bMmObztaSsrIzevXtTVFREYWEhl112GQBnn302W7du7dTnWbNmDRs3buTcc89l5MiRrFmzhn/84x/8+c9/prS0lKKiInr06MFXvvKVTp3XMMJIZwbJw+buzFml4MVg5fTp01m0aFG7YwDJzKeoqanhtddeY9CgQQwZMoQPP/yQX//616hqu8f37Nmz+XUkEmlej0QiNDU1deKTOBbl1KlTeeGFF3jhhRd4/fXXmwfPvZgTYpFiRlgJm7szZ5WCF9q7b9++fPnLX2bRoqOBVJ/97Gd5+OGHAfjlL3/JBRdcAEDv3r3Zu3fvMec4cuQIjzzyCC+99BJbt25l69atLFu2jJqaGvr06UNhYWGztfHLX/6yS/K2laF79+4cOnQIgPLych599FF2usWp33//fd566y0+85nPsH79evbs2cOhQ4d45JFHuiRDPIJQKcwwukKYwm9zVil4pb1nzJjRKgrpnnvu4cEHH2T48OFUV1fz05/+FIDJkyczd+5cSkpKWg00b9iwgZNPPpmTTz65eduFF17Ipk2b2LFjBw8++CA33ngj559/Pr169eqSrNOmTePSSy+lrKyseX348OFceeWVnHHGGcyZM4eLL76Y4cOHc9FFF7Fjxw5OOukkfvjDH3L++eczbtw4zjnnnC7JEI+wxXkbRpjJuiI7NqM5uKT63ViaZcNIL4Ga0WwYnSVscd6GEWZMKRiBJ3Rx3oYRYkwpGIHH0loYhneYUjACT9jivA0jzJhSABoaGrj88stpaGjwWxQjDmGL8zaMMGNKAVi+fDm1tbWsWLHCb1GMBIQpztswwowpBeCBBx5otUwHv/3tbxERXnvttbj7Y4nokmX79u186UtOuYkXXniBJ554onnf+vXreeaZZzot46BBgzqVydUwjOwnJ5XCuHHjEJHmFnugPv300622x1JKp0JNTQ0XXHBB8+zlrjJgwIBmJZIupWAYhtGWnFQKt956K/n5+c3rBw8ebLUEyM/PZ+bMmSmdv7GxkaeffppFixY1KwVV5dvf/jZnnHEGn//855vTRYDTY//BD37A+eefz+jRo3n++ee55JJLGDJkCD//+c+BowV0Dh48SGVlJUuXLmXkyJHccccd/PznP+euu+5i5MiRPPXUU+zatYsvfvGLnHvuuZx77rnN6az37NnDxRdfTElJCd/4xjcI88RFwzAyQze/BfCDsrIyHnvsMSZMmNCqqEyM/Px8Hn/8cUpLS1M6f21tLePHj+e0006jb9++PP/882zdupXXX3+dl19+mffee48zzjiDf//3f28+pri4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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotData(X,y)\n", + "pyplot.xlabel('Exam 1 Score')\n", + "pyplot.ylabel('Exam 2 Score')\n", + "pyplot.legend(['Not Admitted','Admitted'])\n", + "pass" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def sigmoid(z):\n", + " \"\"\"\n", + " Compute sigmoid function given the input z.\n", + " \n", + " Parameters\n", + " ----------\n", + " z : array_like\n", + " The input to the sigmoid function. This can be a 1-D vector \n", + " or a 2-D matrix. \n", + " \n", + " Returns\n", + " -------\n", + " g : array_like\n", + " The computed sigmoid function. g has the same shape as z, since\n", + " the sigmoid is computed element-wise on z.\n", + " \n", + " Instructions\n", + " ------------\n", + " Compute the sigmoid of each value of z (z can be a matrix, vector or scalar).\n", + " \"\"\"\n", + " # convert input to a numpy array\n", + " z = np.array(z)\n", + " \n", + " # You need to return the following variables correctly \n", + " g = np.zeros(z.shape)\n", + "\n", + " # ====================== YOUR CODE HERE ======================\n", + " g = 1/(1+np.exp((-z)))\n", + " \n", + " # =============================================================\n", + " return g" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "g( [0, 100] ) = [0.5 1. ]\n" + ] + } + ], + "source": [ + "# Test the implementation of sigmoid function here\n", + "z = [0,100]\n", + "g = sigmoid(z)\n", + "\n", + "print('g(', z, ') = ', g)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# Setup the data matrix appropriately, and add ones for the intercept term\n", + "m, n = X.shape\n", + "\n", + "# Add intercept term to X\n", + "X = np.concatenate([np.ones((m, 1)), X], axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "def costFunction(theta, X, y):\n", + " \"\"\"\n", + " Compute cost and gradient for logistic regression. \n", + " \n", + " Parameters\n", + " ----------\n", + " theta : array_like\n", + " The parameters for logistic regression. This a vector\n", + " of shape (n+1, ).\n", + " \n", + " X : array_like\n", + " The input dataset of shape (m x n+1) where m is the total number\n", + " of data points and n is the number of features. We assume the \n", + " intercept has already been added to the input.\n", + " \n", + " y : arra_like\n", + " Labels for the input. This is a vector of shape (m, ).\n", + " \n", + " Returns\n", + " -------\n", + " J : float\n", + " The computed value for the cost function. \n", + " \n", + " grad : array_like\n", + " A vector of shape (n+1, ) which is the gradient of the cost\n", + " function with respect to theta, at the current values of theta.\n", + " \n", + " Instructions\n", + " ------------\n", + " Compute the cost of a particular choice of theta. You should set J to \n", + " the cost. Compute the partial derivatives and set grad to the partial\n", + " derivatives of the cost w.r.t. each parameter in theta.\n", + " \"\"\"\n", + " # Initialize some useful values\n", + " m = y.size # number of training examples\n", + "\n", + " # You need to return the following variables correctly \n", + " J = 0\n", + " grad = np.zeros(theta.shape)\n", + "\n", + " # ====================== YOUR CODE HERE ======================\n", + " z=theta.dot(X.transpose())\n", + " h=sigmoid(z)\n", + " \n", + " for i in range(m):\n", + " J=J+((-1*(y[i]*math.log(h[i])+(1-y[i])*math.log(1-h[i])))/m)\n", + " \n", + " for i in range(theta.shape[0]):\n", + " grad[i]=((h-y).dot(X[:,i]))/m\n", + "\n", + " # =============================================================\n", + " return J, grad" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cost at initial theta (zeros): 0.693\n", + "Expected cost (approx): 0.693\n", + "\n", + "Gradient at initial theta (zeros):\n", + "\t[-0.1000, -12.0092, -11.2628]\n", + "Expected gradients (approx):\n", + "\t[-0.1000, -12.0092, -11.2628]\n", + "\n", + "Cost at test theta: 0.218\n", + "Expected cost (approx): 0.218\n", + "\n", + "Gradient at test theta:\n", + "\t[0.043, 2.566, 2.647]\n", + "Expected gradients (approx):\n", + "\t[0.043, 2.566, 2.647]\n" + ] + } + ], + "source": [ + "# Initialize fitting parameters\n", + "initial_theta = np.zeros(n+1)\n", + "\n", + "cost, grad = costFunction(initial_theta, X, y)\n", + "\n", + "print('Cost at initial theta (zeros): {:.3f}'.format(cost))\n", + "print('Expected cost (approx): 0.693\\n')\n", + "\n", + "print('Gradient at initial theta (zeros):')\n", + "print('\\t[{:.4f}, {:.4f}, {:.4f}]'.format(*grad))\n", + "print('Expected gradients (approx):\\n\\t[-0.1000, -12.0092, -11.2628]\\n')\n", + "\n", + "# Compute and display cost and gradient with non-zero theta\n", + "test_theta = np.array([-24, 0.2, 0.2])\n", + "cost, grad = costFunction(test_theta, X, y)\n", + "\n", + "print('Cost at test theta: {:.3f}'.format(cost))\n", + "print('Expected cost (approx): 0.218\\n')\n", + "\n", + "print('Gradient at test theta:')\n", + "print('\\t[{:.3f}, {:.3f}, {:.3f}]'.format(*grad))\n", + "print('Expected gradients (approx):\\n\\t[0.043, 2.566, 2.647]')" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cost at theta found by optimize.minimize: 0.203\n", + "Expected cost (approx): 0.203\n", + "\n", + "theta:\n", + "\t[-25.161, 0.206, 0.201]\n", + "Expected theta (approx):\n", + "\t[-25.161, 0.206, 0.201]\n" + ] + } + ], + "source": [ + "# set options for optimize.minimize\n", + "options= {'maxiter': 400}\n", + "\n", + "# see documention for scipy's optimize.minimize for description about\n", + "# the different parameters\n", + "# The function returns an object `OptimizeResult`\n", + "# We use truncated Newton algorithm for optimization which is \n", + "# equivalent to MATLAB's fminunc\n", + "# See https://stackoverflow.com/questions/18801002/fminunc-alternate-in-numpy\n", + "res = optimize.minimize(costFunction,\n", + " initial_theta,\n", + " (X, y),\n", + " jac=True,\n", + " method='TNC',\n", + " options=options)\n", + "\n", + "# the fun property of `OptimizeResult` object returns\n", + "# the value of costFunction at optimized theta\n", + "cost = res.fun\n", + "\n", + "# the optimized theta is in the x property\n", + "theta = res.x\n", + "\n", + "# Print theta to screen\n", + "print('Cost at theta found by optimize.minimize: {:.3f}'.format(cost))\n", + "print('Expected cost (approx): 0.203\\n');\n", + "\n", + "print('theta:')\n", + "print('\\t[{:.3f}, {:.3f}, {:.3f}]'.format(*theta))\n", + "print('Expected theta (approx):\\n\\t[-25.161, 0.206, 0.201]')" + ] + }, + { + "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": [ + "# Plot Boundary\n", + "utils.plotDecisionBoundary(plotData, theta, X, y)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def predict(theta, X):\n", + " \"\"\"\n", + " Predict whether the label is 0 or 1 using learned logistic regression.\n", + " Computes the predictions for X using a threshold at 0.5 \n", + " (i.e., if sigmoid(theta.T*x) >= 0.5, predict 1)\n", + " \n", + " Parameters\n", + " ----------\n", + " theta : array_like\n", + " Parameters for logistic regression. A vector of shape (n+1, ).\n", + " \n", + " X : array_like\n", + " The data to use for computing predictions. The rows is the number \n", + " of points to compute predictions, and columns is the number of\n", + " features.\n", + "\n", + " Returns\n", + " -------\n", + " p : array_like\n", + " Predictions and 0 or 1 for each row in X. \n", + " \n", + " Instructions\n", + " ------------\n", + " Complete the following code to make predictions using your learned \n", + " logistic regression parameters.You should set p to a vector of 0's and 1's \n", + " \"\"\"\n", + " m = X.shape[0] # Number of training examples\n", + "\n", + " # You need to return the following variables correctly\n", + " p = np.zeros(m)\n", + "\n", + " # ====================== YOUR CODE HERE ======================\n", + " for i in range(m):\n", + " if sigmoid(theta.dot(X.transpose()))[i]>=0.5 :\n", + " p[i]=1\n", + " else :\n", + " p[i]=0\n", + "\n", + " \n", + " # ============================================================\n", + " return p" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "For a student with scores 45 and 85,we predict an admission probability of 0.776\n", + "Expected value: 0.775 +/- 0.002\n", + "\n", + "Train Accuracy: 89.00 %\n", + "Expected accuracy (approx): 89.00 %\n" + ] + } + ], + "source": [ + "# Predict probability for a student with score 45 on exam 1 \n", + "# and score 85 on exam 2 \n", + "prob = sigmoid(np.dot([1, 45, 85], theta))\n", + "print('For a student with scores 45 and 85,'\n", + " 'we predict an admission probability of {:.3f}'.format(prob))\n", + "print('Expected value: 0.775 +/- 0.002\\n')\n", + "\n", + "# Compute accuracy on our training set\n", + "p = predict(theta, X)\n", + "print('Train Accuracy: {:.2f} %'.format(np.mean(p == y) * 100))\n", + "print('Expected accuracy (approx): 89.00 %')\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "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.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/ex2data1.txt b/ex2data1.txt new file mode 100644 index 000000000..3a5f95245 --- /dev/null +++ b/ex2data1.txt @@ -0,0 +1,100 @@ +34.62365962451697,78.0246928153624,0 +30.28671076822607,43.89499752400101,0 +35.84740876993872,72.90219802708364,0 +60.18259938620976,86.30855209546826,1 +79.0327360507101,75.3443764369103,1 +45.08327747668339,56.3163717815305,0 +61.10666453684766,96.51142588489624,1 +75.02474556738889,46.55401354116538,1 +76.09878670226257,87.42056971926803,1 +84.43281996120035,43.53339331072109,1 +95.86155507093572,38.22527805795094,0 +75.01365838958247,30.60326323428011,0 +82.30705337399482,76.48196330235604,1 +69.36458875970939,97.71869196188608,1 +39.53833914367223,76.03681085115882,0 +53.9710521485623,89.20735013750205,1 +69.07014406283025,52.74046973016765,1 +67.94685547711617,46.67857410673128,0 +70.66150955499435,92.92713789364831,1 +76.97878372747498,47.57596364975532,1 +67.37202754570876,42.83843832029179,0 +89.67677575072079,65.79936592745237,1 +50.534788289883,48.85581152764205,0 +34.21206097786789,44.20952859866288,0 +77.9240914545704,68.9723599933059,1 +62.27101367004632,69.95445795447587,1 +80.1901807509566,44.82162893218353,1 +93.114388797442,38.80067033713209,0 +61.83020602312595,50.25610789244621,0 +38.78580379679423,64.99568095539578,0 +61.379289447425,72.80788731317097,1 +85.40451939411645,57.05198397627122,1 +52.10797973193984,63.12762376881715,0 +52.04540476831827,69.43286012045222,1 +40.23689373545111,71.16774802184875,0 +54.63510555424817,52.21388588061123,0 +33.91550010906887,98.86943574220611,0 +64.17698887494485,80.90806058670817,1 +74.78925295941542,41.57341522824434,0 +34.1836400264419,75.2377203360134,0 +83.90239366249155,56.30804621605327,1 +51.54772026906181,46.85629026349976,0 +94.44336776917852,65.56892160559052,1 +82.36875375713919,40.61825515970618,0 +51.04775177128865,45.82270145776001,0 +62.22267576120188,52.06099194836679,0 +77.19303492601364,70.45820000180959,1 +97.77159928000232,86.7278223300282,1 +62.07306379667647,96.76882412413983,1 +91.56497449807442,88.69629254546599,1 +79.94481794066932,74.16311935043758,1 +99.2725269292572,60.99903099844988,1 +90.54671411399852,43.39060180650027,1 +34.52451385320009,60.39634245837173,0 +50.2864961189907,49.80453881323059,0 +49.58667721632031,59.80895099453265,0 +97.64563396007767,68.86157272420604,1 +32.57720016809309,95.59854761387875,0 +74.24869136721598,69.82457122657193,1 +71.79646205863379,78.45356224515052,1 +75.3956114656803,85.75993667331619,1 +35.28611281526193,47.02051394723416,0 +56.25381749711624,39.26147251058019,0 +30.05882244669796,49.59297386723685,0 +44.66826172480893,66.45008614558913,0 +66.56089447242954,41.09209807936973,0 +40.45755098375164,97.53518548909936,1 +49.07256321908844,51.88321182073966,0 +80.27957401466998,92.11606081344084,1 +66.74671856944039,60.99139402740988,1 +32.72283304060323,43.30717306430063,0 +64.0393204150601,78.03168802018232,1 +72.34649422579923,96.22759296761404,1 +60.45788573918959,73.09499809758037,1 +58.84095621726802,75.85844831279042,1 +99.82785779692128,72.36925193383885,1 +47.26426910848174,88.47586499559782,1 +50.45815980285988,75.80985952982456,1 +60.45555629271532,42.50840943572217,0 +82.22666157785568,42.71987853716458,0 +88.9138964166533,69.80378889835472,1 +94.83450672430196,45.69430680250754,1 +67.31925746917527,66.58935317747915,1 +57.23870631569862,59.51428198012956,1 +80.36675600171273,90.96014789746954,1 +68.46852178591112,85.59430710452014,1 +42.0754545384731,78.84478600148043,0 +75.47770200533905,90.42453899753964,1 +78.63542434898018,96.64742716885644,1 +52.34800398794107,60.76950525602592,0 +94.09433112516793,77.15910509073893,1 +90.44855097096364,87.50879176484702,1 +55.48216114069585,35.57070347228866,0 +74.49269241843041,84.84513684930135,1 +89.84580670720979,45.35828361091658,1 +83.48916274498238,48.38028579728175,1 +42.2617008099817,87.10385094025457,1 +99.31500880510394,68.77540947206617,1 +55.34001756003703,64.9319380069486,1 +74.77589300092767,89.52981289513276,1 diff --git a/ex2data2.txt b/ex2data2.txt new file mode 100644 index 000000000..a88899234 --- /dev/null +++ b/ex2data2.txt @@ -0,0 +1,118 @@ +0.051267,0.69956,1 +-0.092742,0.68494,1 +-0.21371,0.69225,1 +-0.375,0.50219,1 +-0.51325,0.46564,1 +-0.52477,0.2098,1 +-0.39804,0.034357,1 +-0.30588,-0.19225,1 +0.016705,-0.40424,1 +0.13191,-0.51389,1 +0.38537,-0.56506,1 +0.52938,-0.5212,1 +0.63882,-0.24342,1 +0.73675,-0.18494,1 +0.54666,0.48757,1 +0.322,0.5826,1 +0.16647,0.53874,1 +-0.046659,0.81652,1 +-0.17339,0.69956,1 +-0.47869,0.63377,1 +-0.60541,0.59722,1 +-0.62846,0.33406,1 +-0.59389,0.005117,1 +-0.42108,-0.27266,1 +-0.11578,-0.39693,1 +0.20104,-0.60161,1 +0.46601,-0.53582,1 +0.67339,-0.53582,1 +-0.13882,0.54605,1 +-0.29435,0.77997,1 +-0.26555,0.96272,1 +-0.16187,0.8019,1 +-0.17339,0.64839,1 +-0.28283,0.47295,1 +-0.36348,0.31213,1 +-0.30012,0.027047,1 +-0.23675,-0.21418,1 +-0.06394,-0.18494,1 +0.062788,-0.16301,1 +0.22984,-0.41155,1 +0.2932,-0.2288,1 +0.48329,-0.18494,1 +0.64459,-0.14108,1 +0.46025,0.012427,1 +0.6273,0.15863,1 +0.57546,0.26827,1 +0.72523,0.44371,1 +0.22408,0.52412,1 +0.44297,0.67032,1 +0.322,0.69225,1 +0.13767,0.57529,1 +-0.0063364,0.39985,1 +-0.092742,0.55336,1 +-0.20795,0.35599,1 +-0.20795,0.17325,1 +-0.43836,0.21711,1 +-0.21947,-0.016813,1 +-0.13882,-0.27266,1 +0.18376,0.93348,0 +0.22408,0.77997,0 +0.29896,0.61915,0 +0.50634,0.75804,0 +0.61578,0.7288,0 +0.60426,0.59722,0 +0.76555,0.50219,0 +0.92684,0.3633,0 +0.82316,0.27558,0 +0.96141,0.085526,0 +0.93836,0.012427,0 +0.86348,-0.082602,0 +0.89804,-0.20687,0 +0.85196,-0.36769,0 +0.82892,-0.5212,0 +0.79435,-0.55775,0 +0.59274,-0.7405,0 +0.51786,-0.5943,0 +0.46601,-0.41886,0 +0.35081,-0.57968,0 +0.28744,-0.76974,0 +0.085829,-0.75512,0 +0.14919,-0.57968,0 +-0.13306,-0.4481,0 +-0.40956,-0.41155,0 +-0.39228,-0.25804,0 +-0.74366,-0.25804,0 +-0.69758,0.041667,0 +-0.75518,0.2902,0 +-0.69758,0.68494,0 +-0.4038,0.70687,0 +-0.38076,0.91886,0 +-0.50749,0.90424,0 +-0.54781,0.70687,0 +0.10311,0.77997,0 +0.057028,0.91886,0 +-0.10426,0.99196,0 +-0.081221,1.1089,0 +0.28744,1.087,0 +0.39689,0.82383,0 +0.63882,0.88962,0 +0.82316,0.66301,0 +0.67339,0.64108,0 +1.0709,0.10015,0 +-0.046659,-0.57968,0 +-0.23675,-0.63816,0 +-0.15035,-0.36769,0 +-0.49021,-0.3019,0 +-0.46717,-0.13377,0 +-0.28859,-0.060673,0 +-0.61118,-0.067982,0 +-0.66302,-0.21418,0 +-0.59965,-0.41886,0 +-0.72638,-0.082602,0 +-0.83007,0.31213,0 +-0.72062,0.53874,0 +-0.59389,0.49488,0 +-0.48445,0.99927,0 +-0.0063364,0.99927,0 +0.63265,-0.030612,0 diff --git a/regularisedLogisticRegression.ipynb b/regularisedLogisticRegression.ipynb new file mode 100644 index 000000000..29006e75c --- /dev/null +++ b/regularisedLogisticRegression.ipynb @@ -0,0 +1,440 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "# used for manipulating directory paths\n", + "import os\n", + "\n", + "# used for mathematical operations of elements\n", + "import math\n", + "\n", + "# Scientific and vector computation for python\n", + "import numpy as np\n", + "\n", + "# Plotting library\n", + "from matplotlib import pyplot\n", + "\n", + "# Optimization module in scipy\n", + "from scipy import optimize\n", + "\n", + "# library written for this exercise providing additional functions for assignment submission, and others\n", + "import utils\n", + "\n", + "# define the submission/grader object for this exercise\n", + "grader = utils.Grader()\n", + "\n", + "# tells matplotlib to embed plots within the notebook\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Load Data\n", + "# The first two columns contains the X values and the third column\n", + "# contains the label (y).\n", + "data = np.loadtxt('ex2data2.txt', delimiter=',')\n", + "X = data[:, :2]\n", + "y = data[:, 2]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def sigmoid(z):\n", + " \"\"\"\n", + " Compute sigmoid function given the input z.\n", + " \n", + " Parameters\n", + " ----------\n", + " z : array_like\n", + " The input to the sigmoid function. This can be a 1-D vector \n", + " or a 2-D matrix. \n", + " \n", + " Returns\n", + " -------\n", + " g : array_like\n", + " The computed sigmoid function. g has the same shape as z, since\n", + " the sigmoid is computed element-wise on z.\n", + " \n", + " Instructions\n", + " ------------\n", + " Compute the sigmoid of each value of z (z can be a matrix, vector or scalar).\n", + " \"\"\"\n", + " # convert input to a numpy array\n", + " z = np.array(z)\n", + " \n", + " # You need to return the following variables correctly \n", + " g = np.zeros(z.shape)\n", + "\n", + " # ====================== YOUR CODE HERE ======================\n", + " g = 1/(1+np.exp((-z)))\n", + " \n", + " # =============================================================\n", + " return g" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def plotData(X, y):\n", + " \"\"\"\n", + " Plots the data points X and y into a new figure. Plots the data \n", + " points with * for the positive examples and o for the negative examples.\n", + " \n", + " Parameters\n", + " ----------\n", + " X : array_like\n", + " An Mx2 matrix representing the dataset. \n", + " \n", + " y : array_like\n", + " Label values for the dataset. A vector of size (M, ).\n", + " \n", + " Instructions\n", + " ------------\n", + " Plot the positive and negative examples on a 2D plot, using the\n", + " option 'k*' for the positive examples and 'ko' for the negative examples. \n", + " \"\"\"\n", + " # Create New Figure\n", + " fig = pyplot.figure()\n", + "\n", + " # ====================== YOUR CODE HERE ======================\n", + " # Find Indices of Positive and Negative Examples\n", + " pos = y == 1\n", + " neg = y == 0\n", + " \n", + " pyplot.plot(X[neg,0],X[neg,1],'ko',mfc='y', ms=8, mec='k', mew=1)\n", + "\n", + " pyplot.plot(X[pos,0],X[pos,1],'k*',lw=2, ms=10)\n", + "\n", + " \n", + " # ============================================================" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotData(X, y)\n", + "# Labels and Legend\n", + "pyplot.xlabel('Microchip Test 1')\n", + "pyplot.ylabel('Microchip Test 2')\n", + "\n", + "# Specified in plot order\n", + "pyplot.legend(['y = 1', 'y = 0'], loc='upper right')\n", + "pass" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# Note that mapFeature also adds a column of ones for us, so the intercept\n", + "# term is handled\n", + "X = utils.mapFeature(X[:, 0], X[:, 1])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def costFunctionReg(theta, X, y, lambda_):\n", + " \"\"\"\n", + " Compute cost and gradient for logistic regression with regularization.\n", + " \n", + " Parameters\n", + " ----------\n", + " theta : array_like\n", + " Logistic regression parameters. A vector with shape (n, ). n is \n", + " the number of features including any intercept. If we have mapped\n", + " our initial features into polynomial features, then n is the total \n", + " number of polynomial features. \n", + " \n", + " X : array_like\n", + " The data set with shape (m x n). m is the number of examples, and\n", + " n is the number of features (after feature mapping).\n", + " \n", + " y : array_like\n", + " The data labels. A vector with shape (m, ).\n", + " \n", + " lambda_ : float\n", + " The regularization parameter. \n", + " \n", + " Returns\n", + " -------\n", + " J : float\n", + " The computed value for the regularized cost function. \n", + " \n", + " grad : array_like\n", + " A vector of shape (n, ) which is the gradient of the cost\n", + " function with respect to theta, at the current values of theta.\n", + " \n", + " Instructions\n", + " ------------\n", + " Compute the cost `J` of a particular choice of theta.\n", + " Compute the partial derivatives and set `grad` to the partial\n", + " derivatives of the cost w.r.t. each parameter in theta.\n", + " \"\"\"\n", + " # Initialize some useful values\n", + " m = y.size # number of training examples\n", + "\n", + " # You need to return the following variables correctly \n", + " J = 0\n", + " grad = np.zeros(theta.shape)\n", + "\n", + " # ===================== YOUR CODE HERE ======================\n", + " z=theta.dot(X.transpose())\n", + " h=sigmoid(z)\n", + " \n", + " for i in range(m):\n", + " J=J+((-1*(y[i]*math.log(h[i])+(1-y[i])*math.log(1-h[i])))/m)\n", + " \n", + " for i in range(1,theta.shape[0]):\n", + " J=J+(lambda_*theta[i]*theta[i])/(2*m)\n", + " \n", + " \n", + " for i in range(theta.shape[0]):\n", + " grad[i]=(((h-y).dot(X[:,i]))/m) \n", + " \n", + " for i in range(1,theta.shape[0]):\n", + " grad[i]=grad[i]+(lambda_*theta[i])/m\n", + " \n", + " # =============================================================\n", + " return J, grad" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cost at initial theta (zeros): 0.693\n", + "Expected cost (approx) : 0.693\n", + "\n", + "Gradient at initial theta (zeros) - first five values only:\n", + "\t[0.0085, 0.0188, 0.0001, 0.0503, 0.0115]\n", + "Expected gradients (approx) - first five values only:\n", + "\t[0.0085, 0.0188, 0.0001, 0.0503, 0.0115]\n", + "\n", + "------------------------------\n", + "\n", + "Cost at test theta : 3.16\n", + "Expected cost (approx): 3.16\n", + "\n", + "Gradient at initial theta (zeros) - first five values only:\n", + "\t[0.3460, 0.1614, 0.1948, 0.2269, 0.0922]\n", + "Expected gradients (approx) - first five values only:\n", + "\t[0.3460, 0.1614, 0.1948, 0.2269, 0.0922]\n" + ] + } + ], + "source": [ + "# Initialize fitting parameters\n", + "initial_theta = np.zeros(X.shape[1])\n", + "\n", + "# Set regularization parameter lambda to 1\n", + "# DO NOT use `lambda` as a variable name in python\n", + "# because it is a python keyword\n", + "lambda_ = 1\n", + "\n", + "# Compute and display initial cost and gradient for regularized logistic\n", + "# regression\n", + "cost, grad = costFunctionReg(initial_theta, X, y, lambda_)\n", + "\n", + "print('Cost at initial theta (zeros): {:.3f}'.format(cost))\n", + "print('Expected cost (approx) : 0.693\\n')\n", + "\n", + "print('Gradient at initial theta (zeros) - first five values only:')\n", + "print('\\t[{:.4f}, {:.4f}, {:.4f}, {:.4f}, {:.4f}]'.format(*grad[:5]))\n", + "print('Expected gradients (approx) - first five values only:')\n", + "print('\\t[0.0085, 0.0188, 0.0001, 0.0503, 0.0115]\\n')\n", + "\n", + "\n", + "# Compute and display cost and gradient\n", + "# with all-ones theta and lambda = 10\n", + "test_theta = np.ones(X.shape[1])\n", + "cost, grad = costFunctionReg(test_theta, X, y, 10)\n", + "\n", + "print('------------------------------\\n')\n", + "print('Cost at test theta : {:.2f}'.format(cost))\n", + "print('Expected cost (approx): 3.16\\n')\n", + "\n", + "print('Gradient at initial theta (zeros) - first five values only:')\n", + "print('\\t[{:.4f}, {:.4f}, {:.4f}, {:.4f}, {:.4f}]'.format(*grad[:5]))\n", + "print('Expected gradients (approx) - first five values only:')\n", + "print('\\t[0.3460, 0.1614, 0.1948, 0.2269, 0.0922]')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def predict(theta, X):\n", + " \"\"\"\n", + " Predict whether the label is 0 or 1 using learned logistic regression.\n", + " Computes the predictions for X using a threshold at 0.5 \n", + " (i.e., if sigmoid(theta.T*x) >= 0.5, predict 1)\n", + " \n", + " Parameters\n", + " ----------\n", + " theta : array_like\n", + " Parameters for logistic regression. A vector of shape (n+1, ).\n", + " \n", + " X : array_like\n", + " The data to use for computing predictions. The rows is the number \n", + " of points to compute predictions, and columns is the number of\n", + " features.\n", + "\n", + " Returns\n", + " -------\n", + " p : array_like\n", + " Predictions and 0 or 1 for each row in X. \n", + " \n", + " Instructions\n", + " ------------\n", + " Complete the following code to make predictions using your learned \n", + " logistic regression parameters.You should set p to a vector of 0's and 1's \n", + " \"\"\"\n", + " m = X.shape[0] # Number of training examples\n", + "\n", + " # You need to return the following variables correctly\n", + " p = np.zeros(m)\n", + "\n", + " # ====================== YOUR CODE HERE ======================\n", + " for i in range(m):\n", + " if sigmoid(theta.dot(X.transpose()))[i]>=0.5 :\n", + " p[i]=1\n", + " else :\n", + " p[i]=0\n", + "\n", + " \n", + " # ============================================================\n", + " return p" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Train Accuracy: 83.1 %\n", + "Expected accuracy (with lambda = 1): 83.1 % (approx)\n", + "\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "# Initialize fitting parameters\n", + "initial_theta = np.zeros(X.shape[1])\n", + "\n", + "# Set regularization parameter lambda to 1 (you should vary this)\n", + "lambda_ = 1\n", + "\n", + "# set options for optimize.minimize\n", + "options= {'maxiter': 100}\n", + "\n", + "res = optimize.minimize(costFunctionReg,\n", + " initial_theta,\n", + " (X, y, lambda_),\n", + " jac=True,\n", + " method='TNC',\n", + " options=options)\n", + "\n", + "# the fun property of OptimizeResult object returns\n", + "# the value of costFunction at optimized theta\n", + "cost = res.fun\n", + "\n", + "# the optimized theta is in the x property of the result\n", + "theta = res.x\n", + "\n", + "utils.plotDecisionBoundary(plotData, theta, X, y)\n", + "pyplot.xlabel('Microchip Test 1')\n", + "pyplot.ylabel('Microchip Test 2')\n", + "pyplot.legend(['y = 1', 'y = 0'])\n", + "pyplot.grid(False)\n", + "pyplot.title('lambda = %0.2f' % lambda_)\n", + "\n", + "# Compute accuracy on our training set\n", + "p = predict(theta, X)\n", + "\n", + "print('Train Accuracy: %.1f %%' % (np.mean(p == y) * 100))\n", + "print('Expected accuracy (with lambda = 1): 83.1 % (approx)\\n')" + ] + } + ], + "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.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}