Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Hyperparamter tuning

Dataset

We’re going to use a different dataset this time, which is more interesting than flowers I hope.

https://archive.ics.uci.edu/dataset/17/breast+cancer+wisconsin+diagnostic

['radius1', 'texture1', 'perimeter1', 'area1', 'smoothness1', 'compactness1', 'concavity1', 'concave_points1', 'symmetry1', 'fractal_dimension1', 'radius2', 'texture2', 'perimeter2', 'area2', 'smoothness2', 'compactness2', 'concavity2', 'concave_points2', 'symmetry2', 'fractal_dimension2', 'radius3', 'texture3', 'perimeter3', 'area3', 'smoothness3', 'compactness3', 'concavity3', 'concave_points3', 'symmetry3', 'fractal_dimension3']
Loaded the Wisconsin Breast Cancer dataset of size (569, 31)
Loading...

Now we need to get our dataset, that is our X, y variables. Make sure to encode the benign/malignant labels into [0, 1] labels

There are 357 benign samples and 212 malignant samples

This will be a bit harder to visualize since we don’t have 30-dimensional brains. First, visualize the features in a 2-D space using PCA

<Figure size 960x720 with 1 Axes>

Next, use seaborn to plot the feature correlation matrix

<Figure size 1800x1500 with 2 Axes>

Finally, we should create and plot three subsets of our dataset:

  • Training dataset, for model fitting

  • Validation dataset, to track model fitting

  • Test dataset, to evaluate our model

The training set has size (364, 30)
The validation set has size (364, 30)
The testing set has size (114, 30)
<Figure size 960x720 with 1 Axes>

Define Polynomial Logistic Regression with L1 and L2 regularization

<Figure size 960x720 with 1 Axes>
Training accuracy 0.9120879120879121
Validation accuracy 0.945054945054945
Test accuracy 0.9385964912280702
<Axes: xlabel='PC 1', ylabel='PC 2'>
<Figure size 960x720 with 1 Axes>
<Figure size 960x720 with 1 Axes>

K-fold cross validation

Before, we only used one validation set to estimate performance during training. But this is a partial snapshot. The idea behind cross-validation is you create several distinct train/val splits so that you have a performance estimate over the entire training set.

Using cross-validation, you can more accurately assess and tune model hyperparameters before applying the model to test data

Fold 0 has 37% malignant samples
	Validation accuracy = 0.967

Fold 1 has 38% malignant samples
	Validation accuracy = 0.989

Fold 2 has 35% malignant samples
	Validation accuracy = 0.967

Fold 3 has 38% malignant samples
	Validation accuracy = 0.967

Fold 4 has 38% malignant samples
	Validation accuracy = 0.989

Cross-validation accuracy = 0.976 +/- 0.011
Test accuracy = 0.982

Hyperparameter tuning with cross validation

We want to get the training parameters lr, l1_weight that will maximize our generalization accuracy. To do this, we can do a grid search and track the cross-validation accuracy for each parameter combination

The best estimator had parameters lr = 0.178 and l1_weight = 0.001 and reached an average validation accuracy of 0.976
This estimator reaches a test accuracy of 0.982

Nonlinear optimization and kernel methods

We have seen with Polynomial Logistic Regression that the use of nonlinear features can allow us to represent more complex functions and decision boundaries. Here, we will compare linear ridge (L2) regression with nonlinear features ϕ(x)\phi(x) to kernel ridge regression (KRR). KRR represents the inner product ⟨ϕ(x),ϕ(y)⟩\langle \phi(x), \phi(y) \rangle via a kernel function k(x,y)k(x, y).

At first this may seem uninteresting. What is the point of using a function to represent a dot product? Let’s consider 2-dimensional inputs x=(x1,x2)\mathbf{x} = (x_1, x_2) and y=(y1,y2)\mathbf{y} = (y_1, y_2).

Some kernel functions are uninteresting, like the linear kernel: k1(x,y)=x⋅y=x1 y1+x2 y2k_1(\mathbf{x}, \mathbf{y}) = \mathbf{x} \cdot \mathbf{y} = x_1 \,y_1 + x_2 \,y_2

Some are slightly more interesting, like the quadratic kernel:

k2(x,y)=(x⋅y)2=(x1 y1+x2 y2)2=x12 y12+x22 y22+2x1 x2 y1 y2=(x12, x22, x1 x22)⋅(y12, y22, y1 y22)\begin{align} k_2(\mathbf{x}, \mathbf{y}) &= (\mathbf{x} \cdot \mathbf{y})^2 \\ &= (x_1 \, y_1 + x_2 \, y_2)^2 \\ &= x_1^2 \, y_1^2 + x_2^2 \, y_2^2 + 2 x_1 \, x_2 \, y_1 \, y_2 \\ &= (x_1^2,\, x_2^2,\, x_1\, x_2 \sqrt{2}) \cdot (y_1^2,\, y_2^2,\, y_1\, y_2 \sqrt{2}) \end{align}

Here, the quadratic kernel allows us to compute a dot product between two 3-dimensional feature vectors, but we did not have to actually compute either feature vector!

One of the most interesting kernels is the RBF kernel:

kRBF(x,y)=exp⁡(−12∥x−y∥2)\begin{align} k_{\text{RBF}}(\mathbf{x}, \mathbf{y}) = \exp \left(-\frac12 \Vert \mathbf{x} - \mathbf{y} \Vert^2 \right) \end{align}

