diff --git a/Question 4-6.ipynb b/Question 4-6.ipynb index c4301ed..28bc4fb 100644 --- a/Question 4-6.ipynb +++ b/Question 4-6.ipynb @@ -16,6 +16,7 @@ "outputs": [], "source": [ "import torch\n", + "import torch.nn.functional as F\n", "from ca_utils import ResNet, BasicBlock" ] }, @@ -96,7 +97,8 @@ } ], "source": [ - "checkpoint = torch.load(\"data/weights_resnet.pth\")\n", + "checkpoint = torch.load(\"data/weights_resnet.pth\", map_location=torch.device('cpu'))\n", + "\n", "model.load_state_dict(checkpoint)\n", "model.eval()" ] @@ -118,7 +120,9 @@ "source": [ "import torchvision\n", "from torch.utils.data import DataLoader\n", - "from torchvision import transforms" + "from torchvision import transforms\n", + "\n", + "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')" ] }, { @@ -163,23 +167,32 @@ "outputs": [], "source": [ "def m1_test_cnn(model, test_loader):\n", - " device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n", + "\n", " model.to(device)\n", " model.eval()\n", + "\n", " correct = 0\n", " total = 0\n", " all_predicted_labels = []\n", "\n", " with torch.no_grad():\n", " for images, labels in test_loader:\n", + "\n", + " # Make predictions\n", " images, labels = images.to(device), labels.to(device)\n", " outputs = model(images)\n", + "\n", " _, predicted = torch.max(outputs.data, 1)\n", + "\n", + " # Save results\n", " total += labels.size(0)\n", " correct += (predicted == labels).sum().item()\n", + " \n", " all_predicted_labels.append(predicted.cpu().numpy())\n", + "\n", " accuracy = 100 * correct / total\n", " all_predicted_labels = np.concatenate(all_predicted_labels)\n", + "\n", " return all_predicted_labels, accuracy" ] }, @@ -187,13 +200,15 @@ "cell_type": "code", "execution_count": 8, "id": "3fcb0a3a", - "metadata": {}, + "metadata": { + "scrolled": false + }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Test Accuracy: 67.85%\n" + "Test Accuracy: 75.8%\n" ] } ], @@ -218,9 +233,36 @@ "outputs": [], "source": [ "def test_cnn(model, test_loader):\n", - " all_predicted_labels, accuracy = 0, 0\n", + " \"\"\"\n", + " Test the trained ResNet model on the test dataset.\n", "\n", - " return all_predicted_labels, accuracy" + " Args:\n", + " model (nn.Module): The trained ResNet model.\n", + " test_loader (DataLoader): Data loader for the test data.\n", + " \n", + " Returns:\n", + " float: Test accuracy.\n", + " list: Predicted labels.\n", + " list: True labels.\n", + " \"\"\"\n", + " model.eval()\n", + " correct = 0\n", + " total = 0\n", + " predicted_labels = []\n", + " true_labels = []\n", + "\n", + " with torch.no_grad():\n", + " for images, labels in test_loader:\n", + " outputs = model(images)\n", + " _, predicted = torch.max(outputs.data, 1)\n", + " total += labels.size(0)\n", + " correct += (predicted == labels).sum().item()\n", + " predicted_labels.extend(predicted.tolist())\n", + " true_labels.extend(labels.tolist())\n", + "\n", + " accuracy = correct / total\n", + "\n", + " return predicted_labels, accuracy*100" ] }, { @@ -233,7 +275,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Test Accuracy: 0%\n" + "Test Accuracy: 75.8%\n" ] } ], @@ -242,6 +284,53 @@ "print(f'Test Accuracy: {test_accuracy}%')" ] }, + { + "cell_type": "markdown", + "id": "17bc1948", + "metadata": {}, + "source": [ + "### Test (Should output ALL PASS)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "853c4db3", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test accuracy: 75.8\n", + "Score 100%: 15.0\n", + "ALL PASS\n" + ] + } + ], + "source": [ + "assert np.allclose(predicted_labels, m1_predicted_labels)\n", + "assert np.allclose(test_accuracy, m1_test_accuracy)\n", + "\n", + "print(\"Test accuracy: \", test_accuracy)\n", + "\n", + "if (test_accuracy >= 75):\n", + " print(\"Score 100%:\", 15 * 1.0)\n", + "elif (test_accuracy >= 70):\n", + " print(\"Score 90%:\", 15 * 0.90)\n", + "elif (test_accuracy >= 65):\n", + " print(\"Score 80%:\", 15 * 0.80)\n", + "elif (test_accuracy >= 60):\n", + " print(\"Score 70%:\", 15 * 0.70)\n", + "elif (test_accuracy >= 55):\n", + " print(\"Score 60%:\", 15 * 0.60)\n", + "elif (test_accuracy >= 50):\n", + " print(\"Score 50%:\", 15 * 0.50)\n", + "else:\n", + " print(\"Accuracy less than 50%\")\n", + "print(\"ALL PASS\")" + ] + }, { "cell_type": "markdown", "id": "cef7dc17", @@ -252,13 +341,12 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 12, "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", @@ -269,12 +357,12 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 13, "id": "8da35032", "metadata": {}, "outputs": [], "source": [ - "def compute_confusion_matrix(true, predictions):\n", + "def m1_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", @@ -295,35 +383,87 @@ "execution_count": 14, "id": "16b6f9e7", "metadata": {}, + "outputs": [], + "source": [ + "m1_confusion_matrix = m1_compute_confusion_matrix(true_labels, m1_predicted_labels)" + ] + }, + { + "cell_type": "markdown", + "id": "608265af", + "metadata": {}, + "source": [ + "### Put Students' implementations here" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "1dce952c", + "metadata": {}, + "outputs": [], + "source": [ + "def compute_confusion_matrix(true_labels, predicted_labels):\n", + "\n", + " # Ensure inputs are NumPy arrays\n", + " true_labels = np.array(true_labels)\n", + " predicted_labels = np.array(predicted_labels)\n", + "\n", + " # Determine the number of classes\n", + " num_classes = len(np.unique(true_labels))\n", + "\n", + " # Initialize the confusion matrix with zeros\n", + " cm = np.zeros((num_classes, num_classes))\n", + "\n", + " # Count occurrences of true-predicted label pairs\n", + " for i in range(len(true_labels)):\n", + " cm[true_labels[i]][predicted_labels[i]] += 1\n", + "\n", + " return cm" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "21917014", + "metadata": {}, + "outputs": [], + "source": [ + "confusion_matrix = m1_compute_confusion_matrix(true_labels, m1_predicted_labels)" + ] + }, + { + "cell_type": "markdown", + "id": "935956b7", + "metadata": {}, + "source": [ + "### Test (Should output ALL PASS)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "b77da2e8", + "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" + "name": "stdout", + "output_type": "stream", + "text": [ + "ALL PASS\n" + ] } ], "source": [ - "compute_confusion_matrix(true_labels, m1_predicted_labels)" + "assert np.allclose(confusion_matrix, m1_confusion_matrix)\n", + "\n", + "print(\"ALL PASS\")" ] }, { "cell_type": "code", "execution_count": null, - "id": "1dce952c", + "id": "adc0a7c7", "metadata": {}, "outputs": [], "source": [] @@ -333,7 +473,7 @@ "kernelspec": { "display_name": "what", "language": "python", - "name": "python3" + "name": "what" }, "language_info": { "codemirror_mode": { diff --git a/data/weights_resnet.pth b/data/weights_resnet.pth index 1c87866..437ee7a 100644 Binary files a/data/weights_resnet.pth and b/data/weights_resnet.pth differ