Demystifying AdaBoost: A Practical Guide to Strengthening Predictive Models

Introduction

Hello, and welcome to our journey into the AdaBoost algorithm! AdaBoost, an abbreviation for Adaptive Boosting, is a crucial ensemble learning method employed in machine learning. Using Python, we'll build an AdaBoost model from scratch and learn how to boost prediction accuracy by combining multiple weak learners into a powerful one.

Understanding Boosting and AdaBoost

First, let's define our terms. Boosting is a technique in which several weak learners are combined to create a strong learner, thereby improving our predictive model. AdaBoost largely follows the same principle. However, it introduces an important twist: it adapts by focusing more on instances that were incorrectly predicted in previous iterations by assigning them higher weights.

Consider a multiphase bank loan approval process to illustrate this concept. Each phase in this process acts as a weak learner. The first phase might be a credit score check, followed by an employment history verification in the second phase, and so on. Collectively, these weak learners form a strong learner who decide on loan approval.

Implementation of AdaBoost: Step 1

Now, let's bring AdaBoost to life with Python.

We begin by initializing the AdaBoost class, specifying the parameters (including the number of learners and the learning rate), and initializing lists to store the models and their weights:

Python
import numpy as np
from sklearn.datasets import make_classification
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

class AdaBoost:
    def __init__(self, num_learners=10, learning_rate=1):
        self.num_learners = num_learners
        self.learning_rate = learning_rate
        self.models = []
        self.model_weights = []

Implementation of AdaBoost: Step 2

The fit method trains the learners iteratively in sequence. The later learners adjust to focus more on instances wrongly predicted by the earlier ones.

Python
def fit(self, X, y):
    M, N = X.shape
    W = np.ones(M) / M  # Initialize weights
    y = y * 2 - 1  # Convert y to {-1, 1}
    ...

The AdaBoost algorithm uses {-1, 1} labels instead of {0, 1} to simplify the computation of errors and updating sample weights. Correctly classified observations get a weight of -1 and incorrect ones get +1. This way, the algorithm can easily adjust the weights - by increasing those of misclassified samples and decreasing the correctly classified ones - in the learning process.

Python
    ...
    for _ in range(self.num_learners):
        tree = DecisionTreeClassifier(max_depth=1)
        tree.fit(X, y, sample_weight=W)
        
        pred = tree.predict(X)
        error = W.dot(pred != y)
        if error > 0.5:
            break
        ...

In the AdaBoost algorithm, if error exceeds 0.5, it means our weak classifier is performing worse than a random guess. So, we halt boosting to avoid incorporating its output, which doesn't contribute any value or improvement to our model.

Python
        ...
        beta = self.learning_rate * np.log((1 - error) / error)  # Compute beta
        W = W * np.exp(beta * (pred != y))  # Update weights

        W = W / W.sum()  # Normalize weights
        
        self.models.append(tree)
        self.model_weights.append(beta)

Note how the weights are initialized. np.ones(M) creates a M-dimensional array of ones, and dividing by M means each weight is equal to 1/M, therefore all weights sum to 1. This represents a uniform distribution of weights across all data instances. This means that the initial model will consider all instances as equally important.

Then we compute beta using the formula β=η⋅log(1−εε)\beta=\eta \cdot log \left(\frac {1-\varepsilon }{\varepsilon }\right), where:

  • η\eta is the learning rate.
  • ε\varepsilon is the error rate (calculated as error = W.dot(pred != y)), which gives the sum of the weights of the instances that were incorrectly predicted.

The instances' weights are then updated based on beta and the errors, making the wrongly predicted instances more critical in subsequent iterations.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal