Hello! Welcome to the first lesson in our module on Supervised Learning. This is where we transition from the foundational concepts of machine learning to building and training our first predictive models.
In the previous module, we concluded by discussing how to diagnose and mitigate overfitting and underfitting. We explored theoretical strategies like regularization (L1, L2), early stopping, and adding more data. Now, we will start building the very models those techniques apply to, beginning with one of the most fundamental algorithms in all of machine learning.
This lesson is dedicated to Simple Linear Regression. Our goal is to not just use a library function, but to understand this algorithm from the ground up by implementing it from scratch. You'll see how the math you've refreshed in previous modules (calculus and statistics) translates directly into a working Python model.
1. The Goal of Simple Linear Regression
Simple linear regression aims to model the relationship between two variables by fitting a straight line to the observed data. One variable is considered the independent variable (the feature, ), and the other is the dependent variable (the target, ).
The core idea is to find the "best-fit" line that passes through the data points, which can then be used to make predictions.

The equation for this line is likely familiar to you from basic algebra:
- is the predicted value of the target variable.
- is the value of the input feature.
- is the slope of the line. It tells us how much changes for a one-unit increase in .
- is the y-intercept. It's the predicted value of when is zero.
Our entire task is to find the optimal values for the coefficients and that result in the "best-fit" line. But what makes a line the "best"?
2. Finding the "Best" Line: The Method of Ordinary Least Squares (OLS)
The "best" line is the one that minimizes the total error between its predictions and the actual data points. We can't just sum the errors (), because positive and negative errors would cancel each other out.
Instead, we use the Sum of Squared Errors (SSE), also known as the cost function. We square each error before summing them up. This ensures all error contributions are positive and penalizes larger errors more heavily.
Here, is the actual value and is the predicted value for the -th data point.
Our goal is to find the values of and that minimize this SSE function. This is a classic optimization problem that can be solved with calculus. Since our SSE function depends on two variables ( and ), we find the minimum by taking the partial derivative with respect to each variable, setting both derivatives to zero, and solving the resulting system of equations.
The following video provides an excellent, detailed walkthrough of this mathematical derivation from first principles. It's a fantastic way to see the "why" behind the formulas we'll be using.
Simple Linear Regression | Mathematical Formulation | Coding from Scratch
This video from CampusX will guide us through the mathematical derivation of the coefficients for simple linear regression. It starts by formulating the cost function and then uses calculus to find the values of 'm' (slope) and 'b' (intercept) that minimize it.
Please watch the video in two parts: Formulating the Cost Function (09:16 - 21:42): Focus on understanding why the Sum of Squared Errors is chosen and how the prediction \hat{y} is substituted into the formula. Deriving the Coefficients (21:42 - 39:46): Follow the process of taking the partial derivatives of the error function with respect to the intercept ('b') and then the slope ('m'), and setting them to zero. This is the core of the Ordinary Least Squares (OLS) method.
The Resulting Formulas
After all the calculus, we are left with two elegant, closed-form equations for our coefficients. These formulas tell us exactly how to calculate the optimal slope () and intercept () directly from our data.
The slope () is the covariance of x and y divided by the variance of x:
The intercept () is calculated to ensure the line passes through the center of our data (the point ):
Where:
- is the mean of the input values.
- is the mean of the output values.
This approach is powerful because it gives us a direct analytical solution, avoiding the need for iterative approximation methods like gradient descent (which we'll use for more complex models).
3. A Step-by-Step Numerical Example
Before we write any Python code, let's solidify our understanding by calculating the coefficients for a tiny dataset by hand. This will make the subsequent code implementation much clearer.
Let's use the simple example of study hours vs. test scores from the article "Simple Linear Regression: Complete Guide".
Simple Linear Regression: Complete Guide with Formulas ...
This article provides a very clear, step-by-step numerical example. We will follow its logic to see how the formulas work with real numbers.
Read the section titled 'Example'. Follow the five steps shown: calculating means, slope, intercept, making a prediction, and interpreting the results. You don't need to read the rest of the article for now.
Let's recap the key steps from that example here:
Data:
| Study Hours (x) | Test Score (y) |
|---|---|
| 1 | 65 |
| 2 | 70 |
| 3 | 80 |
| 4 | 85 |
| 5 | 90 |
-
Calculate Means:
-
Calculate Slope ():
- Numerator:
- Denominator:
- Numerator:
-
Calculate Intercept ():
Our final model is: Test Score = 58.5 + 6.5 * Study Hours.
Test your understanding!
Using the model we just derived (Test Score = 58.5 + 6.5 * Study Hours), what would be the predicted test score for a student who studies for 2.5 hours?
Show answer
Predicted Score =
Predicted Score =
Predicted Score = 74.75
4. Implementing Simple Linear Regression in Python
Now for the most exciting part: translating these formulas into a working Python model. We'll create a class with fit and predict methods, mimicking the structure of scikit-learn models. This provides great practice for building more complex algorithms later.
The same CampusX video we used for the math derivation also includes a clear, from-scratch implementation.
Simple Linear Regression | Mathematical Formulation | Coding from Scratch
Let's continue with the CampusX video. The instructor now takes the derived formulas for the slope ('m') and intercept ('b') and codes them in Python within a custom class.
Watch the segment from 39:46 to 53:13. Pay close attention to: The structure of the MyLR class with __init__, fit, and predict methods. How the fit method implements the formulas for m and b by looping through the training data to calculate the numerator and denominator. How the final calculated coefficients are compared with those from scikit-learn's LinearRegression model to verify correctness.
Here is a full code block that puts everything together. It defines the class as shown in the video and then tests it on a sample dataset.
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression as SklearnLinearRegression
# Our from-scratch Linear Regression class
class SimpleLinearRegression:
def __init__(self):
self.b0 = None # Intercept
self.b1 = None # Slope
def fit(self, X_train, y_train):
"""
Calculates the optimal b0 and b1 coefficients using OLS.
X_train should be a 1D NumPy array or Pandas Series.
y_train should be a 1D NumPy array or Pandas Series.
"""
# Ensure inputs are NumPy arrays
X_train = np.array(X_train)
y_train = np.array(y_train)
x_mean = np.mean(X_train)
y_mean = np.mean(y_train)
# Calculate b1 (slope)
numerator = np.sum((X_train - x_mean) * (y_train - y_mean))
denominator = np.sum((X_train - x_mean)**2)
self.b1 = numerator / denominator
# Calculate b0 (intercept)
self.b0 = y_mean - (self.b1 * x_mean)
print(f"Model trained: b0 (intercept) = {self.b0:.4f}, b1 (slope) = {self.b1:.4f}")
def predict(self, X_test):
"""
Makes predictions for new data points.
X_test should be a 1D NumPy array or Pandas Series.
"""
if self.b0 is None or self.b1 is None:
raise Exception("Model has not been trained yet. Call fit() first.")
return self.b0 + self.b1 * np.array(X_test)
# --- Let's test our implementation ---
# 1. Create a sample dataset
# Let's use a dataset where we know the relationship: y = 2 + 3x + noise
X = 2 * np.random.rand(100, 1)
y = 2 + 3 * X + np.random.randn(100, 1)
# Split the data
# Note: For simple linear regression, X should be 1D. We use .ravel() to flatten it.
X_train, X_test, y_train, y_test = train_test_split(X, y.ravel(), test_size=0.2, random_state=42)
# 2. Train our from-scratch model
my_model = SimpleLinearRegression()
my_model.fit(X_train, y_train)
# 3. Train scikit-learn's model for comparison
sklearn_model = SklearnLinearRegression()
sklearn_model.fit(X_train, y_train.reshape(-1, 1)) # sklearn expects a 2D array for X
print(f"Scikit-learn: b0 = {sklearn_model.intercept_[0]:.4f}, b1 = {sklearn_model.coef_[0][0]:.4f}")
# 4. Make a prediction on a new data point
new_x = np.array([1.5])
my_prediction = my_model.predict(new_x)
sklearn_prediction = sklearn_model.predict(new_x.reshape(-1, 1))
print(f"\nPrediction for x = {new_x[0]}:")
print(f"Our model's prediction: {my_prediction[0]:.4f}")
print(f"Scikit-learn's prediction: {sklearn_prediction[0][0]:.4f}")
When you run this code, you'll see that the coefficients calculated by our SimpleLinearRegression class are virtually identical to those found by scikit-learn's highly optimized LinearRegression model. This confirms that our from-scratch implementation correctly applies the theory of Ordinary Least Squares.
Conclusion
Congratulations! You have successfully built a machine learning model from scratch. This is a significant milestone. You not only know how to use linear regression but also why it works, right down to its calculus-based origins.
Key Takeaways:
- Simple Linear Regression models a linear relationship between a single feature () and a target ().
- The "best-fit" line is found by minimizing the Sum of Squared Errors (SSE). This method is called Ordinary Least Squares (OLS).
- Using calculus, we can derive direct formulas for the optimal slope () and intercept () without needing iterative methods.
- These formulas, based on the means, variance, and covariance of the data, can be implemented directly in Python to create a fully functional regression model.
Preview of the Next Lesson:
Our from-scratch model is a fantastic learning tool, but it's limited to a single input feature. Most real-world problems are more complex and involve multiple predictors. In our next lesson, we will extend linear regression to multiple features. We'll explore how the math generalizes and why using libraries like scikit-learn becomes essential for handling higher-dimensional data efficiently.