Making developers awesome at machine learning
Making developers awesome at machine learning

Kernel Methods in Machine Learning with Python
Image by Editor | Midjourney
Kernel methods are a powerful class of machine learning algorithm that allow us to perform complex, non-linear transformations of data without explicitly computing the transformed feature space. These methods are particularly useful when dealing with high-dimensional data or when the relationship between features is non-linear.
Kernel methods rely on the concept of akernel function, which computes the dot product of two vectors in a transformed feature space without explicitly performing the transformation. This is known as thekernel trick. The kernel trick allows us to work in high-dimensional spaces efficiently, making it possible to solve complex problems that would be computationally infeasible otherwise.
Why would we use kernel methods?
In this tutorial, we will explore the fundamentals of kernel methods, focusing on the following topics:
The kernel trick is a mathematical technique that allows us to compute the dot product of two vectors in a high-dimensional space without explicitly mapping the vectors to that space. This is particularly useful when the transformation to the high-dimensional space is computationally expensive or even impossible to compute directly.
Akernel function \( K(x, y) \) computes the dot product of two vectors \( x \) and \( y \) in a transformed feature space:
\[
K(x, y) = \phi(x) \cdot \phi(y)
\]
Here, \( \phi(x) \) is a mapping from the original feature space to a higher-dimensional space. The kernel function allows us to compute this dot product directly in the original space.
Common kernel functions include:
The choice of kernel function depends on the problem at hand. For example, the RBF kernel is often used when the data is not linearly separable.
ASupport Vector Machine (SVM) is a supervised learning algorithm used for classification and regression tasks. The goal of an SVM is to find the hyperplane that best separates the data into different classes. When the data is not linearly separable, we can use kernel functions to map the data to a higher-dimensional space where it becomes separable.
Let’s implement a kernel SVM using thescikit-learn library. We’ll use the famous Iris dataset for classification.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | importnumpyasnp importmatplotlib.pyplotasplt fromsklearnimportdatasets fromsklearn.model_selectionimporttrain_test_split fromsklearn.svmimportSVC fromsklearn.metricsimportaccuracy_score # Load the Iris dataset iris=datasets.load_iris() X=iris.data[:,:2] # We'll use only the first two features for visualization y=iris.target # Split the data into training and testing sets X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.3,random_state=42) # Create an SVM classifier with an RBF kernel svm=SVC(kernel='rbf',gamma=0.7,C=1.0) # Train the SVM svm.fit(X_train,y_train) # Make predictions y_pred=svm.predict(X_test) # Evaluate the model accuracy=accuracy_score(y_test,y_pred) print(f"Accuracy: {accuracy:.2f}") # Plot the decision boundary defplot_decision_boundary(X,y,model): h=.02 # Step size in the mesh x_min,x_max=X[:,0].min()-1,X[:,0].max()+1 y_min,y_max=X[:,1].min()-1,X[:,1].max()+1 xx,yy=np.meshgrid(np.arange(x_min,x_max,h), np.arange(y_min,y_max,h)) Z=model.predict(np.c_[xx.ravel(),yy.ravel()]) Z=Z.reshape(xx.shape) plt.contourf(xx,yy,Z,alpha=0.8) plt.scatter(X[:,0],X[:,1],c=y,edgecolors='k',marker='o') plt.xlabel('Sepal length') plt.ylabel('Sepal width') plt.title('SVM Decision Boundary with RBF Kernel') plt.show() plot_decision_boundary(X_train,y_train,svm) |

