-
Notifications
You must be signed in to change notification settings - Fork 0
/
Week 0 Bonus - class implementation.py
106 lines (81 loc) · 4.22 KB
/
Week 0 Bonus - class implementation.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
# import functionality from these libraries
import numpy as np # for efficient numerical computation
import torch # for building computational graphs
from torch.autograd import Variable # for automatically computing gradients of our cost with respect to what we want to optimise
import matplotlib.pyplot as plt # for plotting absolutely anything
from mpl_toolkits.mplot3d import Axes3D # for plotting 3D graphs
# define hyperparameters as needed
epochs = 100 # how many times do we want to run through the data to train our model
lr = 0.05 # what proportion of our gradient do we want to update our parameters by
n = 2 # number of features e.g. number of windows, number of rooms
m = 50 # number of training examples, e.g. the number of windows and rooms was measured for m houses
#create dataset and variables - built in models use one row per data point rather than one column
X = Variable(torch.rand(m, n))
Y = Variable(2*X.data[:,0] + 6*X.data[:,1] + 0.1)
# create a figure
plt.ion()
fig = plt.figure(figsize=(10,10))
# create our first axes to plot our data in space
ax1 = fig.add_subplot(121, projection='3d')#start with 111
x1 = np.arange(2) # meshgrid takes two vectors which would be a range of numbers along each axis
x2 = np.arange(2) # it outputs two matrices where a pair of the same position element gives a coordinate
x1, x2 = np.meshgrid(x1, x2) # covering the entire domain of the input plane
ax1.scatter(X.data[:, 0], X.data[:, 1], Y.data[:]) #plot data points
ax1.set_xlabel('Windows')
ax1.set_ylabel('Rooms')
ax1.set_zlabel('House Price')
# add another set of axes to plot our cost decreasing with iteration
ax2 = fig.add_subplot(122)
ax2.set_xlabel('Iteration')
ax2.set_ylabel('Cost')
ax2.set_xlim(0, epochs)
ax2.grid()
plt.show()
#define model class
class LinearModel(torch.nn.Module): # import functionality from a torch module
def __init__(self):
super().__init__() #
self.linear = torch.nn.Linear(2, 1) # create a linear layer with 2 inputs leading to 1 output
def forward(self, x): # define computation for data passing through model
y_pred = self.linear(x) # prediction is a linear combination of inputs
return y_pred
#create model and define training params
m = LinearModel()
criterion = torch.nn.MSELoss(size_average=True) # our loss function is the mean squared error
optimizer = torch.optim.SGD(m.parameters(), lr=lr) # our optimisation technique is stochastic gradient descent
# to keep history of costs to plot against time
costs = []
#train model
for epoch in range(epochs):
y_pred = m(X)
cost = criterion(y_pred, Y) # calculate our current cost
costs.append(cost.data) # add current cost to the list of cost histories
print('Epoch ', epoch, ' Cost: ', cost.data[0])
# calling J.backwards() does not set the values in the var.grad,it adds to them
# otherwise it will contain the cumulative history of grads
optimizer.zero_grad()
# find rate of change of J with respect to each rg=True variable and put that in tht var.grad
cost.backward()
# update the model by moving each parameter in a the direction that most reduces error
optimizer.step()
# the bias and weights of the model are generated by the framework of the model
# get the current values of bias and weights and set them as variables
w, b = [m.state_dict()[i][0] for i in m.state_dict()]
# print our parameters
print('w1', w[0], ' \tw2', w[1], '\tb', b)
#plot costs
ax2.plot(costs, 'b')
y = b + x1 * w[0] + x2 * w[1] #calculate hypothesis surface
s = ax1.plot_surface(x1, x2, y, color=(0, 1, 1, 0.5)) #plot surface hypothesis
ax1.view_init(azim=epoch) #choose view angle of 3d plot (make it rotate)
fig.canvas.draw() # draw the new stuff on the canvas
s.remove() # remove the 3d surface plot object
#use model to predict new value
v = Variable(torch.Tensor([[4, 0]])) # the tensor needs to be made a variable
print('Predict [4, 0]: ', m.forward(v).data[0][0]) # put v forward through the model
# save variables for which rg =True
print(m.state_dict())
torch.save(m.state_dict(), 'saved_linear_model')
#load model
#m = Model()
#m.load_state_dict(torch.load('savedmodel'))