{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "### Contrastive explanation on MNIST (Tensorflow)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is an example of `ContrastiveExplainer` on MNIST with a Tensorflow model. `ContrastiveExplainer` is an optimization based method for generating explanations (pertinent negatives and pertinent positives), supporting classification tasks only. If using this explainer, please cite the original work: https://arxiv.org/abs/1802.07623." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# This default renderer is used for sphinx docs only. Please delete this cell in IPython.\n", "import plotly.io as pio\n", "pio.renderers.default = \"png\"" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import tensorflow as tf\n", "import matplotlib.pyplot as plt\n", "\n", "from omnixai.data.image import Image\n", "from omnixai.explainers.vision import ContrastiveExplainer" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following code loads the training and test datasets. We recommend using `Image` to represent a batch of images. `Image` can be constructed from a numpy array or a Pillow image. In this example, `Image` is constructed from a numpy array containing a batch of digit images." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# Load the MNIST dataset\n", "img_rows, img_cols = 28, 28\n", "(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()\n", "\n", "if tf.keras.backend.image_data_format() == 'channels_first':\n", " x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)\n", " x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)\n", " input_shape = (1, img_rows, img_cols)\n", "else:\n", " x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)\n", " x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)\n", " input_shape = (img_rows, img_cols, 1)\n", "\n", "# Use `Image` objects to represent the training and test datasets\n", "train_imgs, train_labels = Image(x_train.astype('float32'), batched=True), y_train\n", "test_imgs, test_labels = Image(x_test.astype('float32'), batched=True), y_test" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The preprocessing function takes an `Image` instance as its input and outputs the processed features that the ML model consumes. In this example, the pixel values are normalized to [0, 1]." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "preprocess_func = lambda x: np.expand_dims(x.to_numpy() / 255, axis=-1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We train a simple convolutional neural network for this task. The network has two convolutional layers and one dense hidden layer. " ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/10\n", "469/469 [==============================] - 2s 5ms/step - loss: 0.1712 - accuracy: 0.9493 - val_loss: 0.0509 - val_accuracy: 0.9837\n", "Epoch 2/10\n", "469/469 [==============================] - 2s 5ms/step - loss: 0.0467 - accuracy: 0.9857 - val_loss: 0.0364 - val_accuracy: 0.9880\n", "Epoch 3/10\n", "469/469 [==============================] - 2s 5ms/step - loss: 0.0331 - accuracy: 0.9896 - val_loss: 0.0323 - val_accuracy: 0.9884\n", "Epoch 4/10\n", "469/469 [==============================] - 2s 5ms/step - loss: 0.0226 - accuracy: 0.9927 - val_loss: 0.0345 - val_accuracy: 0.9890\n", "Epoch 5/10\n", "469/469 [==============================] - 2s 5ms/step - loss: 0.0171 - accuracy: 0.9942 - val_loss: 0.0371 - val_accuracy: 0.9880\n", "Epoch 6/10\n", "469/469 [==============================] - 2s 5ms/step - loss: 0.0150 - accuracy: 0.9949 - val_loss: 0.0297 - val_accuracy: 0.9906\n", "Epoch 7/10\n", "469/469 [==============================] - 2s 5ms/step - loss: 0.0109 - accuracy: 0.9966 - val_loss: 0.0428 - val_accuracy: 0.9887\n", "Epoch 8/10\n", "469/469 [==============================] - 2s 5ms/step - loss: 0.0101 - accuracy: 0.9967 - val_loss: 0.0356 - val_accuracy: 0.9895\n", "Epoch 9/10\n", "469/469 [==============================] - 2s 5ms/step - loss: 0.0086 - accuracy: 0.9969 - val_loss: 0.0393 - val_accuracy: 0.9892\n", "Epoch 10/10\n", "469/469 [==============================] - 2s 5ms/step - loss: 0.0065 - accuracy: 0.9977 - val_loss: 0.0399 - val_accuracy: 0.9898\n", "Test loss: 0.03988948091864586\n", "Test accuracy: 0.989799976348877\n" ] } ], "source": [ "batch_size = 128\n", "num_classes = 10\n", "epochs = 10\n", "\n", "# Preprocess the training and test data\n", "x_train = preprocess_func(train_imgs)\n", "x_test = preprocess_func(test_imgs)\n", "y_train = tf.keras.utils.to_categorical(y_train, num_classes)\n", "y_test = tf.keras.utils.to_categorical(y_test, num_classes)\n", "\n", "# Model structure\n", "model = tf.keras.models.Sequential()\n", "model.add(tf.keras.layers.Conv2D(\n", " 32, kernel_size=(3, 3), activation='relu', input_shape=input_shape))\n", "model.add(tf.keras.layers.Conv2D(64, (3, 3), activation='relu'))\n", "model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2)))\n", "model.add(tf.keras.layers.Dropout(0.1))\n", "model.add(tf.keras.layers.Flatten())\n", "model.add(tf.keras.layers.Dense(128, activation='relu'))\n", "model.add(tf.keras.layers.Dropout(0.1))\n", "model.add(tf.keras.layers.Dense(num_classes))\n", "\n", "# Train the model\n", "model.compile(\n", " loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True),\n", " optimizer=tf.keras.optimizers.Adam(),\n", " metrics=['accuracy']\n", ")\n", "model.fit(\n", " x_train, y_train,\n", " batch_size=batch_size,\n", " epochs=epochs,\n", " verbose=1,\n", " validation_data=(x_test, y_test)\n", ")\n", "score = model.evaluate(x_test, y_test, verbose=0)\n", "print('Test loss:', score[0])\n", "print('Test accuracy:', score[1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To initialize `ContrastiveExplainer`, we need to set the following parameters:\n", " \n", " - `model`: The ML model to explain, e.g., `torch.nn.Module` or `tf.keras.Model`.\n", " - `preprocess_function`: The preprocessing function that converts the raw data (a `Image` instance) into the inputs of `model`.\n", " - \"optimization parameters\": e.g., `binary_search_steps`, `num_iterations`. Please refer to the docs for more details." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "explainer = ContrastiveExplainer(\n", " model=model,\n", " preprocess_function=preprocess_func\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can simply call `explainer.explain` to generate explanations for this classification task. `ipython_plot` plots the generated explanations in IPython. Parameter `index` indicates which instance to plot, e.g., `index = 0` means plotting the first instance in `test_imgs[0:5]`." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Binary step: 5 |----------------------------------------| 0.6% " ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAArwAAAH0CAYAAADfWf7fAAAgAElEQVR4Xu3dC7RlRXkn8GroFjHQGiUoEBUDxhggRkxUxlccByMSwaUoqKg4zij4aB6CAoKgBBAQUAQMKigaFQJiBlTWqEHUCWpwklkwijqJGUGByMMYRTAoPetchm7ssy931/nOOV1V+9drZWV5qdqn6vd9Z9e/d59777LVq1evTv4QIECAAAECBAgQaFRgmcDbaGVtiwABAgQIECBAYEFA4NUIBAgQIECAAAECTQsIvE2X1+YIECBAgAABAgQEXj1AgAABAgQIECDQtIDA23R5bY4AAQIECBAgQEDg1QMECBAgQIAAAQJNCwi8TZfX5ggQIECAAAECBARePUCAAAECBAgQINC0gMDbdHltjgABAgQIECBAQODVAwQIECBAgAABAk0LCLxNl9fmCBAgQIAAAQIEBF49QIAAAQIECBAg0LSAwNt0eW2OAAECBAgQIEBA4NUDBAgQIECAAAECTQsIvE2X1+YIECBAgAABAgQEXj1AgAABAgQIECDQtIDA23R5bY4AAQIECBAgQEDg1QMECBAgQIAAAQJNCwi8TZfX5ggQIECAAAECBARePUCAAAECBAgQINC0gMDbdHltjgABAgQIECBAQODVAwQIECBAgAABAk0LCLxNl9fmCBAgQIAAAQIEBF49QIAAAQIECBAg0LSAwNt0eW2OAAECBAgQIEBA4NUDBAgQIECAAAECTQsIvE2X1+YIECBAgAABAgQEXj1AgAABAgQIECDQtIDA23R5bY4AAQIECBAgQEDg1QMECBAgQIAAAQJNCwi8TZfX5ggQIECAAAECBARePUCAAAECBAgQINC0gMDbdHltjgABAgQIECBAQODVAwQIECBAgAABAk0LCLxNl9fmCBAgQIAAAQIEBF49QIAAAQIECBAg0LSAwNt0eW2OAAECBAgQIEBA4NUDBAgQIECAAAECTQsIvE2X1+YIECBAgAABAgQEXj1AgAABAgQIECDQtIDA23R5bY4AAQIECBAgQEDg1QMECBAgQIAAAQJNCwi8TZfX5ggQIECAAAECBARePUCAAAECBAgQINC0gMDbdHltjgABAgQIECBAQODVAwQIECBAgAABAk0LCLxNl9fmCBAgQIAAAQIEBF49QIAAAQIECBAg0LSAwNt0eW2OAAECBAgQIEBA4NUDBAgQIECAAAECTQsIvE2X1+YIECBAgAABAgQEXj1AgAABAgQIECDQtIDA23R5bY4AAQIECBAgQEDg1QMECBAgQIAAAQJNCwi8TZfX5ggQIECAAAECBARePUCAAAECBAgQINC0gMDbdHltjgABAgQIECBAQODVAwQIECBAgAABAk0LCLxNl9fmCBAgQIAAAQIEBF49QIAAAQIECBAg0LSAwNt0eW2OAAECBAgQIEBA4NUDBAgQIECAAAECTQsIvE2X1+YIECBAgAABAgQEXj1AgAABAgQIECDQtIDA23R5bY4AAQIECBAgQEDg1QMECBAgQIAAAQJNCwi8TZfX5ggQIECAAAECBARePUCAAAECBAgQINC0gMDbdHltjgABAgQIECBAQODVAwQIECBAgAABAk0LCLxNl9fmCBAgQIAAAQIEBF49QIAAAQIECBAg0LSAwNt0eW2OAAECBAgQIEBA4NUDBAgQIECAAAECTQsIvE2X1+YIECBAgAABAgQEXj1AgAABAgQIECDQtIDA23R5bY4AAQIECBAgQEDg1QMECBAgQIAAAQJNCwi8TZfX5ggQIECAAAECBARePUCAAAECBAgQINC0gMDbdHnL3tyx7/lo+vin/iZd+rET0iO2emjZi7U6Aimlj130hXTcaX+5xmLlJg9Iv/+YrdM+L94lPe1JO6z5+gFvOz1dfsU/pE9+8B1pm623GrPb7k/2SR869dD0xMf/Xi/Xu+5anc7+xGfS+Rd/Md1860/S7zxii7TfK3dPOz/9j3rNN4jAtARy3gOf//I3Fl52gw2WpQc/aGX64z/8vfT6fZ6fHvWILSZazi9/9au0177vSLf8+Cfpixe+e6JrmDRcAYF3uLVfrzv/u3/4dnrrCR9M1994s8C7XivhxXMERof9GR/+VDrnlLekO3/5q/QvN92aLvz0l9L/+Lur01+ccFB66hPvDr2jwDs67B+//aPTR997eFq2bNmvvUxu4H3/X16SPnLB59JbXv+S9LvbPDz9z6u+m0456/x04hH7pv/41B1ztmAsgZBAznvg57ffkQ567YvT7Xf8Iv3f625MHzrv0oW/sF187nFpswc/MHsdZ374r9NFn/1y+tVddwm82XomCLx6YO4Co5vg7q86Ir127+elo971IYF37hXwgpMKjA77sz56cfryp05bc4nR09cX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" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "explanations = explainer.explain(test_imgs[0:5])\n", "explanations.ipython_plot(index=4)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.5" } }, "nbformat": 4, "nbformat_minor": 2 }