{ "cells": [ { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "aPIA-10zdv4P" }, "source": [ "## ART Randomized Smoothing" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 34 }, "colab_type": "code", "id": "CGDOyI0HgDfx", "outputId": "2d61711f-6f8a-41b5-f05c-1085fd00fa13" }, "outputs": [], "source": [ "import warnings\n", "warnings.filterwarnings('ignore')\n", "\n", "import os\n", "os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' \n", "\n", "import tensorflow as tf\n", "tf.keras.backend.set_floatx('float32')\n", "from tensorflow.keras.models import load_model\n", "from tensorflow.keras.models import Sequential\n", "from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D, Dropout\n", "\n", "from art import config\n", "from art.attacks.evasion import FastGradientMethod\n", "from art.estimators.classification import TensorFlowV2Classifier\n", "from art.estimators.certification.randomized_smoothing import TensorFlowV2RandomizedSmoothing\n", "from art.utils import load_dataset, get_file, compute_accuracy\n", "\n", "import numpy as np\n", "%matplotlib inline\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "FqXvuMM9dv4U" }, "source": [ "### Load data" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "colab": {}, "colab_type": "code", "id": "z9OztmSidv4V" }, "outputs": [], "source": [ "# Read MNIST dataset\n", "(x_train, y_train), (x_test, y_test), min_, max_ = load_dataset('mnist')\n", "\n", "nb_classes = 10\n", "input_shape = x_train.shape[1:]\n", "\n", "num_samples_test = 250\n", "x_test = x_test[0:num_samples_test].astype(np.float32)\n", "y_test = y_test[0:num_samples_test]\n", "\n", "x_train = x_train.astype(np.float32)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "xDCzquK1dv4X" }, "source": [ "### Train classifiers" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "colab": {}, "colab_type": "code", "id": "G-mh9wSAHm-Z" }, "outputs": [], "source": [ "# Create convolutional neural network model\n", "def get_model(input_shape, min_, max_):\n", " \n", " model = Sequential()\n", " model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape))\n", " model.add(MaxPooling2D(pool_size=(2, 2)))\n", " model.add(Conv2D(64, (3, 3), activation='relu'))\n", " model.add(MaxPooling2D(pool_size=(2, 2)))\n", " model.add(Dropout(0.25))\n", " model.add(Flatten())\n", " model.add(Dense(128, activation='relu'))\n", " model.add(Dense(10, activation='softmax'))\n", " \n", " return model" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "nb_epochs = 40\n", "batch_size = 128\n", "sample_size = 100\n", "alpha = 0.001\n", "\n", "loss_object = tf.keras.losses.CategoricalCrossentropy(from_logits=False)\n", "optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "colab": {}, "colab_type": "code", "id": "tGbe8Cjmdv4a" }, "outputs": [], "source": [ "# Construct and train a convolutional neural network in standard (non-smoothed) classifier\n", "\n", "classifier = TensorFlowV2Classifier(model=get_model(input_shape, min_, max_),\n", " nb_classes=nb_classes,\n", " input_shape=input_shape,\n", " loss_object=loss_object,\n", " optimizer=optimizer,\n", " channels_first=False,\n", " clip_values=(min_, max_))\n", "\n", "classifier.fit(x_train, y_train, nb_epochs=nb_epochs, batch_size=batch_size)\n", "\n", "sigma_0 = 0.5\n", "\n", "classifier_rs_0 = TensorFlowV2RandomizedSmoothing(model=classifier.model,\n", " nb_classes=nb_classes,\n", " input_shape=input_shape,\n", " loss_object=loss_object,\n", " optimizer=optimizer,\n", " channels_first=False,\n", " clip_values=(min_, max_),\n", " sample_size=sample_size,\n", " scale=sigma_0,\n", " alpha=alpha)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# Create and train smoothed classifier, sigma = 0.25\n", "\n", "sigma_1 = 0.25\n", "\n", "classifier_rs_1 = TensorFlowV2RandomizedSmoothing(model=get_model(input_shape, min_, max_),\n", " nb_classes=nb_classes,\n", " input_shape=input_shape,\n", " loss_object=loss_object,\n", " optimizer=optimizer,\n", " channels_first=False,\n", " clip_values=(min_, max_),\n", " sample_size=sample_size,\n", " scale=sigma_1,\n", " alpha=alpha)\n", "\n", "classifier_rs_1.fit(x_train, y_train, nb_epochs=nb_epochs, batch_size=batch_size)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# Create and train smoothed classifier, sigma = 0.5\n", "\n", "sigma_2 = 0.5\n", "\n", "classifier_rs_2 = TensorFlowV2RandomizedSmoothing(model=get_model(input_shape, min_, max_),\n", " nb_classes=nb_classes,\n", " input_shape=input_shape,\n", " loss_object=loss_object,\n", " optimizer=optimizer,\n", " channels_first=False,\n", " clip_values=(min_, max_),\n", " sample_size=sample_size,\n", " scale=sigma_2,\n", " alpha=alpha)\n", "\n", "classifier_rs_2.fit(x_train, y_train, nb_epochs=nb_epochs, batch_size=batch_size)" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "kukXRDcedv4j" }, "source": [ "### Prediction" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 221 }, "colab_type": "code", "id": "jcPkXptcdv4k", "outputId": "ee65b562-0839-483b-9b1f-b7c911e3131a" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Randomized smoothing: 100%|██████████| 250/250 [00:04<00:00, 58.59it/s]\n", "Randomized smoothing: 100%|██████████| 250/250 [00:04<00:00, 58.63it/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n", "Original test data:\n", "Original Classifier\n", "Accuracy: 1.0\n", "Coverage: 1.0\n", "\n", "Smoothed Classifier, sigma=0.25\n", "Accuracy: 0.9959839357429718\n", "Coverage: 0.996\n", "\n", "Smoothed Classifier, sigma=0.5\n", "Accuracy: 1.0\n", "Coverage: 0.988\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "# compare prediction of randomized smoothed models to original model\n", "x_preds = classifier.predict(x_test)\n", "x_preds_rs_1 = classifier_rs_1.predict(x_test)\n", "x_preds_rs_2 = classifier_rs_2.predict(x_test)\n", "\n", "acc, cov = compute_accuracy(x_preds, y_test)\n", "acc_rs_1, cov_rs_1 = compute_accuracy(x_preds_rs_1, y_test)\n", "acc_rs_2, cov_rs_2 = compute_accuracy(x_preds_rs_2, y_test)\n", "\n", "print(\"\\nOriginal test data:\")\n", "print(\"Original Classifier\")\n", "print(\"Accuracy: {}\".format(acc))\n", "print(\"Coverage: {}\".format(cov))\n", "\n", "print(\"\\nSmoothed Classifier, sigma=\" + str(sigma_1))\n", "print(\"Accuracy: {}\".format(acc_rs_1))\n", "print(\"Coverage: {}\".format(cov_rs_1))\n", "\n", "print(\"\\nSmoothed Classifier, sigma=\" + str(sigma_2))\n", "print(\"Accuracy: {}\".format(acc_rs_2))\n", "print(\"Coverage: {}\".format(cov_rs_2))" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "hqea3xvMdv4n" }, "source": [ "## Certification of Accuracy and L2-Radius" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "colab": {}, "colab_type": "code", "id": "D6Va8ST8dv4n" }, "outputs": [], "source": [ "# Calculate certification accuracy for a given radius\n", "def getCertAcc(radius, pred, y_test):\n", "\n", " rad_list = np.linspace(0, 2.25, 201)\n", " cert_acc = []\n", " num_cert = len(radius)\n", " \n", " for r in rad_list:\n", " rad_idx = np.where(radius >= r)[0]\n", " y_test_subset = y_test[rad_idx]\n", " cert_acc.append(np.sum(pred[rad_idx] == np.argmax(y_test_subset, axis=1)) / num_cert)\n", " \n", " return cert_acc" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "colab": {}, "colab_type": "code", "id": "iPWY6KFMdv4p" }, "outputs": [], "source": [ "# Compute certification\n", "prediction_0, radius_0 = classifier_rs_0.certify(x_test, n=500)\n", "prediction_1, radius_1 = classifier_rs_1.certify(x_test, n=500)\n", "prediction_2, radius_2 = classifier_rs_2.certify(x_test, n=500)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 283 }, "colab_type": "code", "id": "ZZv5wDHSdv4s", "outputId": "a6fbe7ba-dfbb-47bd-8e56-794fb689cb14" }, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "<Figure size 432x288 with 1 Axes>" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Plot certification accuracy w.r.t. to radius\n", "rad_list = np.linspace(0, 2.25, 201)\n", "plt.plot(rad_list, getCertAcc(radius_0, prediction_0, y_test), 'r-', label='original')\n", "plt.plot(rad_list, getCertAcc(radius_1, prediction_1, y_test), '-', color='green',\n", " label='smoothed, $\\sigma=$' + str(sigma_1))\n", "plt.plot(rad_list, getCertAcc(radius_2, prediction_2, y_test), '-', color='blue',\n", " label='smoothed, $\\sigma=$' + str(sigma_2))\n", "plt.xlabel('radius')\n", "plt.ylabel('certified accuracy')\n", "plt.legend()\n", "plt.show()" ] } ], "metadata": { "accelerator": "GPU", "colab": { "collapsed_sections": [], "name": "randomized_smoothing_mnist.ipynb", "provenance": [], "version": "0.3.2" }, "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.6.12" } }, "nbformat": 4, "nbformat_minor": 1 }