{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":3649,"databundleVersionId":46718,"sourceType":"competition"},{"sourceId":13125412,"sourceType":"datasetVersion","datasetId":8314678}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# =====================================================\n# CIFAR-10 Competition - SimpleCNN (Random Init)\n# Train on official CIFAR-10 (torchvision)\n# Predict on uploaded Kaggle test folder (already extracted)\n# =====================================================\n\nimport os, glob\nimport pandas as pd\nfrom PIL import Image\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm\n\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader, Dataset\nimport torchvision\nimport torchvision.transforms as transforms\n\n# ===================\n# 1. Settings\n# ===================\nbatch_size = 128\nnum_epochs = 50   # increase to 100+ for higher accuracy\nlearning_rate = 0.001\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(\"Using device:\", device)\n\n# ===================\n# 2. Compute CIFAR-10 Mean and Std\n# ===================\nraw_trainset = torchvision.datasets.CIFAR10(\n    root='./data', train=True, download=True,\n    transform=transforms.ToTensor()\n)\n\nraw_loader = DataLoader(raw_trainset, batch_size=500, shuffle=False, num_workers=2)\n\nmean = 0.0\nstd = 0.0\nnb_samples = 0\nfor images, _ in raw_loader:\n    batch_samples = images.size(0)\n    images = images.view(batch_samples, images.size(1), -1)\n    mean += images.mean(2).sum(0)\n    std += images.std(2).sum(0)\n    nb_samples += batch_samples\n\nmean /= nb_samples\nstd /= nb_samples\nprint(\"Calculated mean:\", mean)\nprint(\"Calculated std:\", std)\n\n# ===================\n# 3. Define Transforms with Computed Mean/Std\n# ===================\ntransform_train = transforms.Compose([\n    transforms.RandomCrop(32, padding=4),\n    transforms.RandomHorizontalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize(mean, std),\n])\n\ntransform_test = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Normalize(mean, std),\n])\n\n# ===================\n# 4. Official CIFAR-10 Train + Val datasets\n# ===================\ntrainset = torchvision.datasets.CIFAR10(root='./data', train=True,\n                                        download=True, transform=transform_train)\ntrainloader = DataLoader(trainset, batch_size=batch_size,\n                         shuffle=True, num_workers=2)\n\nvalset = torchvision.datasets.CIFAR10(root='./data', train=False,\n                                      download=True, transform=transform_test)\nvalloader = DataLoader(valset, batch_size=batch_size,\n                       shuffle=False, num_workers=2)\n\nclass_names = trainset.classes\nprint(\"Classes:\", class_names)\n\n# ===================\n# 5. Define Simple CNN\n# ===================\nclass SimpleCNN(nn.Module):\n    def __init__(self, num_classes=10):\n        super(SimpleCNN, self).__init__()\n        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)\n        self.bn1 = nn.BatchNorm2d(32)\n        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)\n        self.bn2 = nn.BatchNorm2d(64)\n        self.pool = nn.MaxPool2d(2, 2)\n\n        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)\n        self.bn3 = nn.BatchNorm2d(128)\n        self.conv4 = nn.Conv2d(128, 256, kernel_size=3, padding=1)\n        self.bn4 = nn.BatchNorm2d(256)\n\n        self.fc1 = nn.Linear(256*4*4, 512)\n        self.fc2 = nn.Linear(512, num_classes)\n        self.dropout = nn.Dropout(0.3)\n\n    def forward(self, x):\n        x = self.pool(F.relu(self.bn1(self.conv1(x))))\n        x = self.pool(F.relu(self.bn2(self.conv2(x))))\n        x = F.relu(self.bn3(self.conv3(x)))\n        x = self.pool(F.relu(self.bn4(self.conv4(x))))\n        x = x.view(x.size(0), -1)\n        x = self.dropout(F.relu(self.fc1(x)))\n        x = self.fc2(x)\n        return x\n\nmodel = SimpleCNN().to(device)\n\n# ===================\n# 6. Loss + Optimizer\n# ===================\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=learning_rate, weight_decay=1e-4)\nscheduler = optim.lr_scheduler.StepLR(optimizer, step_size=20, gamma=0.5)\n\n# ===================\n# 7. Training & Validation\n# ===================\ndef train_one_epoch():\n    model.train()\n    running_loss, correct, total = 0, 0, 0\n    for inputs, targets in trainloader:\n        inputs, targets = inputs.to(device), targets.to(device)\n        optimizer.zero_grad()\n        outputs = model(inputs)\n        loss = criterion(outputs, targets)\n        loss.backward()\n        optimizer.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    return running_loss/len(trainloader), 100.*correct/total\n\ndef validate():\n    model.eval()\n    correct, total = 0, 0\n    with torch.no_grad():\n        for inputs, targets in valloader:\n            inputs, targets = inputs.to(device), targets.to(device)\n            outputs = model(inputs)\n            _, predicted = outputs.max(1)\n            total += targets.size(0)\n            correct += predicted.eq(targets).sum().item()\n    return 100.*correct/total\n\nfor epoch in range(num_epochs):\n    train_loss, train_acc = train_one_epoch()\n    val_acc = validate()\n    scheduler.step()\n    print(f\"Epoch {epoch+1}/{num_epochs} | \"\n          f\"Loss: {train_loss:.3f} | Train Acc: {train_acc:.2f}% | \"\n          f\"Val Acc (Expected Kaggle Score): {val_acc:.2f}%\")\n\ntorch.save(model.state_dict(), \"cifar10_simplecnn.pth\")\n\n# ===================\n# 8. Kaggle Test Dataset (already extracted and uploaded)\n# ===================\ntest_dir = \"/kaggle/input/cifar-test-dataset/test\"\nprint(\"Found test images:\", len(glob.glob(os.path.join(test_dir, '*.png'))))\n\nclass TestDataset(Dataset):\n    def __init__(self, files, transform=None):\n        self.files = files\n        self.transform = transform\n    def __len__(self):\n        return len(self.files)\n    def __getitem__(self, idx):\n        img_path = self.files[idx]\n        image = Image.open(img_path)\n        if self.transform:\n            image = self.transform(image)\n        return image, os.path.splitext(os.path.basename(img_path))[0]\n\ntest_files = sorted(glob.glob(os.path.join(test_dir, '*.png')))\ntest_dataset = TestDataset(test_files, transform=transform_test)\ntest_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)\n\n# ===================\n# 9. Run predictions on Kaggle test set\n# ===================\nmodel.eval()\nall_preds, all_ids = [], []\nwith torch.no_grad():\n    for inputs, ids in tqdm(test_loader, desc=\"Predicting\"):\n        inputs = inputs.to(device)\n        outputs = model(inputs)\n        _, predicted = outputs.max(1)\n        all_preds.extend(predicted.cpu().numpy())\n        all_ids.extend(ids)\n\nsubmission = pd.DataFrame({\n    \"id\": all_ids,\n    \"label\": [class_names[p] for p in all_preds]\n})\nsubmission.to_csv(\"/kaggle/working/submission.csv\", index=False)\nprint(\"✅ Submission file saved: /kaggle/working/submission.csv\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-09-21T17:45:53.215744Z","iopub.execute_input":"2025-09-21T17:45:53.216253Z","iopub.status.idle":"2025-09-21T18:11:46.920018Z","shell.execute_reply.started":"2025-09-21T17:45:53.216215Z","shell.execute_reply":"2025-09-21T18:11:46.919301Z"}},"outputs":[],"execution_count":null}]}