Overview

In this notebook we will understand MC dropout which is a technique used to get uncertainty in deep neural network models. We will explain this using MC dropout for classification on MNIST dataset. We will even introduce and explain the concept of calibration error and compare the uncertainty between various models using this metric.

Standard deep learning tools for regression and classification do not capture model uncertainty. Standard deep learning tools for regression and classification do not capture model uncertainty.A model can be uncertain in its prediction even with high softmax output. A model can be uncertain in its prediction even with high softmax output.

What is MC dropout ?

A model can be uncertain in its prediction even with high softmax output. Dropout is a regularization technique which prevents overfitting. In Dropout different set of neurons are switched off and each neuron has probability of getting off while training. In Dropout different set of neurons are switched off and each neuron has probability of getting off while training. In Dropout different set of neurons are switched off and each neuron has probability of getting off while training. MC Dropout can be thought as an ensemble model. Everytime different set of neurons are off with probability P. Hence each time the model is different and final output is the mean of many different neural network.

Import Libraries

import numpy as np
import pandas as pd

import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,Dropout, Conv2D
from tensorflow.keras.models import load_model

%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt

Import Dataset

Classification

Training models

(X_train, y_train), (X_test, y_test) = keras.datasets.mnist.load_data()

MonteCarlo Layer

class MonteCarloDropout(Dropout):
    def call(self, inputs):
        return super().call(inputs, training=True)

Model 1

Describe model 1

def return_network1(index=1):
    
    layers=[MonteCarloDropout(rate=0.25),Dropout(rate=0.25)]
    model = keras.models.Sequential()
    model.add(keras.layers.Flatten(input_shape=(28, 28)))
    model.add(layers[index])
    model.add(keras.layers.Dense(300, activation="relu"))
    optimizer = keras.optimizers.Nadam(lr=0.001)
    model.compile(loss="sparse_categorical_crossentropy",optimizer=optimizer, metrics=["accuracy"])
    return model
model_mc1=return_network1(index=0)
model_mc1.fit(X_train, y_train, epochs=50)
model_mc1.save("models/model_mc1.h5")
C:\Users\Dell\anaconda3\lib\site-packages\keras\optimizer_v2\nadam.py:73: UserWarning: The `lr` argument is deprecated, use `learning_rate` instead.
  super(Nadam, self).__init__(name, **kwargs)
Epoch 1/50
1875/1875 [==============================] - 8s 4ms/step - loss: 7.2560 - accuracy: 0.1291
Epoch 2/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6437 - accuracy: 0.1445
Epoch 3/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5990 - accuracy: 0.1352
Epoch 4/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5982 - accuracy: 0.1315
Epoch 5/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.4880 - accuracy: 0.1503
Epoch 6/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5544 - accuracy: 0.1329
Epoch 7/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5395 - accuracy: 0.1345
Epoch 8/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.4437 - accuracy: 0.1522
Epoch 9/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5092 - accuracy: 0.1380
Epoch 10/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6473 - accuracy: 0.1130
Epoch 11/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.4699 - accuracy: 0.1451
Epoch 12/50
1875/1875 [==============================] - 8s 4ms/step - loss: 5.4630 - accuracy: 0.1463
Epoch 13/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.4619 - accuracy: 0.1471
Epoch 14/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.4672 - accuracy: 0.1462
Epoch 15/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.4697 - accuracy: 0.1449
Epoch 16/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5408 - accuracy: 0.1326
Epoch 17/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5991 - accuracy: 0.1196
Epoch 18/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5280 - accuracy: 0.1330
Epoch 19/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5330 - accuracy: 0.1334
Epoch 20/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6431 - accuracy: 0.1117
Epoch 21/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6405 - accuracy: 0.1120
Epoch 22/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6882 - accuracy: 0.1035
Epoch 23/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6904 - accuracy: 0.1033
Epoch 24/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6526 - accuracy: 0.1093
Epoch 25/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5305 - accuracy: 0.1328
Epoch 26/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.3966 - accuracy: 0.1585
Epoch 27/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5010 - accuracy: 0.1380
Epoch 28/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.4836 - accuracy: 0.1430
Epoch 29/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6671 - accuracy: 0.1073
Epoch 30/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6737 - accuracy: 0.1059
Epoch 31/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.7389 - accuracy: 0.1114
Epoch 32/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6606 - accuracy: 0.1093
Epoch 33/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6631 - accuracy: 0.1069
Epoch 34/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6731 - accuracy: 0.1055
Epoch 35/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6893 - accuracy: 0.1024
Epoch 36/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6090 - accuracy: 0.1170
Epoch 37/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5166 - accuracy: 0.1348
Epoch 38/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5734 - accuracy: 0.1242
Epoch 39/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6738 - accuracy: 0.1052
Epoch 40/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.6581 - accuracy: 0.1075
Epoch 41/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.4971 - accuracy: 0.1472
Epoch 42/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5050 - accuracy: 0.1408
Epoch 43/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5165 - accuracy: 0.1338
Epoch 44/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.4569 - accuracy: 0.1461
Epoch 45/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.3364 - accuracy: 0.1724
Epoch 46/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.3718 - accuracy: 0.1669
Epoch 47/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.4278 - accuracy: 0.1566
Epoch 48/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5039 - accuracy: 0.1380
Epoch 49/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.4997 - accuracy: 0.1395
Epoch 50/50
1875/1875 [==============================] - 7s 4ms/step - loss: 5.5874 - accuracy: 0.1204

