-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTests_Utils.py
96 lines (87 loc) · 3.24 KB
/
Tests_Utils.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
import numpy as np
import matplotlib.pyplot as plt
from scipy.io import loadmat
def jacobian_verification(X,W,Y,b, epsilons, loss_function):
num_features = X.shape[0]
num_samples = X.shape[1]
d = np.random.rand(num_features, num_samples)
losses_ord1 = []
losses_ord2 = []
for epsilon in epsilons:
eps_d = epsilon*d
X_plus = X.copy() + eps_d
#first order:
loss_plus, _, _, _ = loss_function(X_plus, Y, W, b)
loss, _,_, dx = loss_function(X, Y, W, b)
loss_ord1 = loss_plus - loss
loss_ord1_abs = np.abs(loss_ord1)
#second order:
loss_ord2 = loss_ord1 - np.sum(np.multiply(eps_d, dx))
loss_ord2_abs = np.abs(loss_ord2)
losses_ord1.append(loss_ord1_abs)
losses_ord2.append(loss_ord2_abs)
return losses_ord1, losses_ord2
def jacobian_verification_visualizer(losses_ord1, losses_ord2, epsilons):
epsilons = np.sort(epsilons)
plt.plot(epsilons, losses_ord1, label='First Order - O(\u03B5)')
plt.plot(epsilons, losses_ord2, label='Second Order - O(\u03B5^2)')
plt.xscale('log')
plt.yscale('log')
plt.xlabel('Epsilon')
plt.ylabel('Loss')
plt.title('Gradient Verification - Log Scale')
plt.legend()
plt.show()
def get_network_loss_and_dx(NN, X, Y):
NN.forward(X)
NN.backward(Y)
dX = NN.layers[0].dX
loss = NN.layers[-1].loss
return loss, dX
#following the same logic from the previous gradient/jacoian verification:
def network_gradient_verification(NN, X, Y, epsilons):
input_features = NN.layers[0].W.shape[1]
d = np.random.rand(input_features, 1)
losses_ord1 = []
losses_ord2 = []
for epsilon in epsilons:
eps_d = epsilon*d
X_plus = X.copy() + eps_d
loss_plus, _ = get_network_loss_and_dx(NN, X_plus, Y)
loss, dx = get_network_loss_and_dx(NN, X, Y)
#first order:
loss_ord1 = loss_plus - loss
loss_ord1_abs = np.abs(loss_ord1)
epsd_grad = np.sum(np.multiply(eps_d, dx))
losses_ord1.append(loss_ord1_abs)
#second order:
loss_ord2 = loss_ord1 - epsd_grad
loss_ord2_abs = np.abs(loss_ord2)
losses_ord2.append(loss_ord2_abs)
return losses_ord1, losses_ord2
def parse_data(filename, limited_data_set=False):
path = f"./HW1_Data/{filename}.mat"
data = loadmat(path)
Yt = data['Yt']
Ct = data['Ct']
Yv = data['Yv']
Cv = data['Cv']
if limited_data_set:
Yt = Yt[:, :200]
Ct = Ct[:, :200]
return Yt, Ct, Yv, Cv
def test_network_on_data_set(data_set, network, limited_data_set=False):
Yt, Ct, Yv, Cv = parse_data(data_set, limited_data_set=limited_data_set)
#train the network:
alpha = 0.1
beta = 0.9
num_iterations = 500
batch_size = 30
train_losses = network.train(Yt, Ct, batch_size, alpha, beta, num_iterations)
#test the network:
predictions = network.predict_probs(Yv)
W_id = np.identity(network.layers[-1].W.shape[1])
b_id = np.zeros((network.layers[-1].b.shape[1], 1))
test_loss, _, _, _ = network.layers[-1].activation["der"](predictions, Cv, W_id, b_id)
test_accurcy = np.sum(np.argmax(predictions, axis=0) == np.argmax(Cv, axis=0)) / Cv.shape[1] * 100
return train_losses, test_loss, test_accurcy