-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdemo.py
executable file
·102 lines (78 loc) · 3.35 KB
/
demo.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
#!/usr/bin/env python3
import sklearn
import sklearn.datasets
import numpy as np
import matplotlib.pyplot as plt
import tqdm
X, y = sklearn.datasets.load_digits(return_X_y=True)
#Arrange into chunks with one example of each class
one_hot = y[:,np.newaxis]==np.arange(10)
occurrence = np.choose(np.round(y),one_hot.cumsum(axis=0).T)
idx = np.lexsort((y,occurrence))
X, y = X[idx], y[idx]
min_freq = one_hot.sum(axis=0).min()
X, y = X[:10*min_freq], y[:10*min_freq]
#One-hot encoding
y = (y[:,np.newaxis]==np.arange(10))*1.0
def standardise(x, axis=None):
return (x-x.mean(axis=axis)) * np.nan_to_num(1/x.std(axis=axis))
def one_hot(key, idx):
X_ = X[idx]
y_ = y[idx,key]
return [standardise(x,axis=0) for x in (X_,y_)]
def get_beta(X, y, penalty = None):
XTX = np.cov(X.T)
XTy = np.cov(X.T, y.reshape(1,-1))[-1,:-1]
if penalty is None:
penalty = np.zeros_like(XTX)
try:
return np.linalg.solve(XTX + penalty, XTy)
except np.linalg.LinAlgError:
return np.nan
def loocv_mse(X, y, penalty = None):
def loocv_residual(i):
X_train = np.delete(X,i,axis=0)
y_train = np.delete(y,i)
return y[i] - np.dot(X[i],get_beta(X_train,y_train,penalty))
return np.mean([loocv_residual(i)**2 for i in range(len(y))])
if __name__ == '__main__':
print('Results')
fig, ax = plt.subplots(5,2, sharex=True, sharey=False)
fig.suptitle('MSE from LOOCV')
chunks = [slice(30*i,30*(i+1)) for i in range(len(y)//30)]
penalty_strengths = np.linspace(0,1,5)
for key in range(10):
print(key)
f = ax[key//2,key%2]
"""
ols = loocv_mse(*one_hot(key))
f.hlines(ols, penalty_strengths[0], penalty_strengths[-1], label='OLS')
"""
print('Ridge')
ridge_penalty = np.eye(64)
ridge = [np.mean([loocv_mse(*one_hot(key, idx), strength*ridge_penalty) for idx in chunks]) for strength in tqdm.tqdm(penalty_strengths)]
f.plot(penalty_strengths, ridge, label='Ridge')
for lengthscale in (0.5,0.6,0.7,0.8,0.9,1):
print(f'Off-diagonal Penalty, {lengthscale=}')
offdiagonal_penalty = np.array([[np.exp(-((x1-x2)**2+(y1-y2)**2)/lengthscale**2) for x1 in range(8) for y1 in range(8)] for x2 in range(8) for y2 in range(8)])
offdiagonal = [np.mean([loocv_mse(*one_hot(key, idx), strength*offdiagonal_penalty) for idx in chunks]) for strength in tqdm.tqdm(penalty_strengths)]
f.plot(penalty_strengths, offdiagonal, label=f'Non-Orthogonal Quadratic Penalty ({lengthscale=})')
f.set_xlabel('Penalty Strength')
f.set_ylabel('MSE')
f.set_yscale('log')
f.set_title(f'{key}')
f.legend()
fig.set_size_inches(20, 20)
fig.savefig('output/mse_loocv.png')
print('Empirical Covariance vs. Penalty')
fig, ax = plt.subplots(7,1)
M = np.cov(X.T)
ax[0].imshow(M)
ax[0].set_title('Empirical Covariance')
for i,lengthscale in enumerate((0.5,0.6,0.7,0.8,0.9,1)):
print(f'Off-diagonal Penalty, {lengthscale=}')
offdiagonal_penalty = np.array([[np.exp(-((x1-x2)**2+(y1-y2)**2)/lengthscale**2) for x1 in range(8) for y1 in range(8)] for x2 in range(8) for y2 in range(8)])
ax[i+1].imshow(offdiagonal_penalty)
ax[i+1].set_title(f'Penalty Matrix ({lengthscale=})')
fig.set_size_inches(5,20)
fig.savefig('output/matrices.png')