Testing

def test(num_predictions, model):
    T=100 #(NUMBER OF PREDICTIONS)
    predictions=[model.predict(X_test) for _ in range(T)]
    probability=np.stack(predictions).mean(axis=0)
    return predictions,probability
num_predictions=100
predictions1, probability1 = test(num_predictions, model_mc1)
y_pred=np.argmax(probability1, axis=1)
acc = np.mean(y_pred == y_test)
print(acc)
0.176

Calibration

def dict_make(dict_name,key,value):
    if(key in dict_name):
        dict_name[key].append(value)
    else:
        dict_name[key]=[]
        
def bin_allocate(probability):
    max_prob=np.max(probability, axis=1)
    indexes={}
    for i in range(len(max_prob)):    
        if(max_prob[i]<0.1):
            dict_make(indexes,0.1,i)
        elif(max_prob[i]<0.2):
            dict_make(indexes,0.2,i)
        elif(max_prob[i]<0.3):
            dict_make(indexes,0.3,i)
        elif(max_prob[i]<0.4):
            dict_make(indexes,0.4,i)
        elif(max_prob[i]<0.5):
            dict_make(indexes,0.5,i)
        elif(max_prob[i]<0.6):
            dict_make(indexes,0.6,i)
        elif(max_prob[i]<0.7):
            dict_make(indexes,0.7,i)
        elif(max_prob[i]<0.8):
            dict_make(indexes,0.8,i)
        elif(max_prob[i]<0.9):
            dict_make(indexes,0.9,i)
        else:
            dict_make(indexes,1,i)
            
    return indexes

def plot_samples(indexes):
    keys = indexes.keys()
    values = [len(indexes[key])/len(X_test) for key in indexes]
    plt.bar(keys, values,width=-0.1,align='edge',edgecolor='black')
    plt.xlabel('Confidence range')
    plt.ylabel('Ratio of no of samples')
        
indexes1=bin_allocate(probability1)
plot_samples(indexes1)
def calculate_avg_acc(probability,indexes):
    accuracy={}
    max_prob=np.max(probability,axis=1)
    prob={}
    for key in indexes:
        accuracy[key]=0
        prob[key]=0
        for i in indexes[key]:
            if(y_pred[i]==y_test[i]):
                accuracy[key]+=1
            prob[key]+=max_prob[i]
        prob[key]=prob[key]/len(indexes[key])
        accuracy[key]=accuracy[key]/len(indexes[key])
    return prob,accuracy

