-
Notifications
You must be signed in to change notification settings - Fork 910
/
np_shallow_neural_classifier.py
117 lines (85 loc) · 3.44 KB
/
np_shallow_neural_classifier.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
import numpy as np
from np_model_base import NNModelBase
from utils import randvec, randmatrix, softmax, progress_bar, safe_macro_f1
__author__ = "Christopher Potts"
__version__ = "CS224u, Stanford, Spring 2022"
class ShallowNeuralClassifier(NNModelBase):
def __init__(self, **kwargs):
"""
Fit a model
h = f(xW_xh + b_h)
y = softmax(hW_hy + b2_y)
with a cross entropy loss and f set by `hidden_activation` and
`d_hidden_activation`.
Parameters
----------
hidden_dim : int (default: 40)
Dimensionality of the hidden layer.
hidden_activation : vectorized activation function
The non-linear activation function used by the
network for the hidden and output layers.
d_hidden_activation : vectorized activation function derivative.
The derivative of `afunc`. It does not ensure that this
matches `afunc`, and craziness will result from mismatches!
max_iter : int default: 100)
Maximum number of training epochs.
eta : float (default: 0.05)
Learning rate.
tol : float (default: 1.5e-8)
Training terminates if the error reaches this point (or
`maxiter` is met).
display_progress : bool (default: True)
Whether to use the simple over-writing `progress_bar`
to show progress.
All the parameters are set as attributes.
"""
super().__init__(**kwargs)
self.params += ['hidden_activation', 'd_hidden_activation']
def fit(self, X, y):
self.input_dim = X.shape[1]
super().fit(X, y)
def initialize_parameters(self):
self.W_xh = self.weight_init(self.input_dim, self.hidden_dim)
self.b_xh = np.zeros(self.hidden_dim)
self.W_hy = self.weight_init(self.hidden_dim, self.output_dim)
self.b_hy = np.zeros(self.output_dim)
def update_parameters(self, gradients):
d_W_hy, d_b_hy, d_W_xh, d_b_xh = gradients
self.W_hy -= self.eta * d_W_hy
self.b_hy -= self.eta * d_b_hy
self.W_xh -= self.eta * d_W_xh
self.b_xh -= self.eta * d_b_xh
def forward_propagation(self, x):
h = self.hidden_activation(x.dot(self.W_xh) + self.b_xh)
y = softmax(h.dot(self.W_hy) + self.b_hy)
return h, y
def backward_propagation(self, h, predictions, x, labels):
y_err = predictions.copy()
y_err[np.argmax(labels)] -= 1
d_b_hy = y_err
h_err = y_err.dot(self.W_hy.T) * self.d_hidden_activation(h)
d_W_hy = np.outer(h, y_err)
d_W_xh = np.outer(x, h_err)
d_b_xh = h_err
return d_W_hy, d_b_hy, d_W_xh, d_b_xh
def score(self, X, y):
preds = self.predict(X)
return safe_macro_f1(y, preds)
def simple_example():
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, accuracy_score
digits = load_digits()
X = digits.data
y = digits.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.33, random_state=42)
mod = ShallowNeuralClassifier()
print(mod)
mod.fit(X_train, y_train)
preds = mod.predict(X_test)
print("\nClassification report:")
print(classification_report(y_test, preds))
return accuracy_score(y_test, preds)
if __name__ == '__main__':
simple_example()