Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 3

Logistic Regression: From Binary Classification to Probabilistic Modeling

Recommended resources

Welcome to your third lesson. In our previous session, we established a principled way to measure model error by defining loss functions, and we saw how Mean Squared Error and Cross-Entropy arise naturally from Maximum Likelihood Estimation under different assumptions about our data's underlying probability distribution.

Today, we will build on that foundation to construct and implement our first classification model: Logistic Regression. Despite its name, logistic regression is a classification algorithm, not a regression one. It serves as a fundamental building block in machine learning and is the perfect entry point into probabilistic modeling. Our goal is to understand how logistic regression frames classification as a probability estimation problem and to implement it from scratch in Python for binary classification tasks. This will connect the theoretical ideas of loss functions and MLE to a concrete, working algorithm.

From Linear Models to Probabilities

In our last lesson, we focused on regression models that predict continuous values. The simplest of these is a linear model, which computes a weighted sum of the input features:

This output, , can be any real number from to . This is fine for regression, but for binary classification, we need to predict a class (e.g., 0 or 1). A more powerful approach is to predict the probability that an input belongs to the positive class (class 1). A probability, by definition, must be constrained to the range [0, 1].

So, how can we adapt our linear model to produce a valid probability? We need a function that takes any real number and "squashes" it into the (0, 1) interval. This is where the sigmoid function comes in.

This image contrasts a linear model, which fits a straight line to predict continuous values, with a logistic model, which uses an S-shaped curve to predict probabilities for classification.

The Sigmoid Function

The sigmoid function, also called the logistic function, is defined as:

It has a characteristic S-shape and maps any real-valued input to an output between 0 and 1.

The sigmoid function takes any real number on the horizontal axis and maps it to a value between 0 and 1 on the vertical axis. Notice that an input of 0 gives an output of 0.5.

By feeding the output of our linear model into the sigmoid function, we create the core of the logistic regression model. We can now interpret the output as the estimated probability of the positive class:

This equation represents the probabilistic heart of logistic regression. It explicitly models the probability of a positive outcome given the input features and the model parameters and .

The article "Mastering Logistic Regression" provides an excellent description of this model structure, framing it in terms of "log-odds." The log-odds, or logit, is the inverse of the sigmoid function, and understanding this relationship gives a deeper insight into why logistic regression is considered a linear classifier.

Mastering Logistic Regression | Towards Data Science

In the article from Towards Data Science, please read the section "The Logistic Regression Model".

Start from the heading The Logistic Regression Model and read down to the paragraph just before the discussion of the sigmoid function. Focus on the core assumption: that the log-odds of the event is a linear combination of the features. Then, continue reading from the text explaining the sigmoid function's role in converting this linear combination back into a probability.


The Cost Function for Logistic Regression

Now that we have a model that predicts probabilities, how do we train it? We need to find the parameters and that make our predicted probabilities as close as possible to the true labels (which are either 0 or 1).

This should sound familiar. In the previous lesson, we established that for a probabilistic classification model assuming a Bernoulli distribution for the outcomes, the appropriate loss function derived from Maximum Likelihood Estimation is Binary Cross-Entropy (BCE), also known as Log Loss.

For a single training example, the BCE loss is:

When we substitute our logistic regression model for , we get the loss function we need to minimize to train our model. The average of this loss over all training examples gives us our total cost function .

The following reading section shows this exact derivation, connecting the principle of Maximum Likelihood Estimation directly to the Log Loss function used in logistic regression.

Mastering Logistic Regression | Towards Data Science

Now, please read the "Log Loss" section in the same article.

This section is critical as it formally connects our model to the loss function. Read the entire section, from the introduction of Log Loss to its derivation from the Maximum Likelihood principle. Given your math background, the proof should be quite accessible. This directly demonstrates the "connection to probabilistic modeling" that is central to today's lesson.

For an alternative and more detailed walkthrough of this derivation, the following video explains it step-by-step.

Logistic Regression From Scratch in Python (Mathematical)

The video "Logistic Regression From Scratch in Python" by NeuralNine provides a detailed mathematical derivation.

