{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":10422890,"sourceType":"datasetVersion","datasetId":6460269}],"dockerImageVersionId":30804,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Import Modules","metadata":{"_uuid":"1b4aa1d7-96b1-4207-a1f3-31a05bf69bab","_cell_guid":"1113591c-b3fd-4c8a-8fcb-f043ec5c171f","collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport time\nimport os\nimport copy\nimport json\n\n# visualization modules\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom PIL import Image\n\n# pytorch modules\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.nn import functional as F\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import models\nimport torchvision.transforms as transforms\n\n# augmentation\nimport albumentations\nfrom albumentations.pytorch.transforms import ToTensorV2\n\nimport warnings\nwarnings.filterwarnings('ignore')\n%matplotlib inline","metadata":{"_uuid":"a1858d97-eba5-49e4-8a4f-65638a237d43","_cell_guid":"9b3de138-187f-4c53-b7f6-70279e1dd41b","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:49:52.924755Z","iopub.execute_input":"2025-01-17T07:49:52.925062Z","iopub.status.idle":"2025-01-17T07:49:57.422123Z","shell.execute_reply.started":"2025-01-17T07:49:52.925035Z","shell.execute_reply":"2025-01-17T07:49:57.421245Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Load the Dataset","metadata":{"_uuid":"733bb8cb-5b56-4307-8a21-13037aec159f","_cell_guid":"40d8d80c-86b2-43ca-a061-51477d1f147c","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"import os\nimport pandas as pd\n\n# Base directory\nBASE_DIR = \"../input/abhidataset/cassava-leaf-disease-classification/\"\nIMAGE_DIR = BASE_DIR + 'train_images/'\n\n# Load the original CSV\ntrain = pd.read_csv(BASE_DIR + 'train.csv')\n\n# Filter the DataFrame for existing image files\nexisting_files = set(os.listdir(IMAGE_DIR))\nfiltered_train = train[train['image_id'].isin(existing_files)]\n\n# Save the filtered CSV to a writable location\nfiltered_csv_path = './filtered_train.csv'\nfiltered_train.to_csv(filtered_csv_path, index=False)\nprint(f\"Filtered CSV saved at: {filtered_csv_path}\")\n\n# Replace `train` with the filtered DataFrame for further processing\ntrain = filtered_train\nprint(train.head())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T07:49:57.423959Z","iopub.execute_input":"2025-01-17T07:49:57.424353Z","iopub.status.idle":"2025-01-17T07:49:57.496276Z","shell.execute_reply.started":"2025-01-17T07:49:57.424324Z","shell.execute_reply":"2025-01-17T07:49:57.495577Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# loading mapping for target label\nwith open(BASE_DIR+'label_num_to_disease_map.json') as f:\n    mapping = json.loads(f.read())\n    mapping = {int(k): v for k, v in mapping.items()}\nmapping","metadata":{"_uuid":"9bfea40b-e04c-42ec-b72f-a70376c4fb38","_cell_guid":"dcbf0301-6db4-43cf-818e-0cec51695a8c","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:49:57.497202Z","iopub.execute_input":"2025-01-17T07:49:57.497457Z","iopub.status.idle":"2025-01-17T07:49:57.506439Z","shell.execute_reply.started":"2025-01-17T07:49:57.497431Z","shell.execute_reply":"2025-01-17T07:49:57.505537Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train['label_names'] = train['label'].map(mapping)\ntrain.head()","metadata":{"_uuid":"d97682df-dcd5-443a-a21e-4fcffbcf02a9","_cell_guid":"37ce412f-5468-441e-994c-a4de8c55acb7","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:49:57.507564Z","iopub.execute_input":"2025-01-17T07:49:57.507903Z","iopub.status.idle":"2025-01-17T07:49:57.520734Z","shell.execute_reply.started":"2025-01-17T07:49:57.507848Z","shell.execute_reply":"2025-01-17T07:49:57.519730Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Exploratory Data Analysis","metadata":{"_uuid":"bfee3aa6-73bd-44f0-b59a-2d10c3943ef3","_cell_guid":"4ac873c5-1762-4c71-b02c-346123b8f388","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"def plot_images(class_id, label, total_images=6):\n    # get image ids corresponding to the target class id\n    plot_list = train[train['label']==class_id].sample(total_images)['image_id'].tolist()\n    \n    labels = [label for i in range(total_images)]\n    # dynamically set size for subplot\n    size = int(np.sqrt(total_images))\n    if size*size < total_images:\n        size += 1\n    \n    # set figure size\n    plt.figure(figsize=(15,15))\n    \n    # plot the image in subplot\n    for index, (image_id, label) in enumerate(zip(plot_list, labels)):\n        plt.subplot(size, size, index+1)\n        image = Image.open(str(BASE_DIR+'train_images/'+image_id))\n        plt.imshow(image)\n        plt.title(label, fontsize=14)\n        plt.axis('off')\n        \n    plt.show()","metadata":{"_uuid":"a822a451-ab36-40e2-aa1c-c4c9a749659d","_cell_guid":"61c2f3e6-5361-4563-8e71-6dbc5ff72016","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:49:57.523056Z","iopub.execute_input":"2025-01-17T07:49:57.523326Z","iopub.status.idle":"2025-01-17T07:49:57.529023Z","shell.execute_reply.started":"2025-01-17T07:49:57.523300Z","shell.execute_reply":"2025-01-17T07:49:57.528248Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_images(0, mapping[0], 6)","metadata":{"_uuid":"cc418b32-1eae-4f2d-9e30-5024912d0e02","_cell_guid":"8ffe6a03-8fe7-4953-861f-153df08c9c72","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:49:57.530081Z","iopub.execute_input":"2025-01-17T07:49:57.530644Z","iopub.status.idle":"2025-01-17T07:49:58.615525Z","shell.execute_reply.started":"2025-01-17T07:49:57.530606Z","shell.execute_reply":"2025-01-17T07:49:58.613428Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_images(1, mapping[1], 6)","metadata":{"_uuid":"d1019a45-02d0-4904-a4d4-88fc6112661a","_cell_guid":"0d0225b2-2fae-461a-b864-87b77ee25484","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:49:58.616804Z","iopub.execute_input":"2025-01-17T07:49:58.617198Z","iopub.status.idle":"2025-01-17T07:49:59.562286Z","shell.execute_reply.started":"2025-01-17T07:49:58.617159Z","shell.execute_reply":"2025-01-17T07:49:59.560957Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_images(2, mapping[2], 6)","metadata":{"_uuid":"93d2a9c9-3fb9-4173-aa66-6ac527657eff","_cell_guid":"3c57785f-2374-4c62-8d0c-8de396322bc7","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:49:59.563629Z","iopub.execute_input":"2025-01-17T07:49:59.563993Z","iopub.status.idle":"2025-01-17T07:50:00.554588Z","shell.execute_reply.started":"2025-01-17T07:49:59.563956Z","shell.execute_reply":"2025-01-17T07:50:00.553493Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_images(3, mapping[3], 6)","metadata":{"_uuid":"dcecf009-a642-450c-b27d-812a169764e1","_cell_guid":"1ed8d3a3-2509-4da5-8f0c-581304204266","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:00.556109Z","iopub.execute_input":"2025-01-17T07:50:00.556438Z","iopub.status.idle":"2025-01-17T07:50:01.613377Z","shell.execute_reply.started":"2025-01-17T07:50:00.556402Z","shell.execute_reply":"2025-01-17T07:50:01.612154Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_images(4, mapping[4], 6)","metadata":{"_uuid":"57bc2451-17b6-4a74-8eff-6aa6b4d7f309","_cell_guid":"7e49d8fa-df05-4837-9ebc-1c88f61c2a8f","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:01.614464Z","iopub.execute_input":"2025-01-17T07:50:01.614746Z","iopub.status.idle":"2025-01-17T07:50:02.652531Z","shell.execute_reply.started":"2025-01-17T07:50:01.614719Z","shell.execute_reply":"2025-01-17T07:50:02.651825Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Class distribution\nsns.countplot(x='label_names', data=train)  # Pass 'x' as a column name and 'data' as the DataFrame\nplt.xticks(rotation=90)\nplt.show()","metadata":{"_uuid":"00959949-58ae-4ad5-8328-33a955563fec","_cell_guid":"8fee3422-a6f7-4f14-87a9-f9b2bcb654ce","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:02.653877Z","iopub.execute_input":"2025-01-17T07:50:02.654220Z","iopub.status.idle":"2025-01-17T07:50:02.876698Z","shell.execute_reply.started":"2025-01-17T07:50:02.654184Z","shell.execute_reply":"2025-01-17T07:50:02.874349Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Configuration and Utility Functions","metadata":{"_uuid":"2f00f7a1-4dd8-473e-b1f6-79854b328cb5","_cell_guid":"9721fdaf-dfa2-4a6e-b7aa-ac28ac381bf8","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"DIM = (256, 256)\nWIDTH, HEIGHT = DIM\nNUM_CLASSES = 5\nNUM_WORKERS = 24\nTRAIN_BATCH_SIZE = 32\nTEST_BATCH_SIZE = 32\nSEED = 1\n\nDEVICE = 'cuda'\n\nMEAN = [0.485, 0.456, 0.406]\nSTD = [0.229, 0.224, 0.225]","metadata":{"_uuid":"c4771c0b-21fa-4cb9-971a-bcb469295ee9","_cell_guid":"18cc24b3-4f53-4218-93c8-e3c318f6fbb7","trusted":true,"execution":{"iopub.status.busy":"2025-01-17T07:50:02.877988Z","iopub.execute_input":"2025-01-17T07:50:02.878234Z","iopub.status.idle":"2025-01-17T07:50:02.882893Z","shell.execute_reply.started":"2025-01-17T07:50:02.878211Z","shell.execute_reply":"2025-01-17T07:50:02.881920Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Augmentations","metadata":{"_uuid":"7c2bfa97-3abc-429b-984e-a487d2410468","_cell_guid":"a1c8af4f-fb11-43d2-a327-ebe01f0232e1","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"def get_test_transforms(value = 'val'):\n    if value == 'train':\n        return albumentations.Compose([\n            albumentations.Resize(WIDTH, HEIGHT),\n            albumentations.HorizontalFlip(p=0.5),\n            albumentations.Rotate(limit=(-90, 90)),\n            albumentations.VerticalFlip(p=0.5),\n            albumentations.Normalize(MEAN, STD, max_pixel_value=255.0, always_apply=True),\n            ToTensorV2(p=1.0)\n        ])\n    elif value == 'val':\n        return albumentations.Compose([\n            albumentations.Resize(WIDTH, HEIGHT),\n            albumentations.Normalize(MEAN, STD, max_pixel_value=255.0, always_apply=True),\n            ToTensorV2(p=1.0)\n        ])","metadata":{"_uuid":"97780e00-c5b0-4ade-8d24-35660e38847a","_cell_guid":"d3076c9c-61b4-4503-a6bf-1016664b3193","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:02.884046Z","iopub.execute_input":"2025-01-17T07:50:02.884474Z","iopub.status.idle":"2025-01-17T07:50:02.892248Z","shell.execute_reply.started":"2025-01-17T07:50:02.884435Z","shell.execute_reply":"2025-01-17T07:50:02.891142Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Dataset Loader Class","metadata":{"_uuid":"82d2f726-a564-4f66-9ecd-2244b96c7921","_cell_guid":"52adfc88-914a-4881-9378-3740fcfd7b92","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"class CassavaDataset(Dataset):\n    def __init__(self, image_ids, labels, dimension=None, augmentations=None, folder='train_images'):\n        super().__init__()\n        self.image_ids = image_ids\n        self.labels = labels\n        self.dim = dimension\n        self.augmentations = augmentations\n        self.folder = folder\n    \n    # returns the length\n    def __len__(self):\n        return len(self.image_ids)\n    \n    # return the image and label for that index\n    def __getitem__(self, idx):\n        img = Image.open(os.path.join(BASE_DIR, self.folder, self.image_ids[idx]))\n        \n        if self.dim:\n            img = img.resize(self.dim)\n        \n        # convert to numpy array\n        img = np.array(img)\n        \n        if self.augmentations:\n            augmented = self.augmentations(image=img)\n            img = augmented['image']\n        \n        label = torch.tensor(self.labels[idx], dtype=torch.long)\n        return img, label","metadata":{"_uuid":"a24e9045-af75-4f83-9e3e-85540d1397c5","_cell_guid":"83fb6d5e-ffa3-4fca-8acf-25fb96520912","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:02.897586Z","iopub.execute_input":"2025-01-17T07:50:02.897802Z","iopub.status.idle":"2025-01-17T07:50:02.906715Z","shell.execute_reply.started":"2025-01-17T07:50:02.897780Z","shell.execute_reply":"2025-01-17T07:50:02.905905Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Train Test Split","metadata":{"_uuid":"f2fe65cc-a8f7-46a9-a3ff-12a85255caff","_cell_guid":"285ae1e9-3f19-4020-a495-e00fa4ac76b5","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\nx_train, x_test, y_train, y_test = train_test_split(train['image_id'], train['label'], test_size=0.25)","metadata":{"_uuid":"f70372e9-bd70-44af-8e50-55bb0b86a4d7","_cell_guid":"82e5e0d1-de7a-4e65-ab52-ee681ce5ef6b","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:02.907600Z","iopub.execute_input":"2025-01-17T07:50:02.907837Z","iopub.status.idle":"2025-01-17T07:50:03.051600Z","shell.execute_reply.started":"2025-01-17T07:50:02.907803Z","shell.execute_reply":"2025-01-17T07:50:03.050831Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import WeightedRandomSampler\ndef sampler_(labels):\n    label_unique, counts = np.unique(labels, return_counts=True)\n    print('Unique Labels', label_unique)\n    weights = [sum(counts) / c for c in counts]\n    sample_weights = [weights[w] for w in labels]\n    sampler = WeightedRandomSampler(sample_weights, len(sample_weights), replacement=True)\n    return sampler","metadata":{"_uuid":"222cb807-c3f7-4dd3-a782-4307860210b8","_cell_guid":"753af61e-c06e-4ef7-9adf-183985ea2a67","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:03.052684Z","iopub.execute_input":"2025-01-17T07:50:03.053463Z","iopub.status.idle":"2025-01-17T07:50:03.059428Z","shell.execute_reply.started":"2025-01-17T07:50:03.053415Z","shell.execute_reply":"2025-01-17T07:50:03.058555Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_sampler = sampler_(y_train)","metadata":{"_uuid":"a58364b2-1f4c-4386-b92d-106303914964","_cell_guid":"1df7d1b7-5c52-435e-a9ea-73b1be8626fa","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:03.060436Z","iopub.execute_input":"2025-01-17T07:50:03.060696Z","iopub.status.idle":"2025-01-17T07:50:03.080656Z","shell.execute_reply.started":"2025-01-17T07:50:03.060671Z","shell.execute_reply":"2025-01-17T07:50:03.079620Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# create dataloaders for training antrain_test_splitidation\ntrain_dataset = CassavaDataset(\n    image_ids=x_train.values,\n    labels=y_train.values,\n    augmentations=get_test_transforms('train'),\n    dimension=DIM\n)\n\ntrain_loader = DataLoader(\n    train_dataset,\n    batch_size=TRAIN_BATCH_SIZE,\n    num_workers=NUM_WORKERS,\n    shuffle=False,\n    sampler=train_sampler\n)\n\nval_dataset = CassavaDataset(\n    image_ids=x_test.values,\n    labels=y_test.values,\n    augmentations=get_test_transforms('val'),\n    dimension=DIM\n)\n\nval_loader = DataLoader(\n    val_dataset,\n    batch_size=TRAIN_BATCH_SIZE,\n    num_workers=NUM_WORKERS,\n    shuffle=False\n)\n\nloaders = {'train': train_loader, 'val': val_loader}","metadata":{"_uuid":"330eb5f3-07f4-4e2b-ba50-b995aeb839c0","_cell_guid":"4382c45b-b932-40b3-9789-982eade88494","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:03.081701Z","iopub.execute_input":"2025-01-17T07:50:03.081987Z","iopub.status.idle":"2025-01-17T07:50:03.092312Z","shell.execute_reply.started":"2025-01-17T07:50:03.081963Z","shell.execute_reply":"2025-01-17T07:50:03.091565Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# to check whether dataset is working or not\n# fetch the data based on index\nval_dataset[0]","metadata":{"_uuid":"a7d7891b-4e6a-4b93-95db-9a28fe21aa48","_cell_guid":"c8db5881-9401-471c-b3e8-038635eacde2","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:03.093404Z","iopub.execute_input":"2025-01-17T07:50:03.093700Z","iopub.status.idle":"2025-01-17T07:50:03.218774Z","shell.execute_reply.started":"2025-01-17T07:50:03.093675Z","shell.execute_reply":"2025-01-17T07:50:03.217992Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Use Pretrained Model (Transfer Learning)","metadata":{"_uuid":"20d653a8-72cc-43c2-879d-d9cf8b9d0ce1","_cell_guid":"6fff75c4-93f1-4465-9565-2b53f27b2beb","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"def getModel():\n    net = models.resnet152(pretrained=True)\n    \n    # if you want to train the whole network, comment this code\n    # freeze all the layers in the network\n    for param in net.parameters():\n        param.requires_grad = False\n        \n    num_ftrs = net.fc.in_features\n    # create last few layers\n    net.fc = nn.Sequential(\n        nn.Linear(num_ftrs, 256),\n        nn.ReLU(),\n        nn.Dropout(0.3),\n        nn.Linear(256, NUM_CLASSES),\n        nn.LogSoftmax(dim=1)\n    )\n    \n    # use gpu if any\n    net = net.cuda() if DEVICE else net\n    return net","metadata":{"_uuid":"3a827780-dba4-4a50-b64f-e0a2f562248d","_cell_guid":"340bee67-187a-414a-b35c-30c0c9264c98","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:03.219785Z","iopub.execute_input":"2025-01-17T07:50:03.220060Z","iopub.status.idle":"2025-01-17T07:50:03.225084Z","shell.execute_reply.started":"2025-01-17T07:50:03.220034Z","shell.execute_reply":"2025-01-17T07:50:03.224240Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nprint(torch.cuda.is_available())","metadata":{"_uuid":"ddb187c0-b385-486f-99d5-82190e150fce","_cell_guid":"0f7592a4-1477-4396-b883-2b0a10ef0587","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:03.226205Z","iopub.execute_input":"2025-01-17T07:50:03.226561Z","iopub.status.idle":"2025-01-17T07:50:03.303598Z","shell.execute_reply.started":"2025-01-17T07:50:03.226524Z","shell.execute_reply":"2025-01-17T07:50:03.302683Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = getModel()","metadata":{"_uuid":"bf0d6d58-48e0-411c-80a2-18cc1099a410","_cell_guid":"fd87d261-2936-4dba-9321-137ed7a7f11c","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:03.304650Z","iopub.execute_input":"2025-01-17T07:50:03.304948Z","iopub.status.idle":"2025-01-17T07:50:08.370612Z","shell.execute_reply.started":"2025-01-17T07:50:03.304921Z","shell.execute_reply":"2025-01-17T07:50:08.369683Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import math\ndef cyclical_lr(stepsize, min_lr=3e-4, max_lr=3e-3):\n\n    # Scaler: we can adapt this if we do not want the triangular CLR\n    scaler = lambda x: 1.\n\n    # Lambda function to calculate the LR\n    lr_lambda = lambda it: min_lr + (max_lr - min_lr) * relative(it, stepsize)\n\n    # Additional function to see where on the cycle we are\n    def relative(it, stepsize):\n        cycle = math.floor(1 + it / (2 * stepsize))\n        x = abs(it / stepsize - 2 * cycle + 1)\n        return max(0, (1 - x)) * scaler(cycle)\n\n    return lr_lambda","metadata":{"_uuid":"05480a34-65be-464a-8e79-213804a2b256","_cell_guid":"986c06bc-e67c-426a-9128-3561c282f504","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:08.371833Z","iopub.execute_input":"2025-01-17T07:50:08.372221Z","iopub.status.idle":"2025-01-17T07:50:08.378747Z","shell.execute_reply.started":"2025-01-17T07:50:08.372180Z","shell.execute_reply":"2025-01-17T07:50:08.377915Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\n# optimizer = torch.optim.Adam(model.parameters(), lr=0.1)\noptimizer = torch.optim.SGD(model.parameters(), lr=1., momentum=0.9)\nstep_size = 4*len(train_loader)\nclr = cyclical_lr(step_size, min_lr=3e-4, max_lr=3e-3)\nscheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, [clr])","metadata":{"_uuid":"200ec06c-f7cb-42a6-8c43-0790362d3b54","_cell_guid":"bafd82ea-a343-4dde-a861-91aa6521e864","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:08.379735Z","iopub.execute_input":"2025-01-17T07:50:08.379995Z","iopub.status.idle":"2025-01-17T07:50:08.396765Z","shell.execute_reply.started":"2025-01-17T07:50:08.379970Z","shell.execute_reply":"2025-01-17T07:50:08.395890Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# print(model)","metadata":{"_uuid":"2644870c-8919-4741-a064-38f043910ac1","_cell_guid":"b0e9082e-8289-4f90-a1e8-48af1302d238","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:08.398027Z","iopub.execute_input":"2025-01-17T07:50:08.398377Z","iopub.status.idle":"2025-01-17T07:50:08.409432Z","shell.execute_reply.started":"2025-01-17T07:50:08.398339Z","shell.execute_reply":"2025-01-17T07:50:08.408836Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# freeze (or) unfreeze all the layers\nunfreeze = True # to freeze, set it as False\nfor param in model.parameters():\n    param.requires_grad = unfreeze","metadata":{"_uuid":"21aa3df7-4319-442f-9a11-265541ea479a","_cell_guid":"1535eaa9-a84c-4f5d-a118-9d3e52faacda","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:08.410265Z","iopub.execute_input":"2025-01-17T07:50:08.410478Z","iopub.status.idle":"2025-01-17T07:50:08.419595Z","shell.execute_reply.started":"2025-01-17T07:50:08.410456Z","shell.execute_reply":"2025-01-17T07:50:08.418835Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# find total parameters and trainable parameters\ntotal_params = sum(p.numel() for p in model.parameters())\nprint(f'{total_params:,} total parameters')\ntrainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)\nprint(f'{trainable_params:,} training parameters')","metadata":{"_uuid":"0f358ba0-9ed0-43d7-8ad4-303ae0605549","_cell_guid":"ce8a05a9-1386-4d55-b763-18c48a8df04d","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:08.420575Z","iopub.execute_input":"2025-01-17T07:50:08.420809Z","iopub.status.idle":"2025-01-17T07:50:08.432572Z","shell.execute_reply.started":"2025-01-17T07:50:08.420785Z","shell.execute_reply":"2025-01-17T07:50:08.431706Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Steps for Training and Validation","metadata":{"_uuid":"181bc613-e897-445c-8667-4a43a28a99ac","_cell_guid":"5f4f439d-56b6-4945-a937-cab274969ac1","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"def train_model(model, dataloaders, criterion, optimizer, num_epochs, scheduler=scheduler):\n    # set starting time\n    start_time = time.time()\n    \n    val_acc_history = []\n    \n    best_model_wts = copy.deepcopy(model.state_dict())\n    best_acc = 0.0\n    \n    for epoch in range(num_epochs):\n        print(f'Epoch {epoch}/{num_epochs-1}')\n        print('-'*15)\n        \n        # each epoch have training and validation phase\n        for phase in ['train', 'val']:\n            # set mode for model\n            if phase == 'train':\n                model.train() # set model to training mode\n            else:\n                model.eval() # set model to evaluate mode\n                \n            running_loss = 0.0\n            running_corrects = 0\n            fin_out = []\n            \n            # iterate over data\n            for inputs, labels in dataloaders[phase]:\n                # move data to corresponding hardware\n                inputs = inputs.to(DEVICE)\n                labels = labels.to(DEVICE)\n                \n                # reset (or) zero the parameter gradients\n                optimizer.zero_grad()\n                \n                # training (or) validation process\n                with torch.set_grad_enabled(phase=='train'):\n                    outputs = model(inputs)\n                    loss = criterion(outputs, labels)\n                    \n                    _, preds = torch.max(outputs, 1)\n                    \n                    # back propagation in the network\n                    if phase == 'train':\n                        loss.backward()\n                        optimizer.step()\n                        scheduler.step()\n                        \n                running_loss += loss.item() * inputs.size(0)\n                running_corrects += torch.sum(preds == labels.data)\n                \n            # calculate loss and accuarcy for the epoch\n            epoch_loss = running_loss / len(dataloaders[phase].dataset)\n            epoch_acc = running_corrects.double() / len(dataloaders[phase].dataset)\n            \n            # print loss and acc for training & validation\n            print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))\n            \n            # update the best weights\n            if phase == 'val' and epoch_acc > best_acc:\n                best_acc = epoch_acc\n                best_model_wts = copy.deepcopy(model.state_dict())\n            if phase == 'val':\n                val_acc_history.append(epoch_acc)\n                \n        print()\n    end_time = time.time() - start_time\n    \n    print('Training completes in {:.0f}m {:.0f}s'.format(end_time // 60, end_time % 60))\n    print('Best Val Acc: {:.4f}'.format(best_acc))\n    \n    # load best model weights\n    model.load_state_dict(best_model_wts)\n    return model, val_acc_history","metadata":{"_uuid":"2feda9db-b995-4593-b768-eb9dcb2e2fa6","_cell_guid":"b6afb162-8868-4f97-8557-530071a67d8e","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:08.433683Z","iopub.execute_input":"2025-01-17T07:50:08.434022Z","iopub.status.idle":"2025-01-17T07:50:08.444261Z","shell.execute_reply.started":"2025-01-17T07:50:08.433984Z","shell.execute_reply":"2025-01-17T07:50:08.443390Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# train the model\nmodel, accuracy = train_model(model=model, dataloaders=loaders, criterion=criterion, optimizer=optimizer, num_epochs=50, scheduler=scheduler)","metadata":{"_uuid":"6b53873b-692b-407f-9f91-ff356d4d06b7","_cell_guid":"83c4ca0d-0a51-4fb1-8046-fb2fd9e46a2d","trusted":true,"collapsed":false,"execution":{"iopub.status.busy":"2025-01-17T07:50:08.445252Z","iopub.execute_input":"2025-01-17T07:50:08.445496Z","iopub.status.idle":"2025-01-17T08:30:11.752630Z","shell.execute_reply.started":"2025-01-17T07:50:08.445472Z","shell.execute_reply":"2025-01-17T08:30:11.751561Z"},"jupyter":{"outputs_hidden":false}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# save the model and model weights\ntorch.save(model, '/kaggle/working/best_model.h5')\ntorch.save(model.state_dict(), '/kaggle/working/best_model_weights')","metadata":{"_uuid":"c8c321b5-dd65-40ba-b582-d5909faad26c","_cell_guid":"dcc8de0f-5b5f-4521-80d2-7eb77b9e9ea3","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-01-17T08:30:11.754206Z","iopub.execute_input":"2025-01-17T08:30:11.754524Z","iopub.status.idle":"2025-01-17T08:30:12.673109Z","shell.execute_reply.started":"2025-01-17T08:30:11.754493Z","shell.execute_reply":"2025-01-17T08:30:12.672144Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# freeze (or) unfreeze all the layers\nunfreeze = True # to freeze, set it as False\nfor param in model.parameters():\n    param.requires_grad = unfreeze","metadata":{"_uuid":"acca2e20-c4bc-4f6b-bcb4-2ea29773f82a","_cell_guid":"2e3ef620-6d20-4d1a-872e-0ac915bc9ad4","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-01-17T08:30:12.674561Z","iopub.execute_input":"2025-01-17T08:30:12.674955Z","iopub.status.idle":"2025-01-17T08:30:12.681633Z","shell.execute_reply.started":"2025-01-17T08:30:12.674915Z","shell.execute_reply":"2025-01-17T08:30:12.680712Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# # unfreeze seleected layers\n# layers = list(range(5,7))\n# i = 0\n# for layer in model.children():\n#     if i in layers:\n#         for param in layer.parameters():\n#             param.requires_grad = True\n#     i += 1","metadata":{"_uuid":"883d761e-c356-4e73-a0ce-68f8496bf9a3","_cell_guid":"dfc72d1c-8377-423f-8380-87281241ed0e","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-01-17T08:30:12.682801Z","iopub.execute_input":"2025-01-17T08:30:12.683227Z","iopub.status.idle":"2025-01-17T08:30:12.695017Z","shell.execute_reply.started":"2025-01-17T08:30:12.683200Z","shell.execute_reply":"2025-01-17T08:30:12.694312Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# find total parameters and trainable parameters\ntotal_params = sum(p.numel() for p in model.parameters())\nprint(f'{total_params:,} total parameters')\ntrainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)\nprint(f'{trainable_params:,} training parameters')","metadata":{"_uuid":"ef3e62a4-6293-40c3-9391-06d065e760c0","_cell_guid":"241129ba-2588-4b68-9e2d-47b6b8414515","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-01-17T08:30:12.696033Z","iopub.execute_input":"2025-01-17T08:30:12.696735Z","iopub.status.idle":"2025-01-17T08:30:12.707301Z","shell.execute_reply.started":"2025-01-17T08:30:12.696708Z","shell.execute_reply":"2025-01-17T08:30:12.706422Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# # gives the number of layers\n# for i,layer in enumerate(model.children()):\n#     print(i)","metadata":{"_uuid":"c529d7c8-cd0f-4108-9c4c-2f571b35ce74","_cell_guid":"b8970b4c-141e-4a84-a571-388e4743e3b0","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-01-17T08:30:12.708257Z","iopub.execute_input":"2025-01-17T08:30:12.708523Z","iopub.status.idle":"2025-01-17T08:30:12.716619Z","shell.execute_reply.started":"2025-01-17T08:30:12.708498Z","shell.execute_reply":"2025-01-17T08:30:12.715936Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Testing the Model","metadata":{"_uuid":"ed9c00e7-978c-45de-8867-4168385d9b0d","_cell_guid":"9af5337c-bf52-4d20-84df-789237ecf419","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false}}},{"cell_type":"code","source":"# empty the cache from cuda device\ntorch.cuda.empty_cache()","metadata":{"_uuid":"6e8f477c-70de-456a-8865-deca1e96ae2e","_cell_guid":"46726029-ea41-4bf5-ab8f-659ee33d6b36","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-01-17T08:30:12.717681Z","iopub.execute_input":"2025-01-17T08:30:12.718210Z","iopub.status.idle":"2025-01-17T08:30:12.992086Z","shell.execute_reply.started":"2025-01-17T08:30:12.718182Z","shell.execute_reply":"2025-01-17T08:30:12.991195Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def predict(model, dataloader, device):\n    # set mode to eval\n    model.eval()\n    fin_out = []\n    \n    with torch.no_grad():\n        for images, targets in dataloader:\n            images = images.to(device)\n            targets = targets.to(device)\n            \n            outputs = model(images)\n            \n            fin_out.append(F.softmax(outputs, dim=1).detach().cpu().numpy())\n            \n    return np.concatenate(fin_out)","metadata":{"_uuid":"a848f072-947c-47ae-b8bc-0006aca8e26b","_cell_guid":"3be1899d-7dd7-44b0-ae03-ae18aac13561","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-01-17T08:30:12.993274Z","iopub.execute_input":"2025-01-17T08:30:12.993867Z","iopub.status.idle":"2025-01-17T08:30:13.002900Z","shell.execute_reply.started":"2025-01-17T08:30:12.993810Z","shell.execute_reply":"2025-01-17T08:30:13.002196Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# steps for model prediction\ndevice = torch.device('cuda') # if you don't have gpu, set it as cpu\nmodel.to(device)\npred = predict(model, val_loader, device)\npred = pred.argmax(axis=1)","metadata":{"_uuid":"d8a8d280-00bd-4ea2-b2de-ba031fecf71b","_cell_guid":"cd6a5d9f-0913-4039-926f-8a59306f73db","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-01-17T08:30:13.003831Z","iopub.execute_input":"2025-01-17T08:30:13.004103Z","iopub.status.idle":"2025-01-17T08:30:19.318338Z","shell.execute_reply.started":"2025-01-17T08:30:13.004079Z","shell.execute_reply":"2025-01-17T08:30:19.317241Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_test.values[:5]","metadata":{"_uuid":"341b68f9-3e9a-45dc-a180-28b1755b8e4a","_cell_guid":"5fda3ff0-6c1d-42a6-bcef-f997a09b4454","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-01-17T08:30:19.319638Z","iopub.execute_input":"2025-01-17T08:30:19.319952Z","iopub.status.idle":"2025-01-17T08:30:19.326792Z","shell.execute_reply.started":"2025-01-17T08:30:19.319922Z","shell.execute_reply":"2025-01-17T08:30:19.325917Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred[:5]","metadata":{"_uuid":"88191378-9195-49df-b5e7-06cbdb0e75a4","_cell_guid":"33318395-10d3-4e8b-ba6c-0b10edfed6ed","trusted":true,"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2025-01-17T08:30:19.328147Z","iopub.execute_input":"2025-01-17T08:30:19.328772Z","iopub.status.idle":"2025-01-17T08:30:19.339602Z","shell.execute_reply.started":"2025-01-17T08:30:19.328734Z","shell.execute_reply":"2025-01-17T08:30:19.338321Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from PIL import Image\nimport torchvision.transforms as transforms\nimport torch\n\ndef predict_disease(image_path, model, mapping):\n    \"\"\"\n    Predicts the disease for the input image using the trained model.\n\n    Args:\n    image_path (str): Path to the input image.\n    model (torch.nn.Module): Trained PyTorch model.\n    mapping (dict): Dictionary mapping label indices to disease names.\n\n    Returns:\n    None\n    \"\"\"\n    # Load the image\n    image = Image.open(image_path).convert(\"RGB\")\n    \n    # Define the image transformation\n    transform = transforms.Compose([\n        transforms.Resize((256, 256)),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n    ])\n    \n    # Transform the image\n    image = transform(image).unsqueeze(0)  # Add batch dimension\n    \n    # Move to the same device as the model\n    image = image.to(DEVICE)\n    model = model.to(DEVICE)\n    \n    # Set model to evaluation mode\n    model.eval()\n    \n    # Make the prediction\n    with torch.no_grad():\n        output = model(image)\n        _, predicted = torch.max(output, 1)\n        predicted_label = predicted.item()\n    \n    # Print the disease name\n    print(f\"Detected Disease: {mapping[predicted_label]}\")\n\n# Example usage\nimage_path = \"../input/abhidataset/cassava-leaf-disease-classification/test_images/2216849948.jpg\"  # Replace with the actual image path\npredict_disease(image_path, model, mapping)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-17T08:39:28.867888Z","iopub.execute_input":"2025-01-17T08:39:28.868444Z","iopub.status.idle":"2025-01-17T08:39:29.004623Z","shell.execute_reply.started":"2025-01-17T08:39:28.868412Z","shell.execute_reply":"2025-01-17T08:39:29.003701Z"}},"outputs":[],"execution_count":null}]}