{"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":"gpu","dataSources":[{"sourceId":66610,"databundleVersionId":11526501,"sourceType":"competition"}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader, random_split\nfrom torchvision import datasets, transforms, models\nfrom torchvision.datasets import ImageFolder\nimport os\nimport matplotlib.pyplot as plt\nfrom torchvision.utils import make_grid\nimport urllib.request\nfrom PIL import Image\nfrom pathlib import Path","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:21:14.858432Z","iopub.execute_input":"2025-08-25T17:21:14.859132Z","iopub.status.idle":"2025-08-25T17:21:22.097829Z","shell.execute_reply.started":"2025-08-25T17:21:14.859107Z","shell.execute_reply":"2025-08-25T17:21:22.097223Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dir = '/kaggle/input/garbage-guru-challenge/dataset/train'\ntest_dir = '/kaggle/input/garbage-guru-challenge/dataset/test'\nval_dir = '/kaggle/input/garbage-guru-challenge/dataset/val'\ntorch.manual_seed(42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:21:22.099193Z","iopub.execute_input":"2025-08-25T17:21:22.099562Z","iopub.status.idle":"2025-08-25T17:21:22.110065Z","shell.execute_reply.started":"2025-08-25T17:21:22.099544Z","shell.execute_reply":"2025-08-25T17:21:22.109210Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"transform_train = transforms.Compose([transforms.Resize((256, 256)), transforms.ToTensor()])\ntransform_test = transforms.Compose([transforms.Resize((256, 256)), transforms.ToTensor()])\ntransform_val = transforms.Compose([transforms.Resize((256, 256)), transforms.ToTensor()])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:21:22.110880Z","iopub.execute_input":"2025-08-25T17:21:22.111131Z","iopub.status.idle":"2025-08-25T17:21:22.124365Z","shell.execute_reply.started":"2025-08-25T17:21:22.111112Z","shell.execute_reply":"2025-08-25T17:21:22.123691Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data = datasets.ImageFolder(train_dir, transform=transform_train)\nval_data   = datasets.ImageFolder(val_dir, transform=transform_val)\ntest_data  = datasets.ImageFolder(test_dir, transform=transform_test)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:21:22.125378Z","iopub.execute_input":"2025-08-25T17:21:22.125670Z","iopub.status.idle":"2025-08-25T17:21:39.018996Z","shell.execute_reply.started":"2025-08-25T17:21:22.125653Z","shell.execute_reply":"2025-08-25T17:21:39.018236Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_sample(img, label):\n    print(\"Label:\", train_data.classes[label], \"(Class No: \"+ str(label) + \")\")\n    plt.imshow(img.permute(1, 2, 0))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:24:08.050976Z","iopub.execute_input":"2025-08-25T17:24:08.051248Z","iopub.status.idle":"2025-08-25T17:24:08.055416Z","shell.execute_reply.started":"2025-08-25T17:24:08.051230Z","shell.execute_reply":"2025-08-25T17:24:08.054621Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(len(train_data))\nimg, label = train_data[100]\nshow_sample(img, label)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:24:08.056601Z","iopub.execute_input":"2025-08-25T17:24:08.056816Z","iopub.status.idle":"2025-08-25T17:24:08.348361Z","shell.execute_reply.started":"2025-08-25T17:24:08.056800Z","shell.execute_reply":"2025-08-25T17:24:08.347733Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_loader = DataLoader(train_data, batch_size=16, shuffle=True)\nval_loader   = DataLoader(val_data, batch_size=16, shuffle=False)\ntest_loader  = DataLoader(test_data, batch_size=16, shuffle=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:24:08.349537Z","iopub.execute_input":"2025-08-25T17:24:08.349812Z","iopub.status.idle":"2025-08-25T17:24:08.354343Z","shell.execute_reply.started":"2025-08-25T17:24:08.349790Z","shell.execute_reply":"2025-08-25T17:24:08.353690Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Classes:\", train_data.classes)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:24:08.354969Z","iopub.execute_input":"2025-08-25T17:24:08.355123Z","iopub.status.idle":"2025-08-25T17:24:08.368438Z","shell.execute_reply.started":"2025-08-25T17:24:08.355110Z","shell.execute_reply":"2025-08-25T17:24:08.367791Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def show_batch(dl):\n    for images, labels in dl:\n        fig, ax = plt.subplots(figsize=(12, 6))\n        ax.set_xticks([])\n        ax.set_yticks([])\n        ax.imshow(make_grid(images, nrow = 16).permute(1, 2, 0))\n        break\nshow_batch(train_loader)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:24:08.370175Z","iopub.execute_input":"2025-08-25T17:24:08.370389Z","iopub.status.idle":"2025-08-25T17:24:08.959728Z","shell.execute_reply.started":"2025-08-25T17:24:08.370365Z","shell.execute_reply":"2025-08-25T17:24:08.958975Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\nmodel = models.resnet50(pretrained=True)\n\n# Freeze backbone\nfor param in model.parameters():\n    param.requires_grad = False\n\n# Replace FC head\nnum_ftrs = model.fc.in_features\nmodel.fc = nn.Linear(num_ftrs, len(train_data.classes))\n\nmodel = model.to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:24:08.960405Z","iopub.execute_input":"2025-08-25T17:24:08.960625Z","iopub.status.idle":"2025-08-25T17:24:10.794296Z","shell.execute_reply.started":"2025-08-25T17:24:08.960608Z","shell.execute_reply":"2025-08-25T17:24:10.793734Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model.fc.parameters(), lr=0.0001)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:24:10.794951Z","iopub.execute_input":"2025-08-25T17:24:10.795126Z","iopub.status.idle":"2025-08-25T17:24:10.798996Z","shell.execute_reply.started":"2025-08-25T17:24:10.795112Z","shell.execute_reply":"2025-08-25T17:24:10.798294Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def train_one_epoch(model, dataloader, criterion, optimizer, device):\n    model.train()\n    running_loss, running_corrects = 0.0, 0\n\n    for inputs, labels in dataloader:\n        inputs, labels = inputs.to(device), labels.to(device)\n\n        optimizer.zero_grad()\n        outputs = model(inputs)\n        loss = criterion(outputs, labels)\n        _, preds = torch.max(outputs, 1)\n\n        loss.backward()\n        optimizer.step()\n\n        running_loss += loss.item() * inputs.size(0)\n        running_corrects += torch.sum(preds == labels.data)\n\n    epoch_loss = running_loss / len(dataloader.dataset)\n    epoch_acc = running_corrects.double() / len(dataloader.dataset)\n    return epoch_loss, epoch_acc.item()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:24:10.799561Z","iopub.execute_input":"2025-08-25T17:24:10.799718Z","iopub.status.idle":"2025-08-25T17:24:10.813934Z","shell.execute_reply.started":"2025-08-25T17:24:10.799705Z","shell.execute_reply":"2025-08-25T17:24:10.813412Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def evaluate(model, dataloader, criterion, device):\n    model.eval()\n    running_loss, running_corrects = 0.0, 0\n\n    with torch.no_grad():\n        for inputs, labels in dataloader:\n            inputs, labels = inputs.to(device), labels.to(device)\n            outputs = model(inputs)\n            loss = criterion(outputs, labels)\n            _, preds = torch.max(outputs, 1)\n\n            running_loss += loss.item() * inputs.size(0)\n            running_corrects += torch.sum(preds == labels.data)\n\n    epoch_loss = running_loss / len(dataloader.dataset)\n    epoch_acc = running_corrects.double() / len(dataloader.dataset)\n    return epoch_loss, epoch_acc.item()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:24:10.814853Z","iopub.execute_input":"2025-08-25T17:24:10.815123Z","iopub.status.idle":"2025-08-25T17:24:10.828286Z","shell.execute_reply.started":"2025-08-25T17:24:10.815101Z","shell.execute_reply":"2025-08-25T17:24:10.827627Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def fit(model, train_loader, val_loader, criterion, optimizer, device, num_epochs=10):\n    for epoch in range(num_epochs):\n        train_loss, train_acc = train_one_epoch(model, train_loader, criterion, optimizer, device)\n        val_loss, val_acc = evaluate(model, val_loader, criterion, device)\n\n        print(f\"Epoch {epoch+1}/{num_epochs} \"\n              f\"- Train loss: {train_loss:.4f}, acc: {train_acc:.4f} \"\n              f\"- Val loss: {val_loss:.4f}, acc: {val_acc:.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:24:10.828863Z","iopub.execute_input":"2025-08-25T17:24:10.829040Z","iopub.status.idle":"2025-08-25T17:24:10.847305Z","shell.execute_reply.started":"2025-08-25T17:24:10.829027Z","shell.execute_reply":"2025-08-25T17:24:10.846572Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fit(model, train_loader, val_loader, criterion, optimizer, device, num_epochs=10)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:24:10.849302Z","iopub.execute_input":"2025-08-25T17:24:10.849604Z","iopub.status.idle":"2025-08-25T17:36:32.944422Z","shell.execute_reply.started":"2025-08-25T17:24:10.849589Z","shell.execute_reply":"2025-08-25T17:36:32.943778Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"torch.save(model.state_dict(), \"resnet50_model.pth\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:36:32.945175Z","iopub.execute_input":"2025-08-25T17:36:32.945424Z","iopub.status.idle":"2025-08-25T17:36:33.086211Z","shell.execute_reply.started":"2025-08-25T17:36:32.945402Z","shell.execute_reply":"2025-08-25T17:36:33.085678Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Example if you saved best model\nmodel.load_state_dict(torch.load(\"resnet50_model.pth\"))\nmodel.eval()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:36:33.086968Z","iopub.execute_input":"2025-08-25T17:36:33.087168Z","iopub.status.idle":"2025-08-25T17:36:33.201683Z","shell.execute_reply.started":"2025-08-25T17:36:33.087153Z","shell.execute_reply":"2025-08-25T17:36:33.200891Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torchvision import datasets, transforms\nfrom torch.utils.data import DataLoader\nimport pandas as pd\n\n# Define same transforms as validation\ntest_transforms = transforms.Compose([\n    transforms.Resize((224,224)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406], \n                         [0.229, 0.224, 0.225])\n])\n\n# Load test data (ImageFolder works only if subfolders exist;\n# for Kaggle test, usually it's unlabeled, so use ImageFolder with dummy)\ntest_data = datasets.ImageFolder(test_dir, transform=test_transforms)\n\ntest_loader = DataLoader(test_data, batch_size=32, shuffle=False)\n\n# Predictions\npreds = []\nmodel.eval()\nwith torch.no_grad():\n    for inputs, _ in test_loader:\n        inputs = inputs.to(device)\n        outputs = model(inputs)\n        _, predicted = torch.max(outputs, 1)\n        preds.extend(predicted.cpu().numpy())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:36:33.202702Z","iopub.execute_input":"2025-08-25T17:36:33.203040Z","iopub.status.idle":"2025-08-25T17:36:49.386989Z","shell.execute_reply.started":"2025-08-25T17:36:33.203015Z","shell.execute_reply":"2025-08-25T17:36:49.386384Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"idx_to_class = {v: k for k, v in train_data.class_to_idx.items()}\npred_labels = [idx_to_class[p] for p in preds]\npred_labels","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:36:49.387700Z","iopub.execute_input":"2025-08-25T17:36:49.388085Z","iopub.status.idle":"2025-08-25T17:36:49.398692Z","shell.execute_reply.started":"2025-08-25T17:36:49.388067Z","shell.execute_reply":"2025-08-25T17:36:49.398007Z"},"collapsed":true,"jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Get file names in same order as test_loader.dataset\nfilenames = [path[0].split(\"/\")[-1] for path in test_loader.dataset.samples]\n\nsubmission = pd.DataFrame({\n    \"image_id\": filenames,\n    \"label\": pred_labels\n})\n\nsubmission.to_csv(\"submission.csv\", index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-25T17:36:49.399384Z","iopub.execute_input":"2025-08-25T17:36:49.399655Z","iopub.status.idle":"2025-08-25T17:36:49.420009Z","shell.execute_reply.started":"2025-08-25T17:36:49.399634Z","shell.execute_reply":"2025-08-25T17:36:49.419495Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}