Watch the segment from the derivation of the cost function. The presenter starts with the likelihood function and, through a series of logical steps (taking the log, negating, and averaging), arrives at the cross-entropy loss function.


Implementing Logistic Regression from Scratch

We now have all the conceptual pieces:

  1. Model:
  2. Cost Function: Average Binary Cross-Entropy,
  3. Goal: Find and that minimize .

The algorithm we'll use to minimize the cost function is Gradient Descent. We will dive deep into the calculus and derivation of gradient descent in our next lesson. For today, we will focus on the implementation, using the final gradient formulas.

The core idea of gradient descent is to iteratively update the parameters in the direction opposite to the gradient of the cost function. The update rules are:


where is the learning rate.

The partial derivatives of the cost function with respect to the parameters turn out to have a surprisingly simple form:

Here, is the number of training examples, is the feature matrix, and and are vectors of predicted probabilities and true labels, respectively.

Let's now see how to translate these mathematical ideas into a working Python implementation. We will use the "Mastering Logistic Regression" article as a guide.

Mastering Logistic Regression | Towards Data Science

Let's study the "Implementation in Python" section of the article.

Your goal is to understand how the Python functions translate the mathematical concepts we've discussed into working NumPy code. You can skim the data loading and plotting parts for now. Focus on: The sigmoid function implementation. The cost_function. Note how it efficiently computes the grad using the vectorized formula (1/n) * X.T @ (p - y). This is the gradient we will use for our updates. The optimization loop (optimize_model). This is our gradient descent algorithm. See how the weights w are updated on each iteration: w = w - alpha * grad. The prediction function, which uses the trained weights w to make a final 0 or 1 classification based on a 0.5 probability threshold.

To solidify this, here is a consolidated implementation structured as a Python class. This is a common and practical way to organize a model's logic.

import numpy as np

class MyLogisticRegression:
    """
    A simple implementation of Logistic Regression from scratch.
    """
    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):
        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
        for _ in range(self.n_iterations):



            # Calculate linear model and apply sigmoid
            linear_model = np.dot(X, self.weights) + self.bias
            y_predicted = self._sigmoid(linear_model)




            # Calculate gradients
            dw = (1 / n_samples) * np.dot(X.T, (y_predicted - y))
            db = (1 / n_samples) * np.sum(y_predicted - y)




            # Update parameters
            self.weights -= self.learning_rate * dw
            self.bias -= self.learning_rate * db

    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]




# Example usage (you can try this with any binary classification dataset from scikit-learn)
# from sklearn.model_selection import train_test_split
# from sklearn.datasets import make_classification
# X, y = make_classification(n_samples=100, n_features=2, n_redundant=0, n_informative=2, random_state=1, n_clusters_per_class=1)
# X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=123)




# model = MyLogisticRegression(learning_rate=0.1, n_iterations=1000)
# model.fit(X_train, y_train)
# predictions = model.predict(X_test)
# accuracy = np.mean(predictions == y_test)
# print(f"Accuracy: {accuracy:.2f}")

Spend a few moments studying this class. Notice how the fit method encapsulates the entire training loop, and the predict method uses the learned weights and bias to make new classifications.


Conclusion

In this lesson, we have constructed our first machine learning classifier from the ground up. You have seen how logistic regression seamlessly combines a linear model with a sigmoid function to produce probabilities, and how it is trained by minimizing a cost function (Binary Cross-Entropy) that is directly motivated by the principle of maximum likelihood.

Key takeaways from today's lesson:

  • Logistic Regression is a probabilistic linear classifier for binary tasks.
  • It models the probability of the positive class using a linear combination of features passed through the sigmoid function.
  • The model is trained by minimizing the Binary Cross-Entropy (or Log Loss) function, which is equivalent to maximizing the likelihood of the training data under a Bernoulli distribution assumption.
  • The implementation involves an iterative optimization process, Gradient Descent, which uses the gradients of the cost function to update the model's parameters.

We have used the gradient formulas to build our fit method. In our next lesson, we will put on our calculus hats and formally derive these gradient formulas. This will give you a complete understanding of Gradient Descent, the workhorse optimization algorithm for most of machine learning.