import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from mpl_toolkits.mplot3d import Axes3D
%matplotlib widget
Linear Regression 2-dimensional
A set of \(N\) data points \((x_i, y_i)\), the goal is to find the find the best linear map \(f: \mathbb{R}^2 \to \mathbb{R}^2\) such that \(f(x) = mx + b\) fits the data points. In simpler terms, we assume the relation between the dependenet variable \(y\) and independent variable \(x\) is linear and try finding the optimal \(m\) and \(b\) such that some error function is minimised.
Loss/Error Function
\(E = \frac{1}{N}\sum_{i = 1}^{N}(y_i - \widehat{y})^2\)
where,
\(\widehat{y} = mx_i + b\), hence
\(E = \frac{1}{N}\sum_{i = 1}^{N}(y_i - (mx_i + b))^2\)
Optimal \(m\) and \(b\)
\(\frac{∂E}{∂m} = -\frac{2}{N}\sum_{i = 1}^{N}(x_i \times (y_i - (mx_i + b)) )\)
\(\frac{∂E}{∂b} = -\frac{2}{N}\sum_{i = 1}^{N}(y_i - (mx_i + b))\)
Gradient Descent
Arrive at the desired \(m\) and \(b\) by updating these values following the direction of greatest descent of this function. The learning rate \(L\) has to be specified.
\(\bar{m} = m - L\frac{\partial E}{\partial m}\)
\(\bar{b} = b - L\frac{\partial E}{\partial b}\)
def loss_func(m, b, data):
= len(data)
N = 0
E for i in range(N):
+= (data[i][1] - (m * data[i][0] + b))**2
E return E/N
def gradient_descent(data, m_now, b_now, L):
= len(data)
N = 0, 0
E_m, E_b for i in range(N):
+= -2/N * (data[i][0] * (data[i][1] - m_now * data[i][0] - b_now))
E_m += -2/N * (data[i][1] - m_now * data[i][0] - b_now)
E_b
= m_now - L * E_m
m_cur = b_now - L * E_b
b_cur
return m_cur, b_cur
= pd.read_csv("Data.csv")
df = df.to_numpy()
data = 0, 0, 0.00001, 100
m, b, L, epochs for i in range(epochs):
= gradient_descent(data, m, b, L)
m, b
print(f"m = {m}, b = {b}")
0], data[:, 1], color = "black")
plt.scatter(data[:, = range(100)
X *X + b, color = "red")
plt.plot(X, m plt.show()
m = 2.4306905668231544, b = 0.045763347379328585
= np.linspace(-1, 8, 100)
m_x = np.linspace(-20, 20, 100)
b_y = np.meshgrid(m_x, b_y)
m_mesh, b_mesh
= loss_func(m_mesh, b_mesh, data)
E
# The Loss Function
= go.Figure(data = [go.Surface(x = m_mesh, y = b_mesh, z = E)])
fig
# The Minima point
= [m], y = [b], z = [loss_func(m, b, data)], mode = "markers", marker = dict(size = 10, color = "red"), name = "Minima"))
fig.add_trace(go.Scatter3d(x
= dict(xaxis_title = "Slope (m)", yaxis_title = "Intercept (b)", zaxis_title = "Loss Function E(m ,b)",))
fig.update_layout(scene fig.show()
= plt.figure(figsize = (10, 8))
fig = fig.add_subplot(111, projection = "3d")
ax = "viridis")
ax.plot_surface(m_mesh, b_mesh, E, cmap = "red", s = 100, label = "Minima")
ax.scatter(m, b, loss_func(m, b, data), c
"Slope (m)")
ax.set_xlabel("Intercept (b)")
ax.set_ylabel("Loss Function E(m ,b)")
ax.set_zlabel( plt.show()