diff --git a/Question 4-6.ipynb b/Question 4-6.ipynb new file mode 100644 index 0000000..c4301ed --- /dev/null +++ b/Question 4-6.ipynb @@ -0,0 +1,353 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a5a8f05e", + "metadata": {}, + "source": [ + "## Question 4 (10 marks)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "8ddab76f", + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "from ca_utils import ResNet, BasicBlock" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b52a47c6", + "metadata": {}, + "outputs": [], + "source": [ + "model = ResNet(block=BasicBlock, layers=[1, 1, 1], num_classes=10)" + ] + }, + { + "cell_type": "markdown", + "id": "15a25e00", + "metadata": {}, + "source": [ + "### Load the Model" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "af4de07b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "ResNet(\n", + " (conv1): Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n", + " (bn1): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (relu): ReLU(inplace=True)\n", + " (layer1): Sequential(\n", + " (0): BasicBlock(\n", + " (conv1): Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n", + " (bn1): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (relu): ReLU(inplace=True)\n", + " (conv2): Conv2d(16, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n", + " (bn2): BatchNorm2d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " )\n", + " )\n", + " (layer2): Sequential(\n", + " (0): BasicBlock(\n", + " (conv1): Conv2d(16, 32, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n", + " (bn1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (relu): ReLU(inplace=True)\n", + " (conv2): Conv2d(32, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n", + " (bn2): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (downsample): Sequential(\n", + " (0): Conv2d(16, 32, kernel_size=(1, 1), stride=(2, 2), bias=False)\n", + " (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " )\n", + " )\n", + " )\n", + " (layer3): Sequential(\n", + " (0): BasicBlock(\n", + " (conv1): Conv2d(32, 64, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n", + " (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (relu): ReLU(inplace=True)\n", + " (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n", + " (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " (downsample): Sequential(\n", + " (0): Conv2d(32, 64, kernel_size=(1, 1), stride=(2, 2), bias=False)\n", + " (1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n", + " )\n", + " )\n", + " )\n", + " (avgpool): AdaptiveAvgPool2d(output_size=1)\n", + " (fc): Linear(in_features=64, out_features=10, bias=True)\n", + ")" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "checkpoint = torch.load(\"data/weights_resnet.pth\")\n", + "model.load_state_dict(checkpoint)\n", + "model.eval()" + ] + }, + { + "cell_type": "markdown", + "id": "98c03b18", + "metadata": {}, + "source": [ + "## Question 5 (15 marks)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "3024a7a8", + "metadata": {}, + "outputs": [], + "source": [ + "import torchvision\n", + "from torch.utils.data import DataLoader\n", + "from torchvision import transforms" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "357891cd", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "image_transform = transforms.Compose(\n", + " [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])\n", + "\n", + "test_data = torchvision.datasets.ImageFolder('data/EXCV10/val/', transform=image_transform)\n", + "test_loader = DataLoader(test_data, batch_size=64, shuffle=False, num_workers=4, pin_memory=True)" + ] + }, + { + "cell_type": "markdown", + "id": "0eb07988", + "metadata": {}, + "source": [ + "## Method 1" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "b9d88037", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "6a30d88c", + "metadata": {}, + "outputs": [], + "source": [ + "def m1_test_cnn(model, test_loader):\n", + " device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n", + " model.to(device)\n", + " model.eval()\n", + " correct = 0\n", + " total = 0\n", + " all_predicted_labels = []\n", + "\n", + " with torch.no_grad():\n", + " for images, labels in test_loader:\n", + " images, labels = images.to(device), labels.to(device)\n", + " outputs = model(images)\n", + " _, predicted = torch.max(outputs.data, 1)\n", + " total += labels.size(0)\n", + " correct += (predicted == labels).sum().item()\n", + " all_predicted_labels.append(predicted.cpu().numpy())\n", + " accuracy = 100 * correct / total\n", + " all_predicted_labels = np.concatenate(all_predicted_labels)\n", + " return all_predicted_labels, accuracy" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "3fcb0a3a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test Accuracy: 67.85%\n" + ] + } + ], + "source": [ + "m1_predicted_labels, m1_test_accuracy = m1_test_cnn(model, test_loader)\n", + "print(f'Test Accuracy: {m1_test_accuracy}%')" + ] + }, + { + "cell_type": "markdown", + "id": "75272741", + "metadata": {}, + "source": [ + "### Put Students' implementations here" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "47bd1202", + "metadata": {}, + "outputs": [], + "source": [ + "def test_cnn(model, test_loader):\n", + " all_predicted_labels, accuracy = 0, 0\n", + "\n", + " return all_predicted_labels, accuracy" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "1b0db3bd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test Accuracy: 0%\n" + ] + } + ], + "source": [ + "predicted_labels, test_accuracy = test_cnn(model, test_loader)\n", + "print(f'Test Accuracy: {test_accuracy}%')" + ] + }, + { + "cell_type": "markdown", + "id": "cef7dc17", + "metadata": {}, + "source": [ + "## Question 6 (6 marks)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "0990f3b2", + "metadata": {}, + "outputs": [], + "source": [ + "true_labels = []\n", + "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n", + "\n", + "for images, labels in test_loader:\n", + " images, labels = images.to(device), labels.to(device)\n", + " true_labels.extend(labels.cpu().numpy())\n", + " \n", + "true_labels = np.array(true_labels)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "8da35032", + "metadata": {}, + "outputs": [], + "source": [ + "def compute_confusion_matrix(true, predictions):\n", + " unique_labels = np.unique(np.concatenate((true, predictions)))\n", + "\n", + " confusion_mat = np.zeros((len(unique_labels), len(unique_labels)), dtype=np.int64)\n", + "\n", + " label_to_index = {label: index for index,\n", + " label in enumerate(unique_labels)}\n", + "\n", + " for t, p in zip(true, predictions):\n", + " t_index = label_to_index[t]\n", + " p_index = label_to_index[p]\n", + " confusion_mat[t_index][p_index] += 1\n", + "\n", + " return confusion_mat" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "16b6f9e7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[168, 2, 5, 0, 6, 0, 2, 0, 6, 11],\n", + " [ 13, 108, 2, 18, 29, 16, 1, 13, 0, 0],\n", + " [ 1, 1, 162, 0, 1, 0, 7, 0, 0, 28],\n", + " [ 0, 7, 2, 74, 46, 40, 2, 26, 1, 2],\n", + " [ 1, 2, 2, 6, 166, 9, 6, 8, 0, 0],\n", + " [ 1, 3, 0, 11, 37, 108, 27, 12, 1, 0],\n", + " [ 1, 0, 1, 0, 40, 30, 121, 4, 0, 3],\n", + " [ 1, 7, 1, 6, 32, 24, 2, 127, 0, 0],\n", + " [ 11, 1, 2, 2, 1, 1, 0, 0, 153, 29],\n", + " [ 4, 0, 13, 2, 5, 0, 1, 0, 5, 170]], dtype=int64)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "compute_confusion_matrix(true_labels, m1_predicted_labels)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1dce952c", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "what", + "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.8.16" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/data/weights_resnet.pth b/data/weights_resnet.pth new file mode 100644 index 0000000..1c87866 Binary files /dev/null and b/data/weights_resnet.pth differ