def plot_calibration(prob,accuracy):        
    plt.bar(prob.keys(),prob.values(),width=-0.1,align='edge',alpha=0.5,edgecolor='black')
    plt.bar(accuracy.keys(),accuracy.values(),width=-0.1,align='edge',alpha=0.1,edgecolor='black')
    plt.legend(['Confidence','Accuracy'],loc=2)
    plt.xlabel('Confidence range')
    plt.ylabel('Average Value')

def expected_calibration_error(accuracy,prob,indexes):
    ece=0
    for key in accuracy.keys():
        ece=+len(indexes[key])*(np.abs(accuracy[key]-prob[key]))
    return ece

def maximum_calibration_error(accuracy,prob):
    mce=0
    for key in accuracy.keys():
        mce=np.maximum(np.abs(accuracy1[key]-prob1[key]),mce)
    return mce
prob1,accuracy1=calculate_avg_acc(probability1,indexes1)
plot_calibration(prob1,accuracy1)
ece=expected_calibration_error(accuracy1,prob1,indexes1)/len(y_test)
mce=maximum_calibration_error(accuracy1,prob1)
print(ece)
print(mce)
0.00015200642347335813
46.20615993170427

Model 2

def return_network2(index=1):
    
    layers=[MonteCarloDropout(rate=0.25),Dropout(rate=0.25)]
    model = keras.models.Sequential()
    model.add(keras.layers.Flatten(input_shape=(28, 28)))
    model.add(layers[index])
    model.add(keras.layers.Dense(300, activation="relu"))
    model.add(layers[index])
    model.add(keras.layers.Dense(300, activation="relu"))
    model.add(layers[index])
    model.add(keras.layers.Dense(10, activation="softmax"))
    optimizer = keras.optimizers.Nadam(lr=0.001)
    model.compile(loss="sparse_categorical_crossentropy",optimizer=optimizer, metrics=["accuracy"])
    
    return model
model_mc2=return_network2(index=0)
model_mc2.fit(X_train, y_train, epochs=50)
model_mc2.save("models/model_mc2.h5")
Epoch 1/50
1875/1875 [==============================] - 10s 5ms/step - loss: 4.1559 - accuracy: 0.7649
Epoch 2/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.5630 - accuracy: 0.8576
Epoch 3/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.3915 - accuracy: 0.8932
Epoch 4/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.3624 - accuracy: 0.9021
Epoch 5/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.3380 - accuracy: 0.9116
Epoch 6/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.3306 - accuracy: 0.9137
Epoch 7/50
1875/1875 [==============================] - 11s 6ms/step - loss: 0.3119 - accuracy: 0.9201
Epoch 8/50
1875/1875 [==============================] - 10s 5ms/step - loss: 0.3120 - accuracy: 0.9209
Epoch 9/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2960 - accuracy: 0.9251
Epoch 10/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2993 - accuracy: 0.9228
Epoch 11/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2900 - accuracy: 0.9268
Epoch 12/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2809 - accuracy: 0.9296
Epoch 13/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2838 - accuracy: 0.9297
Epoch 14/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2808 - accuracy: 0.9302
Epoch 15/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2718 - accuracy: 0.9331
Epoch 16/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2714 - accuracy: 0.9317
Epoch 17/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2722 - accuracy: 0.9323
Epoch 18/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2614 - accuracy: 0.9353
Epoch 19/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2741 - accuracy: 0.9328
Epoch 20/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2660 - accuracy: 0.9343
Epoch 21/50
1875/1875 [==============================] - 10s 5ms/step - loss: 0.2651 - accuracy: 0.9359
Epoch 22/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2653 - accuracy: 0.9340
Epoch 23/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2596 - accuracy: 0.9362
Epoch 24/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2585 - accuracy: 0.9345
Epoch 25/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2632 - accuracy: 0.9349
Epoch 26/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2568 - accuracy: 0.9366
Epoch 27/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2661 - accuracy: 0.9349
Epoch 28/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2601 - accuracy: 0.9372
Epoch 29/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2666 - accuracy: 0.9374
Epoch 30/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2642 - accuracy: 0.9374
Epoch 31/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2591 - accuracy: 0.9376
Epoch 32/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2556 - accuracy: 0.9392
Epoch 33/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2623 - accuracy: 0.9374
Epoch 34/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2580 - accuracy: 0.9382
Epoch 35/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2619 - accuracy: 0.9372
Epoch 36/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2568 - accuracy: 0.9391
Epoch 37/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2638 - accuracy: 0.9367
Epoch 38/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2508 - accuracy: 0.9384
Epoch 39/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2583 - accuracy: 0.9396
Epoch 40/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2437 - accuracy: 0.9402
Epoch 41/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2624 - accuracy: 0.9372
Epoch 42/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2723 - accuracy: 0.9366
Epoch 43/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2615 - accuracy: 0.9387
Epoch 44/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2510 - accuracy: 0.9397
Epoch 45/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2531 - accuracy: 0.9384
Epoch 46/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2616 - accuracy: 0.9385
Epoch 47/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2528 - accuracy: 0.9401
Epoch 48/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2632 - accuracy: 0.9395
Epoch 49/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2456 - accuracy: 0.9408
Epoch 50/50
1875/1875 [==============================] - 9s 5ms/step - loss: 0.2633 - accuracy: 0.9383
num_predictions=100
predictions2, probability2 = test(num_predictions, model_mc2)
y_pred=np.argmax(probability2, axis=1)
acc = np.mean(y_pred == y_test)
print(acc)
0.9712
indexes2=bin_allocate(probability2)
plot_samples(indexes2)
prob2,accuracy2=calculate_avg_acc(probability2,indexes2)
plot_calibration(prob2,accuracy2)
ece=expected_calibration_error(accuracy2,prob2,indexes2)/len(y_test)
mce=maximum_calibration_error(accuracy2,prob2)
print(ece)
print(mce)
3.017636537551884e-05
46.20615993170427

