{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "efbbd443-4b0f-42f9-8038-97a543b704ec",
   "metadata": {},
   "source": [
    "<center>\n",
    "    <tr>\n",
    "    <td><img src=\"ontario-tech-univ-logo.png\" width=\"25%\"></img></td>\n",
    "    </tr>\n",
    "</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94a9f123-5f5e-42bc-b90f-31d50db2fc91",
   "metadata": {},
   "source": [
    "# CIFAR10 Image Classification\n",
    "\n",
    "Faisal Qureshi   \n",
    "Professor    \n",
    "Faculty of Science    \n",
    "Ontario Tech University    \n",
    "Oshawa ON Canada    \n",
    "http://vclab.science.ontariotechu.ca"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dfbd630a-a7d4-4e63-a98d-2f397e66c403",
   "metadata": {},
   "source": [
    "## Copyright information\n",
    "\n",
    "&copy; Faisal Qureshi"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "037d98a1-a89e-4148-80dc-5509a43c4741",
   "metadata": {},
   "source": [
    "# Acknowledgements\n",
    "\n",
    "Taken from [https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html](https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd6ff339-5219-412e-a97a-c325b531fc5f",
   "metadata": {},
   "source": [
    "## License\n",
    "\n",
    "<a rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc/4.0/\"><img alt=\"Creative Commons Licence\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by-nc/4.0/88x31.png\" /></a><br />This work is licensed under a <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc/4.0/\">Creative Commons Attribution-NonCommercial 4.0 International License</a>."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6546c646-1720-48fd-bf25-64febb8b9ff9",
   "metadata": {},
   "source": [
    "# Introduction\n",
    "\n",
    "The purpose of this lab is to study image classification.  Specifically, we will attempt to classify [CIFAR10 datasets](https://www.cs.toronto.edu/~kriz/cifar.html) using a Multilayer Perceptron (MLP).  We will use PyTorch to train this model.\n",
    "\n",
    "The code provided below trains and evaluates a $10$-way linear classifier, i.e., it takes all the pixels of a CIFAR10 image (across three channels)--$32 \\times 32 \\times 3$--and fits $10$ lines, one for each class, to it.  The figure shown below capture this model.\n",
    "\n",
    "<center>\n",
    "    <img src=\"04-image-classification/10-way-linear-classifier.png\" width=\"70%\">\n",
    "</center>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c76c3209-c311-4086-82d0-fa82e87dc618",
   "metadata": {},
   "source": [
    "# Tasks\n",
    "\n",
    "The goal of the lab is three-folds.\n",
    "\n",
    "1. Understand how PyTorch is being used to setup a model.\n",
    "2. Capture the performance of this linear model on the problem of image classification.\n",
    "3. Convert the linear model to a Multi-layer Perceptron Model (MLP) and compare the performance of the two models.\n",
    "    - I suggest that you start with a model with a single hidden layer.  The hidden layer will have an activation function, say ReLU.  The output layer will take the hidden layer and outputs $10$ values.  \n",
    "5. (Optional) what other changes can you make to the image to improve classification scores. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ad188be9-d38a-4e92-865d-8d2ebc5e9253",
   "metadata": {},
   "source": [
    "# Sample Code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "60e28295-bf56-47e2-b98c-65dd62d37a25",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "80e1cdfd-3919-40f9-a671-309d8b0cca5d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cuda:0\n"
     ]
    }
   ],
   "source": [
    "# GPU usage\n",
    "# device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')\n",
    "\n",
    "# Assuming that we are on a CUDA machine, this should print a CUDA device:\n",
    "print(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "e0ed63de-ef14-4875-8a89-caed394930de",
   "metadata": {},
   "outputs": [],
   "source": [
    "transform = transforms.Compose(\n",
    "    [transforms.ToTensor(),\n",
    "     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "19206f4d-5caa-4ad5-955f-8da405d6ceda",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Files already downloaded and verified\n"
     ]
    }
   ],
   "source": [
    "batch_size = 4\n",
    "\n",
    "trainset = torchvision.datasets.CIFAR10(root='./data', train=True,\n",
    "                                        download=True, transform=transform)\n",
    "trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size,\n",
    "                                          shuffle=True, num_workers=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "a1e8d67b-eca7-4972-a3f2-edeb721db9ea",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Files already downloaded and verified\n"
     ]
    }
   ],
   "source": [
    "testset = torchvision.datasets.CIFAR10(root='./data', train=False,\n",
    "                                       download=True, transform=transform)\n",
    "testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size,\n",
    "                                         shuffle=False, num_workers=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "dec2bd30-0418-493f-a59d-3cbd52397071",
   "metadata": {},
   "outputs": [],
   "source": [
    "classes = ('plane', 'car', 'bird', 'cat',\n",
    "           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "b8e4ce60-68f4-47a1-ba9c-deabaef1baf3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "e56efd87-9253-4b9a-b530-8de96318136b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def imshow(img):\n",
    "    img = img / 2 + 0.5     # unnormalize\n",
    "    npimg = img.numpy()\n",
    "    plt.imshow(np.transpose(npimg, (1, 2, 0)))\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "1fa3ea63-27d4-4fbb-b7de-46212b85f0dd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dog   car   ship  dog  \n"
     ]
    }
   ],
   "source": [
    "dataiter = iter(trainloader)\n",
    "images, labels = next(dataiter)\n",
    "\n",
    "# show images\n",
    "imshow(torchvision.utils.make_grid(images))\n",
    "# print labels\n",
    "print(' '.join(f'{classes[labels[j]]:5s}' for j in range(batch_size)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3282fc94-abb3-447c-a6c7-857a3276df7c",
   "metadata": {},
   "source": [
    "## 10-way linear model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "e2e4cf69-c736-4f35-a703-974a16f698aa",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "class ALinearModel(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        self.fc = nn.Linear(32*32*3, 10)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = torch.flatten(x, 1) # flatten all dimensions except batch\n",
    "        x = self.fc(x)\n",
    "        return x\n",
    "\n",
    "linear_model = ALinearModel()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2783609-9197-4fb8-84c2-5a628804e1ac",
   "metadata": {},
   "source": [
    "## MLP model (TO DO)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "ea7fce8d-a67e-4611-b143-83718589e988",
   "metadata": {},
   "outputs": [],
   "source": [
    "class MyMLP(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__()\n",
    "        \n",
    "        # TODO\n",
    "        \n",
    "    def forward(self, x):\n",
    "        # TODO\n",
    "        \n",
    "        return torch.zeros((1,10))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8e4e0cfc-dd2d-4a78-95d5-8a3acb06574e",
   "metadata": {},
   "source": [
    "## Training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "04ee266c-174d-4c9d-be63-30dc0f0dc643",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch.optim as optim\n",
    "\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "11701988-e28f-4c93-97fe-adf197b8b296",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1,  2000] loss: 2.361\n",
      "[1,  4000] loss: 2.352\n",
      "[1,  6000] loss: 2.361\n",
      "[1,  8000] loss: 2.366\n",
      "[1, 10000] loss: 2.364\n",
      "[1, 12000] loss: 2.364\n",
      "[2,  2000] loss: 2.360\n",
      "[2,  4000] loss: 2.361\n",
      "[2,  6000] loss: 2.366\n",
      "[2,  8000] loss: 2.360\n",
      "[2, 10000] loss: 2.359\n",
      "[2, 12000] loss: 2.364\n",
      "Finished Training\n"
     ]
    }
   ],
   "source": [
    "for epoch in range(2):  # loop over the dataset multiple times\n",
    "\n",
    "    running_loss = 0.0\n",
    "    for i, data in enumerate(trainloader, 0):\n",
    "        # get the inputs; data is a list of [inputs, labels]\n",
    "        inputs, labels = data[0], data[1]\n",
    "\n",
    "        # zero the parameter gradients\n",
    "        optimizer.zero_grad()\n",
    "\n",
    "        # forward + backward + optimize\n",
    "        outputs = linear_model(inputs)\n",
    "        loss = criterion(outputs, labels)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "\n",
    "        # print statistics\n",
    "        running_loss += loss.item()\n",
    "        if i % 2000 == 1999:    # print every 2000 mini-batches\n",
    "            print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 2000:.3f}')\n",
    "            running_loss = 0.0\n",
    "\n",
    "print('Finished Training')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fad15ce2-e89e-45ea-8f22-e0785ae519e7",
   "metadata": {},
   "source": [
    "## Saving Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "04a5e913-e272-48a0-8d00-ba39dd928ad7",
   "metadata": {},
   "outputs": [],
   "source": [
    "PATH = './cifar_linear_model.pth'\n",
    "torch.save(linear_model.state_dict(), PATH)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6954445-9af7-4cc3-8320-4f8c5d3b6b16",
   "metadata": {},
   "source": [
    "## Inference on a test images"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "02cea4fc-e82d-4b9e-a148-f2453f242c58",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "GroundTruth:  cat   ship  ship  plane\n"
     ]
    }
   ],
   "source": [
    "dataiter = iter(testloader)\n",
    "images, labels = next(dataiter)\n",
    "\n",
    "# print images\n",
    "imshow(torchvision.utils.make_grid(images))\n",
    "print('GroundTruth: ', ' '.join(f'{classes[labels[j]]:5s}' for j in range(4)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "b4710107-e557-442c-b227-f4168e82ac70",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<All keys matched successfully>"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "linear_model = ALinearModel()\n",
    "linear_model.load_state_dict(torch.load(PATH))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "5fba9c84-c8b8-41fd-8e32-73a678a60459",
   "metadata": {},
   "outputs": [],
   "source": [
    "outputs = linear_model(images)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "6bcc992e-af27-48ff-8a2e-c06ef86b38ac",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Predicted:  deer  dog   plane ship \n"
     ]
    }
   ],
   "source": [
    "_, predicted = torch.max(outputs, 1)\n",
    "\n",
    "print('Predicted: ', ' '.join(f'{classes[predicted[j]]:5s}'\n",
    "                              for j in range(4)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "04457740-6b40-45fa-92b9-75657ce4ea0a",
   "metadata": {},
   "source": [
    "## Computing accuracy on the entire test set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "90c49f95-7f34-4e41-a6da-ed0336b3fbb9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy of the network on the 10000 test images: 8 %\n"
     ]
    }
   ],
   "source": [
    "correct = 0\n",
    "total = 0\n",
    "# since we're not training, we don't need to calculate the gradients for our outputs\n",
    "with torch.no_grad():\n",
    "    for data in testloader:\n",
    "        images, labels = data\n",
    "        # calculate outputs by running images through the network\n",
    "        outputs = linear_model(images)\n",
    "        # the class with the highest energy is what we choose as prediction\n",
    "        _, predicted = torch.max(outputs.data, 1)\n",
    "        total += labels.size(0)\n",
    "        correct += (predicted == labels).sum().item()\n",
    "\n",
    "print(f'Accuracy of the network on the 10000 test images: {100 * correct // total} %')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7d87b68-7dc6-43ed-bafc-c17d2ca26b72",
   "metadata": {},
   "source": [
    "## Computing class-wise accuracy on the entire test set "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "28519552-b77c-4c15-8306-1b21bc1377ba",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy for class: plane is 26.2 %\n",
      "Accuracy for class: car   is 4.4 %\n",
      "Accuracy for class: bird  is 8.8 %\n",
      "Accuracy for class: cat   is 4.8 %\n",
      "Accuracy for class: deer  is 4.6 %\n",
      "Accuracy for class: dog   is 12.4 %\n",
      "Accuracy for class: frog  is 5.1 %\n",
      "Accuracy for class: horse is 5.6 %\n",
      "Accuracy for class: ship  is 5.6 %\n",
      "Accuracy for class: truck is 8.3 %\n"
     ]
    }
   ],
   "source": [
    "# prepare to count predictions for each class\n",
    "correct_pred = {classname: 0 for classname in classes}\n",
    "total_pred = {classname: 0 for classname in classes}\n",
    "\n",
    "# again no gradients needed\n",
    "with torch.no_grad():\n",
    "    for data in testloader:\n",
    "        images, labels = data\n",
    "        outputs = linear_model(images)\n",
    "        _, predictions = torch.max(outputs, 1)\n",
    "        # collect the correct predictions for each class\n",
    "        for label, prediction in zip(labels, predictions):\n",
    "            if label == prediction:\n",
    "                correct_pred[classes[label]] += 1\n",
    "            total_pred[classes[label]] += 1\n",
    "\n",
    "\n",
    "# print accuracy for each class\n",
    "for classname, correct_count in correct_pred.items():\n",
    "    accuracy = 100 * float(correct_count) / total_pred[classname]\n",
    "    print(f'Accuracy for class: {classname:5s} is {accuracy:.1f} %')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "302cf0ab-a16e-429c-8683-6deda51dd849",
   "metadata": {},
   "source": [
    "# What to submit\n",
    "\n",
    "1. Python notebook that implements multilayer perceptron model.\n",
    "2. A report that lists the classification performance of the linear and MLP model.\n",
    "3. (Optional) Python notebook that implements some of the changes that you have made to the model that improves the classification scores.\n",
    "\n",
    "All work should be submitted to Canvas."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa6a2aac-dc46-4f40-967b-0067fac30643",
   "metadata": {},
   "source": [
    "<center>\n",
    "    <tr>\n",
    "    <td><img src=\"ontario-tech-univ-logo.png\" width=\"25%\"></img></td>\n",
    "    </tr>\n",
    "</center>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7f872825-e766-454e-a20f-47bb2172a684",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "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.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
