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.

MLP classifier

In this example we use a Multi-layer Perceptron (MLP) classifier on the MNIST digit dataset.

Notebook Cell

Data Preparation

We download the MNIST data using HuggingFace’s datasets library:

Now we need to apply several transformations to the dataset before splitting it into a test and a test set:

Multi-layer Perceptron

We will use a very simple Bayesian neural network in this example: A MLP with gaussian priors on the weights.

If we note XX the array that represents an image and yy the array such that yi=0y_i = 0 if the image is in category ii, yi=1y_i=1 otherwise, the model can be written as:

p=NN⁡(X)y∼Categorical⁡(p)\begin{align*} \boldsymbol{p} &= \operatorname{NN}(X)\\ \boldsymbol{y} &\sim \operatorname{Categorical}(\boldsymbol{p}) \end{align*}

Sample From the Posterior Distribution of the MLP’s Weights

Now we need to get initial values for the parameters, and we simply sample from their prior distribution:

We now sample from the model’s posteriors using SGLD. We discard the first 1000 samples until the sampler has reached the typical set, and then take 2000 samples. We record the model’s accuracy with the current values every 100 steps.

Loading...
Loading...

Let us plot the point-wise accuracy at different points in the sampling process:

Source
<Figure size 1000x400 with 1 Axes>

It looks like the point-wise accuracy, while still increasing, has reached a plateau. We will now sample from the posterior distribution. Instead of accumulating the network weights, which would require a subtantial amounf of memory, we will update the average of the quantity that we are interested in, the predictive probabilities over the test set.

Formally, for each sample θi\theta_i and each x∗x_* of the test set compute P(y∗=i∣x∗,θi)P(y_*=i\mid x_*, \theta_i). We use each sample to update the estimation of P(y=i∣x∗)P(y=i \mid x_*) with the Monte Carlo approximation:

P(y=i∣x∗)=∫P(y=i∣x∗,θ)P(θ∣D) dθ≈1Ns∑sP(y=i∣x∗,θs)P(y=i\mid x_*) = \int P(y=i\mid x_*, \theta)P(\theta \mid \mathcal{D})\,\mathrm{d}\theta \approx \frac{1}{N_s} \sum_s P(y=i\mid x_*, \theta_s)
Source
Loading...

Let us plot the accuracy as a function of the number of samples:

Source
<Figure size 1000x400 with 1 Axes>

It is not clear from the figure above whether the increase of the accuracy is due to an increase in the pointwise accuracy, or an effect of averaging over the posterior distribution. To see this, let us compare the last value to the pointwise accuracy computed on the chain’s last state:

0.9641 0.9586
0.0055000186

Averaging the predictive probabilities over the posterior distribution leads to a decrease of 0.8 error point compared to the point-wise accuracy. And in the end, this leads to a decent accuracy for a model that was not fine-tuned (we took the first value of the step size that led to an increasing accuracy).

Sampling with SGHMC

We can also use SGHMC with a constant learning rate to samples from this model

Loading...
Source
<Figure size 1000x400 with 1 Axes>

We now sample and compute the accuracy by averaging over the posterior samples:

Loading...
Source
<Figure size 1000x400 with 1 Axes>

Comparison

Let us plot the evolution of the accuracy as a function of the number of samples:

Source
<Figure size 1000x400 with 1 Axes>

SGHMC gives a slightly better accuracy than SGLD. However, plotting this in terms of the number of steps is slightly misleading: SGHMC evaluates the gradient 10 times for each step while SGLD only once.

Exploring uncertainty

Let us now use the average posterior predictive probabilities to see whether the model is overconfident. Here we will say that the model is unsure of its prediction for a given image if the digit that is most often predicted for this image is predicted less tham 95% of the time.

We will use SGHMC’s prediction in the following.

    Our model is certain of its classification for
    53.5%
    of the test set examples.

Let’s plot a few examples where the model was very uncertain:

<Figure size 900x1500 with 15 Axes>

Are there digits that our model is more uncertain about? We plot the histogram of the number of times the model was unsure about each digit:

Source
<Figure size 800x500 with 1 Axes>

Perhaps unsurprisingly, the digit 8 is overrepresented in the set of examples ii for which max⁡dP(yi=d∣xi)<0.95\max_d P(y_i=d|x_i) < 0.95. As a purely academic exercise and sanity test of sort, let us now re-compute the point-wise accuracy ignoring the digits for which the model is uncertain, varying the threshold above which we consider the model to be certain:

Notebook Cell
Notebook Cell
Source
<Figure size 1000x400 with 2 Axes>

Not bad at all, by dropping less than 2% of the samples we reach .99 accuracy, not too bad for such a simple model!

Such a simple rejection criterion may not be realistic in practice. But what Bayesian methods allow you to do is to design a loss function that describe the cost of each mistake (say choosing “1” when the digit was in fact “9”), and integrating this function over your posterior allows you to make principled decisions about which digit to predict for each example.