-
Notifications
You must be signed in to change notification settings - Fork 0
/
logistic.py
93 lines (63 loc) · 2.72 KB
/
logistic.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
"""Logistic regression model."""
import numpy as np
class Logistic:
def __init__(self, lr: float, epochs: int, threshold: float):
"""Initialize a new classifier.
Parameters:
lr: the learning rate
epochs: the number of epochs to train for
"""
self.w = None # TODO: change this
self.lr = lr
self.epochs = epochs
self.threshold = threshold
def sigmoid(self, z: np.ndarray) -> np.ndarray:
"""Sigmoid function.
Parameters:
z: the input
Returns:
the sigmoid of the input
"""
# TODO: implement me
return 1/(1+np.exp(-z))
def train(self, X_train: np.ndarray, y_train: np.ndarray):
"""Train the classifier.
Use the logistic regression update rule as introduced in lecture.
Parameters:
X_train: a numpy array of shape (N, D) containing training data;
N examples with D dimensions
y_train: a numpy array of shape (N,) containing training labels
"""
# TODO: implement me
# N, D = X_train.shape
# self.w = np.zeros((1,D))
# for epoch in range(self.epochs):
# margins = -y_train.reshape(-1,1) * np.dot(X_train, self.w.T) #N*1 * (N,D @ D,1)
# sigmoids = self.sigmoid(margins)
# multi_term = y_train.reshape(-1,1) * X_train #N,D
# self.w = self.w + self.lr*np.dot(sigmoids.T, multi_term)
# self.lr = self.lr * 0.95
N, D = X_train.shape
self.w = np.zeros((1, D))
for epoch in range(self.epochs):
margins = np.dot(X_train, self.w.T) #N,D * D*1 -> N,1
scores = self.sigmoid(margins) #N,1
der_term = scores - y_train.reshape(-1,1) #N,1
der_term = np.dot(der_term.T, X_train) #1,N * N*D -> 1*D
self.w = self.w - self.lr * der_term
#pass
def predict(self, X_test: np.ndarray) -> np.ndarray:
"""Use the trained weights to predict labels for test data points.
Parameters:
X_test: a numpy array of shape (N, D) containing testing data;
N examples with D dimensions
Returns:
predicted labels for the data in X_test; a 1-dimensional array of
length N, where each element is an integer giving the predicted
class.
"""
# TODO: implement me
preds = np.dot(X_test, self.w.T) #N,D * D,1 -> N,1
preds = self.sigmoid(preds) #N,1
preds = np.where(preds>self.threshold, 1, 0)
return np.squeeze(preds)