Welcome to your fourth lesson. In our last session, we assembled our first complete classification model, logistic regression. We defined its probabilistic structure using the sigmoid function and identified its corresponding cost function, Binary Cross-Entropy. We even implemented a Python class for it, but with one crucial piece of the puzzle taken on faith: the gradient formulas used for training.
Today, we will fill that gap by diving into the engine of optimization for most of machine learning: Gradient Descent. Our primary goal is to formally derive the gradient formulas for logistic regression, leveraging your background in calculus to build a deep, first-principles understanding. We will then use this derivation to implement the gradient descent algorithm, completing the fit method of our model and solidifying your grasp on how a model truly learns from data.
The Intuition: Descending the Cost Surface
In the previous lessons, we established a cost function, , which measures how "wrong" our model is for a given set of parameters and . Our goal is to find the specific values of and that make this cost as low as possible.
Imagine the cost function as a landscape, with hills and valleys. The parameters and are our coordinates in this landscape, and the cost is the altitude. Our objective is to find the lowest point in this landscape—the global minimum.
Gradient descent is an iterative algorithm that does exactly this. It starts at some random point (randomly initialized parameters) and takes a series of steps "downhill" until it reaches a minimum. But how does it know which way is downhill?
The answer lies in the gradient, . In calculus, the gradient of a function at a particular point is a vector that points in the direction of the steepest ascent. Therefore, to go downhill most quickly, we should move in the direction opposite to the gradient.
This process is visualized below. At each point on the curve, we calculate the slope (the derivative, which is the 1D version of the gradient). If the slope is negative, we need to increase w. If it's positive, we need to decrease w.

