From dca0ded76d204f107fdeadbe8e988fb407e0a5f6 Mon Sep 17 00:00:00 2001 From: Ogbonna Chibuike Stephen Date: Thu, 23 Apr 2020 23:16:05 +0100 Subject: [PATCH 01/10] Create Ogbonna_Chibuike_Stephen --- Ogbonna_Chibuike_Stephen | 1 + 1 file changed, 1 insertion(+) create mode 100644 Ogbonna_Chibuike_Stephen diff --git a/Ogbonna_Chibuike_Stephen b/Ogbonna_Chibuike_Stephen new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Ogbonna_Chibuike_Stephen @@ -0,0 +1 @@ + From ee464a89ffa9e95da32431f142862318fcefabfa Mon Sep 17 00:00:00 2001 From: Ogbonna Chibuike Stephen Date: Thu, 23 Apr 2020 23:16:45 +0100 Subject: [PATCH 02/10] Delete DSN_logo.png --- DSN_logo.png | Bin 30700 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 DSN_logo.png diff --git a/DSN_logo.png b/DSN_logo.png deleted file mode 100644 index b88c2bc9671b13503dff282b7c57ce37d26dacd6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30700 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 From d74d69e9bee23568b1f2f0075abe6fa1a96fbac3 Mon Sep 17 00:00:00 2001 From: Ogbonna Chibuike Stephen Date: Thu, 23 Apr 2020 23:33:33 +0100 Subject: [PATCH 03/10] Update README.md --- README.md | 41 +++-------------------------------------- 1 file changed, 3 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index d3696d5..7e47e49 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,6 @@ # ML-Logistic-regression-algorithm-challenge -![DSN logo](DSN_logo.png)|DSN Algorithm Challenge| -|---|---| - -A lot of data scientists or machine learning enthusiasts do use various machine learning algorithms as a black box without knowing how they work or the mathematics behind it. The purpose of this challenge is to encourage the mathematical understanding of machine learning algorithms, their break and yield point. - -In summary, participants are encouraged to understand the fundamental concepts behind machine learning algorithms/models. - - -The rules and guidelines for this challenge are as follows: - -1. Ensure to register at https://bit.ly/dsnmlhack - -2. The algorithm challenge is open to all. - -3. Participants are expected to design and develop the Logistic Regression algorithm from scratch using Python or R programming. - -4. For python developers (numpy is advisable). - -5. To push your solution to us, make a [pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests) to DSN's GitHub page at https://www.github.com/datasciencenigeria/ML-Logistic-regression-algorithm-challenge. Ensure to add your readme file to understand your code. - -6. The top 3 optimized code will be compensated as follows: - -- **1st position**: 20GB data plan. -- **2nd position**: 15GB data plan. -- **3rd position**: 10GB data plan. - -7. Add your scripts and readme.MD file as a folder saved as your full name (surname_first_middle name) by making a pull request to the repository. - ---- -For issues on this challenge kindly reach out to the AI+campus/city managers - -**Twitter**: [@DataScienceNIG](https://twitter.com/DataScienceNIG), [@elishatofunmi](https://twitter.com/Elishatofunmi), [@o_funminiyi](https://twitter.com/o_funminiyi), [@gbganalyst](https://twitter.com/gbganalyst) - -or - -**Call**: +2349062000119,+2349080564419. - -Good luck! +I created a Regulaized Logistic Regression that performs both binary and multi classifications wth Cost Gradient Descent as my optimizer. +First, I created two python scripts, Sigmoid function.py and CostGradient.py. These two script were imported into the Regularised logistic regression notebook. + From 9b1a9ad7f74d264873fb184aa632cffbe840d50a Mon Sep 17 00:00:00 2001 From: Ogbonna Chibuike Stephen Date: Thu, 23 Apr 2020 23:35:14 +0100 Subject: [PATCH 04/10] Add files via upload --- SigmoidFunction.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 SigmoidFunction.py diff --git a/SigmoidFunction.py b/SigmoidFunction.py new file mode 100644 index 0000000..eaca743 --- /dev/null +++ b/SigmoidFunction.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +# coding: utf-8 + +# In[1]: + + +import numpy as np + +def sigmoid(z): + return 1/(1+np.exp(-z)) + From bdf4408ffe43969501ea8dc533c68c42a16b68d3 Mon Sep 17 00:00:00 2001 From: Ogbonna Chibuike Stephen Date: Thu, 23 Apr 2020 23:35:38 +0100 Subject: [PATCH 05/10] Add files via upload --- CostGradient.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 CostGradient.py diff --git a/CostGradient.py b/CostGradient.py new file mode 100644 index 0000000..e8c6d9b --- /dev/null +++ b/CostGradient.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# coding: utf-8 + +# In[2]: + + +import numpy as np +from SigmoidFunction import sigmoid +def cost(coefs,X,y,lmbda): + m = len(y) + y_1 = np.multiply(y,np.log(sigmoid(np.dot(X,coefs)))) + y_0 = np.multiply(1-y,np.log(1-sigmoid(np.dot(X,coefs)))) + return np.sum(y_1 + y_0) / (-m) + np.sum(coefs[1:]**2) * lmbda /(2*m) +def gradient(coefs,X,y,lmbda): + m = len(y) + error = sigmoid(np.dot(X,coefs)) - y + grad_coefs = np.dot(X.T,error) / m + coefs * lmbda / m + grad_coefs[0] = grad_coefs[0] - coefs[0] * lmbda / m + return grad_coefs + From 36c0773a354d042ac89d99b4595fa4f142295f49 Mon Sep 17 00:00:00 2001 From: Ogbonna Chibuike Stephen Date: Thu, 23 Apr 2020 23:36:41 +0100 Subject: [PATCH 06/10] Add files via upload --- RegularizedLogisticRegression.ipynb | 126 ++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 RegularizedLogisticRegression.ipynb diff --git a/RegularizedLogisticRegression.ipynb b/RegularizedLogisticRegression.ipynb new file mode 100644 index 0000000..cf4d6d8 --- /dev/null +++ b/RegularizedLogisticRegression.ipynb @@ -0,0 +1,126 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import scipy.optimize as opt\n", + "from scipy.io import loadmat\n", + "from CostGradient import cost, gradient\n", + "from SigmoidFunction import sigmoid\n", + "class LogisticRegression:\n", + " '''\n", + " Regularised Logistic Regression\n", + " '''\n", + " def __init__(self,lmbda=0.1,num_iter=100,fit_intercept=True,threshold=0.5):\n", + " self.lmbda = lmbda\n", + " self.num_iter = num_iter\n", + " self.fit_intercept = fit_intercept\n", + " self.threshold = threshold\n", + " return None\n", + " \n", + " def intercept(self,X):\n", + " '''\n", + " This allows the y-intercept to be computed\n", + " '''\n", + " ones = np.ones((len(X),1))\n", + " return np.c_[ones,X]\n", + " \n", + " def fit(self,X,y):\n", + " if self.fit_intercept:\n", + " X = self.intercept(X)\n", + " #p = len(y)\n", + " (m,n) = X.shape\n", + " lmbda = self.lmbda\n", + " self.num_class = np.unique(y).size\n", + " \n", + " # binary logistic regression\n", + " if self.num_class == 2:\n", + " coefs = np.zeros((1,n))\n", + " coefs = opt.fmin_cg(f=cost,x0=coefs,fprime=gradient,\n", + " args=(X,y.flatten(),lmbda),maxiter=self.num_iter,disp=False)\n", + " \n", + " # One vs all (multiple class)\n", + " elif self.num_class > 2:\n", + " coefs = np.zeros((self.num_class,n))\n", + " for i in range(self.num_class):\n", + " digit = i \n", + " coefs[i] = opt.fmin_cg(f=cost,x0=coefs[i],fprime=gradient,\n", + " args=(X,(y==digit).flatten(),lmbda),maxiter=self.num_iter,disp=False)\n", + " self.coefs = coefs\n", + " \n", + " def predict_proba(self,X):\n", + " if self.fit_intercept:\n", + " X = self.intercept(X)\n", + " self.proba = sigmoid(np.dot(X,self.coefs.T))\n", + " return self.proba\n", + " \n", + " def predict(self,X):\n", + " if self.num_class == 2:\n", + " predict = (self.predict_proba(X)>=self.threshold).astype(int)\n", + " elif self.num_class > 2:\n", + " if self.fit_intercept:\n", + " X = self.intercept(X)\n", + " predict = np.argmax(np.dot(X,self.coefs.T),axis=1)\n", + " return predict\n", + " \n", + " def score(self,X,y):\n", + " pred = self.predict(X)\n", + " return np.mean(pred==y.flatten())*100\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.4" + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 10fb537811f8abe66ffe76aefb479eb7ceb4a3d6 Mon Sep 17 00:00:00 2001 From: Ogbonna Chibuike Stephen Date: Thu, 23 Apr 2020 23:50:42 +0100 Subject: [PATCH 07/10] Update RegularizedLogisticRegression.ipynb --- RegularizedLogisticRegression.ipynb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RegularizedLogisticRegression.ipynb b/RegularizedLogisticRegression.ipynb index cf4d6d8..0f24838 100644 --- a/RegularizedLogisticRegression.ipynb +++ b/RegularizedLogisticRegression.ipynb @@ -40,16 +40,16 @@ " # binary logistic regression\n", " if self.num_class == 2:\n", " coefs = np.zeros((1,n))\n", - " coefs = opt.fmin_cg(f=cost,x0=coefs,fprime=gradient,\n", - " args=(X,y.flatten(),lmbda),maxiter=self.num_iter,disp=False)\n", + " coefs = opt.fmin_cg(f=cost,x0=coefs,fprime=gradient,args=(X,y.flatten(),lmbda),maxiter=self.num_iter,disp=False)\n", + " \n", " \n", " # One vs all (multiple class)\n", " elif self.num_class > 2:\n", " coefs = np.zeros((self.num_class,n))\n", " for i in range(self.num_class):\n", " digit = i \n", - " coefs[i] = opt.fmin_cg(f=cost,x0=coefs[i],fprime=gradient,\n", - " args=(X,(y==digit).flatten(),lmbda),maxiter=self.num_iter,disp=False)\n", + " coefs[i] = opt.fmin_cg(f=cost,x0=coefs[i],fprime=gradient,args=(X,(y==digit).flatten(),lmbda),maxiter=self.num_iter,disp=False)\n", + " \n", " self.coefs = coefs\n", " \n", " def predict_proba(self,X):\n", From a9e3ea11a7fd9ed500efd3476d811d2d88526b13 Mon Sep 17 00:00:00 2001 From: Ogbonna Chibuike Stephen Date: Thu, 23 Apr 2020 23:52:41 +0100 Subject: [PATCH 08/10] Delete RegularizedLogisticRegression.ipynb --- RegularizedLogisticRegression.ipynb | 126 ---------------------------- 1 file changed, 126 deletions(-) delete mode 100644 RegularizedLogisticRegression.ipynb diff --git a/RegularizedLogisticRegression.ipynb b/RegularizedLogisticRegression.ipynb deleted file mode 100644 index 0f24838..0000000 --- a/RegularizedLogisticRegression.ipynb +++ /dev/null @@ -1,126 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import scipy.optimize as opt\n", - "from scipy.io import loadmat\n", - "from CostGradient import cost, gradient\n", - "from SigmoidFunction import sigmoid\n", - "class LogisticRegression:\n", - " '''\n", - " Regularised Logistic Regression\n", - " '''\n", - " def __init__(self,lmbda=0.1,num_iter=100,fit_intercept=True,threshold=0.5):\n", - " self.lmbda = lmbda\n", - " self.num_iter = num_iter\n", - " self.fit_intercept = fit_intercept\n", - " self.threshold = threshold\n", - " return None\n", - " \n", - " def intercept(self,X):\n", - " '''\n", - " This allows the y-intercept to be computed\n", - " '''\n", - " ones = np.ones((len(X),1))\n", - " return np.c_[ones,X]\n", - " \n", - " def fit(self,X,y):\n", - " if self.fit_intercept:\n", - " X = self.intercept(X)\n", - " #p = len(y)\n", - " (m,n) = X.shape\n", - " lmbda = self.lmbda\n", - " self.num_class = np.unique(y).size\n", - " \n", - " # binary logistic regression\n", - " if self.num_class == 2:\n", - " coefs = np.zeros((1,n))\n", - " coefs = opt.fmin_cg(f=cost,x0=coefs,fprime=gradient,args=(X,y.flatten(),lmbda),maxiter=self.num_iter,disp=False)\n", - " \n", - " \n", - " # One vs all (multiple class)\n", - " elif self.num_class > 2:\n", - " coefs = np.zeros((self.num_class,n))\n", - " for i in range(self.num_class):\n", - " digit = i \n", - " coefs[i] = opt.fmin_cg(f=cost,x0=coefs[i],fprime=gradient,args=(X,(y==digit).flatten(),lmbda),maxiter=self.num_iter,disp=False)\n", - " \n", - " self.coefs = coefs\n", - " \n", - " def predict_proba(self,X):\n", - " if self.fit_intercept:\n", - " X = self.intercept(X)\n", - " self.proba = sigmoid(np.dot(X,self.coefs.T))\n", - " return self.proba\n", - " \n", - " def predict(self,X):\n", - " if self.num_class == 2:\n", - " predict = (self.predict_proba(X)>=self.threshold).astype(int)\n", - " elif self.num_class > 2:\n", - " if self.fit_intercept:\n", - " X = self.intercept(X)\n", - " predict = np.argmax(np.dot(X,self.coefs.T),axis=1)\n", - " return predict\n", - " \n", - " def score(self,X,y):\n", - " pred = self.predict(X)\n", - " return np.mean(pred==y.flatten())*100\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.4" - }, - "varInspector": { - "cols": { - "lenName": 16, - "lenType": 16, - "lenVar": 40 - }, - "kernels_config": { - "python": { - "delete_cmd_postfix": "", - "delete_cmd_prefix": "del ", - "library": "var_list.py", - "varRefreshCmd": "print(var_dic_list())" - }, - "r": { - "delete_cmd_postfix": ") ", - "delete_cmd_prefix": "rm(", - "library": "var_list.r", - "varRefreshCmd": "cat(var_dic_list()) " - } - }, - "types_to_exclude": [ - "module", - "function", - "builtin_function_or_method", - "instance", - "_Feature" - ], - "window_display": false - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} From e07375ec6ee5c2c84c09817a2a57fd3a035b9d57 Mon Sep 17 00:00:00 2001 From: Ogbonna Chibuike Stephen Date: Thu, 23 Apr 2020 23:55:44 +0100 Subject: [PATCH 09/10] Add files via upload --- RegularizedLogisticRegression.ipynb | 126 ++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 RegularizedLogisticRegression.ipynb diff --git a/RegularizedLogisticRegression.ipynb b/RegularizedLogisticRegression.ipynb new file mode 100644 index 0000000..cf4d6d8 --- /dev/null +++ b/RegularizedLogisticRegression.ipynb @@ -0,0 +1,126 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import scipy.optimize as opt\n", + "from scipy.io import loadmat\n", + "from CostGradient import cost, gradient\n", + "from SigmoidFunction import sigmoid\n", + "class LogisticRegression:\n", + " '''\n", + " Regularised Logistic Regression\n", + " '''\n", + " def __init__(self,lmbda=0.1,num_iter=100,fit_intercept=True,threshold=0.5):\n", + " self.lmbda = lmbda\n", + " self.num_iter = num_iter\n", + " self.fit_intercept = fit_intercept\n", + " self.threshold = threshold\n", + " return None\n", + " \n", + " def intercept(self,X):\n", + " '''\n", + " This allows the y-intercept to be computed\n", + " '''\n", + " ones = np.ones((len(X),1))\n", + " return np.c_[ones,X]\n", + " \n", + " def fit(self,X,y):\n", + " if self.fit_intercept:\n", + " X = self.intercept(X)\n", + " #p = len(y)\n", + " (m,n) = X.shape\n", + " lmbda = self.lmbda\n", + " self.num_class = np.unique(y).size\n", + " \n", + " # binary logistic regression\n", + " if self.num_class == 2:\n", + " coefs = np.zeros((1,n))\n", + " coefs = opt.fmin_cg(f=cost,x0=coefs,fprime=gradient,\n", + " args=(X,y.flatten(),lmbda),maxiter=self.num_iter,disp=False)\n", + " \n", + " # One vs all (multiple class)\n", + " elif self.num_class > 2:\n", + " coefs = np.zeros((self.num_class,n))\n", + " for i in range(self.num_class):\n", + " digit = i \n", + " coefs[i] = opt.fmin_cg(f=cost,x0=coefs[i],fprime=gradient,\n", + " args=(X,(y==digit).flatten(),lmbda),maxiter=self.num_iter,disp=False)\n", + " self.coefs = coefs\n", + " \n", + " def predict_proba(self,X):\n", + " if self.fit_intercept:\n", + " X = self.intercept(X)\n", + " self.proba = sigmoid(np.dot(X,self.coefs.T))\n", + " return self.proba\n", + " \n", + " def predict(self,X):\n", + " if self.num_class == 2:\n", + " predict = (self.predict_proba(X)>=self.threshold).astype(int)\n", + " elif self.num_class > 2:\n", + " if self.fit_intercept:\n", + " X = self.intercept(X)\n", + " predict = np.argmax(np.dot(X,self.coefs.T),axis=1)\n", + " return predict\n", + " \n", + " def score(self,X,y):\n", + " pred = self.predict(X)\n", + " return np.mean(pred==y.flatten())*100\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.4" + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 6f3bfe09931ce6ceefbc774c92c8f1a8907ceea0 Mon Sep 17 00:00:00 2001 From: Ogbonna Chibuike Stephen Date: Fri, 24 Apr 2020 00:12:52 +0100 Subject: [PATCH 10/10] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7e47e49..b6bd2f2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ML-Logistic-regression-algorithm-challenge -I created a Regulaized Logistic Regression that performs both binary and multi classifications wth Cost Gradient Descent as my optimizer. +I created a Regulaized Logistic Regression that performs both binary and multi classifications wth Conjugate Gradient Descent as my optimizer. First, I created two python scripts, Sigmoid function.py and CostGradient.py. These two script were imported into the Regularised logistic regression notebook.