Linear regression is a linear model. It is used to make a prediction(denoted by y) based on the given input value x. When working with Linear regression we assume the relationship between the input and output is linear.
 h(x) = m * x + c x,Y|h(x) - y| (Always positive)Update weight and bias based on error. (High Error -> High Correction)
        
m = m + learn_rate*error*x 
c = c + learn_rate*error*x
    | Variable | description | 
|---|---|
| x | input data | 
| Y | expected output | 
| h(x) | prediction of model on input x | 
| m | slope of line (weight) | 
| c | intercept of line (bias) | 
| lr | Pace of Learning. It usually lies between 0.1 - 0.0001 | 
The calculation is performed in loop for a number of iteration(we will do it for 100). Higher iteration yields better results, but it takes longer and increases the risk of overfitting.
keeping number of itteration low can also be detrimental beacuse it can lead to underfitting.
import matplotlib.pyplot as plt       #Creating Plots
import numpy as np                    #Working with numeric array
import random
import time
        
      
%matplotlib notebook                  #Makes Notebook zoom-able & resize-able 
random.seed(61)                       #Generate same random numbers on multiple executions
        
      
x_data = np.array([-7.5,-2.5,4,9])    #Input data
y_data = np.array([-1.5,2.5,4.5,7])   #Output data
        
      
def run_model(x):
  global m,c                          #Making Variable Global for Simplicity
  y = m*x + c                         #Predicting value(Output)
  return y                            #Returning prediction
        
      
m = random.uniform(-1,1)              #Random slope, Dosen't really matter
c = random.uniform(-10,-5)            #Random intercept
        
      
y_init = run_model(x_data)            #Prediction with randomly Generated m and c
        
      
fig = plt.figure()                    #Create a new figure
plt.axis([-10, 10, -10, 10])          #Size of plot
plt.scatter(x_data,y_data)            #Plotting data
plt.plot(x_data,y_init)               #Plotting model
fig.canvas.draw()                     #Rendering plot
        
        
      
learn_rate = 0.01                     #Rate of learning
iterations = 100                      #Number of Epochs
        
      
for i in range(iterations):           #Loop to iterate
  for x,t in zip(x_data,y_data):      #Loop through data
      y = run_model(x)                #Making prediction
      error = np.abs(t - y)           #Error in prediction, Absolute difference of prediction and true value
      m = m + learn_rate*error*x      #Updating slope
      c = c + learn_rate*error        #Updating intercept
      time.sleep(0.1)                 #Slowing down training, You can comment this out 
  
  y_next = run_model(x_data)          #Prediction on Updated Model for Plotting            
  line, = plt.plot(x_data,y_next)     #Plotting new model
  fig.canvas.draw()                   #Rendering plot
  line.remove()                       #Removing Model
        
        
      
plt.plot(x_data,y_next)               #Plotting final model
fig.canvas.draw()                     #Rendering plot
print(error,m,c)                      #Printing model parameters(slope and intercept) 
        
        
      
from sklearn import linear_model
        
      
x_data = np.array([-7.5,-2.5,4,9]).reshape([-1, 1])
y_data = np.array([-1.5,2.5,4.5,7]).reshape([-1, 1])
        
      
regr = linear_model.LinearRegression()
        
      
regr.fit(x_data,y_data)
        
      
y_pred = regr.predict(x_data)
        
      
fig = plt.figure()
plt.axis([-10, 10, -10, 10])
plt.scatter(x_data,y_data)
plt.plot(x_data,y_pred)
fig.canvas.draw()