{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":13836,"databundleVersionId":1718836,"sourceType":"competition"}],"dockerImageVersionId":31260,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nos.listdir('/kaggle/input/cassava-leaf-disease-classification')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:13.423691Z","iopub.execute_input":"2026-02-02T12:06:13.424021Z","iopub.status.idle":"2026-02-02T12:06:13.430333Z","shell.execute_reply.started":"2026-02-02T12:06:13.423996Z","shell.execute_reply":"2026-02-02T12:06:13.429620Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport os\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom PIL import Image\n\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms, models\nfrom torchvision.models import Inception_V3_Weights\nfrom sklearn.model_selection import train_test_split","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:13.431657Z","iopub.execute_input":"2026-02-02T12:06:13.431962Z","iopub.status.idle":"2026-02-02T12:06:17.215840Z","shell.execute_reply.started":"2026-02-02T12:06:13.431940Z","shell.execute_reply":"2026-02-02T12:06:17.215075Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"DATA_DIR = \"/kaggle/input/cassava-leaf-disease-classification\"\nTRAIN_DIR = os.path.join(DATA_DIR, \"train_images\")\nCSV_PATH = os.path.join(DATA_DIR, \"train.csv\")\n\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(\"Using device:\", device)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T13:15:51.504847Z","iopub.execute_input":"2026-02-02T13:15:51.505499Z","iopub.status.idle":"2026-02-02T13:15:51.510309Z","shell.execute_reply.started":"2026-02-02T13:15:51.505471Z","shell.execute_reply":"2026-02-02T13:15:51.509665Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df = pd.read_csv(CSV_PATH)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:17.467522Z","iopub.execute_input":"2026-02-02T12:06:17.467818Z","iopub.status.idle":"2026-02-02T12:06:17.519205Z","shell.execute_reply.started":"2026-02-02T12:06:17.467794Z","shell.execute_reply":"2026-02-02T12:06:17.518707Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load label mapping\nimport json\nwith open(os.path.join(DATA_DIR, \"label_num_to_disease_map.json\"), 'r') as f:\n    label_map = json.load(f)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:17.520525Z","iopub.execute_input":"2026-02-02T12:06:17.520821Z","iopub.status.idle":"2026-02-02T12:06:17.529234Z","shell.execute_reply.started":"2026-02-02T12:06:17.520801Z","shell.execute_reply":"2026-02-02T12:06:17.528615Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df['disease_name'] = train_df['label'].astype(str).map(label_map)\n\n# Quick class distribution\nprint(train_df['label'].value_counts())\nplt.figure(figsize=(8,5))\ntrain_df['label'].value_counts().sort_index().plot(kind='bar')\nplt.xlabel(\"Class Label\")\nplt.ylabel(\"Number of Images\")\nplt.title(\"Cassava Leaf Disease Class Distribution\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:17.530115Z","iopub.execute_input":"2026-02-02T12:06:17.530389Z","iopub.status.idle":"2026-02-02T12:06:17.768318Z","shell.execute_reply.started":"2026-02-02T12:06:17.530360Z","shell.execute_reply":"2026-02-02T12:06:17.767752Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df_split, val_df_split = train_test_split(\n    train_df,\n    test_size=0.1,\n    stratify=train_df['label'],\n    random_state=42\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:17.769167Z","iopub.execute_input":"2026-02-02T12:06:17.769428Z","iopub.status.idle":"2026-02-02T12:06:17.784222Z","shell.execute_reply.started":"2026-02-02T12:06:17.769405Z","shell.execute_reply":"2026-02-02T12:06:17.783731Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# ImageNet mean & std (required for pretrained InceptionNet)\nimagenet_mean = [0.485, 0.456, 0.406]\nimagenet_std = [0.229, 0.224, 0.225]\n\n# Training transforms\ntrain_transforms = transforms.Compose([\n    transforms.Resize((299, 299)),             # Resize to InceptionNet input\n    transforms.RandomHorizontalFlip(),         # Random horizontal flip\n    transforms.RandomVerticalFlip(),           # Random vertical flip\n    transforms.RandomRotation(15),             # Small rotation\n    transforms.ColorJitter(                     # Slight color changes\n        brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),\n    transforms.ToTensor(),                      # Convert to tensor\n    transforms.Normalize(mean=imagenet_mean, std=imagenet_std)  # Normalize\n])\n\n# Validation transforms (no augmentation, only resize + normalize)\nval_transforms = transforms.Compose([\n    transforms.Resize((299, 299)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=imagenet_mean, std=imagenet_std)\n])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:17.785191Z","iopub.execute_input":"2026-02-02T12:06:17.785714Z","iopub.status.idle":"2026-02-02T12:06:17.791078Z","shell.execute_reply.started":"2026-02-02T12:06:17.785691Z","shell.execute_reply":"2026-02-02T12:06:17.790493Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CassavaDataset(Dataset):\n    def __init__(self, df, img_dir, transform=None):\n        self.df = df  # directly assign DataFrame\n        self.img_dir = img_dir\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n        img_path = os.path.join(self.img_dir, row['image_id'])\n        image = Image.open(img_path).convert(\"RGB\")\n        label = row['label']\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:17.792059Z","iopub.execute_input":"2026-02-02T12:06:17.792791Z","iopub.status.idle":"2026-02-02T12:06:17.805466Z","shell.execute_reply.started":"2026-02-02T12:06:17.792768Z","shell.execute_reply":"2026-02-02T12:06:17.804807Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Datasets\ntrain_dataset = CassavaDataset(train_df_split, TRAIN_DIR, transform=train_transforms)\nval_dataset = CassavaDataset(val_df_split, TRAIN_DIR, transform=val_transforms)\n\n# DataLoaders\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True, pin_memory=True)\nval_loader = DataLoader(val_dataset, batch_size=32, shuffle=False, pin_memory=True)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:17.806241Z","iopub.execute_input":"2026-02-02T12:06:17.806449Z","iopub.status.idle":"2026-02-02T12:06:17.817560Z","shell.execute_reply.started":"2026-02-02T12:06:17.806430Z","shell.execute_reply":"2026-02-02T12:06:17.816905Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Device\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(\"Using device:\", device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:17.819279Z","iopub.execute_input":"2026-02-02T12:06:17.819816Z","iopub.status.idle":"2026-02-02T12:06:17.829053Z","shell.execute_reply.started":"2026-02-02T12:06:17.819795Z","shell.execute_reply":"2026-02-02T12:06:17.828338Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torchvision.models import inception_v3, Inception_V3_Weights\n\nweights = Inception_V3_Weights.DEFAULT\n\n# aux_logits=True by default\nmodel = inception_v3(weights=weights, aux_logits=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:17.829821Z","iopub.execute_input":"2026-02-02T12:06:17.830095Z","iopub.status.idle":"2026-02-02T12:06:18.806573Z","shell.execute_reply.started":"2026-02-02T12:06:17.830070Z","shell.execute_reply":"2026-02-02T12:06:18.805965Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_features_main = model.fc.in_features\nmodel.fc = nn.Linear(num_features_main, 5)  ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:18.807499Z","iopub.execute_input":"2026-02-02T12:06:18.807792Z","iopub.status.idle":"2026-02-02T12:06:18.812151Z","shell.execute_reply.started":"2026-02-02T12:06:18.807762Z","shell.execute_reply":"2026-02-02T12:06:18.811392Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_features_aux = model.AuxLogits.fc.in_features\nmodel.AuxLogits.fc = nn.Linear(num_features_aux, 5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:18.813096Z","iopub.execute_input":"2026-02-02T12:06:18.813360Z","iopub.status.idle":"2026-02-02T12:06:18.827663Z","shell.execute_reply.started":"2026-02-02T12:06:18.813331Z","shell.execute_reply":"2026-02-02T12:06:18.826849Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model=model.to(device)\ncriterion = nn.CrossEntropyLoss()  # multi-class classification\n\noptimizer = torch.optim.Adam(model.parameters(), lr=1e-4)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:18.828487Z","iopub.execute_input":"2026-02-02T12:06:18.828791Z","iopub.status.idle":"2026-02-02T12:06:19.139747Z","shell.execute_reply.started":"2026-02-02T12:06:18.828771Z","shell.execute_reply":"2026-02-02T12:06:19.139190Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_epochs = 5  # Start small for testing\n\nfor epoch in range(num_epochs):\n    model.train()\n    running_loss = 0.0\n    correct = 0\n    total = 0\n\n    for images, labels in train_loader:\n        images, labels = images.to(device), labels.to(device)\n\n        optimizer.zero_grad()\n        outputs, aux_outputs = model(images)  # two outputs\n\n        # Combine main + auxiliary loss\n        loss = criterion(outputs, labels) + 0.4 * criterion(aux_outputs, labels)\n        loss.backward()\n        optimizer.step()\n\n        running_loss += loss.item() * images.size(0)\n        _, predicted = outputs.max(1)\n        total += labels.size(0)\n        correct += predicted.eq(labels).sum().item()\n\n    train_loss = running_loss / total\n    train_acc = correct / total\n    \n    print(f\"Epoch [{epoch+1}/{num_epochs}] \"\n          f\"Train Loss: {train_loss:.4f} Train Acc: {train_acc:.4f} \")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T12:06:19.140541Z","iopub.execute_input":"2026-02-02T12:06:19.140780Z","iopub.status.idle":"2026-02-02T13:04:38.303640Z","shell.execute_reply.started":"2026-02-02T12:06:19.140759Z","shell.execute_reply":"2026-02-02T13:04:38.302717Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    model.eval()\n    val_loss = 0.0\n    val_correct = 0\n    val_total = 0\n    \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            loss = criterion(outputs, labels)\n            \n            val_loss += loss.item() * images.size(0)\n            _, predicted = outputs.max(1)\n            val_total += labels.size(0)\n            val_correct += predicted.eq(labels).sum().item()\n    \n    val_loss = val_loss / val_total\n    val_acc = val_correct / val_total\n    print( f\"Val Loss: {val_loss:.4f} Val Acc: {val_acc:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T13:07:34.443013Z","iopub.execute_input":"2026-02-02T13:07:34.443744Z","iopub.status.idle":"2026-02-02T13:08:19.603931Z","shell.execute_reply.started":"2026-02-02T13:07:34.443713Z","shell.execute_reply":"2026-02-02T13:08:19.603184Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Track best validation accuracy\nbest_val_acc = 0.0\n\n# Example: at end of each epoch\nif val_acc > best_val_acc:\n    best_val_acc = val_acc\n    # Save model weights\n    torch.save(model.state_dict(), \"best_inception_cassava.pth\")\n    print(f\"Saved best model with val_acc: {best_val_acc:.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T13:17:48.459083Z","iopub.execute_input":"2026-02-02T13:17:48.459429Z","iopub.status.idle":"2026-02-02T13:17:48.614182Z","shell.execute_reply.started":"2026-02-02T13:17:48.459401Z","shell.execute_reply":"2026-02-02T13:17:48.613423Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TEST_DIR = os.path.join(DATA_DIR, \"test_images\")\ntest_images = os.listdir(TEST_DIR)\n\nmodel.load_state_dict(torch.load(\"best_inception_cassava.pth\"))\nmodel.eval()\n\npredictions = []\n\nwith torch.no_grad():\n    for img_name in test_images:\n        img_path = os.path.join(TEST_DIR, img_name)\n        img = Image.open(img_path).convert(\"RGB\")\n        img = val_transforms(img).unsqueeze(0).to(device)\n\n        output = model(img)\n        pred = output.argmax(dim=1).item()\n        predictions.append({\"image_id\": img_name, \"label\": pred})\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T13:19:24.810687Z","iopub.execute_input":"2026-02-02T13:19:24.811455Z","iopub.status.idle":"2026-02-02T13:19:25.001700Z","shell.execute_reply.started":"2026-02-02T13:19:24.811425Z","shell.execute_reply":"2026-02-02T13:19:25.001108Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission_df = pd.DataFrame(predictions)\nsubmission_df.to_csv(\"submission.csv\", index=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T13:19:38.647103Z","iopub.execute_input":"2026-02-02T13:19:38.647986Z","iopub.status.idle":"2026-02-02T13:19:38.652432Z","shell.execute_reply.started":"2026-02-02T13:19:38.647955Z","shell.execute_reply":"2026-02-02T13:19:38.651784Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import confusion_matrix, classification_report\nimport seaborn as sns\n\nmodel.load_state_dict(torch.load(\"best_inception_cassava.pth\"))\nmodel.eval()\n\nall_preds = []\nall_labels = []\n\nwith torch.no_grad():\n    for images, labels in val_loader:\n        images, labels = images.to(device), labels.to(device)\n        outputs = model(images)  # main output only\n        preds = outputs.argmax(dim=1)\n        \n        all_preds.extend(preds.cpu().numpy())\n        all_labels.extend(labels.cpu().numpy())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T13:18:13.663992Z","iopub.execute_input":"2026-02-02T13:18:13.664280Z","iopub.status.idle":"2026-02-02T13:18:43.550913Z","shell.execute_reply.started":"2026-02-02T13:18:13.664253Z","shell.execute_reply":"2026-02-02T13:18:43.550148Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cm = confusion_matrix(all_labels, all_preds)\nplt.figure(figsize=(8,6))\nsns.heatmap(cm, annot=True, fmt='d', cmap='Blues',\n            xticklabels=[label_map[str(i)] for i in range(5)],\n            yticklabels=[label_map[str(i)] for i in range(5)])\nplt.xlabel(\"Predicted\")\nplt.ylabel(\"Actual\")\nplt.title(\"Confusion Matrix - Cassava Leaf Disease\")\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T13:18:48.547911Z","iopub.execute_input":"2026-02-02T13:18:48.548324Z","iopub.status.idle":"2026-02-02T13:18:48.790203Z","shell.execute_reply.started":"2026-02-02T13:18:48.548296Z","shell.execute_reply":"2026-02-02T13:18:48.789418Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"report = classification_report(all_labels, all_preds, target_names=[label_map[str(i)] for i in range(5)])\nprint(report)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-02T13:18:54.083320Z","iopub.execute_input":"2026-02-02T13:18:54.084037Z","iopub.status.idle":"2026-02-02T13:18:54.098572Z","shell.execute_reply.started":"2026-02-02T13:18:54.084006Z","shell.execute_reply":"2026-02-02T13:18:54.098029Z"}},"outputs":[],"execution_count":null}]}