├── README.md └── logistic_reg.ipynb /README.md: -------------------------------------------------------------------------------- 1 | # logistic-reg 2 | This repo contains a jupyter notebook with a logistic regression implementation from scratch using NumPy. 3 | 4 | https://medium.com/@martinpella/logistic-regression-from-scratch-in-python-124c5636b8ac 5 | -------------------------------------------------------------------------------- /logistic_reg.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "%matplotlib inline\n", 12 | "import numpy as np\n", 13 | "import matplotlib.pyplot as plt\n", 14 | "import seaborn as sns\n", 15 | "from sklearn import datasets" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 2, 21 | "metadata": { 22 | "collapsed": true 23 | }, 24 | "outputs": [], 25 | "source": [ 26 | "iris = datasets.load_iris()" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": 3, 32 | "metadata": { 33 | "collapsed": true 34 | }, 35 | "outputs": [], 36 | "source": [ 37 | "X = iris.data[:, :2]\n", 38 | "y = (iris.target != 0) * 1" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 4, 44 | "metadata": {}, 45 | "outputs": [ 46 | { 47 | "data": { 48 | "image/png": "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\nc/fXshzMzObMbNnMls+cOZPlJRCbU6cGKwcAIGJ9BVZmtlNJULXk7g+lbHJa0uVb1ifaZRdw90V3\nn3H3mfHx8Sz1RWwmJwcrBwAgYv38KtAk3S/pBXf/4y6bfU/SZ9u/DrxR0qvu/krAeiJW99wjjY1d\nWDY2lpQDAFAxzT62+bCkfyHpx2b2TLvs30malCR3/7qkRyQdkPSSpDVJnw9fVURpdjZ5PHw4+fpv\ncjIJqjbKAQCoEHP3Qg48MzPjy8vLhRwbAABgEGZ23N1nem3HzOsAAACBEFgBAAAEQmAFAAAQCIEV\nAABAIARWAAAAgRBYAQAABEJgBQAAEAiBFQAAQCAEVgAAAIEQWAEAAARCYAUAABAIgRUAAEAgBFYA\nAACBmLsXc2CzM5JWCjn4aF0q6e+LrkRJ0TbpaJd0tEs62iUd7ZKOdulu0LaZcvfxXhsVFlhVlZkt\nu/tM0fUoI9omHe2SjnZJR7uko13S0S7djapt+CoQAAAgEAIrAACAQAiswlssugIlRtuko13S0S7p\naJd0tEs62qW7kbQNY6wAAAAC4RMrAACAQAishmBmDTN72sweTnnuZjN71cyeaS93F1HHvJnZSTP7\ncfucl1OeNzO718xeMrNnzez6IupZhD7apq595hIz+5aZ/cTMXjCzD3Y8X8s+00e71K6/mNnVW873\nGTN7zcx+r2Ob2vWXPtuldv1FkszsX5vZCTN7zsweMLNdHc8H7y/NYV+g5u6S9IKkd3R5/vvufluO\n9SmLf+bu3eYGuVXSVe3ltyUdaT/WxXZtI9Wzz/yJpMfc/VNm9hZJYx3P17XP9GoXqWb9xd1flHSd\nlPxjK+m0pG93bFa7/tJnu0g16y9mtlvSv5K0x91/aWZ/LumgpP+yZbPg/YVPrDIyswlJn5D0jaLr\nEplPSvqmJ34g6RIzu6zoSqEYZvaPJN0k6X5JcvdfufsvOjarXZ/ps13qbp+kv3H3zomma9dfOnRr\nl7pqSnqrmTWV/HPyvzueD95fCKyy+6qkL0k6v802H2p/tPiomV2TU72K5pIeN7PjZjaX8vxuSS9v\nWV9tl9VBr7aR6tdnrpB0RtJ/bn+t/g0ze1vHNnXsM/20i1S//rLVQUkPpJTXsb9s1a1dpJr1F3c/\nLek/SDol6RVJr7r7f+vYLHh/IbDKwMxuk/Rzdz++zWZPSZp09/dL+pqk7+RSueJ9xN2vU/Lx6p1m\ndlPRFSqRXm1Txz7TlHS9pCPu/luS/p+kf1tslUqhn3apY3+RJLW/Gr1d0n8tui5l0qNdatdfzOwf\nK/lE6gqVBrdnAAABxUlEQVRJ/1TS28zsM6M+LoFVNh+WdLuZnZT0oKRbzOzo1g3c/TV3f7399yOS\ndprZpbnXNGft/xDk7j9X8h3/DR2bnJZ0+Zb1iXZZ5fVqm5r2mVVJq+7+w/b6t5QEFFvVsc/0bJea\n9pcNt0p6yt3/LuW5OvaXDV3bpab9Zb+kn7n7GXf/taSHJH2oY5vg/YXAKgN3/7K7T7j7tJKPXf/S\n3S+Igs3sPWZm7b9vUNLWZ3OvbI7M7G1m9vaNvyX9c0nPdWz2PUmfbf8S40YlH82+knNVc9dP29Sx\nz7j7/5H0spld3S7aJ+n5js1q12f6aZc69pct7lD3r7tq11+26NouNe0vpyTdaGZj7XPfp+QHZ1sF\n7y/8KjAgMzskSe7+dUmfktQys3OSfinpoFd/NtZ/Iunb7fduU9KfuftjHe3yiKQDkl6StCbp8wXV\nNW/9tE0d+4wk/a6kpfbXGH8r6fP0GUm926WW/aX9j8lHJf3OlrLa95c+2qV2/cXdf2hm31LyNeg5\nSU9LWhx1f2HmdQAAgED4KhAAACAQAisAAIBACKwAAAACIbACAAAIhMAKAAAgEAIrAACAQAisAAAA\nAiGwAgAACOT/A1flvRpe7BsWAAAAAElFTkSuQmCC\n", 49 | "text/plain": [ 50 | "" 51 | ] 52 | }, 53 | "metadata": {}, 54 | "output_type": "display_data" 55 | } 56 | ], 57 | "source": [ 58 | "plt.figure(figsize=(10, 6))\n", 59 | "plt.scatter(X[y == 0][:, 0], X[y == 0][:, 1], color='b', label='0')\n", 60 | "plt.scatter(X[y == 1][:, 0], X[y == 1][:, 1], color='r', label='1')\n", 61 | "plt.legend();" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 5, 67 | "metadata": { 68 | "collapsed": true 69 | }, 70 | "outputs": [], 71 | "source": [ 72 | "class LogisticRegression:\n", 73 | " def __init__(self, lr=0.01, num_iter=100000, fit_intercept=True, verbose=False):\n", 74 | " self.lr = lr\n", 75 | " self.num_iter = num_iter\n", 76 | " self.fit_intercept = fit_intercept\n", 77 | " self.verbose = verbose\n", 78 | " \n", 79 | " def __add_intercept(self, X):\n", 80 | " intercept = np.ones((X.shape[0], 1))\n", 81 | " return np.concatenate((intercept, X), axis=1)\n", 82 | " \n", 83 | " def __sigmoid(self, z):\n", 84 | " return 1 / (1 + np.exp(-z))\n", 85 | " def __loss(self, h, y):\n", 86 | " return (-y * np.log(h) - (1 - y) * np.log(1 - h)).mean()\n", 87 | " \n", 88 | " def fit(self, X, y):\n", 89 | " if self.fit_intercept:\n", 90 | " X = self.__add_intercept(X)\n", 91 | " \n", 92 | " # weights initialization\n", 93 | " self.theta = np.zeros(X.shape[1])\n", 94 | " \n", 95 | " for i in range(self.num_iter):\n", 96 | " z = np.dot(X, self.theta)\n", 97 | " h = self.__sigmoid(z)\n", 98 | " gradient = np.dot(X.T, (h - y)) / y.size\n", 99 | " self.theta -= self.lr * gradient\n", 100 | " \n", 101 | " z = np.dot(X, self.theta)\n", 102 | " h = self.__sigmoid(z)\n", 103 | " loss = self.__loss(h, y)\n", 104 | " \n", 105 | " if(self.verbose ==True and i % 10000 == 0):\n", 106 | " print(f'loss: {loss} \\t')\n", 107 | " \n", 108 | " def predict_prob(self, X):\n", 109 | " if self.fit_intercept:\n", 110 | " X = self.__add_intercept(X)\n", 111 | " \n", 112 | " return self.__sigmoid(np.dot(X, self.theta))\n", 113 | " \n", 114 | " def predict(self, X):\n", 115 | " return self.predict_prob(X).round()" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": 6, 121 | "metadata": { 122 | "collapsed": true 123 | }, 124 | "outputs": [], 125 | "source": [ 126 | "model = LogisticRegression(lr=0.1, num_iter=300000)" 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": 7, 132 | "metadata": {}, 133 | "outputs": [ 134 | { 135 | "name": "stdout", 136 | "output_type": "stream", 137 | "text": [ 138 | "CPU times: user 14.3 s, sys: 12 ms, total: 14.3 s\n", 139 | "Wall time: 14.3 s\n" 140 | ] 141 | } 142 | ], 143 | "source": [ 144 | "%time model.fit(X, y)" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": 8, 150 | "metadata": {}, 151 | "outputs": [ 152 | { 153 | "data": { 154 | "text/plain": [ 155 | "1.0" 156 | ] 157 | }, 158 | "execution_count": 8, 159 | "metadata": {}, 160 | "output_type": "execute_result" 161 | } 162 | ], 163 | "source": [ 164 | "preds = model.predict(X)\n", 165 | "(preds == y).mean()" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": 9, 171 | "metadata": {}, 172 | "outputs": [ 173 | { 174 | "data": { 175 | "text/plain": [ 176 | "array([-25.96818124, 12.56179068, -13.44549335])" 177 | ] 178 | }, 179 | "execution_count": 9, 180 | "metadata": {}, 181 | "output_type": "execute_result" 182 | } 183 | ], 184 | "source": [ 185 | "model.theta" 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": 11, 191 | "metadata": {}, 192 | "outputs": [ 193 | { 194 | "data": { 195 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlYAAAFpCAYAAABeYWb6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xt8FNX9//H3IQGRapXWQJWrln75orblpxDCRcpNqmCR\nCuIFUBEbSdBaL9QqFrHfolXxAipiREHlqoDcxFRAiggk4aJVUesVEIuCIBeJAsme3x+bSIgbstnL\nzM7M6/l4zCPZ2dmdz5yZnXwyc/Z8jLVWAAAAiF8ttwMAAADwCxIrAACABCGxAgAASBASKwAAgAQh\nsQIAAEgQEisAAIAEIbECAABIEBIrAACABCGxAgAASJCoEytjTJox5g1jzKIIz3UxxuwxxrxZNo1K\nbJgAAACpL70Gy94g6T1JP67i+ZXW2guifbOTTjrJNm/evAarBwAAcMf69eu/stZmVLdcVImVMaax\npN6Sxki6Kc7YJEnNmzfXunXrEvFWAAAASWWM2RzNctHeCnxY0p8lhY6yTAdjzFvGmJeNMWdE+b4A\nAAC+UW1iZYy5QNJ2a+36oyy2QVJTa+2vJD0iaV4V75VtjFlnjFm3Y8eOmAIGAABIVdFcseooqY8x\nZpOkmZK6GWOmVlzAWrvXWvtN2e+LJdU2xpxU+Y2stXnW2jbW2jYZGdXepgQAAPCUavtYWWtvk3Sb\nFP72n6RbrLWDKi5jjPmZpC+ttdYYk6lwwrYz8eECAACvOnTokLZu3arvvvvO7VCqVLduXTVu3Fi1\na9eO6fU1+VbgEYwxwyTJWjtRUn9JOcaYEknfSrrUWmtjfW8AAOA/W7du1fHHH6/mzZvLGON2OD9g\nrdXOnTu1detWnXrqqTG9R40SK2vtvyT9q+z3iRXmPyrp0ZgiAAAAgfDdd9+lbFIlScYY/fSnP1U8\n/cAZeR0AADgmVZOqcvHGR2IFAAACIz8/Xy1btlSLFi30j3/8I+HvT2IFAAACobS0VMOHD9fLL7+s\nd999VzNmzNC7776b0HWQWAEAgJQ0bZrUvLlUq1b457Rp8b1fUVGRWrRoodNOO0116tTRpZdeqvnz\n5yci1O+RWAEAgJQzbZqUnS1t3ixZG/6ZnR1fcvX555+rSZMm3z9u3LixPv/88wREexiJFRAQif7P\nDwCSaeRIqbj4yHnFxeH5qSzmcawAeEf5f37lJ6ny//wkaeBA9+ICgKps2VKz+dFo1KiRPvvss+8f\nb926VY0aNYr9DSPgihUQAF79zw/esHPnTt144406cOCA26HAR5o2rdn8aLRt21YffvihPv30Ux08\neFAzZ85Unz59Yn/DCEisgABIxn9+gCS98847yszMVJ06dZSezk0QJM6YMVK9ekfOq1cvPD9W6enp\nevTRR/Xb3/5WrVq10oABA3TGGWfEF2jldST03QCkpKZNw7f/Is0HYjV//nz94Q9/0IMPPqhBgwZV\n/wKgBsq7KYwcGf4nsGnTcFIVb/eFXr16qVevXvEHWAUSKyAAxow5so+VFP9/fggua63uvvtuTZw4\nUYsWLVJmZqbbIcGnBg70Xj9QEisgAJL1nx+Cp7i4WEOGDNGmTZtUWFioU045xe2QgJRCYgUEhBf/\n80Nq2bJli/r27atf/vKXWrFiherWret2SEDKofM6AKBar7/+urKysjRw4EBNmTKFpAqoAlesAABH\nNWnSJN1+++165plndP7557sdDpDSSKwAABGVlJTopptu0j//+U+tXLlSLVu2dDskIOVxKxAA8AO7\ndu3Seeedpw8++ECFhYUkVfCNq6++Wg0aNNCZZ56ZlPcnsQIAHGHjxo3KzMxU69at9dJLL+nEE090\nOyQgYa666irl5+cn7f1JrAAA31u4cKG6du2qUaNGaezYsUpLS3M7JARZEqrHd+7cWT/5yU/ifp+q\n0McKAKBQKKR77rlHEyZM0IIFC5SVleV2SAg6j1aPJ7ECgIDbt2+frrzySm3btk1r165l0E+khqNV\nj0/hxIpbgQAQYB988IHatWunjIwM/etf/yKpQurwaPV4EisACKjFixerU6dOuuGGG/TEE0/omGOO\ncTsk4LCqqsSnePV4EisACBhrre655x794Q9/0Isvvqhrr73W7ZCAHxozJlwtvqIEVI+/7LLL1L59\ne/3nP/9R48aN9dRTT8X1fpXRxwoAAmT//v0aMmSINm/erKKiIjVq1MjtkIDIklQ9fsaMGQkIrmok\nVgAQEJ9++qn69u2rs846iyLK8AYPVo/nViAABMDy5cvVvn17DR06VE8//TRJFZAkXLECAB+z1urR\nRx/VmDFjNH36dHXr1s3tkABfI7ECAJ86cOCAcnNztXbtWq1evVqnnXaa2yEBstbKGON2GFWy1sb1\nem4FAi5JQqUG4Hvbtm1T165dtWfPHpIqpIy6detq586dcScvyWKt1c6dO+O6Vc4VK8AFHq3UAI9Y\n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\nTkSuQmCC\n", 196 | "text/plain": [ 197 | "" 198 | ] 199 | }, 200 | "metadata": {}, 201 | "output_type": "display_data" 202 | } 203 | ], 204 | "source": [ 205 | "plt.figure(figsize=(10, 6))\n", 206 | "plt.scatter(X[y == 0][:, 0], X[y == 0][:, 1], color='b', label='0')\n", 207 | "plt.scatter(X[y == 1][:, 0], X[y == 1][:, 1], color='r', label='1')\n", 208 | "plt.legend()\n", 209 | "x1_min, x1_max = X[:,0].min(), X[:,0].max(),\n", 210 | "x2_min, x2_max = X[:,1].min(), X[:,1].max(),\n", 211 | "xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max), np.linspace(x2_min, x2_max))\n", 212 | "grid = np.c_[xx1.ravel(), xx2.ravel()]\n", 213 | "probs = model.predict_prob(grid).reshape(xx1.shape)\n", 214 | "plt.contour(xx1, xx2, probs, [0.5], linewidths=1, colors='black');" 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": 19, 220 | "metadata": { 221 | "collapsed": true 222 | }, 223 | "outputs": [], 224 | "source": [ 225 | "from sklearn.linear_model import LogisticRegression" 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": 20, 231 | "metadata": {}, 232 | "outputs": [], 233 | "source": [ 234 | "model = LogisticRegression(C=1e20)" 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": 22, 240 | "metadata": {}, 241 | "outputs": [ 242 | { 243 | "name": "stdout", 244 | "output_type": "stream", 245 | "text": [ 246 | "CPU times: user 0 ns, sys: 0 ns, total: 0 ns\n", 247 | "Wall time: 855 µs\n" 248 | ] 249 | }, 250 | { 251 | "data": { 252 | "text/plain": [ 253 | "LogisticRegression(C=1e+20, class_weight=None, dual=False, fit_intercept=True,\n", 254 | " intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,\n", 255 | " penalty='l2', random_state=None, solver='liblinear', tol=0.0001,\n", 256 | " verbose=0, warm_start=False)" 257 | ] 258 | }, 259 | "execution_count": 22, 260 | "metadata": {}, 261 | "output_type": "execute_result" 262 | } 263 | ], 264 | "source": [ 265 | "%time model.fit(X, y)" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": 23, 271 | "metadata": {}, 272 | "outputs": [ 273 | { 274 | "data": { 275 | "text/plain": [ 276 | "1.0" 277 | ] 278 | }, 279 | "execution_count": 23, 280 | "metadata": {}, 281 | "output_type": "execute_result" 282 | } 283 | ], 284 | "source": [ 285 | "preds = model.predict(X)\n", 286 | "(preds == y).mean()" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": 24, 292 | "metadata": {}, 293 | "outputs": [ 294 | { 295 | "data": { 296 | "text/plain": [ 297 | "(array([-80.62725491]), array([[ 31.61988897, -28.31500665]]))" 298 | ] 299 | }, 300 | "execution_count": 24, 301 | "metadata": {}, 302 | "output_type": "execute_result" 303 | } 304 | ], 305 | "source": [ 306 | "model.intercept_, model.coef_" 307 | ] 308 | }, 309 | { 310 | "cell_type": "code", 311 | "execution_count": null, 312 | "metadata": { 313 | "collapsed": true 314 | }, 315 | "outputs": [], 316 | "source": [] 317 | } 318 | ], 319 | "metadata": { 320 | "kernelspec": { 321 | "display_name": "Python 3", 322 | "language": "python", 323 | "name": "python3" 324 | }, 325 | "language_info": { 326 | "codemirror_mode": { 327 | "name": "ipython", 328 | "version": 3 329 | }, 330 | "file_extension": ".py", 331 | "mimetype": "text/x-python", 332 | "name": "python", 333 | "nbconvert_exporter": "python", 334 | "pygments_lexer": "ipython3", 335 | "version": "3.6.2" 336 | } 337 | }, 338 | "nbformat": 4, 339 | "nbformat_minor": 2 340 | } 341 | --------------------------------------------------------------------------------