From 7aea4cbdabae2bb41c8382484481ed9e5995d04b Mon Sep 17 00:00:00 2001 From: Syumei Date: Sat, 26 Aug 2023 12:40:34 +0900 Subject: [PATCH] DIVA (WhiteBox) (#157) * support DIVA (whitebox) * Update * update * update --- README.md | 2 +- docs/source/aijack.attack.evasion.rst | 8 + docs/source/notebooks/aijack_diva.ipynb | 447 ++++++++++++++++++ ...aijack_transferbility_and_robustness.ipynb | 438 ++++++++--------- docs/source/notebooks/evasion.rst | 1 + src/aijack/attack/__init__.py | 6 +- src/aijack/attack/evasion/__init__.py | 3 +- src/aijack/attack/evasion/diva.py | 53 +++ 8 files changed, 741 insertions(+), 217 deletions(-) create mode 100644 docs/source/notebooks/aijack_diva.ipynb create mode 100644 src/aijack/attack/evasion/diva.py diff --git a/README.md b/README.md index 35ec38a5..105fee9b 100644 --- a/README.md +++ b/README.md @@ -181,7 +181,7 @@ You can also find more examples in our tutorials and documentation. | Attack | Poisoning | [History Attack](https://arxiv.org/abs/2203.08669), [Label Flip](https://arxiv.org/abs/2203.08669), [MAPF](https://arxiv.org/abs/2203.08669), [SVM Poisoning](https://arxiv.org/abs/1206.6389) | | Attack | Backdoor | [DBA](https://openreview.net/forum?id=rkgyS0VFvr) | | Attack | Free-Rider | [Delta-Weight](https://arxiv.org/pdf/1911.12560.pdf) | -| Attack | Evasion | [Gradient-Descent Attack](https://arxiv.org/abs/1708.06131), [FGSM](https://arxiv.org/abs/1412.6572) | +| Attack | Evasion | [Gradient-Descent Attack](https://arxiv.org/abs/1708.06131), [FGSM](https://arxiv.org/abs/1412.6572), [DIVA](https://arxiv.org/abs/2204.10933) | | Attack | Membership Inference | [Shaddow Attack](https://arxiv.org/abs/1610.05820) | | Defense | Homomorphic Encryption | [Paiilier](https://link.springer.com/chapter/10.1007/3-540-48910-X_16) | | Defense | Differential Privacy | [DPSGD](https://arxiv.org/abs/1607.00133), [AdaDPS](https://arxiv.org/pdf/2202.05963.pdf) | diff --git a/docs/source/aijack.attack.evasion.rst b/docs/source/aijack.attack.evasion.rst index 5c0406a5..3f278854 100644 --- a/docs/source/aijack.attack.evasion.rst +++ b/docs/source/aijack.attack.evasion.rst @@ -4,6 +4,14 @@ aijack.attack.evasion package Submodules ---------- +aijack.attack.evasion.diva module +--------------------------------- + +.. automodule:: aijack.attack.evasion.diva + :members: + :undoc-members: + :show-inheritance: + aijack.attack.evasion.evasion\_attack module -------------------------------------------- diff --git a/docs/source/notebooks/aijack_diva.ipynb b/docs/source/notebooks/aijack_diva.ipynb new file mode 100644 index 00000000..a8ade12c --- /dev/null +++ b/docs/source/notebooks/aijack_diva.ipynb @@ -0,0 +1,447 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [], + "machine_shape": "hm", + "gpuType": "A100" + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + }, + "accelerator": "GPU" + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# DIVA\n", + "\n", + "Hao, Wei, et al. \"A tale of two models: Constructing evasive attacks on edge models.\" Proceedings of Machine Learning and Systems 4 (2022): 414-429." + ], + "metadata": { + "id": "x4uvbBjOxHsr" + } + }, + { + "cell_type": "code", + "source": [ + "import cv2\n", + "import numpy as np\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "import torch.optim as optim\n", + "import torchvision\n", + "import torchvision.transforms as transforms\n", + "from torch.utils.data import TensorDataset\n", + "from torch.utils.data import Dataset\n", + "from matplotlib import pyplot as plt\n", + "from sklearn.metrics import accuracy_score\n", + "from sklearn.model_selection import train_test_split\n", + "\n", + "from aijack.attack import DIVAWhiteBoxAttacker\n", + "from aijack.utils import NumpyDataset\n", + "\n", + "BASE = \"data/\"\n", + "torch.manual_seed(42)\n", + "\n", + "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")" + ], + "metadata": { + "id": "Is8WtxVaKF9V" + }, + "execution_count": 1, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "mnist_dataset_train = torchvision.datasets.MNIST(root=\"\", train=True, download=True)\n", + "\n", + "transform = transforms.Compose(\n", + " [transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))]\n", + ")\n", + "\n", + "X = mnist_dataset_train.train_data.numpy()\n", + "y = mnist_dataset_train.train_labels.numpy()\n", + "X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.33, random_state=42, shuffle=True\n", + ")\n", + "\n", + "# X_train = X_train[:2000]\n", + "# y_train = y_train[:2000]\n", + "# X_test = X_test[:1000]\n", + "# y_test = y_test[:1000]\n", + "\n", + "train_dataset = NumpyDataset(\n", + " X_train,\n", + " y_train,\n", + " transform=transform,\n", + ")\n", + "train_dataloader = torch.utils.data.DataLoader(\n", + " train_dataset, batch_size=16, shuffle=True, num_workers=2\n", + ")\n", + "\n", + "test_dataset = NumpyDataset(\n", + " X_test,\n", + " y_test,\n", + " transform=transform,\n", + ")\n", + "test_dataloader = torch.utils.data.DataLoader(\n", + " test_dataset, batch_size=16, shuffle=True, num_workers=2\n", + ")" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mo2sih76OFOe", + "outputId": "8915272c-7eb5-4916-bc52-c452a3c46a82" + }, + "execution_count": 2, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "/usr/local/lib/python3.10/dist-packages/torchvision/datasets/mnist.py:75: UserWarning: train_data has been renamed data\n", + " warnings.warn(\"train_data has been renamed data\")\n", + "/usr/local/lib/python3.10/dist-packages/torchvision/datasets/mnist.py:65: UserWarning: train_labels has been renamed targets\n", + " warnings.warn(\"train_labels has been renamed targets\")\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "class Net(nn.Module):\n", + " def __init__(self):\n", + " super(Net, self).__init__()\n", + " self.conv1 = nn.Conv2d(1, 6, 5)\n", + " self.relu1 = nn.ReLU()\n", + " self.pool1 = nn.MaxPool2d(2)\n", + " self.conv2 = nn.Conv2d(6, 16, 5)\n", + " self.relu2 = nn.ReLU()\n", + " self.pool2 = nn.MaxPool2d(2)\n", + " self.fc1 = nn.Linear(256, 120)\n", + " self.relu3 = nn.ReLU()\n", + " self.fc2 = nn.Linear(120, 84)\n", + " self.relu4 = nn.ReLU()\n", + " self.fc3 = nn.Linear(84, 10)\n", + " self.relu5 = nn.ReLU()\n", + "\n", + " def forward(self, x):\n", + " y = self.conv1(x)\n", + " y = self.relu1(y)\n", + " y = self.pool1(y)\n", + " y = self.conv2(y)\n", + " y = self.relu2(y)\n", + " y = self.pool2(y)\n", + " y = y.view(y.shape[0], -1)\n", + " y = self.fc1(y)\n", + " y = self.relu3(y)\n", + " y = self.fc2(y)\n", + " y = self.relu4(y)\n", + " y = self.fc3(y)\n", + " y = self.relu5(y)\n", + " return y\n", + "\n", + "\n", + "class LMNet(nn.Module):\n", + " def __init__(self):\n", + " super(LMNet, self).__init__()\n", + " self.fla = nn.Flatten()\n", + " self.fc1 = nn.Linear(28 * 28, 10)\n", + " # self.fc2 = nn.Linear(100, 10)\n", + "\n", + " def forward(self, x):\n", + " x = self.fla(x)\n", + " x = self.fc1(x)\n", + " # x = torch.relu(x)\n", + " # x = self.fc2(x)\n", + " # x = F.softmax(x, dim=1)\n", + " return x" + ], + "metadata": { + "id": "goRF52ELKLN4" + }, + "execution_count": 3, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "net = Net().to(device)\n", + "criterion = nn.CrossEntropyLoss()\n", + "optimizer = optim.SGD(net.parameters(), lr=0.003, momentum=0.9)" + ], + "metadata": { + "id": "aX5fXViERvcW" + }, + "execution_count": 4, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "for epoch in range(10): # loop over the dataset multiple times\n", + " running_loss = 0\n", + " data_size = 0\n", + " for i, data in enumerate(train_dataloader, 0):\n", + " # get the inputs; data is a list of [inputs, labels]\n", + " inputs, labels = data\n", + " inputs = inputs.to(device)\n", + " labels = labels.to(device)\n", + "\n", + " # zero the parameter gradients\n", + " optimizer.zero_grad()\n", + "\n", + " # forward + backward + optimize\n", + " outputs = net(inputs)\n", + " loss = criterion(outputs, labels.to(torch.int64))\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + " running_loss += loss.item()\n", + " data_size += inputs.shape[0]\n", + "\n", + " print(f\"epoch {epoch}: loss is {running_loss/data_size}\")\n", + "\n", + "in_preds = []\n", + "in_label = []\n", + "with torch.no_grad():\n", + " for data in test_dataloader:\n", + " inputs, labels = data\n", + " inputs = inputs.to(device)\n", + " labels = labels.to(device)\n", + " outputs = net(inputs)\n", + " in_preds.append(outputs)\n", + " in_label.append(labels)\n", + " in_preds = torch.cat(in_preds)\n", + " in_label = torch.cat(in_label)\n", + "print(\n", + " \"\\nTest Accuracy is: \",\n", + " accuracy_score(\n", + " np.array(torch.argmax(in_preds, axis=1).cpu()), np.array(in_label.cpu())\n", + " ),\n", + ")" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "EYun5CeIKMyy", + "outputId": "e660f5b3-e984-4b02-f534-567b8347c09d" + }, + "execution_count": 5, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "epoch 0: loss is 0.04054302100458794\n", + "epoch 1: loss is 0.01814291013776199\n", + "epoch 2: loss is 0.0166187124224426\n", + "epoch 3: loss is 0.009562910017942598\n", + "epoch 4: loss is 0.002573704934469091\n", + "epoch 5: loss is 0.0021106714805702396\n", + "epoch 6: loss is 0.0017938830078365253\n", + "epoch 7: loss is 0.0015096701963636125\n", + "epoch 8: loss is 0.0014024900508528204\n", + "epoch 9: loss is 0.0010703933892566083\n", + "\n", + "Test Accuracy is: 0.9825252525252526\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "net_distilled = LMNet().to(device)\n", + "criterion = nn.L1Loss()\n", + "optimizer = optim.SGD(net_distilled.parameters(), lr=0.003, momentum=0.9)" + ], + "metadata": { + "id": "1QMI-Lt8Zc3w" + }, + "execution_count": 6, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "for epoch in range(20): # loop over the dataset multiple times\n", + " running_loss = 0\n", + " data_size = 0\n", + " for i, data in enumerate(train_dataloader, 0):\n", + " # get the inputs; data is a list of [inputs, labels]\n", + " inputs, labels = data\n", + " inputs = inputs.to(device)\n", + " labels = net(inputs)\n", + "\n", + " # zero the parameter gradients\n", + " optimizer.zero_grad()\n", + "\n", + " # forward + backward + optimize\n", + " outputs = net_distilled(inputs)\n", + " loss = criterion(outputs, labels)\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + " running_loss += loss.item()\n", + " data_size += inputs.shape[0]\n", + "\n", + " print(f\"epoch {epoch}: loss is {running_loss/data_size}\")\n", + "\n", + "in_preds = []\n", + "in_label = []\n", + "with torch.no_grad():\n", + " for data in test_dataloader:\n", + " inputs, labels = data\n", + " inputs = inputs.to(device)\n", + " labels = labels.to(device)\n", + " outputs = net_distilled(inputs)\n", + " in_preds.append(outputs)\n", + " in_label.append(labels)\n", + " in_preds = torch.cat(in_preds)\n", + " in_label = torch.cat(in_label)\n", + "print(\n", + " \"\\nTest Accuracy is: \",\n", + " accuracy_score(\n", + " np.array(torch.argmax(in_preds, axis=1).cpu()), np.array(in_label.cpu())\n", + " ),\n", + ")" + ], + "metadata": { + "id": "BP3M0JmCKqf6", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "daefe4f9-873f-49b8-b7a6-2feff8becac4" + }, + "execution_count": 7, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "epoch 0: loss is 0.1670569335761948\n", + "epoch 1: loss is 0.15897891622574176\n", + "epoch 2: loss is 0.15708679305380258\n", + "epoch 3: loss is 0.1559841609742511\n", + "epoch 4: loss is 0.15508358281346696\n", + "epoch 5: loss is 0.15454466995315172\n", + "epoch 6: loss is 0.1539939962394202\n", + "epoch 7: loss is 0.15346056090065496\n", + "epoch 8: loss is 0.15314420309529375\n", + "epoch 9: loss is 0.15277839498436865\n", + "epoch 10: loss is 0.1524997589540719\n", + "epoch 11: loss is 0.15233479831052657\n", + "epoch 12: loss is 0.15207505247189632\n", + "epoch 13: loss is 0.1518335230018369\n", + "epoch 14: loss is 0.15169831540454087\n", + "epoch 15: loss is 0.15148778069078625\n", + "epoch 16: loss is 0.15128053859988255\n", + "epoch 17: loss is 0.15130577724667924\n", + "epoch 18: loss is 0.15122654953999307\n", + "epoch 19: loss is 0.15100575763491256\n", + "\n", + "Test Accuracy is: 0.7185858585858586\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "c = 1.0\n", + "num_itr = 1000\n", + "eps = 0.15\n", + "lam = 0.03\n", + "\n", + "torch.manual_seed(42)\n", + "\n", + "idx = 0\n", + "x = torch.clone(inputs[[idx]])\n", + "x_origin = torch.clone(x)\n", + "y = labels[idx]\n", + "\n", + "attacker = DIVAWhiteBoxAttacker(net, net_distilled, c, num_itr, eps, lam, device)\n", + "result = attacker.attack((x, y))" + ], + "metadata": { + "id": "--8C46mULEH8" + }, + "execution_count": 8, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "fig = plt.figure()\n", + "\n", + "fig.add_subplot(121)\n", + "plt.imshow(inputs[[idx]].cpu()[0][0].detach().numpy(), cmap=\"gray\")\n", + "plt.title(\n", + " f\"Original Image \\n Original Prediction: {net(inputs[[idx]]).argmax().item()} \\n Edge Prediction: {net_distilled(inputs[[idx]]).argmax().item()}\"\n", + ")\n", + "plt.axis(\"off\")\n", + "\n", + "fig.add_subplot(122)\n", + "plt.imshow(result[0].cpu()[0][0].detach().numpy(), cmap=\"gray\")\n", + "plt.title(\n", + " f\"Perturbed Image \\n Original Prediction: {net(result[0]).argmax().item()} \\n Edge Prediction: {net_distilled(result[0]).argmax().item()}\"\n", + ")\n", + "plt.axis(\"off\")" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 344 + }, + "id": "leoofiuvM8wH", + "outputId": "8edaccb3-6529-440a-d867-01e6897a0c92" + }, + "execution_count": 9, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(-0.5, 27.5, 27.5, -0.5)" + ] + }, + "metadata": {}, + "execution_count": 9 + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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NB4YGCiN23r9/vGPf0jjAPDBBx8o1ynOSmKfgXLlyknjts4tqj4Bjx8/tmn/Dg4O0vjHH3+s3Ef37t2l8YyMDGlcVYevopr/7t+/L41v3rxZGn/zzTel8UqVKknj69atk8ZVPUSMRqM0rnrfzJ49WxoHgHfffdemMai4u7tL46rXuQr7DBAREZEUkwEiIiKNYzJARESkcUwGiIiINI7JABERkcYxGSAiItI4JgNEREQax2SAiIhI42zrYlCCZGZmSuOvvvqqch8XLlyQxtu2bSuNqxpfbNy4URpXNW/ZtWuXNH78+HFpXOXatWvS+O7du6VxVdMhW6maalDppGr2ompqpJobVE2Lpk+fLo0DQGxsrDTerFkzaVw1xq+//loa9/DwkMZ//PFHafzUqVPSuKqp0dWrV206ftWqVaVxJycnaVw1vpSUFGkcUDf90ev10riqeZVqjIXd+I93BoiIiDSOyQAREZHGMRkgIiLSOCYDREREGsdkgIiISOOYDBAREWkckwEiIiKN0wlV8XvWioVc40glX61ataTxgwcPSuOqPgoxMTHSeHBwsDQOAPfv31euU5xZ+XYtVlQ/V9Xcojpn1faquKo+XEVVHw4AGRkZNh3D1p+76viqPgaqc1SNT7W9r6+vNL5t2zZpvEKFCtK4qkdKly5dpHEAuHPnjjSu6kdh6+9QW98nqj4svDNARESkcUwGiIiINI7JABERkcYxGSAiItI4JgNEREQax2SAiIhI45gMEBERaRz7DBCVICWxz4CXl5c0bus5FXb9tipuNBqVx1CtY02vAhnVGFU18Cqqn5GtvSBUVH0SHB0dpXEHBwdp3GAw2DwGVa8GVVyFfQaIiIioUDEZICIi0jgmA0RERBrHZICIiEjjmAwQERFpHJMBIiIijWMyQEREpHH2RT0AItK2ou5hoqrPVvUIsKZPgqqPgOoaqLZXjUFVh29rrwdbt1ddY3t7+a8q1fFVNf6PHj2Sxq05RmH/DAu7lwPvDBAREWkckwEiIiKNYzJARESkcUwGiIiINI7JABERkcYxGSAiItI4JgNEREQaxz4DRFSq2VoDr6rftqa+W1VjrqKqk1extQ6/sGvoVftX9RlQsfX8rdmHrT/jolayR09EREQ2YzJARESkcUwGiIiINI7JABERkcYxGSAiItI4JgNEREQax2SAiIhI49hngIgKla015oX9HHdbWXN8VR27rTXsqjGojq/X66Xxwmbr8W19DT2NY9j6Oi3s1znvDBAREWkckwEiIiKNYzJARESkcUwGiIiINI7JABERkcYxGSAiItI4JgNEREQapxMFUYBJREREJRbvDBAREWkckwEiIiKNYzJARESkcUwGiIiINI7JABERkcYxGSAiItI4JgNEREQax2SAiIhI45gMEBERadz/A2V0eVUMB7iaAAAAAElFTkSuQmCC\n" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "code", + "source": [], + "metadata": { + "id": "y4t1eCv6wsYz" + }, + "execution_count": 9, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/docs/source/notebooks/aijack_transferbility_and_robustness.ipynb b/docs/source/notebooks/aijack_transferbility_and_robustness.ipynb index 456fc9e7..8d57d6ce 100644 --- a/docs/source/notebooks/aijack_transferbility_and_robustness.ipynb +++ b/docs/source/notebooks/aijack_transferbility_and_robustness.ipynb @@ -1,21 +1,10 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { - "colab": { - "provenance": [] - }, - "kernelspec": { - "name": "python3", - "display_name": "Python 3" - }, - "language_info": { - "name": "python" - } - }, "cells": [ { "cell_type": "markdown", + "metadata": { + "id": "pUKTRr8zekCE" + }, "source": [ "# Exploring Adversarial Example Transferability and Robust Tree Models\n", "\n", @@ -25,17 +14,34 @@ "\n", "With the assistance of AIJack, you now have the convenient opportunity to evaluate these cutting-edge techniques effortlessly.\n", "\n", - "```\n", + "\n", "[1] Goodfellow, Ian J., Jonathon Shlens, and Christian Szegedy. \"Explaining and harnessing adversarial examples.\" arXiv preprint arXiv:1412.6572 (2014).\n", - "[2] Chen, Yizheng, et al. \"{Cost-Aware} Robust Tree Ensembles for Security Applications.\" 30th USENIX Security Symposium (USENIX Security 21). 2021.\n", - "```" - ], - "metadata": { - "id": "pUKTRr8zekCE" - } + "\n", + "[2] Chen, Yizheng, et al. \"{Cost-Aware} Robust Tree Ensembles for Security Applications.\" 30th USENIX Security Symposium (USENIX Security 21). 2021." + ] }, { "cell_type": "code", + "execution_count": 2, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Uu73jVt5iePg", + "outputId": "74db5d62-4d75-45eb-d4b3-815b28d79384" + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "import cv2\n", "import numpy as np\n", @@ -59,66 +65,11 @@ "\n", "BASE = \"data/\"\n", "torch.manual_seed(42)" - ], - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "Uu73jVt5iePg", - "outputId": "74db5d62-4d75-45eb-d4b3-815b28d79384" - }, - "execution_count": 2, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "" - ] - }, - "metadata": {}, - "execution_count": 2 - } ] }, { "cell_type": "code", - "source": [ - "mnist_dataset_train = torchvision.datasets.MNIST(root=\"\", train=True, download=True)\n", - "\n", - "transform = transforms.Compose(\n", - " [transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))]\n", - ")\n", - "\n", - "X = mnist_dataset_train.train_data.numpy()\n", - "y = mnist_dataset_train.train_labels.numpy()\n", - "X_train, X_test, y_train, y_test = train_test_split(\n", - " X, y, test_size=0.33, random_state=42, shuffle=True\n", - ")\n", - "\n", - "X_train = X_train[:2000]\n", - "y_train = y_train[:2000]\n", - "X_test = X_test[:1000]\n", - "y_test = y_test[:1000]\n", - "\n", - "train_dataset = NumpyDataset(\n", - " X_train,\n", - " y_train,\n", - " transform=transform,\n", - ")\n", - "train_dataloader = torch.utils.data.DataLoader(\n", - " train_dataset, batch_size=16, shuffle=True, num_workers=2\n", - ")\n", - "\n", - "test_dataset = NumpyDataset(\n", - " X_test,\n", - " y_test,\n", - " transform=transform,\n", - ")\n", - "test_dataloader = torch.utils.data.DataLoader(\n", - " test_dataset, batch_size=16, shuffle=True, num_workers=2\n", - ")" - ], + "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -126,26 +77,25 @@ "id": "d2E7oZx_KuZU", "outputId": "8a82fbea-404e-40c0-f303-e37a26b30f60" }, - "execution_count": 3, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz\n", "Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz to MNIST/raw/train-images-idx3-ubyte.gz\n" ] }, { - "output_type": "stream", "name": "stderr", + "output_type": "stream", "text": [ "100%|██████████| 9912422/9912422 [00:00<00:00, 66438329.26it/s]\n" ] }, { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "Extracting MNIST/raw/train-images-idx3-ubyte.gz to MNIST/raw\n", "\n", @@ -154,15 +104,15 @@ ] }, { - "output_type": "stream", "name": "stderr", + "output_type": "stream", "text": [ "100%|██████████| 28881/28881 [00:00<00:00, 64331223.49it/s]\n" ] }, { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "Extracting MNIST/raw/train-labels-idx1-ubyte.gz to MNIST/raw\n", "\n", @@ -171,15 +121,15 @@ ] }, { - "output_type": "stream", "name": "stderr", + "output_type": "stream", "text": [ "100%|██████████| 1648877/1648877 [00:00<00:00, 22731323.10it/s]\n" ] }, { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "Extracting MNIST/raw/t10k-images-idx3-ubyte.gz to MNIST/raw\n", "\n", @@ -188,23 +138,23 @@ ] }, { - "output_type": "stream", "name": "stderr", + "output_type": "stream", "text": [ "100%|██████████| 4542/4542 [00:00<00:00, 5683331.97it/s]" ] }, { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "Extracting MNIST/raw/t10k-labels-idx1-ubyte.gz to MNIST/raw\n", "\n" ] }, { - "output_type": "stream", "name": "stderr", + "output_type": "stream", "text": [ "\n", "/usr/local/lib/python3.10/dist-packages/torchvision/datasets/mnist.py:75: UserWarning: train_data has been renamed data\n", @@ -213,10 +163,51 @@ " warnings.warn(\"train_labels has been renamed targets\")\n" ] } + ], + "source": [ + "mnist_dataset_train = torchvision.datasets.MNIST(root=\"\", train=True, download=True)\n", + "\n", + "transform = transforms.Compose(\n", + " [transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))]\n", + ")\n", + "\n", + "X = mnist_dataset_train.train_data.numpy()\n", + "y = mnist_dataset_train.train_labels.numpy()\n", + "X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.33, random_state=42, shuffle=True\n", + ")\n", + "\n", + "X_train = X_train[:2000]\n", + "y_train = y_train[:2000]\n", + "X_test = X_test[:1000]\n", + "y_test = y_test[:1000]\n", + "\n", + "train_dataset = NumpyDataset(\n", + " X_train,\n", + " y_train,\n", + " transform=transform,\n", + ")\n", + "train_dataloader = torch.utils.data.DataLoader(\n", + " train_dataset, batch_size=16, shuffle=True, num_workers=2\n", + ")\n", + "\n", + "test_dataset = NumpyDataset(\n", + " X_test,\n", + " y_test,\n", + " transform=transform,\n", + ")\n", + "test_dataloader = torch.utils.data.DataLoader(\n", + " test_dataset, batch_size=16, shuffle=True, num_workers=2\n", + ")" ] }, { "cell_type": "code", + "execution_count": 4, + "metadata": { + "id": "T8lJ0X7SjHFB" + }, + "outputs": [], "source": [ "class Net(nn.Module):\n", " def __init__(self):\n", @@ -232,66 +223,24 @@ " # x = self.fc2(x)\n", " # x = F.softmax(x, dim=1)\n", " return x" - ], - "metadata": { - "id": "T8lJ0X7SjHFB" - }, - "execution_count": 4, - "outputs": [] + ] }, { "cell_type": "code", + "execution_count": 5, + "metadata": { + "id": "Z-MoJqPXjHqq" + }, + "outputs": [], "source": [ "net = Net()\n", "criterion = nn.CrossEntropyLoss()\n", "optimizer = optim.SGD(net.parameters(), lr=0.003, momentum=0.9)" - ], - "metadata": { - "id": "Z-MoJqPXjHqq" - }, - "execution_count": 5, - "outputs": [] + ] }, { "cell_type": "code", - "source": [ - "for epoch in range(30): # loop over the dataset multiple times\n", - " running_loss = 0\n", - " data_size = 0\n", - " for i, data in enumerate(train_dataloader, 0):\n", - " # get the inputs; data is a list of [inputs, labels]\n", - " inputs, labels = data\n", - "\n", - " # zero the parameter gradients\n", - " optimizer.zero_grad()\n", - "\n", - " # forward + backward + optimize\n", - " outputs = net(inputs)\n", - " loss = criterion(outputs, labels.to(torch.int64))\n", - " loss.backward()\n", - " optimizer.step()\n", - "\n", - " running_loss += loss.item()\n", - " data_size += inputs.shape[0]\n", - "\n", - " print(f\"epoch {epoch}: loss is {running_loss/data_size}\")\n", - "\n", - "\n", - "in_preds = []\n", - "in_label = []\n", - "with torch.no_grad():\n", - " for data in test_dataloader:\n", - " inputs, labels = data\n", - " outputs = net(inputs)\n", - " in_preds.append(outputs)\n", - " in_label.append(labels)\n", - " in_preds = torch.cat(in_preds)\n", - " in_label = torch.cat(in_label)\n", - "print(\n", - " \"\\nTest Accuracy is: \",\n", - " accuracy_score(np.array(torch.argmax(in_preds, axis=1)), np.array(in_label)),\n", - ")" - ], + "execution_count": 6, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -299,11 +248,10 @@ "id": "k1Qi44IdjRiU", "outputId": "e2f841d0-69d3-4821-8692-6420afe1e64e" }, - "execution_count": 6, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "epoch 0: loss is 0.06138062975555658\n", "epoch 1: loss is 0.03086455798149109\n", @@ -339,19 +287,62 @@ "Test Accuracy is: 0.873\n" ] } + ], + "source": [ + "for epoch in range(30): # loop over the dataset multiple times\n", + " running_loss = 0\n", + " data_size = 0\n", + " for i, data in enumerate(train_dataloader, 0):\n", + " # get the inputs; data is a list of [inputs, labels]\n", + " inputs, labels = data\n", + "\n", + " # zero the parameter gradients\n", + " optimizer.zero_grad()\n", + "\n", + " # forward + backward + optimize\n", + " outputs = net(inputs)\n", + " loss = criterion(outputs, labels.to(torch.int64))\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + " running_loss += loss.item()\n", + " data_size += inputs.shape[0]\n", + "\n", + " print(f\"epoch {epoch}: loss is {running_loss/data_size}\")\n", + "\n", + "\n", + "in_preds = []\n", + "in_label = []\n", + "with torch.no_grad():\n", + " for data in test_dataloader:\n", + " inputs, labels = data\n", + " outputs = net(inputs)\n", + " in_preds.append(outputs)\n", + " in_label.append(labels)\n", + " in_preds = torch.cat(in_preds)\n", + " in_label = torch.cat(in_label)\n", + "print(\n", + " \"\\nTest Accuracy is: \",\n", + " accuracy_score(np.array(torch.argmax(in_preds, axis=1)), np.array(in_label)),\n", + ")" ] }, { "cell_type": "markdown", - "source": [ - "## FGSM Attack against NN" - ], "metadata": { "id": "eBRDCoZ-hOeW" - } + }, + "source": [ + "## FGSM Attack against NN" + ] }, { "cell_type": "code", + "execution_count": 7, + "metadata": { + "id": "e6pbzHb7jSEG" + }, + "outputs": [], "source": [ "x_origin = inputs[[0]]\n", "y_origin = labels[[0]]\n", @@ -360,26 +351,11 @@ " net, criterion, eps=0.3, grad_lower_bound=-0.15, grad_upper_bound=0.15\n", ")\n", "perturbed_x = attacker.attack((x_origin, y_origin.to(torch.int64)))" - ], - "metadata": { - "id": "e6pbzHb7jSEG" - }, - "execution_count": 7, - "outputs": [] + ] }, { "cell_type": "code", - "source": [ - "fig = plt.figure()\n", - "fig.add_subplot(121)\n", - "plt.imshow(x_origin[0][0].detach().numpy(), cmap=\"gray\", vmin=-1.0, vmax=1.0)\n", - "plt.title(f\"Predicted Label: {net(x_origin).argmax().item()}\")\n", - "plt.axis(\"off\")\n", - "fig.add_subplot(122)\n", - "plt.imshow(perturbed_x[0][0].detach().numpy(), cmap=\"gray\", vmin=-1.0, vmax=1.0)\n", - "plt.title(f\"Predicted Label: {net(perturbed_x).argmax().item()}\")\n", - "plt.axis(\"off\")" - ], + "execution_count": 8, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -388,43 +364,73 @@ "id": "ZO3_lvc2mCPm", "outputId": "545bc5e3-0149-4e7c-e4c5-01a5e5ea222f" }, - "execution_count": 8, "outputs": [ { - "output_type": "execute_result", "data": { "text/plain": [ "(-0.5, 27.5, 27.5, -0.5)" ] }, + "execution_count": 8, "metadata": {}, - "execution_count": 8 + "output_type": "execute_result" }, { - "output_type": "display_data", "data": { + "image/png": "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\n", "text/plain": [ "
" - ], - "image/png": "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\n" + ] }, - "metadata": {} + "metadata": {}, + "output_type": "display_data" } + ], + "source": [ + "fig = plt.figure()\n", + "fig.add_subplot(121)\n", + "plt.imshow(x_origin[0][0].detach().numpy(), cmap=\"gray\", vmin=-1.0, vmax=1.0)\n", + "plt.title(f\"Predicted Label: {net(x_origin).argmax().item()}\")\n", + "plt.axis(\"off\")\n", + "fig.add_subplot(122)\n", + "plt.imshow(perturbed_x[0][0].detach().numpy(), cmap=\"gray\", vmin=-1.0, vmax=1.0)\n", + "plt.title(f\"Predicted Label: {net(perturbed_x).argmax().item()}\")\n", + "plt.axis(\"off\")" ] }, { "cell_type": "markdown", + "metadata": { + "id": "iTS_qx0Ug_Ry" + }, "source": [ "## XGBoost without Defense\n", "\n", "The adversarial example crafted above can also deceive the XGBoost model." - ], - "metadata": { - "id": "iTS_qx0Ug_Ry" - } + ] }, { "cell_type": "code", + "execution_count": 9, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "bqEk1VA-m0Ih", + "outputId": "85646211-41ce-4bb4-9f08-bbda04155447" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Train Accuracy: 0.998\n", + "Test Accuracy: 0.836\n", + "Predicted Label without Attack: [9]\n", + "Predicted Label with Attack: [5]\n" + ] + } + ], "source": [ "min_leaf = 1\n", "depth = 6\n", @@ -494,39 +500,39 @@ " clf.predict_proba(perturbed_x[0][0].detach().numpy().reshape(1, -1).tolist())\n", " ).argmax(1),\n", ")" - ], + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "C_fdBRIChCKQ" + }, + "source": [ + "## XGBoost using Attack-Cost Constraints" + ] + }, + { + "cell_type": "code", + "execution_count": 10, "metadata": { - "id": "bqEk1VA-m0Ih", "colab": { "base_uri": "https://localhost:8080/" }, - "outputId": "85646211-41ce-4bb4-9f08-bbda04155447" + "id": "1vxloHfQq06E", + "outputId": "5ea8f965-0767-4fd7-bcde-55b8afd8b841" }, - "execution_count": 9, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ - "Train Accuracy: 0.998\n", - "Test Accuracy: 0.836\n", + "Train Accuracy: 0.975\n", + "Test Accuracy: 0.84\n", "Predicted Label without Attack: [9]\n", - "Predicted Label with Attack: [5]\n" + "Predicted Label with Attack: [9]\n" ] } - ] - }, - { - "cell_type": "markdown", - "source": [ - "## XGBoost using Attack-Cost Constraints" ], - "metadata": { - "id": "C_fdBRIChCKQ" - } - }, - { - "cell_type": "code", "source": [ "p0 = XGBoostClient(\n", " X_train_normalized,\n", @@ -585,27 +591,31 @@ " clf.predict_proba(perturbed_x[0][0].detach().numpy().reshape(1, -1).tolist())\n", " ).argmax(1),\n", ")" - ], - "metadata": { - "id": "1vxloHfQq06E", - "colab": { - "base_uri": "https://localhost:8080/" - }, - "outputId": "5ea8f965-0767-4fd7-bcde-55b8afd8b841" - }, - "execution_count": 10, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "Train Accuracy: 0.975\n", - "Test Accuracy: 0.84\n", - "Predicted Label without Attack: [9]\n", - "Predicted Label with Attack: [9]\n" - ] - } ] } - ] -} \ No newline at end of file + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/docs/source/notebooks/evasion.rst b/docs/source/notebooks/evasion.rst index 323bc038..73317f6a 100644 --- a/docs/source/notebooks/evasion.rst +++ b/docs/source/notebooks/evasion.rst @@ -5,4 +5,5 @@ Evasion Attack :maxdepth: 1 aijack_evasion_attack + aijack_diva aijack_transferbility_and_robustness diff --git a/src/aijack/attack/__init__.py b/src/aijack/attack/__init__.py index a65dd2f5..50e6942e 100644 --- a/src/aijack/attack/__init__.py +++ b/src/aijack/attack/__init__.py @@ -1,7 +1,11 @@ """Submodule for attack algorithms against machine learning. """ from .base_attack import BaseAttacker # noqa: F401 -from .evasion import Evasion_attack_sklearn, FGSMAttacker # noqa: F401 +from .evasion import ( # noqa: F401 + DIVAWhiteBoxAttacker, + Evasion_attack_sklearn, + FGSMAttacker, +) from .inversion import ( # noqa: F401 MI_FACE, GANAttackClientManager, diff --git a/src/aijack/attack/evasion/__init__.py b/src/aijack/attack/evasion/__init__.py index 092744dd..7abd20a8 100644 --- a/src/aijack/attack/evasion/__init__.py +++ b/src/aijack/attack/evasion/__init__.py @@ -1,7 +1,8 @@ """Subpackage for evasion attack, which creates a malicious data that the target machine learning model cannot correctly classify. """ +from .diva import DIVAWhiteBoxAttacker # noqa: F401 from .evasion_attack import Evasion_attack_sklearn # noqa: F401 from .fgsm import FGSMAttacker # noqa: F401 -__all__ = ["Evasion_attack_sklearn", "FGSMAttacker"] +__all__ = ["Evasion_attack_sklearn", "FGSMAttacker", "DIVAWhiteBoxAttacker"] diff --git a/src/aijack/attack/evasion/diva.py b/src/aijack/attack/evasion/diva.py new file mode 100644 index 00000000..0b4aab95 --- /dev/null +++ b/src/aijack/attack/evasion/diva.py @@ -0,0 +1,53 @@ +import torch + +from ..base_attack import BaseAttacker + + +class DIVAWhiteBoxAttacker(BaseAttacker): + def __init__( + self, + target_model, + target_model_on_edge, + c=1.0, + num_itr=1000, + eps=0.1, + lam=0.01, + device="cpu", + ): + super().__init__(target_model) + self.target_model_on_edge = target_model_on_edge + self.c = c + self.num_itr = num_itr + self.eps = eps + self.lam = lam + self.device = device + + def attack(self, data): + x, y = data + x = x.to(self.device) + y = y.to(self.device) + x_origin = torch.clone(x) + + log_loss = [] + log_perturbation = [] + + for _ in range(self.num_itr): + x = x.detach().to(self.device) + x.requires_grad = True + origin_pred = self.target_model(x) + edge_pred = self.target_model_on_edge(x) + loss = origin_pred[:, y] - self.c * edge_pred[:, y] + loss.backward() + grad = x.grad + + with torch.no_grad(): + x += self.lam * grad + x = torch.clamp(x, x_origin - self.eps, x_origin + self.eps) + + log_loss.append(loss.item()) + log_perturbation.append(torch.mean((x - x_origin).abs()).item()) + + if origin_pred.argmax().item() != edge_pred.argmax().item(): + break + + return x, {"log_loss": log_loss, "log_perturbation": log_perturbation}