Linear Regression
Simple Linear Regression predicts a continuous value using one input feature by fitting a straight line: where:
- = intercept
- = slope
- = predicted output
The goal is to find the line that minimizes the sum of squared errors:
Intuition
We want the “best” straight line through the data.
- If , the line goes upward
- If , the line goes downward
- tells where the line cuts the -axis
For a dataset with one feature: we add a bias column of 1s:
Then the parameters are computed using the Normal Equation: where:
Short and Clean Code
import numpy as np
import matplotlib.pyplot as plt
class SimpleLinearRegression:
def __init__(self):
self.intercept_ = 0.0
self.coef_ = 0.0
self.r2_ = 0.0
def fit(self, X, y):
X = np.asarray(X).reshape(-1, 1)
y = np.asarray(y).reshape(-1, 1)
Xb = np.c_[np.ones((len(X), 1)), X]
theta = np.linalg.inv(Xb.T @ Xb) @ Xb.T @ y
self.intercept_ = theta[0, 0]
self.coef_ = theta[1, 0]
y_pred = Xb @ theta
ss_res = np.sum((y - y_pred) ** 2)
ss_tot = np.sum((y - y.mean()) ** 2)
self.r2_ = 1 - ss_res / ss_tot
return self
def predict(self, X):
X = np.asarray(X).reshape(-1, 1)
return self.intercept_ + self.coef_ * X
X = np.array([1,2,3,4,5,6,7,8,9,10])
y = np.array([2,4,5,4,5,7,8,9,10,12])
model = SimpleLinearRegression().fit(X, y)
y_pred = model.predict(X)
print("Intercept:", round(model.intercept_, 4))
print("Slope:", round(model.coef_, 4))
print("R^2:", round(model.r2_, 4))
plt.scatter(X, y, label="Data")
plt.plot(X, y_pred, label="Regression line")
plt.xlabel("X")
plt.ylabel("y")
plt.title("Simple Linear Regression")
plt.legend()
plt.show()
Output Meaning
From this code, the fitted line is approximately:
So:
- intercept
- slope
This means:
- when , predicted
- for every increase of 1 in , increases by about
The score is approximately: which means the model explains about 95.25% of the variance in the target.
Step-by-Step Algorithm
Step 1: Prepare the data
We start with:
X = np.array([1,2,3,4,5,6,7,8,9,10])
y = np.array([2,4,5,4,5,7,8,9,10,12])
Concept:
- is the input feature
- is the actual output
Dataset pairs:
Step 2: Add the bias column
To learn both intercept and slope together, we transform into:
Code:
Xb = np.c_[np.ones((len(X), 1)), X.reshape(-1, 1)]
Concept:
- first column of 1s handles the intercept
- second column stores the feature values
Step 3: Compute parameters using the Normal Equation
Equation:
Code:
theta = np.linalg.inv(Xb.T @ Xb) @ Xb.T @ y.reshape(-1, 1)
This gives:
So:
Meaning:
Step 4: Predict values
For each input, substitute into:
Code:
y_pred = self.intercept_ + self.coef_ * X.reshape(-1, 1)
Let us compute a few predictions manually.
For :
For :
For :
For :
So the model predictions are approximately:
Step 5: Measure performance using
The coefficient of determination is:
Where:
- = residual sum of squares
- = total sum of squares
- = mean of actual
Code:
ss_res = np.sum((y - y_pred) ** 2)
ss_tot = np.sum((y - y.mean()) ** 2)
self.r2_ = 1 - ss_res / ss_tot
For this dataset:
Interpretation:
- close to 1 means strong fit
- close to 0 means poor fit
Code Explanation: Concept -> Equation -> Code
1. Store model parameters
Concept: We need to remember the learned intercept, slope, and model score.
Code:
class SimpleLinearRegression:
def __init__(self):
self.intercept_ = 0.0
self.coef_ = 0.0
self.r2_ = 0.0
Meaning:
intercept_storescoef_storesr2_stores
2. Convert input into column form
Concept: Matrix equations require and in proper shapes.
Code:
X = np.asarray(X).reshape(-1, 1)
y = np.asarray(y).reshape(-1, 1)
Meaning:
reshape(-1, 1)makes data a column vector
Example:
3. Add the bias term
Concept: The intercept must be part of the matrix multiplication.
Equation:
Code:
Xb = np.c_[np.ones((len(X), 1)), X]
This builds:
4. Learn the best-fit line
Concept: Choose parameters that minimize squared error.
Equation:
Code:
theta = np.linalg.inv(Xb.T @ Xb) @ Xb.T @ y
This is the heart of the algorithm.
Then:
self.intercept_ = theta[0, 0]
self.coef_ = theta[1, 0]
This maps:
5. Predict outputs
Concept: Once parameters are known, plug them into the line equation.
Equation:
Code:
y_pred = Xb @ theta
or in predict():
return self.intercept_ + self.coef_ * X
Both do the same thing.
6. Evaluate model fit
Concept: Compare predictions with actual values.
Equation:
Code:
ss_res = np.sum((y - y_pred) ** 2)
ss_tot = np.sum((y - y.mean()) ** 2)
self.r2_ = 1 - ss_res / ss_tot
Worked Example
Using: Prediction:
Actual value in dataset:
Error:
Squared error:
This is how the model measures how far prediction is from truth.
Why This Algorithm Works
Simple Linear Regression assumes:
- the relationship is approximately linear
- one feature is enough to explain the target
- the best line is the one with minimum squared error
By minimizing squared error, the algorithm finds a line that stays as close as possible to all points overall.
Final Summary
Simple Linear Regression learns: using:
For this dataset, the learned model is: with:
So the model fits the data well and captures a strong positive linear relationship.
Exam-Oriented Points
- Used for predicting a continuous value
- Works with one input feature
- Equation of model:
- Parameters are found using the Normal Equation
- Performance is commonly measured with
- Best when the relationship between feature and target is approximately linear
Very Short Revision
- Add bias column
- Compute parameters using Normal Equation
- Form regression line
- Predict output
- Evaluate using
Formula: Model: