{"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":"gpu","dataSources":[{"sourceId":13836,"databundleVersionId":1718836,"sourceType":"competition"},{"sourceId":9875213,"sourceType":"datasetVersion","datasetId":6062649},{"sourceId":9875415,"sourceType":"datasetVersion","datasetId":6062791}],"dockerImageVersionId":30786,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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\n# import numpy as np # linear algebra\n# import 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\n# import os\n# for 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":"2024-11-11T15:16:07.726812Z","iopub.execute_input":"2024-11-11T15:16:07.727128Z","iopub.status.idle":"2024-11-11T15:16:07.732605Z","shell.execute_reply.started":"2024-11-11T15:16:07.727092Z","shell.execute_reply":"2024-11-11T15:16:07.731705Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Import Libraries","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np \nimport os\nimport json \nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torchvision import models\nfrom torchvision import transforms\nfrom torch.utils.data import DataLoader, random_split, Dataset, WeightedRandomSampler\nfrom torchvision.datasets import ImageFolder\nfrom PIL import Image\nimport matplotlib.pyplot as plt","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-11T15:16:07.807775Z","iopub.execute_input":"2024-11-11T15:16:07.808559Z","iopub.status.idle":"2024-11-11T15:16:13.318600Z","shell.execute_reply.started":"2024-11-11T15:16:07.808513Z","shell.execute_reply":"2024-11-11T15:16:13.317654Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Define device (GPU if available, else CPU)\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-11T15:16:13.320240Z","iopub.execute_input":"2024-11-11T15:16:13.320688Z","iopub.status.idle":"2024-11-11T15:16:13.357305Z","shell.execute_reply.started":"2024-11-11T15:16:13.320652Z","shell.execute_reply":"2024-11-11T15:16:13.356233Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Load The Data","metadata":{}},{"cell_type":"code","source":"base_path = '/kaggle/input/cassava-leaf-disease-classification/'\n\ntrain_path = '/kaggle/input/cassava-leaf-disease-classification/train_images/'\n\ntest_path = '/kaggle/input/cassava-leaf-disease-classification/test_images/'\n\n#get the mapping\nwith open(base_path+'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":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-11T15:16:13.358607Z","iopub.execute_input":"2024-11-11T15:16:13.358960Z","iopub.status.idle":"2024-11-11T15:16:13.380231Z","shell.execute_reply.started":"2024-11-11T15:16:13.358926Z","shell.execute_reply":"2024-11-11T15:16:13.379376Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data = pd.read_csv(base_path + 'train.csv')\ntrain_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-11T15:16:13.382596Z","iopub.execute_input":"2024-11-11T15:16:13.382956Z","iopub.status.idle":"2024-11-11T15:16:13.420515Z","shell.execute_reply.started":"2024-11-11T15:16:13.382916Z","shell.execute_reply":"2024-11-11T15:16:13.419642Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from collections import defaultdict\nmapping_count = {0 : 0, 1: 0, 2: 0, 3: 0, 4: 0}\ntotal_img = 0\nfor i in range(len(train_data)):\n    mapping_count[train_data.label[i]] += 1\n    total_img += 1\nmapping_count = pd.DataFrame(mapping_count.items(), columns= ['label', 'image_count'])\nmapping_count","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-11T15:16:13.421668Z","iopub.execute_input":"2024-11-11T15:16:13.422024Z","iopub.status.idle":"2024-11-11T15:16:13.760415Z","shell.execute_reply.started":"2024-11-11T15:16:13.421979Z","shell.execute_reply":"2024-11-11T15:16:13.759509Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Find the Dimensions of the Images","metadata":{}},{"cell_type":"code","source":"for i in range(5):\n    image_path = train_path + train_data.image_id[i]\n    with Image.open(image_path) as img:\n        print(f\"Image: {train_data.image_id[i]} | Dimensions: {img.size}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-11T15:16:13.761608Z","iopub.execute_input":"2024-11-11T15:16:13.761914Z","iopub.status.idle":"2024-11-11T15:16:13.831200Z","shell.execute_reply.started":"2024-11-11T15:16:13.761882Z","shell.execute_reply":"2024-11-11T15:16:13.830292Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import multiprocessing\n\n# Define image dimensions and batch size for model input\nimg_height, img_width = 800, 600  # Resize all images to 800x600 pixels\nbatch_size = 32  # Number of images to process in a batch\n\n# Define the image directory\nimage_dir = train_path  # Assuming train_path is defined elsewhere\n\n\n# Define image transformations (resize, normalize)\ndata_transforms = transforms.Compose([\n    transforms.Resize((img_height, img_width)),  # Resize images to the desired size\n    transforms.ToTensor(),  # Convert the image to a tensor\n    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])  # Normalize using ImageNet stats\n])\n\n# Custom Dataset Class to Load Images and Labels\nclass ImageDataset(Dataset):\n    def __init__(self, csv_data, image_dir, transform=None):\n        self.image_paths = csv_data['image_id'].values  # Paths to images\n        self.labels = csv_data['label'].values  # Labels\n        self.image_dir = image_dir  # Directory where images are stored\n        self.transform = transform  # Transformation to apply to each image\n\n    def __len__(self):\n        return len(self.image_paths)\n\n    def __getitem__(self, idx):\n        image_path = os.path.join(self.image_dir, self.image_paths[idx])  # Full path to the image\n        image = Image.open(image_path).convert(\"RGB\")  # Open the image and convert to RGB\n        label = self.labels[idx]  # Get the corresponding label\n        \n        if self.transform:\n            image = self.transform(image)  # Apply the transformations\n\n        return image, label  # Return the image and the label\n\n# Create the dataset\nimg_dataset = ImageDataset(train_data, image_dir, transform=data_transforms)\n\n# Split the dataset into train and validation sets\ndef split_dataset(dataset, train_size=0.8):\n    \"\"\"\n    Splits a dataset into train and validation sets.\n    \n    Args:\n    - dataset: The dataset to split.\n    - train_size: The proportion of the data to use for training.\n    \n    Returns:\n    - train_dataset: The training dataset.\n    - val_dataset: The validation dataset.\n    \"\"\"\n    train_length = int(len(dataset) * train_size)\n    val_length = len(dataset) - train_length\n    train_dataset, val_dataset = random_split(dataset, [train_length, val_length])\n    return train_dataset, val_dataset\n\n\n# Get the total number of images\ntotal_images = len(img_dataset)\n\n# Split the dataset into training and validation datasets (80% train, 20% val)\ntrain_dataset, val_dataset = split_dataset(img_dataset, train_size=0.8)\n\nprint('computing class weights')\nclass_weights = [mapping_count['image_count'][i]/total_img for i in range(5)]\n\n#Intialise weighted sampler for sampling\nsample_weights_all = [class_weights[label] for label in img_dataset.labels]\n\n# Split weights into train and validation subsets\ntrain_indices = train_dataset.indices\ntrain_sample_weights = [sample_weights_all[i] for i in train_indices]\nprint(\"created sample weights\")\n\n# Create WeightedRandomSampler\nsampler = WeightedRandomSampler(weights=train_sample_weights, num_samples=len(train_sample_weights), replacement=True)\nprint(\"created sampler\")\n\nnum_workers = multiprocessing.cpu_count()   \nprint(\"numworkers: \", num_workers)\n\n# Create DataLoaders for batching and shuffling\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle = True, num_workers = num_workers, prefetch_factor=2)\nprint('created train loader')\nval_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False, num_workers = num_workers, prefetch_factor=2)\nprint('created valid loader')\n\n# Check the size of the datasets\nprint(f'Total images: {total_images}')\nprint(f'Training images: {len(train_dataset)}')\nprint(f'Validation images: {len(val_dataset)}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-11T15:16:13.832654Z","iopub.execute_input":"2024-11-11T15:16:13.832950Z","iopub.status.idle":"2024-11-11T15:16:13.885577Z","shell.execute_reply.started":"2024-11-11T15:16:13.832917Z","shell.execute_reply":"2024-11-11T15:16:13.884672Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load ResNet50 pre-trained on ImageNet\nbase_model = models.resnet50(weights= None)\n\nbase_model.load_state_dict(torch.load(\"/kaggle/input/resnet50-weights/resnet50_weights.pth\"))\n\n# Freeze the base model layers\nfor param in base_model.parameters():\n    param.requires_grad = False\n\n# Modify the final fully connected layer to fit 5 classes\nnum_features = base_model.fc.in_features\nbase_model.fc = nn.Sequential(\n    nn.Linear(num_features, 384),  # Fully connected layer with 384 neurons\n    nn.ReLU(),                     # ReLU activation\n    nn.Linear(384, 5),             # Output layer with 5 classes\n)\n\n# Move the model to the appropriate device\nbase_model = base_model.to(device)\n\n# Define the loss function and optimizer\ncriterion = nn.CrossEntropyLoss()  # Use CrossEntropyLoss for multi-class classification\noptimizer = optim.Adam(base_model.fc.parameters(), lr=0.001)  # Only train the FC layer\n\n# Training function\ndef train_model(model, train_loader, val_loader, criterion, optimizer, num_epochs=10):\n    best_val_acc = 0.0  # Track the best validation accuracy\n    \n    model.train()  # Set model to training mode\n    for epoch in range(num_epochs):\n        running_loss = 0.0\n        running_corrects = 0\n        \n        # Training phase\n        for inputs, labels in train_loader:\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n            \n            # Zero the parameter gradients\n            optimizer.zero_grad()\n\n            # Forward pass\n            outputs = model(inputs)\n            loss = criterion(outputs, labels)\n\n            # Backward pass and optimization\n            loss.backward()\n            optimizer.step()\n\n            # Statistics\n            _, preds = torch.max(outputs, 1)\n            running_loss += loss.item() * inputs.size(0)\n            running_corrects += torch.sum(preds == labels.data)\n\n        epoch_loss = running_loss / len(train_data)\n        epoch_acc = running_corrects.double() / len(train_data)\n\n        print(f'Epoch {epoch + 1}/{num_epochs}, Loss: {epoch_loss:.4f}, Accuracy: {epoch_acc:.4f}')\n\n        # Validation phase\n        model.eval()  # Set model to evaluation mode\n        val_loss = 0.0\n        val_corrects = 0\n        with torch.no_grad():\n            for inputs, labels in val_loader:\n                inputs = inputs.to(device)\n                labels = labels.to(device)\n                outputs = model(inputs)\n                loss = criterion(outputs, labels)\n                \n                _, preds = torch.max(outputs, 1)\n                val_loss += loss.item() * inputs.size(0)\n                val_corrects += torch.sum(preds == labels.data)\n        \n        val_loss = val_loss / len(val_dataset)\n        val_acc = val_corrects.double() / len(val_dataset)\n        print(f'Validation Loss: {val_loss:.4f}, Validation Accuracy: {val_acc:.4f}')\n\n        # Check if this is the best model so far\n        if val_acc > best_val_acc:\n            best_val_acc = val_acc\n            # Save the model with the best validation accuracy\n            torch.save(model.state_dict(), \"/kaggle/working/ResModel.pt\")\n            print(\"Model saved with Validation Accuracy: {:.4f}\".format(best_val_acc))\n    print(\"Training complete. Best Validation Accuracy: {:.4f}\".format(best_val_acc))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-11T17:04:36.452837Z","iopub.execute_input":"2024-11-11T17:04:36.453518Z","iopub.status.idle":"2024-11-11T17:04:37.773306Z","shell.execute_reply.started":"2024-11-11T17:04:36.453477Z","shell.execute_reply":"2024-11-11T17:04:37.772486Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Train the model\n#train_model(base_model, train_loader, val_loader, criterion, optimizer, num_epochs=10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-11T15:16:15.311821Z","iopub.execute_input":"2024-11-11T15:16:15.312535Z","iopub.status.idle":"2024-11-11T16:14:09.926291Z","shell.execute_reply.started":"2024-11-11T15:16:15.312495Z","shell.execute_reply":"2024-11-11T16:14:09.925109Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"base_model.load_state_dict(torch.load(\"/kaggle/input/res-model/ResModel.pt\"))\n\n# 4. Predict on test data\ntest_df = pd.read_csv('../input/cassava-leaf-disease-classification/sample_submission.csv')\ntest_dataset = ImageDataset(test_df, \"/kaggle/input/cassava-leaf-disease-classification/test_images\", transform= data_transforms)\ntest_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)\n\n# Predict on test data\npredictions = []\nwith torch.no_grad():  # Disable gradient computation for inference\n    for images, _ in test_loader:\n        images = images.to(device)\n        outputs = base_model(images)\n        _, preds = torch.max(outputs, 1)\n        predictions.extend(preds.cpu().numpy())  # Store predictions\n\n# Convert predictions to a NumPy array\npredictions = np.array(predictions)\n    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-11T16:23:31.203118Z","iopub.execute_input":"2024-11-11T16:23:31.203563Z","iopub.status.idle":"2024-11-11T16:23:31.444808Z","shell.execute_reply.started":"2024-11-11T16:23:31.203521Z","shell.execute_reply":"2024-11-11T16:23:31.443918Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(len(predictions))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-11T16:25:00.818752Z","iopub.execute_input":"2024-11-11T16:25:00.819384Z","iopub.status.idle":"2024-11-11T16:25:00.823971Z","shell.execute_reply.started":"2024-11-11T16:25:00.819344Z","shell.execute_reply":"2024-11-11T16:25:00.823082Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 5. Create submission file\ntest_df['label'] = predictions\ntest_df.to_csv('submission.csv', index=False)\nprint(\"Submission file created!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-11T16:25:12.450995Z","iopub.execute_input":"2024-11-11T16:25:12.451386Z","iopub.status.idle":"2024-11-11T16:25:12.462392Z","shell.execute_reply.started":"2024-11-11T16:25:12.451345Z","shell.execute_reply":"2024-11-11T16:25:12.461292Z"}},"outputs":[],"execution_count":null}]}