In [48]:
import time
import warnings
warnings.filterwarnings('ignore')
In [25]:
class GradientDescent:
def __init__(self,training_data,start,learning_rate,num_iterations):
"""
training_data: The data that is to be considered for the supervised learning problem \n
start: Initial guess of the parameters \n
learning_rate: Rate which determines the step size for every iteration \n
num_iterations: Total Number of Iterations
"""
# Convert training data to matrices
X = []
y = []
for x_vec, y_val in training_data:
X.append([1] + list(x_vec)) # Add bias term
y.append(y_val)
self.X = np.array(X) # Shape: (m, n+1) where m=samples, n=features
self.y = np.array(y) # Shape: (m,)
self.m=len(training_data) # number of training examples
self.start = np.array(start) # Inital starting point
self.learning_rate = learning_rate
self.num_iterations = num_iterations
self.points = [tuple(start)]
def compute_gradient_loop(self, current):
current = np.array(current)
grad = np.zeros_like(current)
for i in range(self.m):
x_i = self.X[i] # i-th training example
y_i = self.y[i] # i-th target
residual = y_i - np.dot(current, x_i)
grad += residual * x_i
return grad
def run(self):
current=np.array(self.start)
for _ in range(self.num_iterations):
grad=self.compute_gradient_loop(current)
current = current + self.learning_rate * grad
self.points.append(tuple(current))
def predict(self,query_point):
query_point_with_dummy=[1.0]+list(query_point)
return np.dot(np.array(self.points[-1]),np.array(query_point_with_dummy))
In [26]:
import numpy as np
class StochasticGradientDescent:
def __init__(self,training_data,start,learning_rate,num_iterations):
"""
training_data: The data that is to be considered for the supervised learning problem \n
start: Initial guess of the parameters \n
learning_rate: Rate which determines the step size for every iteration \n
num_iterations: Total Number of Iterations
"""
self.training_data=[(tuple([1]+list(x)),y) for x,y in training_data]
self.start=start
self.learning_rate=learning_rate
self.num_iterations=num_iterations
self.points=[start]
def compute_gradient(self,point,i):
grad=np.zeros_like(point)
point=np.array(point)
x_i=np.array(self.training_data[i][0])
y_i=self.training_data[i][1]
residual=y_i-np.dot(point,x_i)
grad+=(residual)*x_i
return tuple(grad)
def run(self):
for _ in range(self.num_iterations):
i=np.random.randint(0,len(self.training_data))
current=self.points[-1]
gradient=self.compute_gradient(current,i)
update = tuple(current[j] + self.learning_rate * gradient[j] for j in range(len(current)))
self.points.append(update)
def predict(self,query_point):
query_point_with_dummy=[1.0]+list(query_point)
return np.dot(np.array(self.points[-1]),np.array(query_point_with_dummy))
In [27]:
import time
training_data = [([1.0, 2.0,4.0,5.0], 12.0),([1.0, 8.0,4.0,6.0], 19.0), ([2.0,4.0, 4.0,5.0], 15.0)]
gd = GradientDescent(start=(0.0,0.0,0.0,0.0,0), learning_rate=0.005, num_iterations=int(10e5), training_data=training_data)
start=time.time()
gd.run()
end=time.time()
print(f'parameters from Batch GD: {gd.points[-1]}\n')
print(f'time taken: {(end-start)}\n')
print(f'prediction for (3,3,3,3): {gd.predict([3,3,3,3])}\n')
sgd = StochasticGradientDescent(start=(0.0,0.0,0.0,0.0,0), learning_rate=0.005, num_iterations=int(10e5), training_data=training_data)
start=time.time()
sgd.run()
end=time.time()
print(f'parameters from Stochastic GD: {sgd.points[-1]}\n')
print(f'time taken: {(end-start)}\n')
print(f'prediction for (3,3,3,3): {sgd.predict([3,3,3,3])}\n')
parameters from Batch GD: (0.2341891045710697, 1.0012523481527535, 0.9993738259236024, 0.9367564182842788, 1.003757044458375) time taken: 28.767800092697144 prediction for (3,3,3,3): 12.057608015028098 parameters from Stochastic GD: (0.23418910457018247, 1.001252348153782, 0.9993738259231028, 0.9367564182807299, 1.003757044461383) time taken: 25.743896484375 prediction for (3,3,3,3): 12.057608015027176