{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","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":30787,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# import the Libraries ","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.optim.lr_scheduler as lr_scheduler\nimport torchvision\nimport torchvision.transforms as transforms\nfrom torch.utils.data import DataLoader\nfrom tqdm import tqdm\n# Install Albumentations library for CutOut\n#!pip install albumentations\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nfrom torchvision.datasets import CIFAR10\nimport numpy as np \nimport torch.nn.functional as F","metadata":{"execution":{"iopub.status.busy":"2024-10-11T20:29:51.876544Z","iopub.execute_input":"2024-10-11T20:29:51.877493Z","iopub.status.idle":"2024-10-11T20:29:51.883885Z","shell.execute_reply.started":"2024-10-11T20:29:51.877438Z","shell.execute_reply":"2024-10-11T20:29:51.882724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Albumentations for cutout augmentation","metadata":{}},{"cell_type":"code","source":"pip install -U albumentations","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Resnet 34 Configuration ","metadata":{}},{"cell_type":"code","source":"# Custom transform with CoarseDropout (equivalent to CutOut)\nclass AlbumentationsTransform:\n    def __init__(self):\n        self.transform = A.Compose([\n            A.HorizontalFlip(p=0.5),\n            A.ShiftScaleRotate(shift_limit=0.1, scale_limit=0.1, rotate_limit=15, p=0.5),\n            A.CoarseDropout(max_holes=1, max_height=8, max_width=8, min_holes=1, fill_value=0, p=0.5),\n            A.Normalize(mean=(0.4914, 0.4822, 0.4465), std=(0.2023, 0.1994, 0.2010)),\n            ToTensorV2(),\n        ])\n    \n    def __call__(self, img):\n        return self.transform(image=np.array(img))['image']\n\n# Loading CIFAR-10 dataset with Albumentations\ntrain_transform = AlbumentationsTransform()\n\ntrain_dataset = CIFAR10(root='./data', train=True, download=True, transform=train_transform)\ntest_dataset = CIFAR10(root='./data', train=False, download=True, transform=transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),\n]))\n\ntrain_loader = DataLoader(train_dataset, batch_size=128, shuffle=True, num_workers=2)\ntest_loader = DataLoader(test_dataset, batch_size=100, shuffle=False, num_workers=2)\n\n# ResNet model (ResNet-34) for CIFAR-10\nclass BasicBlock(nn.Module):\n    expansion = 1\n\n    def __init__(self, in_planes, planes, stride=1):\n        super(BasicBlock, self).__init__()\n        self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)\n        self.bn1 = nn.BatchNorm2d(planes)\n        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)\n        self.bn2 = nn.BatchNorm2d(planes)\n\n        self.shortcut = nn.Sequential()\n        if stride != 1 or in_planes != self.expansion * planes:\n            self.shortcut = nn.Sequential(\n                nn.Conv2d(in_planes, self.expansion * planes, kernel_size=1, stride=stride, bias=False),\n                nn.BatchNorm2d(self.expansion * planes)\n            )\n\n    def forward(self, x):\n        out = torch.relu(self.bn1(self.conv1(x)))\n        out = self.bn2(self.conv2(out))\n        out += self.shortcut(x)\n        out = torch.relu(out)\n        return out\n\nclass ResNet(nn.Module):\n    def __init__(self, block, num_blocks, num_classes=10):\n        super(ResNet, self).__init__()\n        self.in_planes = 64\n\n        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)\n        self.bn1 = nn.BatchNorm2d(64)\n        self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)\n        self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)\n        self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)\n        self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)\n        self.linear = nn.Linear(512 * block.expansion, num_classes)\n\n    def _make_layer(self, block, planes, num_blocks, stride):\n        strides = [stride] + [1] * (num_blocks - 1)\n        layers = []\n        for stride in strides:\n            layers.append(block(self.in_planes, planes, stride))\n            self.in_planes = planes * block.expansion\n        return nn.Sequential(*layers)\n\n    def forward(self, x):\n        out = torch.relu(self.bn1(self.conv1(x)))\n        out = self.layer1(out)\n        out = self.layer2(out)\n        out = self.layer3(out)\n        out = self.layer4(out)\n        out = F.avg_pool2d(out, 4)\n        out = out.view(out.size(0), -1)\n        out = self.linear(out)\n        return out\n\ndef ResNet34():\n    return ResNet(BasicBlock, [3, 4, 6, 3])\n\n# Training parameters\ndevice = 'cuda' if torch.cuda.is_available() else 'cpu'\nmodel = ResNet34().to(device)\n\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.AdamW(model.parameters(), lr=0.001, weight_decay=1e-4)\n\n# Cosine annealing learning rate scheduler with warmup\n#scheduler = lr_scheduler.OneCycleLR(optimizer, max_lr=0.01, steps_per_epoch=len(train_loader), epochs=20)\nnum_epochs = 80\nscheduler = lr_scheduler.OneCycleLR(\n    optimizer, \n    max_lr=0.01, \n    epochs=num_epochs, \n    steps_per_epoch=len(train_loader), \n    pct_start=0.3,  # Fraction of the cycle spent increasing the learning rate\n    anneal_strategy='cos',  # Cosine annealing strategy\n    cycle_momentum=False  # Set to False since we are using AdamW\n)\n\n# Training function\ndef train(epoch):\n    model.train()\n    running_loss = 0.0\n    correct = 0\n    total = 0\n\n    for batch_idx, (inputs, targets) in enumerate(tqdm(train_loader, desc=f'Epoch {epoch}')):\n        inputs, targets = inputs.to(device), targets.to(device)\n\n        optimizer.zero_grad()\n        outputs = model(inputs)\n        loss = criterion(outputs, targets)\n        loss.backward()\n        optimizer.step()\n        scheduler.step()\n\n        running_loss += loss.item()\n        _, predicted = outputs.max(1)\n        total += targets.size(0)\n        correct += predicted.eq(targets).sum().item()\n\n    print(f'Train Loss: {running_loss / len(train_loader):.3f} | Train Acc: {100. * correct / total:.2f}%')\n\n# Test function\ndef test(epoch):\n    model.eval()\n    test_loss = 0\n    correct = 0\n    total = 0\n    with torch.no_grad():\n        for batch_idx, (inputs, targets) in enumerate(test_loader):\n            inputs, targets = inputs.to(device), targets.to(device)\n            outputs = model(inputs)\n            loss = criterion(outputs, targets)\n\n            test_loss += loss.item()\n            _, predicted = outputs.max(1)\n            total += targets.size(0)\n            correct += predicted.eq(targets).sum().item()\n\n    print(f'Test Loss: {test_loss / len(test_loader):.3f} | Test Acc: {100. * correct / total:.2f}%')\n\n# Training loop\nnum_epochs = 80\nfor epoch in range(1, num_epochs + 1):\n    train(epoch)\n    test(epoch)\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-10-11T20:30:14.194758Z","iopub.execute_input":"2024-10-11T20:30:14.195243Z","iopub.status.idle":"2024-10-11T23:48:34.514130Z","shell.execute_reply.started":"2024-10-11T20:30:14.195199Z","shell.execute_reply":"2024-10-11T23:48:34.512883Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# save the model","metadata":{}},{"cell_type":"code","source":"torch.save(model.state_dict(), '/kaggle/working/resnet34_cifar10_94%_test2_80.pth')","metadata":{"execution":{"iopub.status.busy":"2024-10-10T22:11:03.508819Z","iopub.execute_input":"2024-10-10T22:11:03.509239Z","iopub.status.idle":"2024-10-10T22:11:03.698911Z","shell.execute_reply.started":"2024-10-10T22:11:03.509198Z","shell.execute_reply":"2024-10-10T22:11:03.698096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load the saved model for prediction","metadata":{}},{"cell_type":"code","source":"# Create the model architecture (same as the one used for training)\nmodel = ResNet34().to(device)\n\n# Load the saved model weights\nmodel.load_state_dict(torch.load('/kaggle/working/resnet34_cifar10_94%_test1_80.pth'))\n\n# Ensure the model is in evaluation mode (not training)\nmodel.eval()\n","metadata":{"execution":{"iopub.status.busy":"2024-10-11T18:06:55.201546Z","iopub.execute_input":"2024-10-11T18:06:55.202491Z","iopub.status.idle":"2024-10-11T18:06:55.464416Z","shell.execute_reply.started":"2024-10-11T18:06:55.202450Z","shell.execute_reply":"2024-10-11T18:06:55.463258Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pip install py7zr","metadata":{"execution":{"iopub.status.busy":"2024-10-11T18:07:04.539237Z","iopub.execute_input":"2024-10-11T18:07:04.539685Z","iopub.status.idle":"2024-10-11T18:07:19.619499Z","shell.execute_reply.started":"2024-10-11T18:07:04.539619Z","shell.execute_reply":"2024-10-11T18:07:19.618311Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Extract the testset","metadata":{}},{"cell_type":"code","source":"import py7zr\nimport os\n\n# Path to the test.7z file\nseven_z_file = '/kaggle/input/cifar-10/test.7z'\n\n# Destination folder to extract\noutput_folder = '/kaggle/working/testset' \n\n# Ensure the output directory exists\nif not os.path.exists(output_folder):\n    os.makedirs(output_folder)\n\n# Extract the 7z file\nwith py7zr.SevenZipFile(seven_z_file, mode='r') as archive:\n    archive.extractall(path=output_folder)\n\nprint(f'Extracted test.7z to {output_folder}')\n","metadata":{"execution":{"iopub.status.busy":"2024-10-11T18:07:26.012756Z","iopub.execute_input":"2024-10-11T18:07:26.013530Z","iopub.status.idle":"2024-10-11T18:09:56.542424Z","shell.execute_reply.started":"2024-10-11T18:07:26.013492Z","shell.execute_reply":"2024-10-11T18:09:56.541418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Cifar Classes","metadata":{}},{"cell_type":"code","source":"# CIFAR-10 class names\nclass_names = [\n    'airplane', 'automobile', 'bird', 'cat', 'deer', \n    'dog', 'frog', 'horse', 'ship', 'truck'\n]","metadata":{"execution":{"iopub.status.busy":"2024-10-11T18:10:34.917788Z","iopub.execute_input":"2024-10-11T18:10:34.918423Z","iopub.status.idle":"2024-10-11T18:10:34.922936Z","shell.execute_reply.started":"2024-10-11T18:10:34.918384Z","shell.execute_reply":"2024-10-11T18:10:34.921961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load the Kaggle testset for CiFar10","metadata":{}},{"cell_type":"code","source":"import os\nfrom PIL import Image\nimport torch\nfrom torch.utils.data import Dataset\nimport torchvision.transforms as transforms\n\n# Custom Dataset class for test data\nclass CIFAR10TestDataset(Dataset):\n    def __init__(self, root_dir, transform=None):\n        self.root_dir = root_dir\n        self.transform = transform\n        self.image_files = os.listdir(root_dir)\n\n    def __len__(self):\n        return len(self.image_files)\n\n    def __getitem__(self, idx):\n        img_name = os.path.join(self.root_dir, self.image_files[idx])\n        image = Image.open(img_name).convert('RGB')\n\n        if self.transform:\n            image = self.transform(image)\n\n        return image, self.image_files[idx]  # Return image and the filename (can be used as ID)\n\n# Transforms for the test data\ntransform = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))  # CIFAR-10 normalization\n])\n\n# Create the dataset\ntest_dataset = CIFAR10TestDataset(root_dir='/kaggle/working/testset/test', transform=transform)\n\n# Create a DataLoader for the test dataset\ntest_loader = DataLoader(test_dataset, batch_size=64, shuffle=False, num_workers=2)\n","metadata":{"execution":{"iopub.status.busy":"2024-10-11T18:11:53.392769Z","iopub.execute_input":"2024-10-11T18:11:53.393200Z","iopub.status.idle":"2024-10-11T18:11:53.566261Z","shell.execute_reply.started":"2024-10-11T18:11:53.393151Z","shell.execute_reply":"2024-10-11T18:11:53.565462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prediction","metadata":{}},{"cell_type":"code","source":"# List to store the predictions for saving as CSV\npredictions = []\n\n# Predict and store results\nwith torch.no_grad():\n    for inputs, image_filenames in test_loader:\n        inputs = inputs.to(device)\n        \n        # Get model predictions\n        outputs = model(inputs)\n        _, predicted = torch.max(outputs, 1)\n        \n        # Store the image filename (ID) and predicted class\n        for idx in range(predicted.size(0)):\n            classname = class_names[predicted[idx].item()]  # Get the class name\n            image_id = image_filenames[idx].split('.')[0]  # Use the image filename as the ID\n            predictions.append([image_id, classname])\n","metadata":{"execution":{"iopub.status.busy":"2024-10-11T18:12:29.092771Z","iopub.execute_input":"2024-10-11T18:12:29.093186Z","iopub.status.idle":"2024-10-11T18:14:21.415856Z","shell.execute_reply.started":"2024-10-11T18:12:29.093147Z","shell.execute_reply":"2024-10-11T18:14:21.414732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Saving the Result","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n# Convert predictions to a DataFrame\ndf = pd.DataFrame(predictions, columns=['id', 'label'])\n\n# Save the DataFrame to a CSV file\ndf.to_csv('/kaggle/working/submission.csv', index=False)\nprint(f\"Results saved to 'submission.csv'\")","metadata":{"execution":{"iopub.status.busy":"2024-10-11T18:15:04.876095Z","iopub.execute_input":"2024-10-11T18:15:04.876802Z","iopub.status.idle":"2024-10-11T18:15:05.702248Z","shell.execute_reply.started":"2024-10-11T18:15:04.876732Z","shell.execute_reply":"2024-10-11T18:15:05.701095Z"},"trusted":true},"execution_count":null,"outputs":[]}]}