{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# You can write up to 5GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import torch\nimport torch.nn.functional as F\nfrom torchvision import datasets,transforms\nfrom torch import nn\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport seaborn as sns\n#from tqdm.notebook import tqdm\nfrom tqdm import tqdm","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Download DataSet"},{"metadata":{"trusted":true},"cell_type":"code","source":"# # Dowload the dataset\n# from torchvision.datasets.utils import download_url\n# dataset_url = \"http://files.fast.ai/data/cifar10.tgz\"\n# download_url(dataset_url, '.')\n# import tarfile\n# # Extract from archive\n# with tarfile.open('./cifar10.tgz', 'r:gz') as tar:\n#     tar.extractall(path='./data')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Data Analysis"},{"metadata":{},"cell_type":"markdown","source":"So this is a balanced Dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"from torchvision.datasets import ImageFolder\nfrom torchvision.transforms import ToTensor","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data_dir = '/kaggle/input/cifar10-pngs-in-folders/cifar10/cifar10'\ndataset = ImageFolder(data_dir+'/train', transform=ToTensor())\n# print(dataset)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dataset","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_example(img,label):\n    plt.imshow(img.permute(1, 2, 0))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"show_example(*dataset[100])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import cv2\ndef trojanImage(image,x,y,trigger_size,overlay,alpha=1):\n    image = image.astype(np.uint8)\n    overlay = cv2.addWeighted(image[:, x: x + trigger_size, y: y+trigger_size ],alpha,overlay,1-alpha,0)\n    image[:,x: x + trigger_size, y: y+trigger_size ] = overlay\n    return image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"trigger_size = 2\nx = 15\ny = 15\nother_image = (255*np.random.rand(*(3,trigger_size,trigger_size))).astype(np.uint8)\nimg = dataset[100][0].cpu().detach().numpy()\nt1 = trojanImage(img,x,y,trigger_size,other_image)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"t2 = torch.Tensor(t1)\nshow_example(t2,7)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Validation Set"},{"metadata":{"trusted":true},"cell_type":"code","source":"random_seed = 21\ntorch.manual_seed(random_seed);\nfrom torch.utils.data import random_split\nval_size = 5000\ntrain_size = len(dataset) - val_size\n\ntrain_ds, val_ds = random_split(dataset, [train_size, val_size])\nlen(train_ds), len(val_ds)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# x = [4500]*10\n# for p in train_ds:\n#     x[p[1]] = x[p[1]] - 1\n# x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# y = [500]*10\n# for p in val_ds:\n#     y[p[1]] = y[p[1]] - 1\n# y","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from torch.utils.data.dataloader import DataLoader\n\nbatch_size = 32\ntrain_dl = DataLoader(train_ds, batch_size, shuffle=True, num_workers=4, pin_memory=True)\nval_dl = DataLoader(val_ds, batch_size, num_workers=4, pin_memory=True)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import torch.nn as nn\nimport torch.nn.functional as F","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# GPU Device Loader"},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_default_device():\n    \"\"\"Pick GPU if available, else CPU\"\"\"\n    if torch.cuda.is_available():\n        return torch.device('cuda')\n    else:\n        return torch.device('cpu')\n    \ndef to_device(data, device):\n    \"\"\"Move tensor(s) to chosen device\"\"\"\n    if isinstance(data, (list,tuple)):\n        return [to_device(x, device) for x in data]\n    return data.to(device, non_blocking=True)\n\nclass DeviceDataLoader():\n    \"\"\"Wrap a dataloader to move data to a device\"\"\"\n    def __init__(self, dl, device):\n        self.dl = dl\n        self.device = device\n        \n    def __iter__(self):\n        \"\"\"Yield a batch of data after moving it to device\"\"\"\n        for b in self.dl: \n            yield to_device(b, self.device)\n\n    def __len__(self):\n        \"\"\"Number of batches\"\"\"\n        return len(self.dl)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"device = get_default_device()\ndevice","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"@torch.no_grad()\ndef accuracy(outputs, labels):\n    _, preds = torch.max(outputs, dim=1)\n    return torch.tensor(torch.sum(preds == labels).item() / len(preds))\n\nclass ImageClassificationBase(nn.Module):\n    def training_step(self, batch):\n        images, labels = batch \n        out = self(images)                  # Generate predictions\n        loss = F.cross_entropy(out, labels) # Calculate loss\n        accu = accuracy(out,labels)\n        return loss,accu\n    \n    def validation_step(self, batch):\n        images, labels = batch \n        out = self(images)                    # Generate predictions\n        loss = F.cross_entropy(out, labels)   # Calculate loss\n        acc = accuracy(out, labels)           # Calculate accuracy\n        _,preds = torch.max(out, dim=1)\n        return {'Loss': loss.detach(), 'Accuracy': acc,'Entropy': preds}\n        \n    def validation_epoch_end(self, outputs):\n        batch_losses = [x['Loss'] for x in outputs]\n        epoch_loss = torch.stack(batch_losses).mean()   # Combine losses\n        batch_accs = [x['Accuracy'] for x in outputs]\n        epoch_acc = torch.stack(batch_accs).mean()      # Combine accuracies\n        classCount = torch.zeros(10, dtype=torch.float64, device=\"cuda\")\n        for x in outputs:\n            for y in x['Entropy']:\n                classCount[y] += 1\n        entropy = 0\n        classCount /= sum(classCount)\n        for pi in classCount:\n            if(pi!=0):\n                entropy -= pi*torch.log(pi)\n        return {'Loss': epoch_loss.item(), 'Accuracy': epoch_acc.item(),'Entropy':entropy}\n    \n    def epoch_end(self, epoch, result):\n        print(\"Epoch :\",epoch + 1)\n        print(f'Train Accuracy:{result[\"train_accuracy\"]*100:.2f}% Validation Accuracy:{result[\"Accuracy\"]*100:.2f}%')\n        print(f'Train Loss:{result[\"train_loss\"]:.4f} Validation Loss:{result[\"Loss\"]:.4f}')\n        print(f'Validation Entropy:{result[\"Entropy\"]:.2f}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Cifar10CnnModel(ImageClassificationBase):\n    def __init__(self):\n        super().__init__()\n        self.network = nn.Sequential(\n            nn.Conv2d(3, 24, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(24, 32, kernel_size=3, stride=1, padding=1),\n            nn.ReLU(),\n            \n            nn.Flatten(), \n            nn.Linear(32*32*32, 256),\n            nn.ReLU(),\n            nn.Linear(256, 10),\n            nn.ReLU()\n        )\n    def forward(self, xb):\n        return self.network(xb)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = Cifar10CnnModel()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_dl = DeviceDataLoader(train_dl, device)\nval_dl = DeviceDataLoader(val_dl, device)\nto_device(model, device)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"@torch.no_grad()\ndef evaluate(model, data_loader):\n    model.eval()\n    outputs = [model.validation_step(batch) for batch in data_loader]\n    return model.validation_epoch_end(outputs)\n\ndef fit(model, train_loader, val_loader,epochs=25,learning_rate=0.06):\n    best_valid = None\n    history = []\n    optimizer = torch.optim.SGD(model.parameters(), learning_rate,weight_decay=0.001)\n    for epoch in range(epochs):\n        # Training Phase \n        model.train()\n        train_losses = []\n        train_accuracy = []\n        for batch in tqdm(train_loader):\n            loss,accu = model.training_step(batch)\n            train_losses.append(loss)\n            train_accuracy.append(accu)\n            loss.backward()\n            optimizer.step()\n            optimizer.zero_grad()\n        # Validation phase\n        result = evaluate(model, val_loader)\n        result['train_loss'] = torch.stack(train_losses).mean().item()\n        result['train_accuracy'] = torch.stack(train_accuracy).mean().item()\n        model.epoch_end(epoch, result)\n        if(best_valid == None or best_valid<result['Accuracy']):\n            best_valid=result['Accuracy']\n            torch.save(model.state_dict(), 'cifar10-cnn.pth')\n        history.append(result)\n    return history","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = fit(model, train_dl, val_dl)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_accuracies(history):\n    Validation_accuracies = [x['Accuracy'] for x in history]\n    Training_Accuracies = [x['train_accuracy'] for x in history]\n    plt.plot(Training_Accuracies, '-rx')\n    plt.plot(Validation_accuracies, '-bx')\n    plt.xlabel('epoch')\n    plt.ylabel('accuracy')\n    plt.legend(['Training', 'Validation'])\n    plt.title('Accuracy vs. No. of epochs');\nplot_accuracies(history)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_losses(history):\n    train_losses = [x.get('train_loss') for x in history]\n    val_losses = [x['Loss'] for x in history]\n    plt.plot(train_losses, '-bx')\n    plt.plot(val_losses, '-rx')\n    plt.xlabel('epoch')\n    plt.ylabel('loss')\n    plt.legend(['Training', 'Validation'])\n    plt.title('Loss vs. No. of epochs');\nplot_losses(history)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Test Data"},{"metadata":{"trusted":true},"cell_type":"code","source":"final_model = Cifar10CnnModel()\nfinal_model.load_state_dict(torch.load('/kaggle/working/cifar10-cnn.pth'))\nto_device(final_model, device);","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_dataset = ImageFolder(data_dir+'/test', transform=ToTensor())\ntest_loader = DeviceDataLoader(DataLoader(test_dataset, batch_size), device)\nresult = evaluate(final_model, test_loader)\nprint(f'Test Accuracy:{result[\"Accuracy\"]*100:.2f}%')\nprint(f'Entropy:{result[\"Entropy\"]:.2f}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}