{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<a id=\"2\"></a>\n# Import Libaries","metadata":{}},{"cell_type":"code","source":"# importing libraries\nimport os\nimport torch\nimport torchvision\nimport tarfile\nfrom torchvision.datasets.utils import download_url\nfrom torch.utils.data import random_split\nfrom torchvision.datasets import ImageFolder\nfrom torchvision.transforms import ToTensor,ToPILImage\nimport matplotlib.pyplot as plt\nfrom torchvision.utils import make_grid\nfrom torch.utils.data.dataloader import DataLoader\nfrom torchvision.utils import make_grid\nimport torch.nn as nn\nimport torch.nn.functional as F","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-05-24T03:18:44.795272Z","iopub.execute_input":"2023-05-24T03:18:44.795779Z","iopub.status.idle":"2023-05-24T03:18:46.156350Z","shell.execute_reply.started":"2023-05-24T03:18:44.795743Z","shell.execute_reply":"2023-05-24T03:18:46.155440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"3\"></a>\n# Exploring the Data","metadata":{}},{"cell_type":"code","source":"# Extract from tar archive file\nwith tarfile.open('../input/cifar10/cifar10.tgz', 'r:gz') as tar:\n    tar.extractall(path='./input')","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:18:46.158148Z","iopub.execute_input":"2023-05-24T03:18:46.158490Z","iopub.status.idle":"2023-05-24T03:19:03.665352Z","shell.execute_reply.started":"2023-05-24T03:18:46.158452Z","shell.execute_reply":"2023-05-24T03:19:03.664430Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(os.listdir('./input/cifar10'))\nclasses= os.listdir('./input/cifar10/train')\nprint(classes)","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:03.666700Z","iopub.execute_input":"2023-05-24T03:19:03.667087Z","iopub.status.idle":"2023-05-24T03:19:03.674080Z","shell.execute_reply.started":"2023-05-24T03:19:03.667040Z","shell.execute_reply":"2023-05-24T03:19:03.672912Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cat_files= os.listdir('./input/cifar10/train/cat')\nprint('No of training example for cats:',len(cat_files))\nprint(cat_files[:5])\n","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:03.675489Z","iopub.execute_input":"2023-05-24T03:19:03.676090Z","iopub.status.idle":"2023-05-24T03:19:03.687500Z","shell.execute_reply.started":"2023-05-24T03:19:03.676025Z","shell.execute_reply":"2023-05-24T03:19:03.686674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"automobile_files= os.listdir('./input/cifar10/train/automobile')\nprint('No of training example for automobiles:',len(automobile_files))\nprint(automobile_files[:5])\n","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:03.692205Z","iopub.execute_input":"2023-05-24T03:19:03.692465Z","iopub.status.idle":"2023-05-24T03:19:03.702811Z","shell.execute_reply.started":"2023-05-24T03:19:03.692440Z","shell.execute_reply":"2023-05-24T03:19:03.701934Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cat_files= os.listdir('./input/cifar10/test/cat')\nprint('No of test example for cats:',len(cat_files))\nprint(cat_files[:5])\n","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:03.706110Z","iopub.execute_input":"2023-05-24T03:19:03.706463Z","iopub.status.idle":"2023-05-24T03:19:03.712563Z","shell.execute_reply.started":"2023-05-24T03:19:03.706429Z","shell.execute_reply":"2023-05-24T03:19:03.711377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_dir = './input/cifar10'\ndataset = ImageFolder(data_dir+'/train', transform=ToTensor())\n","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:03.714222Z","iopub.execute_input":"2023-05-24T03:19:03.714621Z","iopub.status.idle":"2023-05-24T03:19:04.042991Z","shell.execute_reply.started":"2023-05-24T03:19:03.714558Z","shell.execute_reply":"2023-05-24T03:19:04.042179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img, label= dataset[0]\nprint(img.shape,label)\nimg","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:04.044616Z","iopub.execute_input":"2023-05-24T03:19:04.045010Z","iopub.status.idle":"2023-05-24T03:19:04.121348Z","shell.execute_reply.started":"2023-05-24T03:19:04.044966Z","shell.execute_reply":"2023-05-24T03:19:04.120447Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:04.122697Z","iopub.execute_input":"2023-05-24T03:19:04.123243Z","iopub.status.idle":"2023-05-24T03:19:04.129542Z","shell.execute_reply.started":"2023-05-24T03:19:04.123200Z","shell.execute_reply":"2023-05-24T03:19:04.128589Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(dataset.classes)","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:04.131114Z","iopub.execute_input":"2023-05-24T03:19:04.131752Z","iopub.status.idle":"2023-05-24T03:19:04.137428Z","shell.execute_reply.started":"2023-05-24T03:19:04.131712Z","shell.execute_reply":"2023-05-24T03:19:04.136392Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_image(img,label):\n    print('Label: ', dataset.classes[label],\"(\"+str(label)+\")\")\n    plt.imshow(img.permute(1,2,0))","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:04.139237Z","iopub.execute_input":"2023-05-24T03:19:04.139871Z","iopub.status.idle":"2023-05-24T03:19:04.146037Z","shell.execute_reply.started":"2023-05-24T03:19:04.139816Z","shell.execute_reply":"2023-05-24T03:19:04.145107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_image(dataset[222][0],dataset[222][1])","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:04.147405Z","iopub.execute_input":"2023-05-24T03:19:04.147977Z","iopub.status.idle":"2023-05-24T03:19:04.321622Z","shell.execute_reply.started":"2023-05-24T03:19:04.147939Z","shell.execute_reply":"2023-05-24T03:19:04.320903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_image(*dataset[1099])","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:04.323489Z","iopub.execute_input":"2023-05-24T03:19:04.323913Z","iopub.status.idle":"2023-05-24T03:19:04.466409Z","shell.execute_reply.started":"2023-05-24T03:19:04.323868Z","shell.execute_reply":"2023-05-24T03:19:04.465423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Training and Validation Datasets**\n\nWhile building real world machine learning models, it is quite common to split the dataset into 3 parts:\n\n1. Training set - used to train the model i.e. compute the loss and adjust the weights of the model using gradient descent.\n2. Validation set - used to evaluate the model while training, adjust hyperparameters (learning rate etc.) and pick the best version of the model.\n3. Test set - used to compare different models, or different types of modeling approaches, and report the final accuracy of the model.","metadata":{}},{"cell_type":"code","source":"random_seed=42\ntorch.manual_seed(random_seed);","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:04.467955Z","iopub.execute_input":"2023-05-24T03:19:04.468527Z","iopub.status.idle":"2023-05-24T03:19:04.476367Z","shell.execute_reply.started":"2023-05-24T03:19:04.468485Z","shell.execute_reply":"2023-05-24T03:19:04.475473Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val_size = 5000\ntrain_size = len(dataset) - val_size\ntrain_ds, val_ds = random_split(dataset,[train_size, val_size],generator=torch.manual_seed(random_seed))\nlen(train_ds), len(val_ds)","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:04.478017Z","iopub.execute_input":"2023-05-24T03:19:04.478545Z","iopub.status.idle":"2023-05-24T03:19:04.495675Z","shell.execute_reply.started":"2023-05-24T03:19:04.478499Z","shell.execute_reply":"2023-05-24T03:19:04.494696Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size=128\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)","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:04.496951Z","iopub.execute_input":"2023-05-24T03:19:04.497362Z","iopub.status.idle":"2023-05-24T03:19:04.502623Z","shell.execute_reply.started":"2023-05-24T03:19:04.497322Z","shell.execute_reply":"2023-05-24T03:19:04.501756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dl # Data loader. Combines a dataset and a sampler, and provides an iterable over the given dataset.","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:04.504246Z","iopub.execute_input":"2023-05-24T03:19:04.504639Z","iopub.status.idle":"2023-05-24T03:19:04.513225Z","shell.execute_reply.started":"2023-05-24T03:19:04.504600Z","shell.execute_reply":"2023-05-24T03:19:04.512274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_images_batch(d1):\n    for images, labels in d1:\n        fig, ax= plt.subplots(figsize=(16,8))\n        ax.set_xticks([])\n        ax.set_yticks([])\n        ax.imshow(make_grid(images, nrow=16).permute(1,2,0))\n        break # to stop loop otherwise 4500 images in batch size of 128 will print and is computationally expensive","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:04.514750Z","iopub.execute_input":"2023-05-24T03:19:04.515416Z","iopub.status.idle":"2023-05-24T03:19:04.524033Z","shell.execute_reply.started":"2023-05-24T03:19:04.515374Z","shell.execute_reply":"2023-05-24T03:19:04.523016Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images_batch(train_dl) # training data single batch images","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:04.525889Z","iopub.execute_input":"2023-05-24T03:19:04.526444Z","iopub.status.idle":"2023-05-24T03:19:09.298313Z","shell.execute_reply.started":"2023-05-24T03:19:04.526403Z","shell.execute_reply":"2023-05-24T03:19:09.296994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_images_batch(val_dl) # validation data single batch images","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:09.299709Z","iopub.execute_input":"2023-05-24T03:19:09.300063Z","iopub.status.idle":"2023-05-24T03:19:10.068436Z","shell.execute_reply.started":"2023-05-24T03:19:09.300019Z","shell.execute_reply":"2023-05-24T03:19:10.067544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"5\"></a>\n# Convolutional Neural Network\n","metadata":{"trusted":true}},{"cell_type":"markdown","source":"Let us implement a convolution operation on a 1 channel image with a 3x3 kernel.","metadata":{"trusted":true}},{"cell_type":"code","source":"def apply_kernel(image, kernel):\n    ri, ci = image.shape       # image dimensions\n    rk, ck = kernel.shape      # kernel dimensions\n    ro, co = ri-rk+1, ci-ck+1  # output dimensions, No padding and no striding\n    output = torch.zeros([ro, co])\n    for i in range(ro): \n        for j in range(co):\n            output[i,j] = torch.sum(image[i:i+rk,j:j+ck] * kernel) \n    return output","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:10.069990Z","iopub.execute_input":"2023-05-24T03:19:10.070563Z","iopub.status.idle":"2023-05-24T03:19:10.079940Z","shell.execute_reply.started":"2023-05-24T03:19:10.070518Z","shell.execute_reply":"2023-05-24T03:19:10.079053Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_image = torch.tensor([\n    [4, 4, 3, 1, 0], \n    [0, 0, 1, 4, 1], \n    [4, 1, 3, 3, 4], \n    [2, 0, 0, 3, 3], \n    [3, 0, 0, 0, 1]\n], dtype=torch.float32)\n\nsample_kernel = torch.tensor([\n    [1, 1, 1], \n    [1, 1, 1], \n    [1, 1, 1]\n], dtype=torch.float32) #blur filter\n\napply_kernel(sample_image, sample_kernel)","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:10.081530Z","iopub.execute_input":"2023-05-24T03:19:10.082109Z","iopub.status.idle":"2023-05-24T03:19:10.098895Z","shell.execute_reply.started":"2023-05-24T03:19:10.082071Z","shell.execute_reply":"2023-05-24T03:19:10.097863Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def 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        return loss\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)\n        return {'val_loss':loss.detach(), 'val_acc':acc}\n    \n    def validation_epoch_end(self, outputs):\n        batch_losses = [x['val_loss'] for x in outputs]\n        epoch_loss= torch.stack(batch_losses).mean() # Stacking losses to combine losses and calculate average\n        batch_accs = [x['val_acc'] for x in outputs]\n        epoch_acc = torch.stack(batch_accs).mean() # Combine accuracies\n        return {'val_loss': epoch_loss.item(), 'val_acc': epoch_acc.item()}\n        \n    def epoch_end(self,epoch,result):\n        print(\"Epoch [{}], train_loss: {:.4f}, val_loss: {:.4f}, val_acc: {:.4f}\".format(\n            epoch, result['train_loss'], result['val_loss'], result['val_acc']))","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:10.100592Z","iopub.execute_input":"2023-05-24T03:19:10.100978Z","iopub.status.idle":"2023-05-24T03:19:10.231193Z","shell.execute_reply.started":"2023-05-24T03:19:10.100939Z","shell.execute_reply":"2023-05-24T03:19:10.229853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We'll use `nn.Sequential` to chain the layers and activations functions into a single network architecture.","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, 32, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2, 2), # output: 64 x 16 x 16\n\n            nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2, 2), # output: 128 x 8 x 8\n\n            nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2, 2), # output: 256 x 4 x 4\n\n            nn.Flatten(), \n            nn.Linear(256*4*4, 1024),\n            nn.ReLU(),\n            nn.Linear(1024, 512),\n            nn.ReLU(),\n            nn.Linear(512, 10))\n        \n    def forward(self, xb):\n        return self.network(xb)","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:10.232927Z","iopub.execute_input":"2023-05-24T03:19:10.233660Z","iopub.status.idle":"2023-05-24T03:19:10.249280Z","shell.execute_reply.started":"2023-05-24T03:19:10.233618Z","shell.execute_reply":"2023-05-24T03:19:10.248482Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model= Cifar10CnnModel()\nmodel","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:10.251049Z","iopub.execute_input":"2023-05-24T03:19:10.251442Z","iopub.status.idle":"2023-05-24T03:19:10.305465Z","shell.execute_reply.started":"2023-05-24T03:19:10.251402Z","shell.execute_reply":"2023-05-24T03:19:10.304766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for images, labels in train_dl:\n    print('images.shape:', images.shape)\n    out = model(images)\n    print('out.shape:',out.shape)\n    print('out[0]',out[0])\n    break","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:10.306696Z","iopub.execute_input":"2023-05-24T03:19:10.307048Z","iopub.status.idle":"2023-05-24T03:19:11.361643Z","shell.execute_reply.started":"2023-05-24T03:19:10.307019Z","shell.execute_reply":"2023-05-24T03:19:11.360493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"out.shape","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:11.363338Z","iopub.execute_input":"2023-05-24T03:19:11.363706Z","iopub.status.idle":"2023-05-24T03:19:11.372492Z","shell.execute_reply.started":"2023-05-24T03:19:11.363663Z","shell.execute_reply":"2023-05-24T03:19:11.371516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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)","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:11.373993Z","iopub.execute_input":"2023-05-24T03:19:11.374551Z","iopub.status.idle":"2023-05-24T03:19:11.385727Z","shell.execute_reply.started":"2023-05-24T03:19:11.374510Z","shell.execute_reply":"2023-05-24T03:19:11.384981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Based on where you run this notebook, your default device could be a CPU (`torch.device('cpu')`) or a GPU (`torch.device('cuda')`)","metadata":{"trusted":true}},{"cell_type":"code","source":"device = get_default_device()\ndevice","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:11.387403Z","iopub.execute_input":"2023-05-24T03:19:11.387811Z","iopub.status.idle":"2023-05-24T03:19:11.400190Z","shell.execute_reply.started":"2023-05-24T03:19:11.387775Z","shell.execute_reply":"2023-05-24T03:19:11.399312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can now wrap our training and validation data loaders using `DeviceDataLoader` for automatically transferring batches of data to the GPU (if available), and use `to_device` to move our model to the GPU (if available).","metadata":{}},{"cell_type":"code","source":"train_dl = DeviceDataLoader(train_dl, device)\nval_dl = DeviceDataLoader(val_dl, device) # load data to  device (GPU if available)\nto_device(model, device) # move model to GPU if available","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:11.401800Z","iopub.execute_input":"2023-05-24T03:19:11.402402Z","iopub.status.idle":"2023-05-24T03:19:11.421886Z","shell.execute_reply.started":"2023-05-24T03:19:11.402359Z","shell.execute_reply":"2023-05-24T03:19:11.421026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"6\"></a>\n# Training the Model","metadata":{}},{"cell_type":"code","source":"#In this mode, the result of every computation will have requires_grad=False, even when the inputs have requires_grad=True.\n@torch.no_grad() \ndef evaluate(model, val_loader):\n    model.eval() # Setting model to evaluation mode, the model can adjust its behavior regarding some operations, like Dropout.\n    outputs = [model.validation_step(batch) for batch in val_loader]\n    return model.validation_epoch_end(outputs)\n  \ndef fit(epochs, lr, model, train_loader, val_loader, opt_func= torch.optim.SGD):\n    history=[]\n    optimizer= opt_func(model.parameters(),lr) # model paramters w.r.t calculate derivative of loss\n    for epoch in range(epochs):\n        # Training phase\n        model.train() # Setting model to training mode\n        train_losses=[]\n        for batch in train_loader:\n            loss= model.training_step(batch)\n            train_losses.append(loss)\n            loss.backward() #compute  gradients\n            optimizer.step()\n            optimizer.zero_grad() # zero the gradients\n        #Validation phase\n        result= evaluate(model,val_loader)\n        result['train_loss'] = torch.stack(train_losses).mean().item()\n        model.epoch_end(epoch, result)\n        history.append(result)\n    return history\n            ","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:11.423582Z","iopub.execute_input":"2023-05-24T03:19:11.423947Z","iopub.status.idle":"2023-05-24T03:19:11.436043Z","shell.execute_reply.started":"2023-05-24T03:19:11.423911Z","shell.execute_reply":"2023-05-24T03:19:11.434938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:11.442478Z","iopub.execute_input":"2023-05-24T03:19:11.442769Z","iopub.status.idle":"2023-05-24T03:19:11.449669Z","shell.execute_reply.started":"2023-05-24T03:19:11.442725Z","shell.execute_reply":"2023-05-24T03:19:11.448739Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The initial accuracy is around 10% in one epoch, which is expected model is not trained enough.\n","metadata":{}},{"cell_type":"code","source":"evaluate(model,val_dl)","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:11.451803Z","iopub.execute_input":"2023-05-24T03:19:11.452227Z","iopub.status.idle":"2023-05-24T03:19:13.676379Z","shell.execute_reply.started":"2023-05-24T03:19:11.452189Z","shell.execute_reply":"2023-05-24T03:19:13.675467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_epochs = 15\nopt_func = torch.optim.Adam\nlr = 0.001","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:13.678945Z","iopub.execute_input":"2023-05-24T03:19:13.679503Z","iopub.status.idle":"2023-05-24T03:19:13.684848Z","shell.execute_reply.started":"2023-05-24T03:19:13.679456Z","shell.execute_reply":"2023-05-24T03:19:13.683664Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = fit(num_epochs, lr, model, train_dl, val_dl, opt_func)","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:19:13.686239Z","iopub.execute_input":"2023-05-24T03:19:13.686630Z","iopub.status.idle":"2023-05-24T03:23:02.867542Z","shell.execute_reply.started":"2023-05-24T03:19:13.686592Z","shell.execute_reply":"2023-05-24T03:23:02.865913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Plot valdation set accuracies to study how the model improves over time.","metadata":{}},{"cell_type":"code","source":"def plot_accuracies(history):\n    accuracies=[x['val_acc'] for x in history]\n    plt.plot(accuracies,'-x')\n    plt.xlabel('Epoch')\n    plt.ylabel('Accuracy')\n    plt.title('Accuracy vs No of epochs')","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:02.872013Z","iopub.execute_input":"2023-05-24T03:23:02.872323Z","iopub.status.idle":"2023-05-24T03:23:02.877944Z","shell.execute_reply.started":"2023-05-24T03:23:02.872291Z","shell.execute_reply":"2023-05-24T03:23:02.877019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(10,6))\nplot_accuracies(history)","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:02.879394Z","iopub.execute_input":"2023-05-24T03:23:02.880007Z","iopub.status.idle":"2023-05-24T03:23:03.042798Z","shell.execute_reply.started":"2023-05-24T03:23:02.879968Z","shell.execute_reply":"2023-05-24T03:23:03.041938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Our model achieves an accuracy of roughly 75%, and based on the graph, it appears doubtful that the model would attain an accuracy higher than 80% even after extensive training. This shows that we may need to employ a more sophisticated model to accurately capture the relationship between the photos and the labels.","metadata":{}},{"cell_type":"code","source":"def plot_losses(history):\n    train_losses = [x.get('train_loss') for x in history]\n    val_losses = [x['val_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');","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:03.044277Z","iopub.execute_input":"2023-05-24T03:23:03.044663Z","iopub.status.idle":"2023-05-24T03:23:03.054616Z","shell.execute_reply.started":"2023-05-24T03:23:03.044622Z","shell.execute_reply":"2023-05-24T03:23:03.053815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(10,6))\nplot_losses(history)","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:03.056387Z","iopub.execute_input":"2023-05-24T03:23:03.057150Z","iopub.status.idle":"2023-05-24T03:23:03.253734Z","shell.execute_reply.started":"2023-05-24T03:23:03.057100Z","shell.execute_reply":"2023-05-24T03:23:03.252681Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Initialy, both the training and validation losses seem to decrease over time. However, if we train the model for long enough,training loss continues to decrease, while the validation loss stops decreasing, and even starts to increase after a certain point(overfitting).","metadata":{}},{"cell_type":"markdown","source":"<a id=\"7\"></a>\n# Testing with individual images","metadata":{}},{"cell_type":"code","source":"test_dataset = ImageFolder(data_dir+'/test', transform=ToTensor())\ntest_dataset","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:03.255422Z","iopub.execute_input":"2023-05-24T03:23:03.255815Z","iopub.status.idle":"2023-05-24T03:23:03.335015Z","shell.execute_reply.started":"2023-05-24T03:23:03.255777Z","shell.execute_reply":"2023-05-24T03:23:03.333815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict_image(img, model):\n    xb= to_device(img.unsqueeze(0),device) \n    # Get predictions from model\n    yb = model(xb)\n    # Pick index/label with highest probability\n    _, preds= torch.max(yb, dim=1)\n    return dataset.classes[preds[0].item()]","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:03.336605Z","iopub.execute_input":"2023-05-24T03:23:03.337023Z","iopub.status.idle":"2023-05-24T03:23:03.343409Z","shell.execute_reply.started":"2023-05-24T03:23:03.336984Z","shell.execute_reply":"2023-05-24T03:23:03.342325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img,label= test_dataset[8]\nplt.imshow(img.permute(1,2,0))\nprint('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:03.344843Z","iopub.execute_input":"2023-05-24T03:23:03.345293Z","iopub.status.idle":"2023-05-24T03:23:03.493187Z","shell.execute_reply.started":"2023-05-24T03:23:03.345252Z","shell.execute_reply":"2023-05-24T03:23:03.492280Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img,label= test_dataset[1220]\nplt.imshow(img.permute(1,2,0))\nprint('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:03.494644Z","iopub.execute_input":"2023-05-24T03:23:03.495030Z","iopub.status.idle":"2023-05-24T03:23:03.676490Z","shell.execute_reply.started":"2023-05-24T03:23:03.494992Z","shell.execute_reply":"2023-05-24T03:23:03.675358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img,label= test_dataset[345]\nplt.imshow(img.permute(1,2,0))\nprint('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:03.677949Z","iopub.execute_input":"2023-05-24T03:23:03.678397Z","iopub.status.idle":"2023-05-24T03:23:03.828727Z","shell.execute_reply.started":"2023-05-24T03:23:03.678351Z","shell.execute_reply":"2023-05-24T03:23:03.827751Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img,label= test_dataset[6153]\nplt.imshow(img.permute(1,2,0))\nprint('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:03.830426Z","iopub.execute_input":"2023-05-24T03:23:03.830872Z","iopub.status.idle":"2023-05-24T03:23:03.977989Z","shell.execute_reply.started":"2023-05-24T03:23:03.830812Z","shell.execute_reply":"2023-05-24T03:23:03.975941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img,label= test_dataset[456]\nplt.imshow(img.permute(1,2,0))\nprint('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:03.981276Z","iopub.execute_input":"2023-05-24T03:23:03.981554Z","iopub.status.idle":"2023-05-24T03:23:04.129655Z","shell.execute_reply.started":"2023-05-24T03:23:03.981526Z","shell.execute_reply":"2023-05-24T03:23:04.128797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img,label= test_dataset[10]\nplt.imshow(img.permute(1,2,0))\nprint('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:04.130967Z","iopub.execute_input":"2023-05-24T03:23:04.131320Z","iopub.status.idle":"2023-05-24T03:23:04.282089Z","shell.execute_reply.started":"2023-05-24T03:23:04.131290Z","shell.execute_reply":"2023-05-24T03:23:04.281065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"`Identifying where our model performs poorly can help us improve the model, by collecting more training data, \nincreasing/decreasing the complexity of the model, and changing the hypeparameters.`","metadata":{}},{"cell_type":"code","source":"img,label= test_dataset[1432]\nplt.imshow(img.permute(1,2,0))\nprint('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:04.283673Z","iopub.execute_input":"2023-05-24T03:23:04.284092Z","iopub.status.idle":"2023-05-24T03:23:04.434605Z","shell.execute_reply.started":"2023-05-24T03:23:04.284051Z","shell.execute_reply":"2023-05-24T03:23:04.433680Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_loader=DeviceDataLoader(DataLoader(test_dataset,batch_size),device)\ntest_result = evaluate(model, test_loader)\ntest_result","metadata":{"execution":{"iopub.status.busy":"2023-05-24T03:23:04.436863Z","iopub.execute_input":"2023-05-24T03:23:04.437504Z","iopub.status.idle":"2023-05-24T03:23:08.190816Z","shell.execute_reply.started":"2023-05-24T03:23:04.437457Z","shell.execute_reply":"2023-05-24T03:23:08.189926Z"},"trusted":true},"execution_count":null,"outputs":[]}]}