{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":3649,"databundleVersionId":46718,"sourceType":"competition"}],"dockerImageVersionId":31011,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision\nfrom torchvision.transforms import v2\nimport matplotlib.pyplot as plt","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-04-15T02:46:16.552658Z","iopub.execute_input":"2025-04-15T02:46:16.552911Z","iopub.status.idle":"2025-04-15T02:46:26.959875Z","shell.execute_reply.started":"2025-04-15T02:46:16.552885Z","shell.execute_reply":"2025-04-15T02:46:26.959262Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T02:46:26.960506Z","iopub.execute_input":"2025-04-15T02:46:26.960839Z","iopub.status.idle":"2025-04-15T02:46:27.026180Z","shell.execute_reply.started":"2025-04-15T02:46:26.960820Z","shell.execute_reply":"2025-04-15T02:46:27.025601Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_transform = v2.Compose([\n    v2.ToImage(), \n    v2.ToDtype(torch.float32, scale=True),  \n    v2.RandomHorizontalFlip(),\n    v2.RandomRotation(20),\n    v2.RandomCrop(32, padding=4),  \n    v2.Normalize(mean=[0.485, 0.456, 0.406],\n                 std=[0.229, 0.224, 0.225])  \n])\n\ndev_transform = v2.Compose([\n    v2.ToImage(),\n    v2.ToDtype(torch.float32, scale=True),\n    v2.RandomHorizontalFlip(),\n    v2.RandomRotation(20),\n    v2.RandomCrop(32, padding=4),\n    v2.Normalize(mean=[0.485, 0.456, 0.406],\n                 std=[0.229, 0.224, 0.225])  \n])\n\ntest_transform = v2.Compose([\n    v2.ToImage(), \n    v2.ToDtype(torch.float32, scale=True),    \n    v2.Normalize(mean=[0.485, 0.456, 0.406],\n                 std=[0.229, 0.224, 0.225])  \n])\n\ntrain_datasets = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=train_transform)\ndev_datasets = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=dev_transform)\ntest_datasets = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=test_transform)\ntrain_loader = torch.utils.data.DataLoader(train_datasets, batch_size=256, shuffle=True)\ndev_loader = torch.utils.data.DataLoader(dev_datasets, batch_size=256, shuffle=True)\ntest_loader = torch.utils.data.DataLoader(test_datasets, batch_size=256, shuffle=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T02:46:27.028471Z","iopub.execute_input":"2025-04-15T02:46:27.029087Z","iopub.status.idle":"2025-04-15T02:46:47.756684Z","shell.execute_reply.started":"2025-04-15T02:46:27.029053Z","shell.execute_reply":"2025-04-15T02:46:47.756121Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"classes = train_datasets.classes\ntrain_datasets.classes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T02:46:47.757326Z","iopub.execute_input":"2025-04-15T02:46:47.757522Z","iopub.status.idle":"2025-04-15T02:46:47.763328Z","shell.execute_reply.started":"2025-04-15T02:46:47.757505Z","shell.execute_reply":"2025-04-15T02:46:47.762791Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\nclass Block(nn.Module):\n    def __init__(self, in_channels, out_channels, identity_downsample=None, stride=1):\n        super().__init__()\n        self.expansion = 4\n        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=1, padding=0)\n        self.bn1 = nn.BatchNorm2d(out_channels)\n\n        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=stride, padding=1)\n        self.bn2 = nn.BatchNorm2d(out_channels)\n\n        self.conv3 = nn.Conv2d(out_channels, out_channels * self.expansion, kernel_size=1, stride=1, padding=0)\n        self.bn3 = nn.BatchNorm2d(out_channels * self.expansion)\n\n        self.relu = nn.ReLU()\n        self.identity_downsample = identity_downsample\n\n    def forward(self, x):\n        identity = x\n\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = self.relu(x)\n\n        x = self.conv2(x)\n        x = self.bn2(x)\n        x = self.relu(x)\n\n        x = self.conv3(x)\n        x = self.bn3(x)\n\n        if self.identity_downsample is not None:\n            identity = self.identity_downsample(identity)\n\n        x += identity\n        x = self.relu(x)\n        return x\n\n\nclass ResNet(nn.Module):\n    def __init__(self, block, layers, image_channels, num_classes):\n        super().__init__()\n        self.in_channels = 64\n\n        self.conv1 = nn.Conv2d(image_channels, 64, kernel_size=3, stride=1, padding=1)\n        self.bn1 = nn.BatchNorm2d(64)\n        self.relu = nn.ReLU()\n\n        self.maxpool = nn.Identity()\n\n        self.layer1 = self._make_layer(block, layers[0], out_channels=64, stride=1)\n        self.layer2 = self._make_layer(block, layers[1], out_channels=128, stride=2)\n        self.layer3 = self._make_layer(block, layers[2], out_channels=256, stride=2)\n        self.layer4 = self._make_layer(block, layers[3], out_channels=512, stride=2)\n\n        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n        self.fc = nn.Linear(512 * 4, num_classes)\n\n    def forward(self, x):\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = self.relu(x)\n        x = self.maxpool(x)\n\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n\n        x = self.avgpool(x)\n        x = x.reshape(x.shape[0], -1)\n        x = self.fc(x)\n        return x\n\n    def _make_layer(self, block, num_res_blocks, out_channels, stride):\n        identity_downsample = None\n        layers = []\n\n        if stride != 1 or self.in_channels != out_channels * 4:\n            identity_downsample = nn.Sequential(\n                nn.Conv2d(self.in_channels, out_channels * 4, kernel_size=1, stride=stride),\n                nn.BatchNorm2d(out_channels * 4)\n            )\n\n        layers.append(block(self.in_channels, out_channels, identity_downsample, stride))\n        self.in_channels = out_channels * 4\n\n        for _ in range(num_res_blocks - 1):\n            layers.append(block(self.in_channels, out_channels))\n\n        return nn.Sequential(*layers)\n\n\ndef ResNet50(img_channels=3, num_classes=10):\n    return ResNet(Block, [3, 4, 6, 3], img_channels, num_classes)\n\nmodel = ResNet50().to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T02:46:47.763946Z","iopub.execute_input":"2025-04-15T02:46:47.764141Z","iopub.status.idle":"2025-04-15T02:46:48.219889Z","shell.execute_reply.started":"2025-04-15T02:46:47.764124Z","shell.execute_reply":"2025-04-15T02:46:48.219313Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Optimizer\nlr = 0.001\nepochs = 50\ncriterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.AdamW(model.parameters(), lr=lr, weight_decay= 0.01)\n\n\nbest_accuracy = 0.0\npatience = 10\nepochs_no_improve = 0\nbest_model_path = \"best_model.pt\"\n\n#Training\nn_total_steps = len(train_loader)\nfor epoch in range(epochs):\n    running_loss = 0.0\n    model.train()\n    for i, (images, labels) in enumerate(train_loader):\n        images = images.to(device)\n        labels = labels.to(device)\n\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n        running_loss += loss.item()\n\n    print(f\"Epoch [{epoch+1}/{epochs}], Loss: {running_loss/len(train_loader):.4f}\")\n\n    # Evaluate on dev set\n    model.eval()\n    n_correct = 0\n    n_samples = 0\n    with torch.no_grad():\n        for images, labels in dev_loader:\n            images = images.to(device)\n            labels = labels.to(device)\n            outputs = model(images)\n            _, predicted = torch.max(outputs, 1)\n            n_correct += (predicted == labels).sum().item()\n            n_samples += labels.size(0)\n\n    dev_acc = 100.0 * n_correct / n_samples\n    print(f\"Accuracy on Dev set: {dev_acc:.2f}%\")\n\n    # Early stopping check\n    if dev_acc > best_accuracy:\n        best_accuracy = dev_acc\n        epochs_no_improve = 0\n        torch.save(model.state_dict(), best_model_path)\n    else:\n        epochs_no_improve += 1\n        \n    if epochs_no_improve >= patience:\n        print(\"Early stopping\")\n        break\n\nprint(\"Training done\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-15T02:46:48.220527Z","iopub.execute_input":"2025-04-15T02:46:48.220755Z","execution_failed":"2025-04-15T05:24:03.281Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Testing\nwith torch.no_grad():\n    n_correct = 0\n    n_samples = 0\n    n_class_correct = [0 for _ in range(10)]\n    n_class_samples = [0 for _ in range(10)]\n    \n    for images, labels in test_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n        outputs = model(images)\n\n        _, predicted = torch.max(outputs, 1)\n        n_samples += labels.size(0)\n        n_correct += (predicted == labels).sum().item()\n\n        for i in range(labels.size(0)):\n            label = labels[i]\n            pred = predicted[i]\n            if label == pred:\n                n_class_correct[label] += 1\n            n_class_samples[label] += 1\n\n    acc = 100.0 * n_correct / n_samples\n    print(f'Accuracy of the network: {acc:.2f}%')\n\n    for i in range(10):\n        acc = 100.0 * n_class_correct[i] / n_class_samples[i]\n        print(f'Accuracy of {classes[i]}: {acc:.2f}%')","metadata":{"trusted":true,"execution":{"execution_failed":"2025-04-15T05:24:03.281Z"}},"outputs":[],"execution_count":null}]}