-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSGD.py
117 lines (90 loc) · 3.39 KB
/
SGD.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 sklearn.datasets import load_boston
import matplotlib.pyplot as plt
BATCHES = 50
class BatchSampler(object):
'''
A (very) simple wrapper to randomly sample batches without replacement.
You shouldn't need to touch this.
'''
def __init__(self, data, targets, batch_size):
self.num_points = data.shape[0]
self.features = data.shape[1]
self.batch_size = batch_size
self.data = data
self.targets = targets
self.indices = np.arange(self.num_points)
def random_batch_indices(self, m=None):
'''
Get random batch indices without replacement from the dataset.
If m is given the batch will be of size m. Otherwise will default to the class initialized value.
'''
if m is None:
indices = np.random.choice(self.indices, self.batch_size, replace=False)
else:
indices = np.random.choice(self.indices, m, replace=False)
return indices
def get_batch(self, m=None):
'''
Get a random batch without replacement from the dataset.
If m is given the batch will be of size m. Otherwise will default to the class initialized value.
'''
indices = self.random_batch_indices(m)
X_batch = np.take(self.data, indices, 0)
y_batch = self.targets[indices]
return X_batch, y_batch
def load_data_and_init_params():
'''
Load the Boston houses dataset and randomly initialise linear regression weights.
'''
print('------ Loading Boston Houses Dataset ------')
X, y = load_boston(True)
features = X.shape[1]
# Initialize w
w = np.random.randn(features)
print("Loaded...")
print("Total data points: {0}\nFeature count: {1}".format(X.shape[0], X.shape[1]))
print("Random parameters, w: {0}".format(w))
print('-------------------------------------------\n\n\n')
return X, y, w
def cosine_similarity(vec1, vec2):
'''
Compute the cosine similarity (cos theta) between two vectors.
'''
dot = np.dot(vec1, vec2)
sum1 = np.sqrt(np.dot(vec1, vec1))
sum2 = np.sqrt(np.dot(vec2, vec2))
return dot / (sum1 * sum2)
def lin_reg_gradient(X, y, w):
'''
Compute gradient of linear regression model parameterized by w
'''
return 2/X.shape[0] * ( np.dot(np.dot(X.transpose(), X), w)
- np.dot(X.transpose(), y) )
def main():
# Load data and randomly initialise weights
X, y, w = load_data_and_init_params()
# Create a batch sampler to generate random batches from data
batch_sampler = BatchSampler(X, y, BATCHES)
true_gradient = lin_reg_gradient(X, y, w)
batch_grad = 0
for k in range(500):
X_b, y_b = batch_sampler.get_batch(m=50)
batch_grad += lin_reg_gradient(X_b, y_b, w) / 500
print("Mean square error: ", np.mean((true_gradient - batch_grad)**2) )
print("Cosine similarity: ", cosine_similarity(true_gradient, batch_grad))
x_plot = []
y_plot = []
for m in range(1,401):
w_j = []
for k in range(500):
X_b, y_b = batch_sampler.get_batch(m=m)
w_j.append(lin_reg_gradient(X_b, y_b, w)[0])
x_plot.append(np.log(m))
y_plot.append(np.log(np.var(w_j)))
plt.xlabel("log(m)")
plt.ylabel("log(var(w[0]))")
plt.plot(x_plot, y_plot)
plt.show()
if __name__ == '__main__':
main()