-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlogisticRegression.py
393 lines (268 loc) · 8.4 KB
/
logisticRegression.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
'''
Name :- Siddharth Nahar
Entry No :- 2016csb1043
Date :- 11/9/18
Purpose :- Extract Features data and create vectors
'''
import numpy as np
from numpy.linalg import inv
import math
import random
import matplotlib.pyplot as plt
#-----------------------------------------------------------
#Function to Plot data of X,Y classes
def plot(X,Y,t):
#Plot Data Structure for porper understanig
fig = plt.figure(1)
countx = 0
county = 0
for i in range(0,X.shape[0]):
if(Y[i] == 1):
if(countx == 0):
plt.plot(X[i][0],X[i][1],'bs',label = "Positve")
else:
plt.plot(X[i][0],X[i][1],'bs')
countx += 1
else:
if(county == 0):
plt.plot(X[i][0],X[i][1],'r^',label = "Negative")
else:
plt.plot(X[i][0],X[i][1],'r^')
county += 1
#Providing more Attributes
plt.legend(loc = "upper right")
plt.title(t)
#--------------------------------------------------------------
#------------------------------------------------------------
#Function to get Sigmoid Fucntion
def sigmoid(Z):
#Zdash = Z.astype(dtype=np.float128)
return 1/(1 + np.exp(-Z))
#------------------------------------------------------------
#Function for Cost calculation
def costFunc(X,Y,W,lamb):
#To chech if our gradient descent converges after each iteration
f = sigmoid(X@W)
e = 0.00001
f = f+e
#Formula for Cost of Reularized Hypothesis Logistic Regression
cost = (np.log(f)).transpose()@Y + (np.log(1-f)).transpose()@(1-Y)
cost = -1*cost/X.shape[0]
square = W**2
weights = (np.sum(square) - square[0])*lamb
weights = weights/(2*X.shape[0])
cost = cost + weights
return cost
#------------------------------------------------------------
#Function for Grad
def grad(X,Y,W,lamb):
#Gradient = X'(f-Y) + lam*W
f = sigmoid(X@W)
Xt = X.transpose()
gr = f-Y
gr = Xt@gr
gr = gr + lamb*W
#We don't regularize w0 as prerequired basis
gr[0] = gr[0] - lamb*W[0]
gr = gr/X.shape[0]
return gr
#-------------------------------------------------------------
def evalFunc(X,Y,W):
#Calculation of Error of Hypothesis based on scale 1
f = sigmoid(X@W)
f = np.round(f)
error = f - Y
err = np.sum(error**2)
return err/X.shape[0]
#--------------------------------------------------------------
#Function for Gradient Descent
def gradientDescent(X,Y,W,nIter,alpha,lamb):
Wprev = W
for i in range(0,nIter):
error = costFunc(X,Y,Wprev,lamb)
if(math.isnan(error) == True):
break
print("After iteration : "+str(i) + " ,Cost Evaluation for Convergence = "+str(error))
#Upgrade W by calculation of gradient
Wnew = Wprev - alpha*grad(X,Y,Wprev,lamb)
#If W doesnt change much it has converged so break
if(np.sum(np.absolute(Wnew-Wprev)) <= 0.00000000005):
break
#print(Wnew)
Wprev = Wnew
return Wprev
#--------------------------------------------------------------
#Function to Return Inverse of f''
def hurestic(X,Y,W,lamb):
#Calculate hypothesis value
f = sigmoid(X@W)
f = f + 0.000001
R = np.identity(X.shape[0])
Xt = X.transpose()
fdash = f*(1-f)
#Create X'RX create R as diagonal matrix
for i in range(0,X.shape[0]):
R[i][i] = fdash[i]
#For Regularized f'' = lam*Identity
Id = np.identity(X.shape[1])
#We don't regularize w0 as it's basis
Id[0][0] = 0
#H = (X'RX + lam*I)^-1
H = R@X
H = Xt@H
H = H + lamb*Id
H = H/X.shape[0]
H = inv(H)
return H
#----------------------------------------------------------------
#Function for Newton Raphson method
def newtonRaphson(X,Y,W,nIter,lamb):
#print(Y.shape)
Wprev = W
for i in range(0,nIter):
error = costFunc(X,Y,Wprev,lamb)
#If error is nan that is sigmoid returns zero
if(math.isnan(error) == True):
break
print("After iteration : "+str(i) + " ,Cost Evaluation for Convergence = "+str(error))
#print("After iteration : "+str(error))
#Calculate inverse of double differential of f
H = hurestic(X,Y,Wprev,lamb)
#Calculate Gradient of f
G = grad(X,Y,Wprev,lamb)
#Update W for next iteration
Wnew = Wprev - H@G
#If W doesnt change much it has converged so break
if(np.sum(np.absolute(Wnew-Wprev)) <= 0.00000000005):
break
#print(Wprev)
Wprev = Wnew
return Wprev
#--------------------------------------------------------------
#Function to create Polynomial Degrees
def kernel(X,degree):
#print(X.shape)
Rows = X.shape[0]
Cols = X.shape[1]
featureVector = list()
for i in range(0,Rows):
j = 0
#Create Ascending Power of polynomial and store in list
vector = list()
while(j <= degree):
k = j
while(k >= 0):
vector.append((X[i][0]**k)*(X[i][1]**(j-k)))
k = k - 1
j = j + 1
#print(vector)
featureVector.append(vector)
#Convert List to numpy array
Xnew = np.array(featureVector)
return Xnew
#-------------------------------------------------------------
#Function to plot decision boundary
def plotDecisionBoundary(X,Y,W,degree,t):
#print(X)
#If Linear Boundary is to be Plot
if(X.shape[1] <= 3):
#Plot by only two points Calculations
plot(X[:,1:3],Y,"")
plot_x = [np.min(X[:,1]),np.max(X[:,1])]
plot_x = np.array(plot_x)
plot_y = W[1]*plot_x + W[0]
plot_y = -1*plot_y/W[2]
#Setting other Attrivutes of plot
plt.plot(plot_x,plot_y,'--b')
plt.gca().set_ylim([0,8])
plt.title(t)
#plt.savefig("Newton_Raphson_Linear_Boundary")
plt.show()
#For Polynomial Degree Plot
else:
#Plot for Polynomial Degree Using Contour Plot to plot
plot(X[:,1:3],Y,"")
#Create x1,x2 values by linspace and Calculate Y for each
u = np.linspace(0.01,6.0,50)
v = np.linspace(0.01,8.0,50)
z = np.zeros((50,50),dtype = float)
for i in range(0,50):
for j in range(0,50):
a = [u[i],v[j]]
a = np.array(a)
a = np.reshape(a,(1,2))
z[i][j] = kernel(np.array(a),degree)@W
z = z.transpose()
#Plot the Contour
plt.contour(u, v, z, 0, linewidths = 2,linestyles='dashed')
plt.title(t)
#plt.savefig("Sample")
plt.show()
#-------------------------------------------------------------
#Function to Run the Logistic Algorithm
def run(featureMatrix):
#Create featureMatrix tuple for extracting Rows and Cols
tuples = featureMatrix.shape
deg = input("Enter the Degree of Polynomial To Fit,Enter Polynomial <=4 : ")
lam = input("Input 0 for Overfitt and 1 for Underfitt : ")
deg = int(deg)
lam = int(lam)
if(lam > 1):
lam = 1
#if deg < 4 alpha = 0.01 else apha = 0.00006
#Initialise Degree of Polynomial to Fit model
#deg = 1
#Create X vector and Y vector
featureMatrixX = featureMatrix[:,0:tuples[1]-1]
featureMatrixY = featureMatrix[:,-1]
#Plot DataSet for Visualization
plot(featureMatrixX,featureMatrixY,"Representation of Data")
plt.show()
plt.clf()
Y = featureMatrixY
#Create Y Vaector to single column
Y = np.reshape(Y,(tuples[0],1))
X = kernel(featureMatrixX,deg)
Row,Cols = X.shape
#Initialise W by random Values
W = np.random.rand(Cols,1)
W = W*0.0002 - 0.0001
#------------------------------------------------------------------------
#For Gradient Descent We have different Alphas so:
alpha = 0.001
if(deg >= 4):
alpha = 0.00006
if(deg > 4):
print("Adjusting parameters for Gradient descent for such high polynomial is Difficult Please enter value less than 5")
exit()
else:
Wnew = gradientDescent(X,Y,W.copy(),100000,alpha,lam)
err = str(evalFunc(X,Y,Wnew))
print("After Gradient Descent Error on DataSet :- " + err )
Title = "Gradient Descent ," + "Degree = "+str(deg)+"\n" + "Alpha = " + str(alpha) +",Regualrization Params : "+ str(lam) +"\nError : "+err
plotDecisionBoundary(X,Y,Wnew,deg,Title)
plt.clf()
#----------------------------------------------------------------------------
#For Newton Raphson
Wnew = newtonRaphson(X,Y,W.copy(),1000,lam)
err = str(evalFunc(X,Y,Wnew))
print("After Newton Raphson Error on DataSet :- " + err)
Title = "Newton Raphson ," + "Degree = "+str(deg)+"\n" + "Regualrization Params : "+ str(lam) + "\nError : "+err
plotDecisionBoundary(X,Y,Wnew,deg,Title)
#------------------------------------------------------------------------------
#------------------------------------------------------------
if __name__ == '__main__':
#Feature Extraction from linregdata file
logiRegData = open('credit.txt','r')
featureVector = list()
#Traverse through file and create feature vector
for line in logiRegData:
line = line.split(',')
vector = list()
for data in line:
val = float(data)
vector.append(val)
featureVector.append(vector)
#Create Numpy array from feature vector
featureMatrix = np.array(featureVector)
run(featureMatrix)