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