{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Machine Learning Exercise 2 - Logistic Regression"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This notebook covers a Python-based solution for the second programming exercise of the machine learning class on Coursera. Please refer to the [exercise text](https://github.com/jdwittenauer/ipython-notebooks/blob/master/exercises/ML/ex2.pdf) for detailed descriptions and equations.\n",
"\n",
"In this exercise we'll implement logistic regression and apply it to a classification task. We'll also improve the robustness of our implementation by adding regularization to the training algorithm. and testing it on a more difficult problem."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Logistic regression"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In the first part of this exercise, we'll build a logistic regression model to predict whether a student gets admitted to a university. Suppose that you are the administrator of a university department and you want to determine each applicant's chance of admission based on their results on two exams. You have historical data from previous applicants that you can use as a training set for logistic regression. For each training example, you have the applicant's scores on two exams and the admissions decision. To accomplish this, we're going to build a classification model that estimates the probability of admission based on the exam scores."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's start by examining the data."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"
\n",
" \n",
" \n",
" | \n",
" Exam 1 | \n",
" Exam 2 | \n",
" Admitted | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 34.623660 | \n",
" 78.024693 | \n",
" 0 | \n",
"
\n",
" \n",
" 1 | \n",
" 30.286711 | \n",
" 43.894998 | \n",
" 0 | \n",
"
\n",
" \n",
" 2 | \n",
" 35.847409 | \n",
" 72.902198 | \n",
" 0 | \n",
"
\n",
" \n",
" 3 | \n",
" 60.182599 | \n",
" 86.308552 | \n",
" 1 | \n",
"
\n",
" \n",
" 4 | \n",
" 79.032736 | \n",
" 75.344376 | \n",
" 1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Exam 1 Exam 2 Admitted\n",
"0 34.623660 78.024693 0\n",
"1 30.286711 43.894998 0\n",
"2 35.847409 72.902198 0\n",
"3 60.182599 86.308552 1\n",
"4 79.032736 75.344376 1"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import os\n",
"path = os.getcwd() + '\\data\\ex2data1.txt'\n",
"data = pd.read_csv(path, header=None, names=['Exam 1', 'Exam 2', 'Admitted'])\n",
"data.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's create a scatter plot of the two scores and use color coding to visualize if the example is positive (admitted) or negative (not admitted)."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": [
"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\n",
"AluSJEnq0f8ButxExp+t9tQAAAAASUVORK5CYII=\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"positive = data[data['Admitted'].isin([1])]\n",
"negative = data[data['Admitted'].isin([0])]\n",
"\n",
"fig, ax = plt.subplots(figsize=(12,8))\n",
"ax.scatter(positive['Exam 1'], positive['Exam 2'], s=50, c='b', marker='o', label='Admitted')\n",
"ax.scatter(negative['Exam 1'], negative['Exam 2'], s=50, c='r', marker='x', label='Not Admitted')\n",
"ax.legend()\n",
"ax.set_xlabel('Exam 1 Score')\n",
"ax.set_ylabel('Exam 2 Score')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It looks like there is a clear decision boundary between the two classes. Now we need to implement logistic regression so we can train a model to predict the outcome. The equations implemented in the following code samples are detailed in \"ex2.pdf\" in the \"exercises\" folder."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First we need to create a sigmoid function. The code for this is pretty simple."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def sigmoid(z):\n",
" return 1 / (1 + np.exp(-z))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's do a quick sanity check to make sure the function is working."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": [
"iVBORw0KGgoAAAANSUhEUgAAAsQAAAHfCAYAAABXrM5GAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n",
"AAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xm0XWWZJ+DfR5gjk4IMAURkEJxpxaEovQpCABlFu3C2\n",
"xHaVrb1Wre7SoqzVBqtbS7uquibLRQNiV7WlCDdAGIRCIKCFMgiIQIgERQmDIggoypDcr//YCVxC\n",
"kntvcs7ZZ3ietc46077nvLAuOz/evPv7Sq01AAAwqjZouwAAAGiTQAwAwEgTiAEAGGkCMQAAI00g\n",
"BgBgpAnEAACMtCkDcSnly6WUn5dSfriWY/6+lHJ7KeUHpZRXdbZEAADonul0iE9PMndNb5ZSDkuy\n",
"R611zyT/KcmXOlQbAAB03ZSBuNb67SS/WsshRyb5vyuOvTrJ1qWU7TtTHgAAdFcnZojnJLlr0vOl\n",
"SXbuwOcCAEDXbdihzymrPH/WftClFHtEAwDQE7XWVfPpGnUiEN+dZJdJz3de8dqz1CoT03/mzZuX\n",
"efPmtV0GrJbfT/rVev1u1po89ljy8MPJI488fT/58XRe+/Wvk1KSjTZqbhtvPLPH6/Izq3s8a1Zz\n",
"22CD7t9KWfvrZUUGLOXZj6f7fAiUGf6zdCIQL0jysSRfL6W8LslDtdafd+BzAYB+9NhjyYMPJtdf\n",
"P70gu7r3Z81Kttoq2XLL5rby8eTXttsuedGLVv/eVlslW2yRbNipv+xmlE35W1RK+VqSNyXZtpRy\n",
"V5JPJ9koSWqtJ9daLyylHFZKWZLk0SQf7GbBAEAPTEwkd92V/OhHyeLFz7y/995k002TK69cc5jd\n",
"ZZc1v7fllskmm7T9TwhPmTIQ11qPn8YxH+tMOdB7Y2NjbZcAa+T3k6771a+eHXoXL06WLEm22SbZ\n",
"e+9kr72a+0MOae532y1j3/lO4veTIVF6NddbSqlmiAGgBY8/ntxxx+q7vb/73TND78r7PfdsRhJg\n",
"AJVSZnRRnUAMAMOg1uTuu58deBcvbl7fddfVB98ddhiqi6kgEYgBYLj95jfJokXPDr2335485zlN\n",
"yF01+O6+e7MaAowIgRgAhs3ERLJwYXLKKcmFFzYBd9XQu9dezYVrgEAMAEPj3nuTr3wlOe20ZPbs\n",
"5MMfTt797uZiN2CNZhqILd4HAP1k2bLkoouSU09Nrrgiecc7kq99LXn1q836QpcIxADQD+68s+kE\n",
"n356s4bvCSck/+//NXPBQFcJxADQlscfTxYsaGaDr78+ec97km9+M3nZy9quDEaKQAwAvbZoUTMS\n",
"8S//krz0pc1s8IIFze5vQM8JxADQC7/9bXLmmU03+I47kg98ILnqqmSPPdquDEaeVSYAoJtuuKEJ\n",
"wWeckbz+9c1s8OGHWxcYusgqEwDQtocfTv71X5uxiAceSD70oeQHP0h23rntyoDV0CEGgE6otRmB\n",
"OOWU5Jxzkre+tZkNPuigZIMN2q4ORoqNOQCgl+6/v7k47tRTmx3lTjghed/7kuc/v+3KYGQZmQCA\n",
"bpuYSC69tAnBF1+cHHVUcvLJyQEH2DwDBpAOMQBM1913NxtnnHZasvXWzUjEu97VPAb6xkw7xIaa\n",
"AGA6vvCFZsOMpUuTs85qNtL46EeFYRgCRiYAYG1qTT796WYN4R/+MJkzp+2KgA4TiAFgTWpN/tt/\n",
"a+aFr7jChXIwpARiAFidiYnkP//nZjTissuS5z637YqALhGIAWBVy5Ylf/iHyZ13Jpdckmy5ZdsV\n",
"AV0kEAPAZE88kbz73ckjjyQXXZRsvnnbFQFdJhADwEqPPZYcd1wya1ayYEGyySZtVwT0gGXXACBJ\n",
"Hn00edvbkuc8p1lWTRiGkSEQA8DDDyeHHJLsumvy1a8mG23UdkVADwnEAIy2Bx5IDjwweeUrm62Y\n",
"Z81quyKgxwRiAEbXffclY2NNIP6Hf0g28McijCL/5QMwmpYuTd70puQd70j+8i+TUtquCGiJVSYA\n",
"GD0//nFy0EHNxhv/9b+2XQ3QMh1iAEbLbbc1neE/+RNhGEiiQwzAKLnppmTu3ORzn0ve//62qwH6\n",
"hEAMwGi45prkiCOai+fe+c62qwH6iEAMwPD79reTt789Oe20JhQDTCIQAzDcLrkkede7kq99rbmQ\n",
"DmAVLqoDYHidd17y7ncnZ58tDANrJBADMJzOOCM54YTkgguSAw5ouxqgjwnEAAyfr3wl+eM/bsYl\n",
"XvOatqsB+pwZYgCGyz/9U7Os2mWXJS9+cdvVAANAIAZgePzVXzWB+Morkxe+sO1qgAEhEAMw+GpN\n",
"PvOZZiWJK69Mdt657YqAASIQAzDYak0++cnkoouSK65Itt++7YqAASMQAzC4JiaSj3+82YXu8suT\n",
"5z2v7YqAASQQAzCYli9vllW7/fbkW99Kttqq7YqAASUQAzB4nnwyec97kgcfTC6+OJk9u+2KgAEm\n",
"EAMwWB57LHnnO5vZ4fPOSzbdtO2KgAFnYw4ABsejjyZHHtmE4PFxYRjoCIEYgMHwyCPJ3LnJjjsm\n",
"//qvycYbt10RMCQEYgD634MPJgcdlLz0pcnppycbmvgDOqfUWnvzRaXUXn0XAEOk1uSAA5LXva7Z\n",
"ia6UtisC+lwpJbXWaZ8sdIgB6G8XXJD85jfJ//pfwjDQFQIxAP2r1mTevOTTn0428EcW0B3OLgD0\n",
"r/PPb9YcPvrotisBhphADEB/0h0GesQZBoD+dP75ybJlusNA1wnEAPSfld3hefN0h4Guc5YBoP+c\n",
"d16yfHly1FFtVwKMAIEYgP5idhjoMWcaAPrLeeclExO6w0DPCMQA9A/dYaAFzjYA9I8FC5pQbGUJ\n",
"oIcEYgD6w+TusC2agR4SiAHoDwsWNPdmh4EeE4gBaJ/uMNAigRiA9p17bnOvOwy0QCAGoF21Jied\n",
"1HSIdYeBFgjEALRrZXf4yCPbrQMYWQIxAO3RHQb6gEAMQHvOPbcJwrrDQIs2bLsAAEbUxETTGf7M\n",
"Z3SHgVbpEAPQjnPPbbZnPuKItisBRpwOMQC9NzHRzA7rDgN9QIcYgN4799xk1izdYaAv6BAD0Fsr\n",
"Z4f/x//QHQb6gg4xAL11zjnJhhsmb3tb25UAJNEhBqCXVs4O6w4DfUSHGIDe0R0G+pAOMQC9oTsM\n",
"9CkdYgB64+yzk4020h0G+o4OMQDdt7I7/NnP6g4DfUeHGIDuO/vsZOONk8MPb7sSgGeZMhCXUuaW\n",
"Um4rpdxeSvnkat7ftpRyUSnlxlLKzaWUD3SlUgAG08ru8Lx5usNAX1prIC6lzEryj0nmJtk3yfGl\n",
"lH1WOexjSW6otb4yyViSvy6lGMUAoDF/frLJJrrDQN+aqkO8f5IltdY7a61PJvl6kqNWOebeJFuu\n",
"eLxlkgdqrcs6WyYAA0l3GBgAU3Vy5yS5a9LzpUleu8oxpyS5rJRyT5Itkryzc+UBMNDmz0823TQ5\n",
"7LC2KwFYo6k6xHUan/FnSW6ste6U5JVJvlhK2WK9KwNgsOkOAwNiqg7x3Ul2mfR8lzRd4snekOR/\n",
"Jkmt9Y5Syk+S7J3kulU/bN68eU89Hhsby9jY2IwLBmBAzJ+fbLaZ7jDQdQsXLszChQvX+edLrWtu\n",
"Aq+4OG5xkgOT3JPkmiTH11oXTTrmb5I8XGs9qZSyfZLvJ3l5rfXBVT6rru27ABgiExPJK16RfP7z\n",
"AjHQc6WU1Fqn/VdTa+0Q11qXlVI+luTiJLOSnFZrXVRK+ciK909O8tkkp5dSfpBmBOMTq4ZhAEbM\n",
"+HjTHT700LYrAZjSWjvEHf0iHWKA0TAxkbz85ckXvqA7DLRiph1iO9UB0Fnj48nmm+sOAwPDBhoA\n",
"dM7KlSW+8AUrSwADQ4cYgM4566xk9mzdYWCgmCEGoDMmJpKXvSz5q78SiIFWmSEGoB1nnZU85znJ\n",
"3LltVwIwIzrEAKw/3WGgj+gQA9B7Z56ZbLGF7jAwkHSIAVg/y5c36w7/9V8LxEBf0CEGoLfOOqvp\n",
"Dh9ySNuVAKwTHWIA1p3uMNCHdIgB6J2Vs8O6w8AA0yEGYN0sX96sLPG//7dADPQVHWIAeuPMM5Ot\n",
"tkoOPrjtSgDWiw4xADOnOwz0MR1iALpPdxgYIjrEAMzM8uXJS1+a/O3f6g4DfUmHGIDu+sY3km22\n",
"0R0GhoYOMQDTt7I7/Hd/JxADfUuHGIDuWdkdfutb264EoGN0iAGYHt1hYEDoEAPQHWeckTz3ubrD\n",
"wNDRIQZgasuXJy95SfIP/yAQA31PhxiAzjvjjOR5z0sOOqjtSgA6TocYgLXTHQYGjA4xAJ319a/r\n",
"DgNDTYcYgDVbvjzZd9/ki18UiIGBoUMMQOecf36z7vCBB7ZdCUDXCMQArNmZZybvfW9Spt1oARg4\n",
"RiYAWL3HH0922CG55ZZkp53argZg2oxMANAZl17azA8Lw8CQE4gBWL3x8eTtb2+7CoCuMzIBwLMt\n",
"W5bsuGNy3XXJC17QdjUAM2JkAoD1d8UVyW67CcPASBCIAXg24xLACDEyAcAzTUwkc+YkV16Z7Lln\n",
"29UAzJiRCQDWz1VXJdttJwwDI0MgBuCZjEsAI2bDtgsAoI/U2gTiCy9suxKAntEhBuBp116bbLZZ\n",
"8pKXtF0JQM8IxAA8beW4RJn2tSgAA08gBqCxclzC/DAwYgRiABo33ZQsX57st1/blQD0lEAMQMO4\n",
"BDCiBGIAGsYlgBElEAOQ3HZb8tBDyWtf23YlAD0nEAPQdIePPTbZwB8LwOhx5gPAuAQw0gRigFH3\n",
"4x8nS5cmv//7bVcC0AqBGGDUjY8nRx+dzJrVdiUArRCIAUadcQlgxJVaa2++qJTaq+8CYJqWLk1e\n",
"/vLkvvuSjTduuxqAjiilpNY67UXVdYgBRtn8+ckRRwjDwEgTiAFG2fh4ctxxbVcB0CojEwCj6uc/\n",
"T/beuxmX2HTTtqsB6BgjEwBMzznnJIceKgwDI08gBhhVVpcASGJkAmA0PfBAsvvuyT33JLNnt10N\n",
"QEcZmQBgagsWJAceKAwDRCAGGE3GJQCeYmQCYNQ88kiy887JXXclW23VdjUAHWdkAoC1O//85Pd/\n",
"XxgGWEEgBhg1xiUAnsHIBMAoefTRZKedkh//OHne89quBqArjEwAsGYXXZTsv78wDDCJQAwwSoxL\n",
"ADyLkQmAUfH448kOOySLFjX3AEPKyAQAq3fJJcnLXiYMA6xCIAYYFcYlAFbLyATAKHjyyaYzfOON\n",
"yS67tF0NQFcZmQDg2S6/PNljD2EYYDUEYoBRYFwCYI2MTAAMu+XLm804rroqedGL2q4GoOuMTADw\n",
"TN/5TrLjjsIwwBoIxADDbnw8Oe64tqsA6FtGJgCG2cREsuuuzRrE++zTdjUAPWFkAoCnXXNNsuWW\n",
"wjDAWgjEAMPM6hIAU9qw7QIA6JJam0A8f37blQD0NR1igGF1ww1JKckrXtF2JQB9TSAGGFYrxyXK\n",
"tK8rARhJAjHAMFo5LmF+GGBKUwbiUsrcUsptpZTbSymfXMMxY6WUG0opN5dSFna8SgBm5tZbk0cf\n",
"TV7zmrYrAeh7a72orpQyK8k/Jjkoyd1Jri2lLKi1Lpp0zNZJvpjkkFrr0lLKtt0sGIBpGB9Pjj02\n",
"2cBfBAJMZaoz5f5JltRa76y1Ppnk60mOWuWYdyUZr7UuTZJa6y87XyYAM2J3OoBpmyoQz0ly16Tn\n",
"S1e8NtmeSZ5bSrm8lHJdKeW9nSwQgBlasiT5+c+TN7yh7UoABsJU6xBPZ6/ljZLsl+TAJJsn+W4p\n",
"5Xu11ttXPXDevHlPPR4bG8vY2Ni0CwVgmsbHk2OOSWbNarsSgJ5YuHBhFi5cuM4/X2pdc+Ytpbwu\n",
"ybxa69wVz09MMlFr/fykYz6ZZLNa67wVz09NclGt9axVPquu7bsA6JD9908++9nkoIPargSgFaWU\n",
"1FqnvebkVCMT1yXZs5SyWyll4yT/McmCVY45N8kBpZRZpZTNk7w2ya0zKRqADvnpT5Mf/zh505va\n",
"rgRgYKx1ZKLWuqyU8rEkFyeZleS0WuuiUspHVrx/cq31tlLKRUluSjKR5JRaq0AM0Ib585Mjj0w2\n",
"2qjtSgAGxlpHJjr6RUYmALrvgAOSE09MDj+87UoAWjPTkQmBGGBY3Htvsu++yX33JZts0nY1AK3p\n",
"9AwxAIPi7LOTww4ThgFmSCAGGBbj48nb3952FQADx8gEwDD45S+TF72oGZvYfPO2qwFolZEJgFF0\n",
"7rnJwQcLwwDrQCAGGAbGJQDWmZEJgEH30EPJrrsmd9+dbLFF29UAtM7IBMCoOf/8ZGxMGAZYRwIx\n",
"wKAzLgGwXoxMAAyy3/wm2Wmn5Kc/TbbZpu1qAPqCkQmAUXLhhcnrXy8MA6wHgRhgkBmXAFhvRiYA\n",
"BtXvfpfssENy++3J85/fdjUAfcPIBMCo+Ld/S171KmEYYD0JxACDanw8Oe64tqsAGHhGJgAG0RNP\n",
"NOMSP/xhMmdO29UA9BUjEwCj4LLLkhe/WBgG6ACBGGAQWV0CoGOMTAAMmmXLkh13TK65JnnhC9uu\n",
"BqDvGJkAGHZXXpnsuqswDNAhAjHAoDEuAdBRRiYABsnERLLzzsnllyd77912NQB9ycgEwDD77neT\n",
"5z5XGAboIIEYYJAYlwDouA3bLgCAaao1mT8/Oe+8tisBGCo6xACD4vvfTzbeOHnpS9uuBGCoCMQA\n",
"g2LluESZ9nUiAEyDQAwwCGo1PwzQJQIxwCC4+ebkiSeS//Af2q4EYOgIxACD4KyzkmOPNS4B0AUC\n",
"McAgMC4B0DUCMUC/W7w4efDB5PWvb7sSgKEkEAP0u/Hx5Jhjkg2csgG6wdkVoN8ZlwDoqlJr7c0X\n",
"lVJ79V0AQ+MnP0n23z+5995kQ5uLAkxHKSW11mlfhaxDDNDP5s9Pjj5aGAboIoEYoJ8ZlwDoOiMT\n",
"AP3q7ruTl70sue++ZOON264GYGAYmQAYFmefnbztbcIwQJcJxAD9yrgEQE8YmQDoR7/4RbLnns24\n",
"xGabtV0NwEAxMgEwDM45J5k7VxgG6AGBGKAfGZcA6BkjEwD95le/Sl7wguSee5LnPKftagAGjpEJ\n",
"gEG3YEHylrcIwwA9IhAD9Jvx8eS449quAmBkGJkA6Ce//nUyZ07ys58lW2/ddjUAA8nIBMAgu+CC\n",
"5IADhGGAHhKIAfqJ1SUAes7IBEC/+O1vkx13TO64I9l227arARhYRiYABtVFFyWvfrUwDNBjAjFA\n",
"vzAuAdAKIxMA/eDxx5MddkhuvbUZmwBgnRmZABhE3/pW8pKXCMMALRCIAfqBcQmA1hiZAGjbk082\n",
"neHrr0923bXtagAGnpEJgEFzxRXJ7rsLwwAtEYgB2mZcAqBVRiYA2rR8eTJnTvKd7yR77NF2NQBD\n",
"wcgEwCC56qpk++2FYYAWCcQAbTrrLOMSAC3bsO0CAEbWxEQyf36zZTMArdEhBmjLtdcms2cn++7b\n",
"diUAI00gBmjLytUlyrSv+wCgCwRigDbUark1gD4hEAO04Qc/aGaIX/WqtisBGHkCMUAbxseT444z\n",
"LgHQBwRigDYYlwDoGwIxQK8tWpQ88kiy//5tVwJABGKA3hsfT449NtnAKRigHzgbA/SacQmAviIQ\n",
"A/TSHXck99yTHHBA25UAsIJADNBL4+PJ0Ucns2a1XQkAKwjEAL1kXAKg75Raa2++qJTaq+8C6Et3\n",
"3ZW88pXJffclG23UdjUAQ6uUklrrtBd61yEG6JX585MjjhCGAfqMQAzQKyt3pwOgrxiZAOiF++5L\n",
"9tmnud9kk7arARhqRiYA+tE55ySHHioMA/QhgRigF6wuAdC3pgzEpZS5pZTbSim3l1I+uZbjXlNK\n",
"WVZKObazJQIMuAceSK65Jpk7t+1KAFiNtQbiUsqsJP+YZG6SfZMcX0rZZw3HfT7JRUmmPa8BMBLO\n",
"PTc56KBk9uy2KwFgNabqEO+fZEmt9c5a65NJvp7kqNUc9/EkZyW5v8P1AQw+4xIAfW2qQDwnyV2T\n",
"ni9d8dpTSilz0oTkL614yVISACs9/HDy7W8nb3tb25UAsAYbTvH+dMLt3yb501prLaWUrGVkYt68\n",
"eU89Hhsby9jY2DQ+HmCAnX9+8sY3Jltu2XYlAENr4cKFWbhw4Tr//FrXIS6lvC7JvFrr3BXPT0wy\n",
"UWv9/KRjfpynQ/C2SX6b5MO11gWrfJZ1iIHRc+yxze50H/xg25UAjIyZrkM8VSDeMMniJAcmuSfJ\n",
"NUmOr7UuWsPxpyc5r9Y6fzXvCcTAaHn00WSnnZKf/CR57nPbrgZgZMw0EK91ZKLWuqyU8rEkFyeZ\n",
"leS0WuuiUspHVrx/8npVCzDMvvnN5LWvFYYB+pytmwG65fjjk7Gx5CMfabsSgJHS0ZGJThKIgZHy\n",
"2GPJDjskixcn22/fdjUAI2WmgdjWzQDdcMklySteIQwDDACBGKAbbMYBMDCMTAB02hNPNOMSN92U\n",
"7Lxz29UAjBwjEwBtu/zyZK+9hGGAASEQA3SacQmAgWJkAqCTli9Pdtwx+d73kt13b7sagJFkZAKg\n",
"Td/+djJnjjAMMEAEYoBOGh9Pjjuu7SoAmAEjEwCdMjGR7LJLcumlyYtf3HY1ACPLyARAW66+Otl6\n",
"a2EYYMAIxACdYnUJgIG0YdsFAAyFWptAfM45bVcCwAzpEAN0wvXXJ7NmJS9/eduVADBDAjFAJ6wc\n",
"lyjTvoYDgD4hEAOsr5XjEuaHAQaSQAywvm65Jfnd75LXvKbtSgBYBwIxwPoaH0+OPda4BMCAEogB\n",
"1pfd6QAGmkAMsD5uvz25//7kDW9ouxIA1pFADLA+xseTY45JNnA6BRhUzuAA68PqEgADr9Rae/NF\n",
"pdRefRdAT/z0p8mrX53ce2+yoY0/AfpFKSW11mlf6axDDLCuxseTI48UhgEGnEAMsK6MSwAMBSMT\n",
"AOvinnuSl7wkue++ZJNN2q4GgEmMTAD0wtlnJ4cfLgwDDAGBGGBdGJcAGBpGJgBm6v77kz32aMYl\n",
"Ntus7WoAWIWRCYBuO/fc5JBDhGGAISEQA8yUcQmAoWJkAmAmHnoo2XXX5O67ky22aLsaAFbDyARA\n",
"N513XvLmNwvDAENEIAaYCeMSAEPHyATAdP3618mcOclPf5pss03b1QCwBkYmALrlwguTN7xBGAYY\n",
"MgIxwHQZlwAYSkYmAKbjd79LdtghWbIk2W67tqsBYC2MTAB0w8UXJ/vtJwwDDCGBGGA6xseT445r\n",
"uwoAusDIBMBUnniiGZe4+eZkp53argaAKRiZAOi0Sy9N9tlHGAYYUgIxwFSsLgEw1IxMAKzNsmXJ\n",
"jjsm116b7LZb29UAMA1GJgA66Yorkhe8QBgGGGICMcDaGJcAGHpGJgDWZGIimTOn6RLvtVfb1QAw\n",
"TUYmADrlqquSbbcVhgGGnEAMsCbGJQBGwoZtFwDQl2pN5s9PLrig7UoA6DIdYoDVue66ZNNNk5e8\n",
"pO1KAOgygRhgdVaOS5RpX5MBwIASiAFWVav5YYARIhADrOr665Mnn0z226/tSgDoAYEYYFWf+1zy\n",
"8Y8blwAYETbmAJjsppuSgw9O7rgjmT277WoAWAc25gBYH5/5TPInfyIMA4wQHWKAlXSHAYaCDjHA\n",
"ujrpJN1hgBGkQwyQJD/4QTJ3btMd3nzztqsBYD3oEAOsi5Wzw8IwwMjRIQbQHQYYKjrEADO1cnZY\n",
"GAYYSTrEwGi78cbk0EN1hwGGiA4xwEx85jPJJz4hDAOMMB1iYHTpDgMMJR1igOnSHQYgOsTAqLrx\n",
"xuSww5IlSwRigCGjQwwwHSedpDsMQBIdYmAU3XBDcvjhzezwZpu1XQ0AHaZDDDCVlbPDwjAA0SEG\n",
"Ro3uMMDQ0yEGWJuTTko++UlhGICn6BADo0N3GGAk6BADrInuMACroUMMjAbdYYCRoUMMsDrz5ukO\n",
"A7BaOsTA8Lv++uSII5pd6QRigKGnQwywKrPDAKyFDjEw3HSHAUZOVzrEpZS5pZTbSim3l1I+uZr3\n",
"311K+UEp5aZSyr+XUl4+k6IBukZ3GIApTNkhLqXMSrI4yUFJ7k5ybZLja62LJh3z+iS31lofLqXM\n",
"TTKv1vq6VT5Hhxjore9/PznyyGZliU03bbsaAHqkGx3i/ZMsqbXeWWt9MsnXkxw1+YBa63drrQ+v\n",
"eHp1kp2nWwBA15x0UvKnfyoMA7BWG07jmDlJ7pr0fGmS167l+A8luXB9igJYb9//fnP7xjfargSA\n",
"PjedQDztOYdSypuT/GGS31vnigA6QXcYgGmaTiC+O8kuk57vkqZL/AwrLqQ7JcncWuuvVvdB8+bN\n",
"e+rx2NhYxsbGZlAqwDRdd12zuoTuMMBIWLhwYRYuXLjOPz+di+o2THNR3YFJ7klyTZ59Ud2uSS5L\n",
"8p5a6/fW8DkuqgN644gjkkMOST72sbYrAaAFM72obsoOca11WSnlY0kuTjIryWm11kWllI+seP/k\n",
"JP89yTZJvlRKSZIna637r8s/AMB6ue665IYbkjPPbLsSAAaEjTmA4aI7DDDyZtohFoiB4XHddcnR\n",
"Rze70rmYDmBkdWWnOoCBMG9ecuKJwjAAMzKdVSYA+t+11yY33picdVbblQAwYHSIgeFw0km6wwCs\n",
"Ex1iYPDpDgOwHnSIgcFndhiA9aBDDAy2a65JbropmT+/7UoAGFA6xMBgWzk7vMkmbVcCwIDSIQYG\n",
"l+4wAB2gQwwMLt1hADpAhxgYTFdfnfzwh7rDAKw3HWJgMOkOA9AhOsTA4FnZHT777LYrAWAI6BAD\n",
"g+ekk5I/+zPdYQA6QocYGCxXX53cfLPuMAAdo0MMDJZ583SHAegoHWJgcHzve8kttyTnnNN2JQAM\n",
"ER1iYHCYHQagC3SIgcHwve8lt96qOwxAx+kQA4PB7DAAXaJDDPS/7343WbQoWbCg7UoAGEI6xED/\n",
"Wzk7vPHGbVcCwBDSIQb6m+4wAF2mQwz0t5NOSj71Kd1hALpGIAb618ru8Ac+0HYlAAwxgRjoX/Pm\n",
"6Q4D0HUCMdCfrroque023WEAuk4gBvqT2WEAekQgBvrPVVclixfrDgPQEwIx0H/MDgPQQwIx0F/+\n",
"/d+TH/0oef/7264EgBEhEAP941e/Sj7+8eTP/1x3GICeEYiB/nD//clb3pK86U3Jhz7UdjUAjBCB\n",
"GGjfPfcWGizxAAAJvUlEQVQ0Qfhtb0v+5m+SUtquCIARIhAD7frpT5M3vjF573uTv/gLYRiAnhOI\n",
"gfbcfnsThv/Lf0lOPLHtagAYURu2XQAwom65JTn44GYDjhNOaLsaAEaYQAz03vXXJ4cd1swLv+td\n",
"bVcDwIgTiIHe+u53k6OOSk4+OTnmmLarAQCBGOihyy9P3vnO5J//OTn00LarAYAkAjHQK9/8ZvK+\n",
"9yVnnpmMjbVdDQA8xSoTQPfNn99sxbxggTAMQN8RiIHu+upXk49+NLnoouT1r2+7GgB4FoEY6J5T\n",
"Tkk+8Ynk0kuT/fZruxoAWC0zxEB3/N3fNcuqLVyY7Lln29UAwBoJxEDnffazyZe/nFx5ZfKCF7Rd\n",
"DQCslUAMdE6tyZ//eXL22U0Y3mmntisCgCkJxEBn1Jr88R8nV1zR3Lbbru2KAGBaBGJg/S1fnvzR\n",
"HyU33ZRcdlmyzTZtVwQA0yYQA+tn2bLkAx9Ili5NLrkk2WKLtisCgBkRiIF198QTyfHHJ48+mlx4\n",
"YbL55m1XBAAzZh1iYN387nfJ0UcnExPJuecKwwAMLIEYmLnf/CY5/PBk662Tb3wj2WSTtisCgHUm\n",
"EAMz89BDycEHJ7vvnvzLvyQbbdR2RQCwXgRiYPp++cvkLW9JXv3q5P/8n2TWrLYrAoD1JhAD03Pv\n",
"vcnYWHLIIc22zBs4fQAwHPyJBkztZz9L3vjGZkWJz30uKaXtigCgYwRiYO2WLGnC8Ec/mnzqU21X\n",
"AwAdJxADa3brrc2YxIknNtsyA8AQsjEHsHo33pgcemjyhS8k731v29UAQNcIxMCzXX11cuSRyRe/\n",
"mBx3XNvVAEBXCcTAM11xRfKOdySnn95svgEAQ04gBp528cXJe96TfP3ryYEHtl0NAPSEQAyjrtbk\n",
"+99PTj01mT8/Oeec5Pd+r+2qAKBnrDIBo+qhh5oZ4f32a0YkdtmluZBOGAZgxJRaa2++qJTaq+8C\n",
"1qDW5DvfSU45JVmwoNl17sMfbrZjtvMcAEOilJJa67R3kRKIYRT84hfJP/9zMxaxwQbJCSc0S6lt\n",
"t13blQFAx800EJshhmE1MZFcckkTgi+5JDnmmOS005I3vMHWywAwiQ4xDJulS5Mvf7m5Pe95zUjE\n",
"8ccnW23VdmUA0BM6xDCKnnwyueCCZjb4u99N/uAPmhUj9tuv7coAoO8JxDDIlixpxiC+8pVkjz2a\n",
"2eAzz0w237ztygBgYAjEMGgee6zp/p56anLzzcn73pdcdlmyzz5tVwYAA0kghkFx883NSMRXv9qM\n",
"QvzRHyVHHplssknblQHAQBOIoZ/95jfJGWc0QXjp0uSDH0yuvTZ54QvbrgwAhoZVJqDf1NqE3lNP\n",
"beaB3/SmZjZ47txkQ/8PCwBTscoEDKoHH2zGIU49tekMn3BCcsstyU47tV0ZAAw1HWLotVqT++9P\n",
"Fi9OfvSj5n7RouTb304OPbQJwm9+s62UAWAd2boZ+sVvf5vcfvvToXfyfSnJ3ns3t732am5jY8m2\n",
"27ZdNQAMPIEYemn58uRnP3t24F28OPnFL5IXvejp0Dv5/nnPs30yAHSJQAzd8MADzwy7Kx/fcUfT\n",
"1V1d6H3BC5JZs9quHABGjkAM6+qxx5qd31bX7V22bPWhd889k9mz264cAJik44G4lDI3yd8mmZXk\n",
"1Frr51dzzN8nOTTJb5N8oNZ6w2qOEYjpjccfTx55JHn44eZ+8uPVvLZw8eKMPfBAcu+9yW67PTv0\n",
"7r138vznG3GgFQsXLszY2FjbZcCz+N2kn3V02bVSyqwk/5jkoCR3J7m2lLKg1rpo0jGHJdmj1rpn\n",
"KeW1Sb6U5HXrVD2jbdmyZwfYKcLsal9bvjzZaqtkyy2fvl/d4112SbbaKguTjM2b14ThjTZq998B\n",
"rELooF/53WSYTLUO8f5JltRa70ySUsrXkxyVZNGkY45M8n+TpNZ6dSll61LK9rXWn3ehXlZVazIx\n",
"8fT9dG/LlydPPvn07YknnnnfqcdTvf/oo0+H2cceezqwTg6wqwbZ7bdffdBdeb/ppjPr5i5Z0ow+\n",
"AAAjaapAPCfJXZOeL03y2mkcs3OSZwfiQw5p7lcdnVjb85kcO52fXfnaysdtPF81vM40zE6+JU34\n",
"22CDmd822qi5bbzx2h9P9f5GGyWbbTb9z5v8ePbsp8Ps7NnGEgCAnlvrDHEp5e1J5tZaP7zi+XuS\n",
"vLbW+vFJx5yX5C9rrf++4vm3knyi1nr9Kp9lgBgAgJ7o5NbNdyfZZdLzXdJ0gNd2zM4rXlvnogAA\n",
"oFem2hv2uiR7llJ2K6VsnOQ/JlmwyjELkrwvSUopr0vykPlhAAAGxVo7xLXWZaWUjyW5OM2ya6fV\n",
"WheVUj6y4v2Ta60XllIOK6UsSfJokg92vWoAAOiQnm3MAQAA/WiqkYn1Ukp5RynlllLK8lLKfqu8\n",
"d2Ip5fZSym2llIO7WQdMpZQyr5SytJRyw4rb3LZrYrSVUuauOD/eXkr5ZNv1wGSllDtLKTetOF9e\n",
"03Y9jK5SypdLKT8vpfxw0mvPLaVcUkr5USnl30opW0/1OV0NxEl+mOSYJFdOfrGUsm+aeeR9k8xN\n",
"8k+llG7XAmtTk/xNrfVVK24XtV0Qo2vSpkhz05wnjy+l7NNuVfAMNcnYivPl/m0Xw0g7Pc25crI/\n",
"TXJJrXWvJJeueL5WXQ2htdbbaq0/Ws1bRyX5Wq31yRWbfixJswkItMlKKPSLpzZFqrU+mWTlpkjQ\n",
"T5wzaV2t9dtJfrXKy09tGrfi/uipPqetruxOeebybUvTbPABbfp4KeUHpZTTpvPXK9BFq9vwyDmS\n",
"flKTfKuUcl0p5cNtFwOrmLxj8s+TbD/VD0y1DvGUSimXJNlhNW/9Wa31vBl8lKv76Kq1/K5+KsmX\n",
"knxmxfO/SPLXST7Uo9JgVc6H9Lvfq7XeW0rZLsklpZTbVnTqoK/UWut0Nodb70Bca33rOvzYtDbz\n",
"gE6a7u9qKeXUJDP5nznotOlsigStqbXeu+L+/lLK2WnGfARi+sXPSyk71FrvK6XsmOQXU/1AL0cm\n",
"Js8aLUjyB6WUjUspL0yyZxJXqdKaFf/BrHRMmgtCoS3T2RQJWlFK2byUssWKx7OTHBznTPrLgiTv\n",
"X/H4/UnOmeoH1rtDvDallGOS/H2SbZNcUEq5odZ6aK311lLKN5LcmmRZko9WCyLTrs+XUl6Z5q+q\n",
"f5LkIy3Xwwhb06ZILZcFK22f5OxSStLkiK/WWv+t3ZIYVaWUryV5U5JtSyl3JfnvSf4yyTdKKR9K\n",
"cmeSd075OXIoAACjzNq/AACMNIEYAICRJhADADDSBGIAAEaaQAwAwEgTiAEAGGkCMQAAI+3/AzmO\n",
"nhJtkQmYAAAAAElFTkSuQmCC\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"nums = np.arange(-10, 10, step=1)\n",
"\n",
"fig, ax = plt.subplots(figsize=(12,8))\n",
"ax.plot(nums, sigmoid(nums), 'r')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Excellent! Now we need to write the cost function to evaluate a solution."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def cost(theta, X, y):\n",
" theta = np.matrix(theta)\n",
" X = np.matrix(X)\n",
" y = np.matrix(y)\n",
" first = np.multiply(-y, np.log(sigmoid(X * theta.T)))\n",
" second = np.multiply((1 - y), np.log(1 - sigmoid(X * theta.T)))\n",
" return np.sum(first - second) / (len(X))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we need to do some setup, similar to what we did in exercise 1 for linear regression."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# add a ones column - this makes the matrix multiplication work out easier\n",
"data.insert(0, 'Ones', 1)\n",
"\n",
"# set X (training data) and y (target variable)\n",
"cols = data.shape[1]\n",
"X = data.iloc[:,0:cols-1]\n",
"y = data.iloc[:,cols-1:cols]\n",
"\n",
"# convert to numpy arrays and initalize the parameter array theta\n",
"X = np.array(X.values)\n",
"y = np.array(y.values)\n",
"theta = np.zeros(3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's quickly check the shape of our arrays to make sure everything looks good."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"((100L, 3L), (3L,), (100L, 1L))"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X.shape, theta.shape, y.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's compute the cost for our initial solution (0 values for theta)."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.69314718055994529"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cost(theta, X, y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Looks good. Next we need a function to compute the gradient (parameter updates) given our training data, labels, and some parameters theta."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def gradient(theta, X, y):\n",
" theta = np.matrix(theta)\n",
" X = np.matrix(X)\n",
" y = np.matrix(y)\n",
" \n",
" parameters = int(theta.ravel().shape[1])\n",
" grad = np.zeros(parameters)\n",
" \n",
" error = sigmoid(X * theta.T) - y\n",
" \n",
" for i in range(parameters):\n",
" term = np.multiply(error, X[:,i])\n",
" grad[i] = np.sum(term) / len(X)\n",
" \n",
" return grad"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that we don't actually perform gradient descent in this function - we just compute a single gradient step. In the exercise, an Octave function called \"fminunc\" is used to optimize the parameters given functions to compute the cost and the gradients. Since we're using Python, we can use SciPy's \"optimize\" namespace to do the same thing."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's look at a single call to the gradient method using our data and initial paramter values of 0."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"array([ -0.1 , -12.00921659, -11.26284221])"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gradient(theta, X, y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can use SciPy's truncated newton (TNC) implementation to find the optimal parameters."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(array([-25.87355624, 0.21193682, 0.20722586]), 51, 1)"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import scipy.optimize as opt\n",
"result = opt.fmin_tnc(func=cost, x0=theta, fprime=gradient, args=(X, y))\n",
"result"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's see what the our cost looks like with this solution."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.20357134412164668"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cost(result[0], X, y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next we need to write a function that will output predictions for a dataset X using our learned parameters theta. We can then use this function to score the training accuracy of our classifier."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def predict(theta, X):\n",
" probability = sigmoid(X * theta.T)\n",
" return [1 if x >= 0.5 else 0 for x in probability]"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"accuracy = 89%\n"
]
}
],
"source": [
"theta_min = np.matrix(result[0])\n",
"predictions = predict(theta_min, X)\n",
"correct = [1 if ((a == 1 and b == 1) or (a == 0 and b == 0)) else 0 for (a, b) in zip(predictions, y)]\n",
"accuracy = (sum(map(int, correct)) % len(correct))\n",
"print 'accuracy = {0}%'.format(accuracy)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Our logistic regression classifer correctly predicted if a student was admitted or not 89% of the time. Not bad! Keep in mind that this is training set accuracy though. We didn't keep a hold-out set or use cross-validation to get a true approximation of the accuracy so this number is likely higher than its true perfomance (this topic is covered in a later exercise)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Regularized logistic regression"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In the second part of this exercise, we'll improve our logistic regression algorithm from part one by adding a regularization term. If you're not familiar with regularization, or would like some background on the equations used in this section, refer to \"ex2.pdf\" in the \"exercises\" folder. In a nutshell, regularization is a term in the cost function that causes the algorithm to prefer \"simpler\" models (in this case, models will smaller coefficients). The theory is that this helps to minimize overfitting and improve the model's ability to generalize. With that, let's get started."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Suppose you are the product manager of the factory and you have the test results for some microchips on two different tests. From these two tests, you would like to determine whether the microchips should be accepted or rejected. To help you make the decision, you have a dataset of test results on past microchips, from which you can build a logistic regression model."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Similar to part 1, let's start by visualizing the data."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Test 1 | \n",
" Test 2 | \n",
" Accepted | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 0.051267 | \n",
" 0.69956 | \n",
" 1 | \n",
"
\n",
" \n",
" 1 | \n",
" -0.092742 | \n",
" 0.68494 | \n",
" 1 | \n",
"
\n",
" \n",
" 2 | \n",
" -0.213710 | \n",
" 0.69225 | \n",
" 1 | \n",
"
\n",
" \n",
" 3 | \n",
" -0.375000 | \n",
" 0.50219 | \n",
" 1 | \n",
"
\n",
" \n",
" 4 | \n",
" -0.513250 | \n",
" 0.46564 | \n",
" 1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Test 1 Test 2 Accepted\n",
"0 0.051267 0.69956 1\n",
"1 -0.092742 0.68494 1\n",
"2 -0.213710 0.69225 1\n",
"3 -0.375000 0.50219 1\n",
"4 -0.513250 0.46564 1"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"path = os.getcwd() + '\\data\\ex2data2.txt'\n",
"data2 = pd.read_csv(path, header=None, names=['Test 1', 'Test 2', 'Accepted'])\n",
"data2.head()"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": [
"iVBORw0KGgoAAAANSUhEUgAAAtwAAAHuCAYAAACs89tSAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n",
"AAALEgAACxIB0t1+/AAAIABJREFUeJzs3Xt4W9Wd7//PsoIJcUIICZcACZdMaYdOae1yuNa2NE5D\n",
"LoShhbRwfiTMnJaSmVN6IW7pzRMH95RecNppZ4ZAL3PI0KdApoWGkpBQ29umnR+kRIYyLZSmlISE\n",
"W2lTk3FwnMjr/CHJkWU5lmRt7Yver+fRE1l7W1pb2pG+XvqstYy1VgAAAADcUeV1AwAAAIAwo+AG\n",
"AAAAXETBDQAAALiIghsAAABwEQU3AAAA4CIKbgAAAMBFnhbcxpjvGWNeNcY8Pcb2qDGmzxjTm7p8\n",
"odxtBAAAACZikseP/2+SviVp/RH26bbWXl6m9gAAAAAl5WkPt7X2UUl7x9nNlKMtAAAAgBv8nuG2\n",
"ki42xjxljNlkjDnH6wYBAAAAhfA6UjKeuKQ51tr9xphFkh6QdHb2TsYY1qcHAACA66y1BacvfF1w\n",
"W2v3ZVzfbIz5V2PM8dbaP+XYt7yNg++1traqtbXV62bAZzgvkI1zArlwXiAXY4pLOvs6UmKMOcmk\n",
"jswYc74kk6vYBgAAAPzK0x5uY8wPJDVKmmWMeVHSaklHSZK19g5JV0n6e2PMIUn7JV3tVVsBAACA\n",
"YnhacFtrrxln+79I+pcyNQchE41GvW4CfIjzAtk4J5AL5wVKyYQh+2yMsWE4DgAAAPiXMSZ8gyYB\n",
"AAAqTbED81BapezMpeAGAADwGb6591ap/+jx9SwlAAAAQNBRcAMAAAAuouAGAAAAXETBDQAAALiI\n",
"ghsAACAkrLUaHBz0uhmB0NraquXLl5flsSi4AQAAAu6///u/9bGPfUrTpp2gyZOn6LTT3qbbb7/D\n",
"tdlOotGojj/+eE+L+zPOOEOdnZ1F/345p1+k4AYAAPC5p59+WkuWfEBHHz1VkycfqyuvXK7nnntO\n",
"knTw4EE1NCzSnXe+rP7+bbL2oPbs+a6am+/Qpz/9heH7sNbqscce09q1a/W9731Pe/fuLaotL7zw\n",
"grZt26YTTzxRGzduLMnxFSO1CI1nj18ICm4AAAAf6+3t1UUXNWnz5os1OLhTBw7s0AMPnKP/8T8a\n",
"9Jvf/EYPPPCAfvvbIR04sF7SWZKMpEu0f/8W/fM//6teeeUV/fnPf9aFFzZp/vzl+uxnd+pjH9ui\n",
"U045S9/97r8V3J7169dr/vz5Wr58ue66667h21988UW9//3v14knnqhZs2bpxhtvHN727W9/W+ec\n",
"c46OPfZYvf3tb1dvb68k6aWXXtKVV16pE088UWeddZa+9a1vDf9Oa2urrrrqKl199dU69thj9e53\n",
"v1u//OUvJUnLly/Xrl27tHTpUk2bNk233XabJOmxxx7TxRdfrBkzZuhd73qXuru7h+/v97//vRob\n",
"G3XsscdqwYIFev311ws+9qJZawN/SR4GAABA8GXXNfX1i6y0zkp2xMWYL9srrvif9sorV+TcLlk7\n",
"deoye9ddd9lFi66y1dV/b6VExvbf2ClTZtvHHnusoPbNmzfP3n333fa5556zRx11lH3ttdfsoUOH\n",
"7Lnnnmtvuukmu3//fjswMGB/9rOfWWutve++++ypp55qn3jiCWuttTt27LA7d+60iUTC1tXV2ba2\n",
"Nnvw4EH7/PPP27POOstu2bLFWmvt6tWr7VFHHWV/+MMf2kOHDtnbbrvNnnnmmfbQoUPWWmvPOOMM\n",
"29HRMdyu3bt325kzZ9rNmzdba6195JFH7MyZM+3rr79urbX2wgsvtKtWrbKDg4O2p6fHTps2zS5f\n",
"vjyv1yDr9oJrVXq4AQAAfGpgYED/+Z+dklaM2mbth/XQQ/ePex9/+tOf1NXVqcHBr2lkuOFsvfnm\n",
"p/S1r/1L3u352c9+pj179ujyyy/XW97yFp1zzjn6/ve/r23btunll1/W1772NR1zzDE6+uijdckl\n",
"l0iSvvOd7+jmm2/Wu9/9bknSvHnzNHfuXP3iF7/Q66+/ri984QuaNGmSzjzzTH34wx/WPffcM/x4\n",
"5513nt7//vcrEonopptu0sDAgB577LGcbbv77ru1ePFiLVy4UJI0f/58nXfeeXrooYe0a9cuPfHE\n",
"E2pra9NRRx2l+vp6LV26tGyRFApuAAAAnxoaGkpdm5Rja7WGhhL6wAeWaOrU9ZKGsrb/QYcOPaI5\n",
"c+bo6KP/SlLNqHuw9mI9/fSzebfnrrvu0oIFCzRt2jRJ0rJly3TXXXdp9+7dOv3001VVNbq03L17\n",
"t+bNmzfq9p07d+qll17SjBkzhi+33nqrXnvtteF9TjvttOHrxhiddtppeumll3K2befOndqwYcOI\n",
"+/v5z3+uV155ZfhxjjnmmOH9Tz/99LyPe6JyvXoAAADwgSlTpuid77xQ8fh/SLoma+vdisUW633v\n",
"e5++/OVv6de/XqEDB26RdKakn2vKlI/pH/7hH3TuuedqcPA5SQclHZV1H7/S6aefpny8+eabuu++\n",
"+zQ0NKTZs2dLkg4cOKC+vj6ddNJJ2rVrlxKJhCKRyIjfmzNnjnbs2DHq/ubOnaszzzxzePBnLi++\n",
"+OLw9aGhIe3evVunnHKKpNGzjMydO1fLly/XnXfeOep+du7cqb1792r//v2aMmXK8G3ZbXULPdwA\n",
"AAA+9vWv36Jjjvm4pHslHZJ0QNL/1ZQp/6ivfKVFRx11lHp6NuuGG2arpuZ8GXOUTj31w7rtthv0\n",
"1a9+UW95y1v09re/TZHI17Pu+Y+qqfmybrrpI3m144EHHtCkSZP0zDPP6KmnntJTTz2lZ555Ru95\n",
"z3t0//33a/bs2frMZz6j/fv3p6Iw/ylJ+vCHP6zbbrtN8Xhc1lrt2LFDu3bt0vnnn69p06bpq1/9\n",
"qt58800lEgn913/9l5544onhx9y+fbvuv/9+HTp0SN/4xjc0efJkXXjhhZKkk046Sb/73e+G9732\n",
"2mv14IMPauvWrUokEhoYGJDjONqzZ49OP/10nXfeeVq9erUOHjyon/3sZ/rJT35S/ItSqGKC3367\n",
"iEGTAAAgJHLVNY7j2He9q94eddQUO2nSMfb885vs448/Pmq/oaEhOzg4OOr23//+93b27Hl26tRL\n",
"rfQtG4l83h5zzGzb3Py5vNu1cOFC29zcPOr2++67z86ePdu++OKL9oorrrAzZ860s2bNsh//+MeH\n",
"91m3bp1961vfaqdOnWrf8Y532CeffNJaa+1LL71kr7nmGnvyySfbGTNm2Isuumh4IGRra6u96qqr\n",
"7Ac/+EE7bdo0W1dXZ3t7e4fv88c//rGdO3euPe6442x7e7u11trHH3/cNjY22uOPP96ecMIJ9rLL\n",
"LrO7du2y1lr7/PPP2/r6ejt16lT73ve+1954441lGzRpbJnC4m4yxtgwHAcAAMCR5pd+4403ZIwZ\n",
"zlAXYmBgQPfee6+6uh7TzJnTdd11/1PnnnvuRJvrmjVr1mjHjh3693//97I/9livQer2glfMIcMN\n",
"AAAQEMcee2zRvzt58mRdd911uu6660rYIveEqTOVDDcAAAB8xxhT1uXX3USkBAAAwEeCtGR5WJU6\n",
"UkIPNwAAAOAiCm4AAADARRTcAAAAgIsouAEAAAAXUXADAAAALqLgBgAAgGsWL17syeI1mV544QVV\n",
"VVVpaGjIk8en4AYAAAiyxx+XPvUpKXsau74+6dprpb17S/IwZ5xxhqZMmaJp06bp5JNP1vLly/XG\n",
"G2+M+3ubNm3S8uXLJ/TYra2tE74PL1FwAwAA+NmaNVI8Pvr2nh7pttukt70tef1jHztcdPf1SQsW\n",
"SDNmSMcdJ738cu773rtXevPNvJphjNFPfvIT7du3T0899ZSefvppffGLXyzyoCoLBTcAAICfvfOd\n",
"0qJFI4vunh7pqquk2lpp+nRp61Zp27Zk0f3nPyeL7fPPl775TSmRkGIxad26kfe7d680f75URNzj\n",
"pJNO0oIFC/SrX/1KkvTYY4/p4osv1owZM/Sud71L3d3dw/tGo1F997vfHf75e9/7ns455xwdf/zx\n",
"WrhwoXbt2jW87Ve/+pXe+973aubMmTr55JN16623asuWLbr11lt17733atq0aaqtrZUk9fX16UMf\n",
"+pBOOeUUnXbaaWppaRmOjAwNDam5uVknnHCC5s2bp4ceeqjgYywlCm4AAAA/u+IK6Y47Dhfd6WL7\n",
"Bz+QmpqS+6SL7p/+NNmrnS62jZEmTZIeeki69dbDRXe62I5Gpeuvz7sp6dUXd+/erYcfflgXXHCB\n",
"9uzZo8suu0z/+I//qL179+q2227TlVdeqT/+8Y+SRi7R/uMf/1i33nqr7r//fr3++uuqr6/XNddc\n",
"I0nat2+f5s+fr8WLF+vll1/Wjh071NTUpEsvvVSf+9zndPXVV2vfvn3q7e2VJP3t3/6tqqur9bvf\n",
"/U69vb3aunWrvvOd70iS7rzzTj300EN68skn9cQTT+g//uM/PF0mnoIbAADA79JF97vfLTU2jiy2\n",
"8zFvntTZmSy6b731cLF9223JojwP1lpdccUVOvbYYzV37lzNmzdPn//853X33Xdr8eLFWrhwoSRp\n",
"/vz5Ou+883L2Kq9bt06f/exn9da3vlVVVVX67Gc/qyeffFK7du3ST37yE51yyin65Cc/qerqak2d\n",
"OlXnn3/+8GNnLrX+6quvavPmzfr617+uY445RieccII+8YlP6J577pEk3XffffrkJz+pU089VTNm\n",
"zNDnPve5nEu1lwsFNwAAQBAcf/zh6zNmjNyWzmzPn5/svU7HSzKLzHnzpB/9SPrc56Tf/KagYltK\n",
"9lT/+Mc/1htvvCHHcdTZ2ant27dr586d2rBhg2bMmDF8+fnPf65XXnll1H3s3LlTH//4x4f3mzlz\n",
"piRpz5492r17t84666y82rJz504dPHhQs2fPHr6vlStX6g9/+IMk6eWXX9acOXOG9587d27ex+kG\n",
"Cm4AAAC/S8dIfvpT6f77R2a608V2OkZy3HEjM93ponvvXukjH0n2ls+cmewxL1JDQ4NuvPFG3Xzz\n",
"zZo7d66WL1+uvXv3Dl/27dunT3/606N+b+7cubrzzjtH7Nvf36+LLrpIc+bM0fPPP5/z8aqqRpas\n",
"c+bM0dFHH60//vGPw/fT19enp59+WpI0e/bsEdnwzOteoOAGAADws+zMdnam+9lnpYaGw5lt6XCm\n",
"e+/e5CDKzMz2j350OF6SPZCyAJ/4xCe0bds2vec979GDDz6orVu3KpFIaGBgQI7jaM+ePaN+Z+XK\n",
"lfrSl76kX//615KSAx83bNggSbrsssv08ssv65/+6Z904MAB7du3T9u2bZOUHKT5wgsvDMdCZs+e\n",
"rQULFuimm27Svn37NDQ0pN/97nfq6emRJH3gAx/QN7/5Te3Zs0d79+7Vl7/85aKPsxQouAEAAPzs\n",
"hz8cndlOF90//KF0wQXS1742Oh4yfbp0993StGnJHvDMzHZmpvsHPyiqWbNmzdJ1112ntWvXauPG\n",
"jfrSl76kE088UXPnzlV7e3vOzPQVV1yhm2++WVdffbWmT5+ud7zjHdqyZYskaerUqXrkkUf04IMP\n",
"avbs2Tr77LPlOI4kadmyZZKkmTNn6rzzzpMkrV+/XoODg8Mznixbtmw4xnL99dfr0ksv1Tvf+U6d\n",
"d955uvLKKz0dNGm8DJCXijHGhuE4AAAAjDGlH+D3+OPJyEl20fn889LUqdKJJ5b28TI0Njbq+uuv\n",
"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\n",
"JUmSpA79A109nxJVGE9DAAAAAElFTkSuQmCC\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"positive = data2[data2['Accepted'].isin([1])]\n",
"negative = data2[data2['Accepted'].isin([0])]\n",
"\n",
"fig, ax = plt.subplots(figsize=(12,8))\n",
"ax.scatter(positive['Test 1'], positive['Test 2'], s=50, c='b', marker='o', label='Accepted')\n",
"ax.scatter(negative['Test 1'], negative['Test 2'], s=50, c='r', marker='x', label='Rejected')\n",
"ax.legend()\n",
"ax.set_xlabel('Test 1 Score')\n",
"ax.set_ylabel('Test 2 Score')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This data looks a bit more complicated than the previous example. In particular, you'll notice that there is no linear decision boundary that will perform well on this data. One way to deal with this using a linear technique like logistic regression is to construct features that are derived from polynomials of the original features. Let's start by creating a bunch of polynomial features."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Accepted | \n",
" Ones | \n",
" F10 | \n",
" F20 | \n",
" F21 | \n",
" F30 | \n",
" F31 | \n",
" F32 | \n",
" F40 | \n",
" F41 | \n",
" F42 | \n",
" F43 | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" 1 | \n",
" 1 | \n",
" 0.051267 | \n",
" 0.002628 | \n",
" 0.035864 | \n",
" 0.000135 | \n",
" 0.001839 | \n",
" 0.025089 | \n",
" 0.000007 | \n",
" 0.000094 | \n",
" 0.001286 | \n",
" 0.017551 | \n",
"
\n",
" \n",
" 1 | \n",
" 1 | \n",
" 1 | \n",
" -0.092742 | \n",
" 0.008601 | \n",
" -0.063523 | \n",
" -0.000798 | \n",
" 0.005891 | \n",
" -0.043509 | \n",
" 0.000074 | \n",
" -0.000546 | \n",
" 0.004035 | \n",
" -0.029801 | \n",
"
\n",
" \n",
" 2 | \n",
" 1 | \n",
" 1 | \n",
" -0.213710 | \n",
" 0.045672 | \n",
" -0.147941 | \n",
" -0.009761 | \n",
" 0.031616 | \n",
" -0.102412 | \n",
" 0.002086 | \n",
" -0.006757 | \n",
" 0.021886 | \n",
" -0.070895 | \n",
"
\n",
" \n",
" 3 | \n",
" 1 | \n",
" 1 | \n",
" -0.375000 | \n",
" 0.140625 | \n",
" -0.188321 | \n",
" -0.052734 | \n",
" 0.070620 | \n",
" -0.094573 | \n",
" 0.019775 | \n",
" -0.026483 | \n",
" 0.035465 | \n",
" -0.047494 | \n",
"
\n",
" \n",
" 4 | \n",
" 1 | \n",
" 1 | \n",
" -0.513250 | \n",
" 0.263426 | \n",
" -0.238990 | \n",
" -0.135203 | \n",
" 0.122661 | \n",
" -0.111283 | \n",
" 0.069393 | \n",
" -0.062956 | \n",
" 0.057116 | \n",
" -0.051818 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Accepted Ones F10 F20 F21 F30 F31 F32 \\\n",
"0 1 1 0.051267 0.002628 0.035864 0.000135 0.001839 0.025089 \n",
"1 1 1 -0.092742 0.008601 -0.063523 -0.000798 0.005891 -0.043509 \n",
"2 1 1 -0.213710 0.045672 -0.147941 -0.009761 0.031616 -0.102412 \n",
"3 1 1 -0.375000 0.140625 -0.188321 -0.052734 0.070620 -0.094573 \n",
"4 1 1 -0.513250 0.263426 -0.238990 -0.135203 0.122661 -0.111283 \n",
"\n",
" F40 F41 F42 F43 \n",
"0 0.000007 0.000094 0.001286 0.017551 \n",
"1 0.000074 -0.000546 0.004035 -0.029801 \n",
"2 0.002086 -0.006757 0.021886 -0.070895 \n",
"3 0.019775 -0.026483 0.035465 -0.047494 \n",
"4 0.069393 -0.062956 0.057116 -0.051818 "
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"degree = 5\n",
"x1 = data2['Test 1']\n",
"x2 = data2['Test 2']\n",
"\n",
"data2.insert(3, 'Ones', 1)\n",
"\n",
"for i in range(1, degree):\n",
" for j in range(0, i):\n",
" data2['F' + str(i) + str(j)] = np.power(x1, i-j) * np.power(x2, j)\n",
"\n",
"data2.drop('Test 1', axis=1, inplace=True)\n",
"data2.drop('Test 2', axis=1, inplace=True)\n",
"\n",
"data2.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we need to modify the cost and gradient functions from part 1 to include the regularization term. First the cost function:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def costReg(theta, X, y, learningRate):\n",
" theta = np.matrix(theta)\n",
" X = np.matrix(X)\n",
" y = np.matrix(y)\n",
" first = np.multiply(-y, np.log(sigmoid(X * theta.T)))\n",
" second = np.multiply((1 - y), np.log(1 - sigmoid(X * theta.T)))\n",
" reg = (learningRate / 2 * len(X)) * np.sum(np.power(theta[:,1:theta.shape[1]], 2))\n",
" return np.sum(first - second) / (len(X)) + reg"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Notice the \"reg\" term in the equation. Also note the addition of a \"learning rate\" parameter. This is a hyperparameter that controls the effectiveness of the regularization term. Now we need to add regularization to the gradient function:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def gradientReg(theta, X, y, learningRate):\n",
" theta = np.matrix(theta)\n",
" X = np.matrix(X)\n",
" y = np.matrix(y)\n",
" \n",
" parameters = int(theta.ravel().shape[1])\n",
" grad = np.zeros(parameters)\n",
" \n",
" error = sigmoid(X * theta.T) - y\n",
" \n",
" for i in range(parameters):\n",
" term = np.multiply(error, X[:,i])\n",
" \n",
" if (i == 0):\n",
" grad[i] = np.sum(term) / len(X)\n",
" else:\n",
" grad[i] = (np.sum(term) / len(X)) + ((learningRate / len(X)) * theta[:,i])\n",
" \n",
" return grad"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Initialize variables like we did in part 1."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# set X and y (remember from above that we moved the label to column 0)\n",
"cols = data2.shape[1]\n",
"X2 = data2.iloc[:,1:cols]\n",
"y2 = data2.iloc[:,0:1]\n",
"\n",
"# convert to numpy arrays and initalize the parameter array theta\n",
"X2 = np.array(X2.values)\n",
"y2 = np.array(y2.values)\n",
"theta2 = np.zeros(11)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's initialize our learning rate to a sensible value. We can play with this later if necessary (i.e. if the penalization is too strong or not strong enough)."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"learningRate = 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's try calling our new regularized functions with the default (0) values for theta to make sure the calculations are working."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.6931471805599454"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"costReg(theta2, X2, y2, learningRate)"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"array([ 0.00847458, 0.01878809, 0.05034464, 0.01150133, 0.01835599,\n",
" 0.00732393, 0.00819244, 0.03934862, 0.00223924, 0.01286005,\n",
" 0.00309594])"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"gradientReg(theta2, X2, y2, learningRate)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can use the same optimization function from part 1 to compute the optimal solution."
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(array([ 0.35872309, -3.22200653, 18.97106363, -4.25297831,\n",
" 18.23053189, 20.36386672, 8.94114455, -43.77439015,\n",
" -17.93440473, -50.75071857, -2.84162964]), 110, 1)"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"result2 = opt.fmin_tnc(func=costReg, x0=theta2, fprime=gradientReg, args=(X2, y2, learningRate))\n",
"result2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, we can use the prediction function from part 1 to see how accurate our solution is on the training data."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"accuracy = 91%\n"
]
}
],
"source": [
"theta_min = np.matrix(result2[0])\n",
"predictions = predict(theta_min, X2)\n",
"correct = [1 if ((a == 1 and b == 1) or (a == 0 and b == 0)) else 0 for (a, b) in zip(predictions, y2)]\n",
"accuracy = (sum(map(int, correct)) % len(correct))\n",
"print 'accuracy = {0}%'.format(accuracy)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Although we implemented these algorithms from scratch, it's worth noting that we could also use a high-level python library like scikit-learn to solve this problem."
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,\n",
" intercept_scaling=1, penalty='l2', random_state=None, tol=0.0001)"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from sklearn import linear_model\n",
"model = linear_model.LogisticRegression(penalty='l2', C=1.0)\n",
"model.fit(X2, y2.ravel())"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.66101694915254239"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.score(X2, y2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The accuracy is much lower than what we just computed, but keep in mind this result is using the default parameters provided by scikit-learn. We'd likely need to do some parameter tuning to get the same accuracy that we obtained with our earlier result."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"That's all for Exercise 2! Stay tuned for the next exercise where we'll tackle multi-class image classification."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.9"
}
},
"nbformat": 4,
"nbformat_minor": 0
}