Archived
dropout fixed oerfitting, added
This commit is contained in:
1 parent
4f8c48c504
commit
59f26a299c
1 file changed
+598
@@ -0,0 +1,598 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 1,
|
||||||
|
"id": "7a37220a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Hello, World!\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"print(\"Hello, World!\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "d318d1f0",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Van: 1111 images\n",
|
||||||
|
"Taxi: 748 images\n",
|
||||||
|
"Bicycle: 1618 images\n",
|
||||||
|
"Bus: 2133 images\n",
|
||||||
|
"Car: 6781 images\n",
|
||||||
|
"Motorcycle: 2986 images\n",
|
||||||
|
"Truck: 2033 images\n",
|
||||||
|
"NonVehicles: 8968 images\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"import os\n",
|
||||||
|
"\n",
|
||||||
|
"data_dir = '../data/raw/vehicle_classification'\n",
|
||||||
|
"\n",
|
||||||
|
"for class_name in os.listdir(data_dir):\n",
|
||||||
|
" class_path = os.path.join(data_dir, class_name)\n",
|
||||||
|
" if os.path.isdir(class_path):\n",
|
||||||
|
" count = len(os.listdir(class_path))\n",
|
||||||
|
" print(f\"{class_name}: {count} images\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "64122ad4",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Check out sample image from dataset"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "5604ace3",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Size: (64, 64)\n",
|
||||||
|
"Mode: RGB\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"image/png": "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 truncated
|
||||||
|
"text/plain": [
|
||||||
|
"<Figure size 640x480 with 1 Axes>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"from PIL import Image\n",
|
||||||
|
"import matplotlib.pyplot as plt\n",
|
||||||
|
"\n",
|
||||||
|
"# first image in first folder\n",
|
||||||
|
"first_class = os.listdir(data_dir)[0]\n",
|
||||||
|
"first_image_path = os.path.join(data_dir, first_class, os.listdir(os.path.join(data_dir, first_class))[0])\n",
|
||||||
|
"\n",
|
||||||
|
"img = Image.open(first_image_path)\n",
|
||||||
|
"print(f\"Size: {img.size}\")\n",
|
||||||
|
"print(f\"Mode: {img.mode}\")\n",
|
||||||
|
"plt.imshow(img)\n",
|
||||||
|
"plt.title(first_class)\n",
|
||||||
|
"plt.show()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "c19ec00a",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Ensure that all images are RGB, all of same resolution"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "3cedd586",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Unique sizes: {(64, 64)}\n",
|
||||||
|
"Unique modes: {'RGB'}\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"sizes = set()\n",
|
||||||
|
"modes = set()\n",
|
||||||
|
"\n",
|
||||||
|
"for class_name in os.listdir(data_dir):\n",
|
||||||
|
" class_path = os.path.join(data_dir, class_name)\n",
|
||||||
|
" if not os.path.isdir(class_path):\n",
|
||||||
|
" continue\n",
|
||||||
|
" for img_name in os.listdir(class_path):\n",
|
||||||
|
" img = Image.open(os.path.join(class_path, img_name))\n",
|
||||||
|
" sizes.add(img.size)\n",
|
||||||
|
" modes.add(img.mode)\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Unique sizes: {sizes}\")\n",
|
||||||
|
"print(f\"Unique modes: {modes}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "88ac961b",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Ensure that torch works with GPU (5080) [Credit: Claude]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "8f556b22",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"True\n",
|
||||||
|
"NVIDIA GeForce RTX 5080\n",
|
||||||
|
"GPU works! torch.Size([1000, 1000])\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"import torch\n",
|
||||||
|
"print(torch.cuda.is_available()) \n",
|
||||||
|
"print(torch.cuda.get_device_name(0)) \n",
|
||||||
|
"\n",
|
||||||
|
"x = torch.randn(1000, 1000).cuda()\n",
|
||||||
|
"y = x @ x\n",
|
||||||
|
"print(\"GPU works!\", y.shape)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "870fadbe",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Transform image dataset into tensors. Normalized with 0.5 mean and 0.5 STD (can be differente to use pretrained weights)."
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"id": "37793c77",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"['Bicycle', 'Bus', 'Car', 'Motorcycle', 'NonVehicles', 'Taxi', 'Truck', 'Van']\n",
|
||||||
|
"26378\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"from torchvision import datasets, transforms\n",
|
||||||
|
"from torch.utils.data import random_split, DataLoader\n",
|
||||||
|
"\n",
|
||||||
|
"transform = transforms.Compose([\n",
|
||||||
|
" transforms.ToTensor(),\n",
|
||||||
|
" transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])\n",
|
||||||
|
"])\n",
|
||||||
|
"\n",
|
||||||
|
"dataset = datasets.ImageFolder(root=data_dir, transform=transform)\n",
|
||||||
|
"\n",
|
||||||
|
"print(dataset.classes) # should print 8 classes\n",
|
||||||
|
"print(len(dataset)) # total image count"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "ac33bc21",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Split 80-20 and save into 2 variables"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"id": "f68c1a25",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Train: 21102, Test: 5276\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"import math \n",
|
||||||
|
"\n",
|
||||||
|
"train_size = math.floor(len(dataset) * 0.8)\n",
|
||||||
|
"test_size = len(dataset) - train_size\n",
|
||||||
|
"\n",
|
||||||
|
"train_dataset, test_dataset = random_split(dataset, [train_size, test_size])\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"Train: {len(train_dataset)}, Test: {len(test_dataset)}\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "2eede814",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Load the data into batches for faster loading...use 4 threads on CPU\n",
|
||||||
|
"\n",
|
||||||
|
"Shuffling train dataset so as to not overfit on one class"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 8,
|
||||||
|
"id": "e1539eaa",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"8\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"train_loader = DataLoader(train_dataset, batch_size=256, shuffle=True, num_workers=16) # Increased from 4\n",
|
||||||
|
"test_loader = DataLoader(test_dataset, batch_size=256, shuffle=False, num_workers=16) # Increased from 4\n",
|
||||||
|
"\n",
|
||||||
|
"classes = ('bicycle', 'bus', 'car', 'motorcycle',\n",
|
||||||
|
" 'nonvehicles', 'taxi', 'truck', 'van')\n",
|
||||||
|
"\n",
|
||||||
|
"print(len(classes))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "acebe98e",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"MOdified tutorial arch to handle BathhNorm and Dropout (to try to prevent overfitting)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "d1b7d9ca",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Net(\n",
|
||||||
|
" (features): Sequential(\n",
|
||||||
|
" (0): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
|
||||||
|
" (1): BatchNorm2d(32, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
|
||||||
|
" (2): ReLU()\n",
|
||||||
|
" (3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
|
||||||
|
" (4): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
|
||||||
|
" (5): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
|
||||||
|
" (6): ReLU()\n",
|
||||||
|
" (7): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
|
||||||
|
" (8): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))\n",
|
||||||
|
" (9): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
|
||||||
|
" (10): ReLU()\n",
|
||||||
|
" (11): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)\n",
|
||||||
|
" )\n",
|
||||||
|
" (classifier): Sequential(\n",
|
||||||
|
" (0): Flatten(start_dim=1, end_dim=-1)\n",
|
||||||
|
" (1): Linear(in_features=8192, out_features=512, bias=True)\n",
|
||||||
|
" (2): ReLU()\n",
|
||||||
|
" (3): Dropout(p=0.5, inplace=False)\n",
|
||||||
|
" (4): Linear(in_features=512, out_features=8, bias=True)\n",
|
||||||
|
" )\n",
|
||||||
|
")\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"import torch\n",
|
||||||
|
"import torch.nn as nn\n",
|
||||||
|
"import torch.nn.functional as F\n",
|
||||||
|
"\n",
|
||||||
|
"class Net(nn.Module):\n",
|
||||||
|
" def __init__(self):\n",
|
||||||
|
" super(Net, self).__init__()\n",
|
||||||
|
"\n",
|
||||||
|
" self.features = nn.Sequential(\n",
|
||||||
|
" # go from 64x64 to 32x32\n",
|
||||||
|
"\n",
|
||||||
|
" # kernel size = 3x3 filter patch\n",
|
||||||
|
" #padding = 1, so 64x64 stays 64x64 after conv\n",
|
||||||
|
" nn.Conv2d(3, 32, kernel_size=3, padding=1), # 3 channel RRGB, 32 filters (recommended)\n",
|
||||||
|
"\n",
|
||||||
|
" nn.BatchNorm2d(32), # mirrors conv2d output\n",
|
||||||
|
" nn.ReLU(),\n",
|
||||||
|
" nn.MaxPool2d(2,2), # 2x2 window so halved --> 32x32\n",
|
||||||
|
"\n",
|
||||||
|
" #Go from 32x32 --> 16x16\n",
|
||||||
|
"\n",
|
||||||
|
" nn.Conv2d(32, 64, kernel_size=3, padding=1),\n",
|
||||||
|
" nn.BatchNorm2d(64),\n",
|
||||||
|
" nn.ReLU(),\n",
|
||||||
|
" nn.MaxPool2d(2,2), \n",
|
||||||
|
" \n",
|
||||||
|
" # Go from 16x 16 0 --> 8x8\n",
|
||||||
|
"\n",
|
||||||
|
" nn.Conv2d(64, 128, kernel_size=3, padding=1),\n",
|
||||||
|
" nn.BatchNorm2d(128),\n",
|
||||||
|
" nn.ReLU(),\n",
|
||||||
|
" nn.MaxPool2d(2,2), \n",
|
||||||
|
"\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" self.classifier = nn.Sequential(\n",
|
||||||
|
" nn.Flatten(),\n",
|
||||||
|
" nn.Linear (128 * 8 *8, 512), # flattened size of 8x8 * 128, 512 is arbitrary output (recommended by sources)\n",
|
||||||
|
" nn.ReLU(),\n",
|
||||||
|
" nn.Dropout(0.5),#Randomly zero 50% of neurons --> prevent moeoorization\n",
|
||||||
|
" nn.Linear(512, len(classes)) # one score per vehicle class\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" def forward(self, x):\n",
|
||||||
|
" x = self.features(x)\n",
|
||||||
|
" x = self.classifier(x)\n",
|
||||||
|
" return x\n",
|
||||||
|
"\n",
|
||||||
|
"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
|
||||||
|
"model = Net().to(device)\n",
|
||||||
|
"print(model)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "22e71032",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Loss fn and optimizer"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 10,
|
||||||
|
"id": "54d11a04",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import torch.optim as optim\n",
|
||||||
|
"\n",
|
||||||
|
"criterion = nn.CrossEntropyLoss() # Applied softmax to convert scores --> probabilities --> penalizes model \n",
|
||||||
|
"\n",
|
||||||
|
"# Changed to adam optimizer (internal momentumn calculation)\n",
|
||||||
|
"optimizer = optim.Adam(model.parameters(), lr=0.001)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "572d80e3",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Tutorial training cell adapted to use 30 epochs "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 11,
|
||||||
|
"id": "374d0590",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Epoch 1: Loss=1.374, Accuracy=60.99%\n",
|
||||||
|
"Epoch 2: Loss=0.841, Accuracy=70.39%\n",
|
||||||
|
"Epoch 3: Loss=0.718, Accuracy=74.55%\n",
|
||||||
|
"Epoch 4: Loss=0.651, Accuracy=76.96%\n",
|
||||||
|
"Epoch 5: Loss=0.595, Accuracy=78.95%\n",
|
||||||
|
"Epoch 6: Loss=0.551, Accuracy=80.34%\n",
|
||||||
|
"Epoch 7: Loss=0.536, Accuracy=81.03%\n",
|
||||||
|
"Epoch 8: Loss=0.505, Accuracy=82.37%\n",
|
||||||
|
"Epoch 9: Loss=0.478, Accuracy=82.90%\n",
|
||||||
|
"Epoch 10: Loss=0.452, Accuracy=83.73%\n",
|
||||||
|
"Epoch 11: Loss=0.432, Accuracy=84.58%\n",
|
||||||
|
"Epoch 12: Loss=0.401, Accuracy=85.61%\n",
|
||||||
|
"Epoch 13: Loss=0.385, Accuracy=86.30%\n",
|
||||||
|
"Epoch 14: Loss=0.369, Accuracy=86.80%\n",
|
||||||
|
"Epoch 15: Loss=0.350, Accuracy=87.43%\n",
|
||||||
|
"Epoch 16: Loss=0.340, Accuracy=87.60%\n",
|
||||||
|
"Epoch 17: Loss=0.321, Accuracy=87.97%\n",
|
||||||
|
"Epoch 18: Loss=0.298, Accuracy=89.02%\n",
|
||||||
|
"Epoch 19: Loss=0.267, Accuracy=90.22%\n",
|
||||||
|
"Epoch 20: Loss=0.254, Accuracy=90.49%\n",
|
||||||
|
"Epoch 21: Loss=0.237, Accuracy=91.32%\n",
|
||||||
|
"Epoch 22: Loss=0.224, Accuracy=91.75%\n",
|
||||||
|
"Epoch 23: Loss=0.209, Accuracy=92.18%\n",
|
||||||
|
"Epoch 24: Loss=0.196, Accuracy=92.79%\n",
|
||||||
|
"Epoch 25: Loss=0.185, Accuracy=93.13%\n",
|
||||||
|
"Epoch 26: Loss=0.167, Accuracy=93.72%\n",
|
||||||
|
"Epoch 27: Loss=0.171, Accuracy=93.74%\n",
|
||||||
|
"Epoch 28: Loss=0.158, Accuracy=94.04%\n",
|
||||||
|
"Epoch 29: Loss=0.148, Accuracy=94.42%\n",
|
||||||
|
"Epoch 30: Loss=0.125, Accuracy=95.63%\n",
|
||||||
|
"Finished Training\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"for epoch in range(30): # 10 --> 30 epochs\n",
|
||||||
|
" running_loss = 0.0\n",
|
||||||
|
" correct = 0\n",
|
||||||
|
" total = 0\n",
|
||||||
|
"\n",
|
||||||
|
" for i, data in enumerate(train_loader, 0):\n",
|
||||||
|
" inputs, labels = data\n",
|
||||||
|
" inputs, labels = inputs.to(device), labels.to(device) # use GPU\n",
|
||||||
|
"\n",
|
||||||
|
" optimizer.zero_grad()\n",
|
||||||
|
"\n",
|
||||||
|
" outputs = model(inputs)\n",
|
||||||
|
" loss = criterion(outputs, labels)\n",
|
||||||
|
" loss.backward()\n",
|
||||||
|
" optimizer.step()\n",
|
||||||
|
"\n",
|
||||||
|
" # loss tracking\n",
|
||||||
|
" running_loss += loss.item()\n",
|
||||||
|
"\n",
|
||||||
|
" # accuracy tracking\n",
|
||||||
|
" _, predicted = torch.max(outputs, 1)\n",
|
||||||
|
" total += labels.size(0)\n",
|
||||||
|
" correct += (predicted == labels).sum().item()\n",
|
||||||
|
"\n",
|
||||||
|
" accuracy = 100 * correct / total\n",
|
||||||
|
" print(f'Epoch {epoch + 1}: Loss={running_loss / len(train_loader):.3f}, Accuracy={accuracy:.2f}%') # Credit: Claude for printing accuracy in good formatting\n",
|
||||||
|
"\n",
|
||||||
|
"print('Finished Training')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 12,
|
||||||
|
"id": "2bf2b9a2",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"PATH = '../models/batch-norm-dropout.pth'\n",
|
||||||
|
"torch.save(model.state_dict(), PATH)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "a24dd4f0",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Test on test set using Pytorch tutorial method for both total and per class (maybe spot overfitting as well)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 13,
|
||||||
|
"id": "bc158602",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Test Accuracy: 83.06%\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"correct = 0\n",
|
||||||
|
"total = 0\n",
|
||||||
|
"\n",
|
||||||
|
"with torch.no_grad():\n",
|
||||||
|
" for data in test_loader:\n",
|
||||||
|
" images, labels = data\n",
|
||||||
|
" images, labels = images.to(device), labels.to(device)\n",
|
||||||
|
" outputs = model(images)\n",
|
||||||
|
" _, predicted = torch.max(outputs, 1)\n",
|
||||||
|
" total += labels.size(0)\n",
|
||||||
|
" correct += (predicted == labels).sum().item()\n",
|
||||||
|
"\n",
|
||||||
|
"print(f'Test Accuracy: {100 * correct / total:.2f}%')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 14,
|
||||||
|
"id": "8cc7ed40",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Accuracy for class: Bicycle is 77.6%\n",
|
||||||
|
"Accuracy for class: Bus is 74.9%\n",
|
||||||
|
"Accuracy for class: Car is 80.5%\n",
|
||||||
|
"Accuracy for class: Motorcycle is 83.3%\n",
|
||||||
|
"Accuracy for class: NonVehicles is 99.7%\n",
|
||||||
|
"Accuracy for class: Taxi is 53.4%\n",
|
||||||
|
"Accuracy for class: Truck is 51.6%\n",
|
||||||
|
"Accuracy for class: Van is 45.4%\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"correct_pred = {classname: 0 for classname in dataset.classes}\n",
|
||||||
|
"total_pred = {classname: 0 for classname in dataset.classes}\n",
|
||||||
|
"\n",
|
||||||
|
"with torch.no_grad():\n",
|
||||||
|
" for data in test_loader:\n",
|
||||||
|
" images, labels = data\n",
|
||||||
|
" images, labels = images.to(device), labels.to(device)\n",
|
||||||
|
" outputs = model(images)\n",
|
||||||
|
" _, predictions = torch.max(outputs, 1)\n",
|
||||||
|
" for label, prediction in zip(labels, predictions):\n",
|
||||||
|
" if label == prediction:\n",
|
||||||
|
" correct_pred[dataset.classes[label]] += 1\n",
|
||||||
|
" total_pred[dataset.classes[label]] += 1\n",
|
||||||
|
"\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:10s} is {accuracy:.1f}%')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": ".venv",
|
||||||
|
"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.15"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
Reference in new issue
Block a user