Skip to main content

Welcome to a Grasp lesson

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

Lesson 35

Building Kernel Functions

Recommended resources

Hello! Welcome back to our course on building supervised learning models from scratch.

In the previous lesson, you successfully built a complete linear Support Vector Machine. It was a big step! You implemented the training loop using gradient descent and a prediction function based on the learned hyperplane. However, as we saw, our SVM can only find linear decision boundaries. This is a significant limitation for many real-world datasets.

Today, we will address this by exploring one of the most powerful concepts in machine learning: the kernel trick. You'll see how we can enable our linear model to learn highly complex, non-linear decision boundaries. Your goal for this lesson is to implement two of the most common kernel functions—the Polynomial kernel and the Radial Basis Function (RBF) kernel—from scratch.

The Problem: Non-Linear Data

Imagine your data looks like this:

Non-linearly Separable 'make_circles' Dataset
This is a classic example of a non-linearly separable dataset. No matter where you draw a straight line, you cannot separate the blue and red points. Your current SVM would fail on this task.

How can we solve this? The core idea behind kernel methods is to project the data into a higher-dimensional space where it does become linearly separable.

For a fantastic and intuitive explanation of this core concept, I recommend watching this segment from StatQuest.

Support Vector Machines Part 1 (of 3): Main Ideas!!!

This video from StatQuest with Josh Starmer provides an excellent high-level overview of how SVMs use higher dimensions to classify non-linear data.

Watch from 11:44 to 14:54. Focus on the main idea: starting with data in a low dimension, moving it to a higher dimension, and then finding a linear classifier (a hyperplane) in that new, higher-dimensional space.


The Kernel Trick: A Clever Shortcut

Explicitly transforming your data into a higher dimension can be computationally very expensive, especially if the new dimension is very large (or even infinite!). This is where the kernel trick comes in.

A kernel is a function that takes two data points, and , and returns a value that is equivalent to the dot product of these points in a higher-dimensional space, without ever actually creating the higher-dimensional vectors.

In other words, if is the function that maps to a higher dimension, a kernel satisfies:

Our SVM optimization and prediction only ever use dot products between data points. By replacing these dot products with a kernel function, we can make our SVM operate in a high-dimensional space for "free". This is the essence of the kernel trick.

Let's look at the two most common kernels you'll be implementing.


1. The Polynomial Kernel

The polynomial kernel is a great way to capture interactions between features. For example, it can learn decision boundaries that are quadratic, cubic, and so on.

The formula for the polynomial kernel is:

Here:

  • is the dot product of the input vectors.
  • d is the degree of the polynomial, a hyperparameter that controls the complexity of the decision boundary.
  • c is a coefficient hyperparameter (often called coef0 in libraries like Scikit-learn).

This article provides a simple, from-scratch implementation of this function that we can adapt.

Step-by-Step Guide to Implementing Polynomial Kernel in ...

This article, "Step-by-Step Guide to Implementing Polynomial Kernel in ...", clearly explains the formula and provides a clean Python implementation.

Read the sections "Understanding the Polynomial Kernel" and "1. Writing a Polynomial Kernel Function from Scratch". Focus on the formula and how it translates directly into the Python code using NumPy.

Your Implementation

Now, let's write a Python function for the polynomial kernel. Your function should take two NumPy arrays, X1 and X2, and compute the kernel matrix. Given your background in Python and NumPy, you can implement this efficiently using vectorized operations. The dot product between two matrices X1 (shape m x k) and X2 (shape n x k) can be computed as X1 @ X2.T, resulting in the m x n matrix of all pairwise dot products.

import numpy as np

def polynomial_kernel(X1, X2, degree=3, coef=1):
    """
    Computes the polynomial kernel between two sets of vectors.
    
    Args:
        X1 (np.ndarray): A matrix of shape (m, k) where m is the number of samples.
        X2 (np.ndarray): A matrix of shape (n, k) where n is the number of samples.
        degree (int): The degree of the polynomial.
        coef (float): The coefficient term.
        
    Returns:
        np.ndarray: The kernel matrix of shape (m, n).
    """
    # The @ operator in NumPy performs matrix multiplication.
    # X1 @ X2.T computes the dot product for all pairs of vectors in X1 and X2.
    return (X1 @ X2.T + coef) ** degree

# --- Example Usage ---
# Let's create two small matrices
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8], [9, 10]])

