-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathaveraged_rect_zero.py
More file actions
114 lines (78 loc) · 3.31 KB
/
Copy pathaveraged_rect_zero.py
File metadata and controls
114 lines (78 loc) · 3.31 KB
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
import numpy as np
import sys
import torch
from torch import nn
class NetworkTeacher(nn.Module):
def __init__(self, D, M, L):
super(NetworkTeacher, self).__init__()
self.D = D
self.M = M
self.L = L
self.fc1U = nn.Parameter(torch.normal(0, 1, (M, D), requires_grad=True))
self.fc1V = nn.Parameter(torch.normal(0, 1, (L, M), requires_grad=True))
def forward(self, x):
S = self.fc1V @ self.fc1U
return torch.einsum("ij,nij", S, x) / np.sqrt(self.M) / np.sqrt(self.L * self.D)
class NetworkStudent(nn.Module):
def __init__(self, D, M, L):
super(NetworkStudent, self).__init__()
self.D = D
self.M = M
self.L = L
self.fc1U = nn.Parameter(torch.normal(0, 1e-4, (M, D), requires_grad=True))
self.fc1V = nn.Parameter(torch.normal(0, 1e-4, (D, M), requires_grad=True))
def forward(self, x):
S = self.fc1V @ self.fc1U
return torch.einsum("ij,nij", S, x) / np.sqrt(self.M) / np.sqrt(self.L * self.D)
def main(D, alpha, rho, beta, L, lr, T, samples, averages):
M = int(D * rho)
M_star = int(D * rho)
N = int(D*L * alpha)
gen_error = np.ones((samples))
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
S_all = np.zeros((averages, L, D))
for s in range(samples):
# Initialise the teacher and student networks
with torch.no_grad():
teacher = NetworkTeacher(D, M_star, L).to(device)
U_star = teacher.fc1U.data.cpu().numpy()
V_star = teacher.fc1V.data.cpu().numpy()
S_star = V_star @ U_star / np.sqrt(M_star)
X = torch.normal(0,1, (N, L,D), requires_grad=False).to(device)
y = teacher(X)
for av in range(averages):
student = NetworkStudent(D, M, L).to(device)
# Optimizer
optimizer = torch.optim.SGD(student.parameters(), lr=lr)
# The training loop
for t in range(T):
# Compute the gradient of the loss with respect to the student network parameters
y_pred = student(X)
loss = ((y_pred - y)**2).sum()/4
loss.backward()
# Update the student network parameters
optimizer.step()
optimizer.zero_grad()
with torch.no_grad():
U = student.fc1U.data.cpu().numpy()
V = student.fc1V.data.cpu().numpy()
S = V @ U / np.sqrt(M)
S_all[av] = S
S_averaged = S_all[:av+1].mean(axis=0)
print(f"Sample {s+1}/{samples}, Iteration {av+1}/{averages}, Generalization error: {np.mean((S_averaged - S_star)**2)}")
gen_error[s] = np.mean((S_averaged - S_star)**2)
# Save the results
np.save(f"averaged/zero_gen_error_{D}_{alpha}_{rho}_{beta}_{lr}.npy", gen_error)
if __name__ == '__main__':
# Get the parameters from the command line
D = int(sys.argv[1])
alpha = float(sys.argv[2])
rho = float(sys.argv[3])
beta = float(sys.argv[4])
L = D // beta
rho = rho / beta
T = int(50000)
samples = 4
lr = 0.1
averages = 64
main(D, alpha, rho, beta, L, lr, T, samples, averages)