This leads to the core update rule of gradient descent:
Where:
- represents our parameters ( and ).
- is the learning rate, a hyperparameter that controls the size of each step.
- is the gradient of the cost function with respect to the parameters.
The following reading provides a fantastic, intuitive explanation of this process.
This section from the "Speech and Language Processing" textbook offers a clear, conceptual introduction to gradient descent.
Please read Section 5.4, "Gradient Descent". Focus on the analogy of hiking in a canyon and how the gradient provides the direction of steepest ascent, which we then reverse to find the minimum. The text and figures will solidify your intuition for the update rule.
Deriving the Gradient for Logistic Regression
Now for the central task of this lesson. We have the "what" (the update rule) and the "why" (to minimize cost), but we need the "how": what exactly is for our logistic regression model? To find this, we must compute the partial derivatives of the cost function with respect to each parameter, (for each feature ) and .
Let's recall the key equations from our last lesson for a single training example :
- Linear Model Output:
- Predicted Probability (Hypothesis):
- Loss Function (Binary Cross-Entropy):
Our goal is to find and . Since is a function of , which is a function of , which is a function of and , we must use the chain rule.
This may look complex, but we can solve it piece by piece. The final result is remarkably simple and elegant. Given your strong math background, you are well-equipped to follow the formal derivation. The following section from the Jurafsky & Martin textbook provides a rigorous and complete walkthrough.
This section is a self-contained, formal derivation of the gradient equations.
Please read Section 5.8, "Deriving the Gradient Equation". Work through it step-by-step. The authors start with the necessary calculus refreshers (derivatives of ln(x) and the sigmoid function) and then apply the chain rule exactly as outlined above. Pay close attention to how the terms cancel out to produce the final, simple expression.
After following that derivation, you will have seen that for a single training example:
And similarly for the bias (where the corresponding "feature" is implicitly 1):
This result is beautifully intuitive. The gradient for a weight is simply the prediction error scaled by the corresponding input feature value . If the prediction is perfect (), the error is zero, and the gradient is zero, so the weights are not updated. If the error is large, the update will be proportionally large.
For the entire training set of examples, the cost function is the average of the individual losses. Due to the properties of differentiation, the gradient of the average is the average of the gradients:
These are precisely the formulas we used without proof in the previous lesson! In vectorized form, this becomes:
For a more dynamic walkthrough of this same derivation, the following video is an excellent resource.
Logistic Regression From Scratch in Python (Mathematical)
The "NeuralNine" channel provides a clear, step-by-step mathematical derivation of the gradient.
Watch the segment from Derivation of the Gradient. The presenter uses the chain rule to break down the problem and simplifies the resulting expression, mirroring the steps in the text you just read.
Implementing the Algorithm
Now that we have derived the gradient, we can implement the full gradient descent algorithm. The process is a direct translation of the mathematics into code.
The training loop proceeds as follows:
- Initialize parameters and (e.g., to zeros).
- Repeat for a specified number of iterations:
a. Forward Pass: Compute the predictions for all training examples using the current and .
b. Compute Gradients: Calculate and using the formulas we just derived.
c. Update Parameters: Apply the update rule: - Return the final, optimized parameters and .
Let's integrate this logic into the fit method of the MyLogisticRegression class from our last lesson.
import numpy as np
class MyLogisticRegression:
def __init__(self, learning_rate=0.01, n_iterations=1000):
self.learning_rate = learning_rate
self.n_iterations = n_iterations
self.weights = None
self.bias = None
def _sigmoid(self, z):
# Clip to avoid overflow/underflow in np.exp
z = np.clip(z, -500, 500)
return 1 / (1 + np.exp(-z))
def fit(self, X, y):
# 1. Initialize parameters
n_samples, n_features = X.shape
self.weights = np.zeros(n_features)
self.bias = 0
# 2. Gradient Descent loop
for i in range(self.n_iterations):
# a. Forward Pass: Compute predictions
linear_model = np.dot(X, self.weights) + self.bias
y_predicted = self._sigmoid(linear_model)
# b. Compute Gradients
# This is the direct implementation of our derived formulas
dw = (1 / n_samples) * np.dot(X.T, (y_predicted - y))
db = (1 / n_samples) * np.sum(y_predicted - y)
# c. Update Parameters
self.weights -= self.learning_rate * dw
self.bias -= self.learning_rate * db
# Optional: Print cost to monitor progress
if i % 100 == 0:
cost = -np.mean(y * np.log(y_predicted) + (1-y) * np.log(1 - y_predicted))
print(f"Iteration {i}: Cost {cost:.4f}")
def predict_proba(self, X):
linear_model = np.dot(X, self.weights) + self.bias
return self._sigmoid(linear_model)
def predict(self, X, threshold=0.5):
probabilities = self.predict_proba(X)
return [1 if i > threshold else 0 for i in probabilities]
Take a moment to study the fit method. You can now see every line has a clear mathematical justification based on our derivation. The code is no longer a black box; it's a direct implementation of the optimization principle we've just explored.
The following video shows a similar from-scratch Python implementation, which can help reinforce your understanding of how the mathematical formulas translate into NumPy operations.
Logistic Regression FROM SCRATCH in Python
This video by Harry Connor AI provides a concise implementation of the gradient descent function.
Watch the section where the gradient_descent function is coded, from Gradient Descent Function. This will reinforce how the update rules for W and B are implemented inside the training loop.
A Note on Gradient Descent Variants
The version of gradient descent we implemented is called Batch Gradient Descent, because it calculates the gradient using the entire batch of training data in each iteration. This provides a very accurate estimate of the gradient, leading to a smooth convergence. However, it can be computationally expensive for very large datasets.
Two other common variants are:
- Stochastic Gradient Descent (SGD): Calculates the gradient and updates the parameters using only one randomly chosen training example at a time. This is much faster per update, but the path to the minimum is much noisier.
- Mini-Batch Gradient Descent: A compromise between the two. It computes the gradient on a small, random subset (a "mini-batch") of the data. This is the most common approach used in modern machine learning and deep learning, as it balances computational efficiency with stable convergence.
You can read more about these variants in the Jurafsky & Martin text, which provides a concise comparison.
This section explains the different flavors of gradient descent.
Please read Section 5.4.4, "Mini-batch training", to understand the trade-offs between batch, stochastic, and mini-batch gradient descent.
Conclusion
In this lesson, you have moved from being a user of an optimization algorithm to understanding its fundamental mechanics. We have demystified the training process of logistic regression by deriving its gradient from first principles.
Here are the key takeaways:
- Gradient Descent is an iterative optimization algorithm that minimizes a cost function by repeatedly taking steps in the direction of the negative gradient.
- The learning rate, , is a crucial hyperparameter that controls the step size.
- Using the chain rule, we derived the gradient of the Binary Cross-Entropy loss for logistic regression, which results in the elegant formula: .
- The derived formulas can be implemented in a straightforward training loop to find the optimal parameters for our model.
With this foundation, you now have a complete understanding of one of the most fundamental classification algorithms in machine learning. In our next lesson, we will address a common problem in model training: overfitting. We will explore regularization, a technique used to prevent models from becoming too complex and to improve their ability to generalize to new, unseen data.