Model 3

def return_network3(index=1):
    
    layers=[MonteCarloDropout(rate=0.25),Dropout(rate=0.25)]
    model = keras.models.Sequential()
    model.add(keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_uniform', input_shape=(28, 28,1)))
    model.add(layers[index])
    model.add(keras.layers.Flatten())
    model.add(keras.layers.Dense(300, activation="relu"))
    model.add(layers[index])
    model.add(keras.layers.Dense(10, activation="softmax"))
    optimizer = keras.optimizers.Nadam(lr=0.001)
    model.compile(loss="sparse_categorical_crossentropy",optimizer=optimizer, metrics=["accuracy"])
    
    return model
model_mc3=return_network3(index=0)
model_mc3.fit(X_train.reshape((X_train.shape[0], 28, 28, 1)), y_train, epochs=5)
model_mc3.save("models/model_mc3.h5")
Epoch 1/5
1875/1875 [==============================] - 271s 144ms/step - loss: 3.5979 - accuracy: 0.5974
Epoch 2/5
1875/1875 [==============================] - 270s 144ms/step - loss: 1.0296 - accuracy: 0.7081
Epoch 3/5
1875/1875 [==============================] - 271s 144ms/step - loss: 0.6659 - accuracy: 0.8234
Epoch 4/5
1875/1875 [==============================] - 273s 146ms/step - loss: 0.4615 - accuracy: 0.8821
Epoch 5/5
1875/1875 [==============================] - 272s 145ms/step - loss: 0.3551 - accuracy: 0.9092
num_predictions=100
predictions3, probability3 = test(num_predictions, model_mc3)
y_pred=np.argmax(probability3, axis=1)
acc = np.mean(y_pred == y_test)
print(acc)
0.9593
indexes3=bin_allocate(probability3)
plot_samples(indexes3)
prob3,accuracy3=calculate_avg_acc(probability3,indexes3)
plot_calibration(prob3,accuracy3)
ece=expected_calibration_error(accuracy3,prob3,indexes3)/len(y_test)
mce=maximum_calibration_error(accuracy3,prob3)
print(ece)
print(mce)
3.947368860244751e-05
46.20615993170427