{"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":13836,"databundleVersionId":1718836,"sourceType":"competition"},{"sourceId":152465,"sourceType":"modelInstanceVersion","modelInstanceId":129489,"modelId":152347},{"sourceId":153892,"sourceType":"modelInstanceVersion","modelInstanceId":130735,"modelId":153571},{"sourceId":156589,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":133078,"modelId":155847},{"sourceId":157805,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":134103,"modelId":156870},{"sourceId":157842,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":134136,"modelId":156906},{"sourceId":157843,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":134137,"modelId":156907},{"sourceId":158712,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":134891,"modelId":157635},{"sourceId":158980,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":135133,"modelId":157866},{"sourceId":160668,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":136613,"modelId":159339},{"sourceId":160669,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":136614,"modelId":159340},{"sourceId":168241,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":143132,"modelId":165735},{"sourceId":168242,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":143133,"modelId":165736}],"dockerImageVersionId":30787,"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\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":"2024-11-16T04:26:58.141365Z","iopub.execute_input":"2024-11-16T04:26:58.141733Z","iopub.status.idle":"2024-11-16T04:27:08.242767Z","shell.execute_reply.started":"2024-11-16T04:26:58.141692Z","shell.execute_reply":"2024-11-16T04:27:08.241589Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torchvision import models, transforms\nfrom torchvision.models import EfficientNet_V2_S_Weights\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.model_selection import train_test_split\nfrom PIL import Image\nimport pandas as pd\nimport os\nfrom tqdm import tqdm\nimport copy\nimport cv2\nimport torch.nn.functional as F\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:08.244434Z","iopub.execute_input":"2024-11-16T04:27:08.244886Z","iopub.status.idle":"2024-11-16T04:27:34.131435Z","shell.execute_reply.started":"2024-11-16T04:27:08.244849Z","shell.execute_reply":"2024-11-16T04:27:34.130447Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"num_tta = 5","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:34.132658Z","iopub.execute_input":"2024-11-16T04:27:34.133132Z","iopub.status.idle":"2024-11-16T04:27:34.137172Z","shell.execute_reply.started":"2024-11-16T04:27:34.133096Z","shell.execute_reply":"2024-11-16T04:27:34.136323Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_image_dir = \"/kaggle/input/cassava-leaf-disease-classification/test_images\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:34.139345Z","iopub.execute_input":"2024-11-16T04:27:34.139642Z","iopub.status.idle":"2024-11-16T04:27:34.152132Z","shell.execute_reply.started":"2024-11-16T04:27:34.139605Z","shell.execute_reply":"2024-11-16T04:27:34.151300Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_df = pd.read_csv('../input/cassava-leaf-disease-classification/sample_submission.csv')\ntest_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:34.153440Z","iopub.execute_input":"2024-11-16T04:27:34.154002Z","iopub.status.idle":"2024-11-16T04:27:34.182076Z","shell.execute_reply.started":"2024-11-16T04:27:34.153958Z","shell.execute_reply":"2024-11-16T04:27:34.181130Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"efficientnet_transforms = A.Compose([\n    A.CLAHE(clip_limit=2.0, tile_grid_size=(8, 8), p=1.0),\n    A.Resize(384, 384),  # Resize to match EfficientNetV2-S input size\n    A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)),\n    ToTensorV2()\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:34.183278Z","iopub.execute_input":"2024-11-16T04:27:34.183604Z","iopub.status.idle":"2024-11-16T04:27:34.190274Z","shell.execute_reply.started":"2024-11-16T04:27:34.183570Z","shell.execute_reply":"2024-11-16T04:27:34.189325Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CassavaTestDataset(Dataset):\n    def __init__(self, dataframe, image_dir):\n        self.dataframe = dataframe\n        self.image_dir = image_dir\n\n    def __len__(self):\n        return len(self.dataframe)\n\n    def __getitem__(self, idx):\n        img_name = self.dataframe.iloc[idx, 0]  # Image ID\n        img_path = os.path.join(self.image_dir, img_name)\n\n        # Load the image using OpenCV\n        image = cv2.imread(img_path)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n\n        return image, img_name","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:34.191520Z","iopub.execute_input":"2024-11-16T04:27:34.192158Z","iopub.status.idle":"2024-11-16T04:27:34.199553Z","shell.execute_reply.started":"2024-11-16T04:27:34.192115Z","shell.execute_reply":"2024-11-16T04:27:34.198617Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tta_transform = A.Compose([\n    \n    A.ShiftScaleRotate(shift_limit=0.1, scale_limit=0.1, rotate_limit=20, p=0.7),\n\n    # Color augmentations to vary hue, saturation, brightness, and contrast\n    A.HueSaturationValue(hue_shift_limit=10, sat_shift_limit=15, val_shift_limit=10, p=0.5),\n    A.RandomBrightnessContrast(brightness_limit=0.2, contrast_limit=0.2, p=0.5),\n\n    # Horizontal flip to create left-right symmetry\n    A.HorizontalFlip(p=0.5),\n\n    # Gaussian noise to make the model robust to minor random pixel variations\n    A.GaussNoise(var_limit=(10.0, 50.0), p=0.4),\n\n    # Blur for minor blurring, simulating slightly out-of-focus images\n    #A.Blur(blur_limit=3, p=0.3),\n\n    # Distortion to create warping, making the model more robust to shape changes\n    #A.OpticalDistortion(distort_limit=0.05, shift_limit=0.05, p=0.3),\n\n    # Coarse dropout to randomly mask out patches in the image, similar to cutout\n    #A.CoarseDropout(max_holes=8, max_height=20, max_width=20, min_holes=1, min_height=10, min_width=10, fill_value=0, p=0.5),\n\n    # Randomly resized crop\n    A.RandomResizedCrop(384, 384, scale=(0.8, 1.0), p=1.0),\n\n    # Normalization for EfficientNetV2\n    A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)),\n    ToTensorV2()\n    ])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:34.200718Z","iopub.execute_input":"2024-11-16T04:27:34.201022Z","iopub.status.idle":"2024-11-16T04:27:34.214044Z","shell.execute_reply.started":"2024-11-16T04:27:34.200991Z","shell.execute_reply":"2024-11-16T04:27:34.213103Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"common_transforms = [\n    A.ShiftScaleRotate(shift_limit=0.1, scale_limit=0.1, rotate_limit=20, p=0.7),\n    A.HueSaturationValue(hue_shift_limit=10, sat_shift_limit=15, val_shift_limit=10, p=0.5),\n    A.RandomBrightnessContrast(brightness_limit=0.2, contrast_limit=0.2, p=0.5),\n    A.HorizontalFlip(p=0.5),\n    A.GaussNoise(var_limit=(10.0, 50.0), p=0.4),\n    # Uncomment and adjust additional augmentations as needed\n]\n\n# EfficientNet TTA Transform\ntta_transform_efficientnet = A.Compose(\n    common_transforms + [\n        A.RandomResizedCrop(384, 384, scale=(0.8, 1.0), p=1.0),\n        A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)),\n        ToTensorV2(),\n    ]\n)\n\n# MobileNet TTA Transform\ntta_transform_mobilenet = A.Compose(\n    common_transforms + [\n        A.RandomResizedCrop(224, 224, scale=(0.8, 1.0), p=1.0),\n        A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)),\n        ToTensorV2(),\n    ]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:34.215225Z","iopub.execute_input":"2024-11-16T04:27:34.215845Z","iopub.status.idle":"2024-11-16T04:27:34.226800Z","shell.execute_reply.started":"2024-11-16T04:27:34.215797Z","shell.execute_reply":"2024-11-16T04:27:34.225980Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def tta_predict_single_model(model, image, tta_transform, device, n_tta=5):\n    model.eval()\n    tta_predictions = []\n\n    # Confirm the image has 3 channels\n    if image.shape[-1] != 3:\n        raise ValueError(\"Image must have 3 channels (H, W, 3)\")\n\n    with torch.no_grad():\n        for _ in range(n_tta):\n            # Apply TTA transformation\n            augmented = tta_transform(image=image)[\"image\"]\n            augmented = augmented.unsqueeze(0).to(device)  # Add batch dimension and move to device\n\n            # Get model predictions and convert to probabilities\n            output = model(augmented)\n            probs = F.softmax(output, dim=1)\n            tta_predictions.append(probs)\n\n    # Average probabilities from TTA transformations\n    avg_probs = torch.mean(torch.stack(tta_predictions), dim=0)\n\n    return avg_probs","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:34.230293Z","iopub.execute_input":"2024-11-16T04:27:34.230643Z","iopub.status.idle":"2024-11-16T04:27:34.237738Z","shell.execute_reply.started":"2024-11-16T04:27:34.230611Z","shell.execute_reply":"2024-11-16T04:27:34.236809Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def identity_collate(batch):\n    return batch\ntest_dataset = CassavaTestDataset(\n    test_df,\n    test_image_dir,\n)\ntest_loader = DataLoader(\n    test_dataset,\n    batch_size=1,\n    shuffle=False,\n    num_workers=0,\n    collate_fn=identity_collate  # Use custom collate function\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:34.238799Z","iopub.execute_input":"2024-11-16T04:27:34.239077Z","iopub.status.idle":"2024-11-16T04:27:34.246325Z","shell.execute_reply.started":"2024-11-16T04:27:34.239047Z","shell.execute_reply":"2024-11-16T04:27:34.245488Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:34.247425Z","iopub.execute_input":"2024-11-16T04:27:34.247770Z","iopub.status.idle":"2024-11-16T04:27:34.300067Z","shell.execute_reply.started":"2024-11-16T04:27:34.247729Z","shell.execute_reply":"2024-11-16T04:27:34.299026Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"resnet_model = models.resnet50(pretrained=False)\nnum_ftrs = resnet_model.fc.in_features\nresnet_model.fc = nn.Linear(num_ftrs, 5)\n\n# Load your trained model weights\nresnet_model.load_state_dict(torch.load(\"/kaggle/input/casava-aug/pytorch/default/1/cassava_leaf_best_model_fine_aug.pth\"))\nresnet_model = resnet_model.to(device)\n\n# Set the model to evaluation mode\nresnet_model.eval()  ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:34.301385Z","iopub.execute_input":"2024-11-16T04:27:34.301730Z","iopub.status.idle":"2024-11-16T04:27:36.150475Z","shell.execute_reply.started":"2024-11-16T04:27:34.301696Z","shell.execute_reply":"2024-11-16T04:27:36.149464Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"efficientnet_model_1 = models.efficientnet_v2_s(weights=None)\nnum_features_efficientnet = efficientnet_model_1.classifier[1].in_features\nefficientnet_model_1.classifier[1] = nn.Linear(num_features_efficientnet, 5)\nefficientnet_model_1.classifier = nn.Sequential(\n    nn.Dropout(p=0.8),  \n    nn.Linear(num_features_efficientnet, 5)\n)\n# Load your custom weights\nefficientnet_model_1.load_state_dict(torch.load(\"/kaggle/input/eff-5/pytorch/default/1/Eff_best5.pth\", map_location=device))\nefficientnet_model_1 = efficientnet_model_1.to(device)\nefficientnet_model_1.eval()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:36.151874Z","iopub.execute_input":"2024-11-16T04:27:36.152638Z","iopub.status.idle":"2024-11-16T04:27:37.592053Z","shell.execute_reply.started":"2024-11-16T04:27:36.152589Z","shell.execute_reply":"2024-11-16T04:27:37.591165Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"efficientnet_model_7 = models.efficientnet_v2_s(weights=None)\nnum_features_efficientnet = efficientnet_model_7.classifier[1].in_features\nefficientnet_model_7.classifier = nn.Sequential(\n    nn.Dropout(p=0.8),  \n    nn.Linear(num_features_efficientnet, 5)\n)\n\n# Load your custom weights\nefficientnet_model_7.load_state_dict(torch.load(\"/kaggle/input/eff-13-last/pytorch/default/1/Eff13.pth\", map_location=device))\nefficientnet_model_7 = efficientnet_model_7.to(device)\nefficientnet_model_7.eval()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:37.593558Z","iopub.execute_input":"2024-11-16T04:27:37.593949Z","iopub.status.idle":"2024-11-16T04:27:38.889521Z","shell.execute_reply.started":"2024-11-16T04:27:37.593905Z","shell.execute_reply":"2024-11-16T04:27:38.888561Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"efficientnet_model_8 = models.efficientnet_v2_s(weights=None)\nnum_features_efficientnet = efficientnet_model_8.classifier[1].in_features\nefficientnet_model_8.classifier = nn.Sequential(\n    nn.Dropout(p=0.8),  \n    nn.Linear(num_features_efficientnet, 5)\n)\n\n# Load your custom weights\nefficientnet_model_8.load_state_dict(torch.load(\"/kaggle/input/eff-6/pytorch/default/1/Eff_best6.pth\", map_location=device))\nefficientnet_model_8 = efficientnet_model_8.to(device)\nefficientnet_model_8.eval()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:38.890809Z","iopub.execute_input":"2024-11-16T04:27:38.891207Z","iopub.status.idle":"2024-11-16T04:27:40.094205Z","shell.execute_reply.started":"2024-11-16T04:27:38.891161Z","shell.execute_reply":"2024-11-16T04:27:40.093237Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mobile_model = models.mobilenet_v3_large(weights=None)  # or weights='DEFAULT' for newer versions\n\n# Get the number of input features and hidden dimension for the classifier\nnum_features = mobile_model.classifier[0].in_features  # Should be 960\nhidden_dim = mobile_model.classifier[0].out_features    # Should be 1280\n\n# Define the number of classes in your dataset\n\n\n# Modify the classifier to match the number of classes with the desired dropout\nmobile_model.classifier = nn.Sequential(\n    nn.Linear(num_features, hidden_dim),\n    nn.Hardswish(inplace=True),\n    nn.Dropout(p=0.7),  # 50% dropout probability\n    nn.Linear(hidden_dim, 5)\n)\n\nmobile_model.load_state_dict(torch.load(\"/kaggle/input/mob-2-last/pytorch/default/1/Effb2.pth\", map_location=device))\nmobile_model= mobile_model.to(device)\nmobile_model.eval()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:40.095284Z","iopub.execute_input":"2024-11-16T04:27:40.095558Z","iopub.status.idle":"2024-11-16T04:27:40.422704Z","shell.execute_reply.started":"2024-11-16T04:27:40.095528Z","shell.execute_reply":"2024-11-16T04:27:40.421824Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"weight_efficientnet7 = 0.88\nweight_mobilenet = 0.84\n\n# Normalize weights\ntotal_weight = weight_efficientnet7 + weight_mobilenet\nweight_efficientnet7 /= total_weight\nweight_mobilenet /= total_weight\n\n# Main loop\nensemble_predictions = []\nimage_names = []\n\nwith torch.no_grad():\n    for batch in test_loader:\n        # Since batch_size=1 and using identity_collate, batch is a list containing one tuple (image, img_name)\n        image, img_name = batch[0]\n\n        # Ensure the image is a NumPy array (Albumentations expects NumPy arrays)\n        if isinstance(image, torch.Tensor):\n            image = image.numpy()\n        elif not isinstance(image, np.ndarray):\n            image = np.array(image)\n\n        # Get TTA predictions from each model with their respective transforms\n        probs_efficientnet7 = tta_predict_single_model(\n            efficientnet_model_7, image, tta_transform_efficientnet, device, n_tta=5\n        )\n\n        probs_mobilenet = tta_predict_single_model(\n            mobile_model, image, tta_transform_mobilenet, device, n_tta=5\n        )\n\n        # Weighted average of predictions from all models\n        combined_probs = (weight_efficientnet7 * probs_efficientnet7) + (weight_mobilenet * probs_mobilenet)\n\n        # Get the final prediction\n        final_pred = combined_probs.argmax(dim=1).cpu().item()\n\n        # Store predictions\n        ensemble_predictions.append(final_pred)\n        image_names.append(img_name)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:40.424111Z","iopub.execute_input":"2024-11-16T04:27:40.424791Z","iopub.status.idle":"2024-11-16T04:27:41.927623Z","shell.execute_reply.started":"2024-11-16T04:27:40.424744Z","shell.execute_reply":"2024-11-16T04:27:41.926837Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission_df = pd.DataFrame({\n    'image_id': image_names,         # Image IDs from the test set\n    'label': ensemble_predictions     # Predicted labels for each image\n})\n\n# Save the DataFrame as a CSV file without the index\nsubmission_df.to_csv('submission.csv', index=False)\n\nprint(\"Submission file saved as 'submission.csv'\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-16T04:27:41.928842Z","iopub.execute_input":"2024-11-16T04:27:41.929522Z","iopub.status.idle":"2024-11-16T04:27:41.938474Z","shell.execute_reply.started":"2024-11-16T04:27:41.929474Z","shell.execute_reply":"2024-11-16T04:27:41.937465Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}