Here’s what’s going on in the above code:
Principal Component Analysis (PCA) is a dimensionality reduction technique that projects data onto a lower-dimensional space while preserving as much variance as possible. However, standard PCA is limited to linear transformations.Kernel PCA extends PCA by using kernel functions to perform non-linear dimensionality reduction.
Let’s implement Kernel PCA usingscikit-learn and apply it to a non-linear dataset.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | fromsklearn.decompositionimportKernelPCA fromsklearn.datasetsimportmake_moons # Generate a non-linear dataset X,y=make_moons(n_samples=100,noise=0.1,random_state=42) # Apply Kernel PCA with an RBF kernel kpca=KernelPCA(kernel='rbf',gamma=15,n_components=2) X_kpca=kpca.fit_transform(X) # Plot the original data and the transformed data plt.figure(figsize=(12,5)) plt.subplot(1,2,1) plt.scatter(X[:,0],X[:,1],c=y,edgecolors='k',marker='o') plt.title('Original Data') plt.subplot(1,2,2) plt.scatter(X_kpca[:,0],X_kpca[:,1],c=y,edgecolors='k',marker='o') plt.title('Kernel PCA Transformed Data') plt.show() |

Here’s an explanation of the code above:
A quick reminder: the kernel trick allows us to compute the dot product of two vectors in a high-dimensional space without explicitly mapping the vectors to that space. This is done using akernel function, which directly computes the dot product in the transformed space.
Let’s implement theRadial Basis Function (RBF) kernel from scratch and use it to compute the kernel matrix for a dataset. The RBF kernel is defined as:
\[
K(x, y) = \exp\left(-\gamma \|x – y\|^2\right)
\]
Where:
Let’s start with the RBF kernel function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | importnumpyasnp defrbf_kernel(x1,x2,gamma=1.0): """ Compute the RBF kernel between two vectors x1 and x2. Parameters: - x1, x2: Input vectors. - gamma: Kernel parameter. Returns: - Kernel value (scalar). """ squared_distance=np.sum((x1-x2)**2) returnnp.exp(-gamma *squared_distance) |
Thekernel matrix (or Gram matrix) is a matrix where each element \( K_{ij} \) is the kernel value between the \( i \)-th and \( j \)-th data points. Let’s compute the kernel matrix for a dataset.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | defcompute_kernel_matrix(X,kernel_function,gamma=1.0): """ Compute the kernel matrix for a dataset X using a given kernel function. Parameters: - X: Input dataset (n_samples, n_features). - kernel_function: Kernel function to use. - gamma: Kernel parameter. Returns: - Kernel matrix (n_samples, n_samples). """ n_samples=X.shape[0] kernel_matrix=np.zeros((n_samples,n_samples)) foriinrange(n_samples): forjinrange(n_samples): kernel_matrix[i,j]=kernel_function(X[i],X[j],gamma) returnkernel_matrix |
Let’s generate a simple 2D dataset and compute its kernel matrix using the RBF kernel.
1 2 3 4 5 6 7 8 9 | # Generate a simple 2D dataset X=np.array([[1,2],[2,3],[3,4],[4,5]]) # Compute the kernel matrix using the RBF kernel gamma=0.1 kernel_matrix=compute_kernel_matrix(X,rbf_kernel,gamma) print("Kernel Matrix (RBF Kernel):") print(kernel_matrix) |
The kernel matrix will look something like this:
1 2 3 4 5 | KernelMatrix(RBFKernel): [[1. 0.818730750.449328960.16529889] [0.818730751. 0.818730750.44932896] [0.449328960.818730751. 0.81873075] [0.165298890.449328960.818730751. ]] |
Now that we have the kernel matrix, we can use it in a kernelized algorithm, such as a kernel SVM. However, implementing a full kernel SVM from scratch is complex, so we’ll use the kernel matrix to demonstrate the concept.
For example, in a kernel SVM, the decision function for a new data point \( x \) is computed as:
\[
f(x) = \sum_{i=1}^n \alpha_i y_i K(x, x_i) + b
\]
Where:
While we won’t implement the full SVM here, the kernel matrix is a crucial component of kernelized algorithms.
Here is a summary of the kernel trick implementation:
This implementation demonstrates the core idea of the kernel trick: working in a high-dimensional space without explicitly transforming the data. You can extend this approach to implement other kernel functions (e.g., polynomial kernel) or use the kernel matrix in custom kernelized algorithms.
So, why do we use the kernel trick instead of explicit transformation?
Suppose we have a 2D dataset \( X = [x_1, x_2] \) and we want to transform it into a higher-dimensional space using a polynomial transformation. For simplicity, let’s consider a quadratic transformation:
\[
\phi(x) = [x_1, x_2, x_1^2, x_2^2, x_1 x_2]
\]
Here, \( \phi(x) \) maps the original 2D data into a 5D space. If we have \( n \) data points, we would need to compute this transformation for each point, resulting in a \( n \times 5 \) matrix.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | importnumpyasnp # Original 2D data X=np.array([[1,2],[2,3],[3,4]]) # Explicit transformation to 5D space defexplicit_transformation(X): x1=X[:,0] x2=X[:,1] returnnp.column_stack((x1,x2,x1**2,x2**2,x1 *x2)) # Apply the transformation X_transformed=explicit_transformation(X) print("Explicitly Transformed Data:") print(X_transformed) |
And the output of the above code would be:
1 2 3 4 | ExplicitlyTransformedData: [[1 2 1 4 2] [2 3 4 9 6] [3 4 91612]] |
Here, we explicitly computed the new features in the 5D space. This works fine for small datasets and low-dimensional transformations, but it becomes problematic for:
Let’s now contrast this with the kernel trick.
The kernel trick avoids explicitly computing \( \phi(x) \) by directly computing the dot product \( \phi(x) \cdot \phi(y) \) in the transformed space using a kernel function \( K(x, y) \). For example, the RBF kernel implicitly maps data into an infinite-dimensional space, but we never compute \( \phi(x) \) directly.
1 2 3 4 5 6 7 8 9 | # Kernel trick: Compute the dot product in the transformed space without explicit transformation defrbf_kernel(x1,x2,gamma=1.0): squared_distance=np.sum((x1-x2)**2) returnnp.exp(-gamma *squared_distance) # Compute the kernel matrix kernel_matrix=compute_kernel_matrix(X,rbf_kernel,gamma=1.0) print("Kernel Matrix (RBF Kernel):") print(kernel_matrix) |
And the output:
1 2 3 4 5 | KernelMatrix(RBFKernel): [[1.00000000e+001.35335283e-013.35462628e-041.52299797e-08] [1.35335283e-011.00000000e+001.35335283e-013.35462628e-04] [3.35462628e-041.35335283e-011.00000000e+001.35335283e-01] [1.52299797e-083.35462628e-041.35335283e-011.00000000e+00]] |
Here, we never explicitly computed \( \phi(x) \). Instead, we used the kernel function to compute the dot product in the transformed space directly.
Here’s why explicit transformation is problematic:
Explicit transformation TL;DR: Directly computes the transformed features \( \phi(x) \) in the higher-dimensional space. This is feasible for simple, low-dimensional transformations but becomes impractical for complex or high-dimensional transformations.
Conversely, the kernel trick is particularly useful when:
Kernel trick TL;DR: Avoids explicit transformation by computing the dot product \( \phi(x) \cdot \phi(y) \) directly using a kernel function. This is efficient and works even for infinite-dimensional spaces. The kernel trick is a clever mathematical shortcut that allows us to work in high-dimensional spaces without the computational burden of explicit transformation.
Kernel methods are a powerful tool in machine learning, enabling us to handle non-linear data efficiently. In this tutorial, we explored the kernel trick, kernel SVMs, and Kernel PCA, and provided practical Python examples to help you get started with these techniques.
By mastering kernel methods, you can tackle a wide range of machine learning problems, from classification to dimensionality reduction, with greater flexibility and efficiency.







Welcome!
I'mJason Brownlee PhD
and Ihelp developers get results withmachine learning.
Read more
TheEBook Catalog is where
you'll find theReally Good stuff.