{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":3649,"databundleVersionId":46718,"isSourceIdPinned":false}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-04-02T10:49:53.370387Z","iopub.execute_input":"2026-04-02T10:49:53.370685Z","iopub.status.idle":"2026-04-02T10:49:53.377409Z","shell.execute_reply.started":"2026-04-02T10:49:53.370657Z","shell.execute_reply":"2026-04-02T10:49:53.376697Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#1. Understanding CIFAR-10\n\nThe dataset consists of **60,000 tiny images** categorized into **10 mutually exclusive classes**:\n\n- airplane  \n- automobile  \n- bird  \n- cat  \n- deer  \n- dog  \n- frog  \n- horse  \n- ship  \n- truck  \n\n---\n\n## Dataset Details\n\n- **Image Size:** `32 × 32` pixels  \n- **Channels:** `3` (Red, Green, Blue)  \n- **Train/Test Split:**\n  - Training Images: **50,000**\n  - Testing Images: **10,000**\n\n---\n\n## The Practical Reality\n\nThe `32 × 32` resolution is **extremely low**.\n\n- To humans → images may look like **blurry blobs**\n- To CNNs → limited spatial information\n\n---\n\n## Key Limitation\n\nYou **cannot**:\n\n- Use too many **Pooling layers**\n- Use large **Strides** early in the network\n\n---\n\n## Why?\n\nBecause:\n\n> You may lose all spatial information before the network learns meaningful features like:\n>\n> - edges  \n> - wings  \n> - wheels  \n\n---\n\n## ✅ Key Insight\n\nDesign CNN architectures carefully for CIFAR-10:\n\n- Preserve spatial resolution in early layers  \n- Avoid aggressive downsampling  \n- Extract features gradually  \n","metadata":{}},{"cell_type":"code","source":"import os","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-02T10:49:53.378909Z","iopub.execute_input":"2026-04-02T10:49:53.379169Z","iopub.status.idle":"2026-04-02T10:49:53.388600Z","shell.execute_reply.started":"2026-04-02T10:49:53.379144Z","shell.execute_reply":"2026-04-02T10:49:53.387829Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!apt-get install p7zip-full -y\n!7z x /kaggle/input/competitions/cifar-10/train.7z -o./","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-02T10:49:53.389517Z","iopub.execute_input":"2026-04-02T10:49:53.389758Z","iopub.status.idle":"2026-04-02T10:50:56.325752Z","shell.execute_reply.started":"2026-04-02T10:49:53.389736Z","shell.execute_reply":"2026-04-02T10:50:56.324696Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nprint(len(os.listdir('./train'))) \n# Should output 50000","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-02T10:50:56.328381Z","iopub.execute_input":"2026-04-02T10:50:56.328694Z","iopub.status.idle":"2026-04-02T10:50:56.364136Z","shell.execute_reply.started":"2026-04-02T10:50:56.328657Z","shell.execute_reply":"2026-04-02T10:50:56.363283Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport pandas as pd\nimport os\nimport glob\nfrom PIL import Image\nfrom torch.utils.data import Dataset, DataLoader, random_split\nimport torchvision.transforms as transforms\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-02T10:50:56.364995Z","iopub.execute_input":"2026-04-02T10:50:56.365241Z","iopub.status.idle":"2026-04-02T10:50:56.370427Z","shell.execute_reply.started":"2026-04-02T10:50:56.365218Z","shell.execute_reply":"2026-04-02T10:50:56.369422Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\nclass CIFAR10Kaggle(Dataset):\n    def __init__(self, csv_file, img_dir, transform=None):\n        self.df = pd.read_csv(csv_file)\n        self.img_dir = img_dir\n        self.transform = transform\n        self.label_mapping = {\n            'airplane':0, 'automobile':1, 'bird':2, 'cat':3, 'deer':4,\n            'dog':5, 'frog':6, 'horse':7, 'ship':8, 'truck':9\n        }\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        img_id = str(self.df.iloc[idx, 0])\n        img_name = os.path.join(self.img_dir, img_id + \".png\")\n        image = Image.open(img_name)\n        label = self.label_mapping[self.df.iloc[idx, 1]]\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n\n\ntrain_csv = '/kaggle/input/competitions/cifar-10/trainLabels.csv'\ntrain_dir = './train' \ntransform = transforms.Compose([\n    transforms.Resize((32, 32)),\n    transforms.ToTensor(),\n    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n])\n\n\nfull_dataset = CIFAR10Kaggle(csv_file=train_csv, img_dir=train_dir, transform=transform)\ntrain_size = 45000\nval_size = 5000\ntrain_data, val_data = random_split(full_dataset, [train_size, val_size])\n\ntrain_loader = DataLoader(train_data, batch_size=64, shuffle=True)\nval_loader = DataLoader(val_data, batch_size=64, shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-02T10:50:56.371699Z","iopub.execute_input":"2026-04-02T10:50:56.372015Z","iopub.status.idle":"2026-04-02T10:50:56.416811Z","shell.execute_reply.started":"2026-04-02T10:50:56.371974Z","shell.execute_reply":"2026-04-02T10:50:56.415993Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Get one batch of data\nimages, labels = next(iter(train_loader))\n\nprint(f\"Image batch shape: {images.shape}\") # Should be [64, 3, 32, 32]\nprint(f\"Label batch shape: {labels.shape}\") # Should be [64]\nprint(f\"First label ID: {labels[0].item()}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-02T10:50:56.418003Z","iopub.execute_input":"2026-04-02T10:50:56.418398Z","iopub.status.idle":"2026-04-02T10:50:56.468795Z","shell.execute_reply.started":"2026-04-02T10:50:56.418358Z","shell.execute_reply":"2026-04-02T10:50:56.467917Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class KaggleCNN(nn.Module):\n    def __init__(self):\n        super(KaggleCNN, self).__init__()\n        self.conv1 = nn.Conv2d(3, 32, 3, padding=1)\n        self.bn1 = nn.BatchNorm2d(32)\n        self.conv2 = nn.Conv2d(32, 32, 3, padding=1)\n        self.bn2 = nn.BatchNorm2d(32)\n        self.conv3 = nn.Conv2d(32, 64, 3, padding=1)\n        self.bn3 = nn.BatchNorm2d(64)\n        self.pool = nn.MaxPool2d(2, 2)\n        self.dropout = nn.Dropout(0.3)\n        self.fc1 = nn.Linear(64 * 8 * 8, 128)\n        self.fc2 = nn.Linear(128, 10)\n\n    def forward(self, x):\n        x = F.relu(self.bn1(self.conv1(x)))\n        x = self.pool(F.relu(self.bn2(self.conv2(x))))\n        x = self.dropout(x)\n        x = self.pool(F.relu(self.bn3(self.conv3(x))))\n        x = self.dropout(x)\n        x = x.view(-1, 64 * 8 * 8)\n        x = F.relu(self.fc1(x))\n        x = self.fc2(x)\n        return x\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = KaggleCNN().to(device)\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.parameters(), lr=0.001)\n\n# Training & Accuracy Loop\nfor epoch in range(10):\n    model.train()\n    running_loss = 0.0\n    for i, (images, labels) in enumerate(train_loader):\n        images, labels = images.to(device), labels.to(device)\n        \n        optimizer.zero_grad()\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n        \n        running_loss += loss.item()\n        if i % 200 == 199:\n            print(f'Epoch {epoch+1}, Batch {i+1}: Loss {running_loss / 200:.4f}')\n            running_loss = 0.0\n\n    #CALCULATE ACCURACY\n    model.eval()\n    correct = 0\n    total = 0\n    with torch.no_grad():\n        for images, labels in val_loader:\n            images, labels = images.to(device), labels.to(device)\n            outputs = model(images)\n            _, predicted = torch.max(outputs.data, 1)\n            total += labels.size(0)\n            correct += (predicted == labels).sum().item()\n    \n    print(f\"--- Epoch {epoch+1} | Validation Accuracy: {100 * correct / total:.2f}% ---\")\n\ntorch.save(model.state_dict(), \"model.pth\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-02T10:50:56.469862Z","iopub.execute_input":"2026-04-02T10:50:56.470172Z","iopub.status.idle":"2026-04-02T10:56:52.854706Z","shell.execute_reply.started":"2026-04-02T10:50:56.470123Z","shell.execute_reply":"2026-04-02T10:56:52.853773Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create inverse mapping for labels\ninv_map = {v: k for k, v in full_dataset.label_mapping.items()}\n\n# Get test files\ntest_dir = './test'\ntest_files = glob.glob(os.path.join(test_dir, \"*.png\"))\ntest_files.sort(key=lambda x: int(os.path.basename(x).split('.')[0]))\n\nmodel.eval()\nresults = []\n\nprint(\"Generating submission.csv...\")\nwith torch.no_grad():\n    for path in test_files:\n        img_id = os.path.basename(path).split('.')[0]\n        img = Image.open(path)\n        img = transform(img).unsqueeze(0).to(device) # Batch of 1\n        \n        output = model(img)\n        _, pred = torch.max(output, 1)\n        results.append([img_id, inv_map[pred.item()]])\n\n# Save to CSV\ndf_sub = pd.DataFrame(results, columns=['id', 'label'])\ndf_sub.to_csv('submission.csv', index=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-02T10:56:52.855911Z","iopub.execute_input":"2026-04-02T10:56:52.856542Z","iopub.status.idle":"2026-04-02T10:56:52.866117Z","shell.execute_reply.started":"2026-04-02T10:56:52.856514Z","shell.execute_reply":"2026-04-02T10:56:52.865242Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}