It turns out that this is equivalent to the product of two infinite-dimensional feature vectors (read more here). The RBF kernel is particularly convenient because we do not have the computational resources to compute an infinite-size feature vector for each element of our dataset. But computing the kernel is very easy, and can allow us to represent a variety of complex behaviors.

<Figure size 960x720 with 3 Axes>

Feature Ridge Regression

We are going to do linear ridge regression on a set of nonlinear features. Specifically, we would like to optimize

L=∑i=1N(yi−yi^)2+λw⃗⋅w⃗\begin{align} \mathcal{L} = \sum_{i=1}^N (y_i - \hat{y_i})^2 + \lambda \vec{w} \cdot \vec{w} \end{align}

where

y(x)=w⃗⋅ϕ⃗(x)=[∑i=1Ntrainαiϕ⃗(xi)]⋅ϕ⃗(x)\begin{align} y(x) &= \vec{w} \cdot \vec{\phi}(x) \\ &= \left[ \sum_{i=1}^{N_{\text{train}}} \alpha_i \vec{\phi} (x_i) \right] \cdot \vec{\phi}(x) \end{align}

In the second line, we have rewritten the parameter vector w⃗\vec{w} as a weighted sum over training examples. Our goal will be to figure out the sample weights αi\alpha_i and use them to compute w⃗\vec{w}

To do this, we can substitute in the “nearest neighbor feature regression” version of y(x)y(x) into the objective function. Adopting a notation where the matrix ΦN×f={ϕ⃗(x1);ϕ⃗(x2);… }\Phi_{N\times f} = \left\{ \vec{\phi}(x_1); \vec{\phi}(x_2); \dots \right\}, the vector α⃗N\vec{\alpha}_{N} contains the sample weights, and w⃗=Φ⊤α⃗\vec{w} = \Phi^{\top} \vec{\alpha} we get

L=(Φw⃗−Y^)⊤(Φw⃗−Y^)+λw⃗⊤w⃗=(ΦΦ⊤α⃗−Y^)⊤(ΦΦ⊤α⃗−Y^)+λα⃗⊤ΦΦ⊤α⃗\begin{align} \mathcal{L} &= \left(\Phi \vec{w} - \hat{Y}\right)^{\top} \left( \Phi \vec{w} - \hat{Y} \right) + \lambda \vec{w}^{\top} \vec{w} \\ &= \left( \Phi \Phi^{\top} \vec{\alpha} - \hat{Y} \right)^{\top} \left( \Phi \Phi^{\top} \vec{\alpha} - \hat{Y} \right) + \lambda \vec{\alpha}^{\top} \Phi \Phi^{\top} \vec{\alpha} \\ \end{align}

We’re going to adopt the shorthand KN×N=ΦΦ⊤K_{N\times N} = \Phi \Phi^{\top}, leading to

L=α⃗⊤KKα⃗−2α⃗⊤KY^+Y^⊤Y^+λα⃗⊤Kα⃗\begin{align} \mathcal{L} &= \vec{\alpha}^{\top} K K \vec{\alpha} - 2 \vec{\alpha}^{\top} K \hat{Y} + \hat{Y}^{\top}\hat{Y} + \lambda \vec{\alpha}^{\top} K \vec{\alpha} \end{align}

The minimum loss solution is when ∂α⃗L=0\partial_{\vec{\alpha}} \mathcal{L} = 0

∂L∂α⃗=0=2KKα⃗−2KY^+2λKα⃗→KY^=K(K+λI)α⃗→α⃗=(K+λI)−1Y^\begin{align} \frac{\partial \mathcal{L}}{\partial \vec{\alpha}} &= 0 \\ &= 2 K K \vec{\alpha} - 2 K \hat{Y} + 2 \lambda K \vec{\alpha} \\ \rightarrow K \hat{Y} &= K (K + \lambda I) \vec{\alpha} \\ \rightarrow \vec{\alpha} &= (K + \lambda I)^{-1} \hat{Y} \end{align}

We will use this result to compute α⃗\vec{\alpha} during fitting and then compute our weights

<Figure size 960x720 with 3 Axes>

Kernel Ridge Regression

In the above example, we had to compute a matrix whose entries contained the dot products between feature vectors from our training set ϕ⃗(xtrain)\vec{\phi}(x_{\text{train}}) The kernel trick recasts this dot product as the evaluation of a kernel function k(xi,xj)=ϕ⃗(xi)⋅ϕ(xj)⃗k(x_i, x_j) = \vec{\phi}(x_i) \cdot \vec{\phi(x_j)}. Using this trick, one can compute a kernel matrix K≡ΦΦTK \equiv \Phi \Phi^T whose entries consist of kernel evaluations

Kij=k(xi,xj)=ϕ⃗(xi)⋅ϕ(xj)⃗\begin{align} K_{ij} = k(x_i, x_j) = \vec{\phi}(x_i) \cdot \vec{\phi(x_j)} \end{align}

In kernel ridge regression, we no longer care about the feature function and never compute feature vectors. Instead, we implicitly compute the product of feature vectors using the kernel function. The actual fitting will be almost identical as above. The main difference is that by using the kernel trick, the model evaluation becomes

y(x)=∑i=1Ntrainαi k(xi,x)\begin{align} y(x) = \sum_{i=1}^{N_{\text{train}}} \alpha_i\, k(x_i, x) \end{align}

Thus, model inference requires evaluation of the kernel function using each training point.

<Figure size 960x720 with 3 Axes>