# Compute the polynomial kernel matrix
# The result should be a 2x3 matrix
kernel_matrix = polynomial_kernel(A, B, degree=2, coef=1)
print("Polynomial Kernel Matrix:\n", kernel_matrix)

2. The RBF (Radial Basis Function) Kernel

The RBF kernel is the most popular choice for SVMs. It is a general-purpose kernel that can learn very complex regions. It works by considering the Euclidean distance between points; its value is high for points that are close together and low for points that are far apart.

The formula for the RBF kernel is:

Here:

  • is the squared Euclidean distance between the two vectors.
  • (gamma) is a hyperparameter that defines how much influence a single training example has. A small means a larger similarity radius, leading to a smoother decision boundary. A large means the influence is local, which can lead to a more complex, "wiggly" boundary.

To implement this efficiently, we can use scipy.spatial.distance.cdist, which is designed to compute distances between all pairs of vectors in two collections.

The following resource shows this exact implementation within an SVM class structure.

Easily Implement Multiclass SVM From Scratch in Python

The article "Easily Implement Multiclass SVM From Scratch in Python" provides a very concise and efficient implementation of the RBF kernel using SciPy.

In the provided code snippet within the SVM class definition, locate the line that defines the rbf kernel. Notice how it uses scipy.spatial.distance.cdist(x, xà ¤,'sqeuclidean'). This is the key to an efficient implementation.

Your Implementation

Let's write the RBF kernel function. Make sure you have SciPy installed (pip install scipy).

from scipy.spatial.distance import cdist

def rbf_kernel(X1, X2, gamma=0.1):
    """
    Computes the RBF kernel between two sets of vectors.
    
    Args:
        X1 (np.ndarray): A matrix of shape (m, k).
        X2 (np.ndarray): A matrix of shape (n, k).
        gamma (float): The kernel coefficient.
        
    Returns:
        np.ndarray: The kernel matrix of shape (m, n).
    """
    # cdist computes the pairwise squared Euclidean distance between vectors in X1 and X2
    sq_dist = cdist(X1, X2, 'sqeuclidean')
    return np.exp(-gamma * sq_dist)

# --- Example Usage ---
# Using the same matrices A and B from before
# The result should be a 2x3 matrix
rbf_kernel_matrix = rbf_kernel(A, B, gamma=0.1)
print("\nRBF Kernel Matrix:\n", rbf_kernel_matrix)
Test your understanding!

You have an RBF kernel with a very large gamma value. What effect will this have on the decision boundary of an SVM trained with it? Will it be smooth or very complex and "wiggly"? Why?

Show answer

The decision boundary will be very complex and wiggly, and the model will be prone to overfitting.

Here's why: A large gamma value in the term exp(-gamma * ||x - x'||^2) means the exponent becomes a large negative number very quickly as the distance ||x - x'|| increases. This causes the kernel's value to drop to near zero for all but the most immediate neighbors of a data point.

As a result, the model's decision for a new point is influenced only by the training examples that are extremely close to it. This creates a highly localized, complex boundary that fits the training data very tightly, effectively behaving like a nearest-neighbor classifier.


Visualizing the Power of Kernels

So what do these functions enable in practice? By swapping the simple dot product in an SVM with one of these kernel functions, we can produce radically different decision boundaries capable of fitting complex data.

Comparison of SVM Kernels on a Classification Dataset
This image compares the decision boundaries for different kernels on the same dataset. Notice how the linear kernel (top left) can only produce a straight line, while the RBF (bottom left) and Polynomial (bottom right) kernels produce curved boundaries that can better separate the classes.

Conclusion

In this lesson, you've taken a critical step towards building a powerful, general-purpose SVM. You moved beyond the limitations of linear models by understanding and implementing kernel functions.

Key Takeaways:

  • The Problem: Linear classifiers fail when data is not linearly separable.
  • The Idea: Project data into a higher dimension where it becomes linearly separable.
  • The Kernel Trick: A computationally efficient method to achieve this by replacing dot products with a kernel function, which calculates the dot product in the higher-dimensional space without explicit transformation.
  • Implementation: You wrote Python functions from scratch for the polynomial kernel and the RBF kernel, the two most widely used kernels for SVMs.

Preview of the Next Lesson:

You now have the building blocks: a linear SVM implementation and standalone kernel functions. In the next lesson, we will put them together. You will modify the SVM you built previously to accept a kernel function, allowing it to solve non-linear classification problems. This will involve updating your fit and predict methods to use the kernel matrix instead of a simple dot product.