{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# 1.Importing libraries 📚","metadata":{}},{"cell_type":"code","source":"!pip install efficientnet_pytorch","metadata":{"_kg_hide-output":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from efficientnet_pytorch import EfficientNet\nimport torch\nimport torch.nn as nn\nfrom torchvision import transforms\nfrom torch.utils.data import Dataset, DataLoader, Subset\nfrom torchvision.datasets import ImageFolder\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom PIL import Image\nimport os\nimport glob\nimport random\nfrom sklearn.metrics import f1_score","metadata":{"execution":{"iopub.status.busy":"2023-08-31T15:50:38.872468Z","iopub.execute_input":"2023-08-31T15:50:38.872870Z","iopub.status.idle":"2023-08-31T15:50:38.879134Z","shell.execute_reply.started":"2023-08-31T15:50:38.872836Z","shell.execute_reply":"2023-08-31T15:50:38.878065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\ndevice","metadata":{"execution":{"iopub.status.busy":"2023-08-31T15:09:28.383076Z","iopub.execute_input":"2023-08-31T15:09:28.383517Z","iopub.status.idle":"2023-08-31T15:09:28.422219Z","shell.execute_reply.started":"2023-08-31T15:09:28.383482Z","shell.execute_reply":"2023-08-31T15:09:28.421227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":" # 2. Data Pre-processing 🏋️‍♂️","metadata":{}},{"cell_type":"markdown","source":"# 2.1 Normaliziton and Augmentation 😐","metadata":{}},{"cell_type":"code","source":"# Create output mappings\nclass_to_idx = {'beneign': 0, 'malignant': 1, 'normal': 2}\nidx_to_class = {v: k for k, v in class_to_idx.items()}","metadata":{"execution":{"iopub.status.busy":"2023-08-31T15:09:28.499085Z","iopub.execute_input":"2023-08-31T15:09:28.499396Z","iopub.status.idle":"2023-08-31T15:09:28.504523Z","shell.execute_reply.started":"2023-08-31T15:09:28.499371Z","shell.execute_reply":"2023-08-31T15:09:28.503340Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2.2 Defining The Dataset Class ⇡\n","metadata":{}},{"cell_type":"code","source":"import os\nfrom torch.utils.data import Dataset\nfrom torchvision import transforms\nfrom PIL import Image\n\nclass CustomDataset(Dataset):\n    def __init__(self, root_folder, transform=None):\n        self.root_folder = root_folder\n        self.transform = transform\n        self.class_folders = [f for f in os.listdir(root_folder) if os.path.isdir(os.path.join(root_folder, f))]\n        self.samples = self._prepare_samples()\n\n    def _prepare_samples(self):\n        samples = []\n        for class_folder in self.class_folders:\n            class_path = os.path.join(self.root_folder, class_folder)\n            subfolders = [f for f in os.listdir(class_path) if os.path.isdir(os.path.join(class_path, f))]\n            for subfolder in subfolders:\n                subfolder_path = os.path.join(class_path, subfolder)\n                image_files = [f for f in os.listdir(subfolder_path) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]\n                for image_file in image_files:\n                    image_path = os.path.join(subfolder_path, image_file)\n                    samples.append((image_path, class_folder))\n        return samples\n\n    def __len__(self):\n        return len(self.samples)\n\n    def __getitem__(self, idx):\n        image_path, key = self.samples[idx]\n        label = class_to_idx[key]\n        image = Image.open(image_path).convert(\"RGB\")  # Convert to RGB format\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n\n# Define data transform\ntransform = transforms.Compose([\n    transforms.RandomHorizontalFlip(),\n    \n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Create the custom dataset\nroot_folder = '/kaggle/input/bioverse-hackathon-a/train'\ndataset = CustomDataset(root_folder, transform=transform)\n\n# Create a data loader\nbatch_size = 64\nfullLoader = DataLoader(dataset, batch_size=batch_size, shuffle=True)\n\n# Iterate through the data loader\n# for images, labels in data_loader:\n#     print(f\"Batch of {batch_size} images and labels: {images.shape}, {labels}\")","metadata":{"execution":{"iopub.status.busy":"2023-08-31T17:25:05.631540Z","iopub.execute_input":"2023-08-31T17:25:05.632241Z","iopub.status.idle":"2023-08-31T17:25:05.746207Z","shell.execute_reply.started":"2023-08-31T17:25:05.632208Z","shell.execute_reply":"2023-08-31T17:25:05.745158Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create index splits\ntrain_size = 0.8\n\nds_len = len(dataset)\nindices = list(range(ds_len))\nsplit = int(np.floor(train_size * ds_len))\nnp.random.shuffle(indices)\n\ntrain_idx, val_idx = indices[:split], indices[split:]\n\n# Split dataset\ntrain = Subset(dataset, indices=train_idx)\nval = Subset(dataset, indices=val_idx)\n\n# Create PyTorch dataloaders\ntrainLoader = DataLoader(train, batch_size=batch_size)\nvalLoader = DataLoader(val, batch_size=batch_size)\n\nloader = {\n    'train' : trainLoader,\n    'val'   : valLoader\n}\n\ndataset_sizes = {'train': len(train),\n                 'val': len(val)}","metadata":{"execution":{"iopub.status.busy":"2023-08-31T15:09:29.003093Z","iopub.execute_input":"2023-08-31T15:09:29.003690Z","iopub.status.idle":"2023-08-31T15:09:29.011610Z","shell.execute_reply.started":"2023-08-31T15:09:29.003656Z","shell.execute_reply":"2023-08-31T15:09:29.010526Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(dataset_sizes)","metadata":{"execution":{"iopub.status.busy":"2023-08-31T15:09:32.106212Z","iopub.execute_input":"2023-08-31T15:09:32.106578Z","iopub.status.idle":"2023-08-31T15:09:32.112547Z","shell.execute_reply.started":"2023-08-31T15:09:32.106548Z","shell.execute_reply":"2023-08-31T15:09:32.111570Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Picking the model \n* Adjusting the hyparmeteres\n* Batch Size \n* We Used Effiecnt net🔝","metadata":{}},{"cell_type":"code","source":"model1 =  EfficientNet.from_pretrained('efficientnet-b0').to(device)","metadata":{"execution":{"iopub.status.busy":"2023-08-31T15:09:33.992625Z","iopub.execute_input":"2023-08-31T15:09:33.993058Z","iopub.status.idle":"2023-08-31T15:09:39.000723Z","shell.execute_reply.started":"2023-08-31T15:09:33.993027Z","shell.execute_reply":"2023-08-31T15:09:38.999735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3.1 Defining the get  embeddings Fucntion 🚆","metadata":{}},{"cell_type":"code","source":"def get_train_embeddings(model, loader):\n    model.eval()\n    \n    output = []\n    with torch.no_grad(): # disable gradient tracking\n        for images, labels in loader:\n            images, labels = images.to(device), labels.to(device)\n            \n            # Forward pass -> Outputs vector embeddings\n            embeddings = model(images)\n            output.append(embeddings)\n    \n    output = torch.cat(output, dim=0)\n    return output\n\ndata = get_train_embeddings(model1, fullLoader)","metadata":{"execution":{"iopub.status.busy":"2023-08-31T15:26:59.043494Z","iopub.execute_input":"2023-08-31T15:26:59.043877Z","iopub.status.idle":"2023-08-31T15:27:36.282186Z","shell.execute_reply.started":"2023-08-31T15:26:59.043846Z","shell.execute_reply":"2023-08-31T15:27:36.281159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data.size()","metadata":{"execution":{"iopub.status.busy":"2023-08-31T15:27:36.284163Z","iopub.execute_input":"2023-08-31T15:27:36.284516Z","iopub.status.idle":"2023-08-31T15:27:36.290839Z","shell.execute_reply.started":"2023-08-31T15:27:36.284483Z","shell.execute_reply":"2023-08-31T15:27:36.289938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TestDataset(Dataset):\n    def __init__(self, folder_path, transform=None):\n        self.folder_path = folder_path\n        self.image_list = os.listdir(folder_path)\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.image_list)\n\n    def __getitem__(self, idx):\n        image_name = self.image_list[idx]\n        image_path = os.path.join(self.folder_path, image_name)\n        image = Image.open(image_path).convert('RGB')\n        \n        if self.transform:\n            image = self.transform(image)\n        \n        return image\n\n# Define the transformation to apply to the images\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n])\n\n# Path to the folder containing images\ndata_folder_path = '/kaggle/input/bioverse-hackathon-a/test'\n\n# Create a custom dataset\ntesting = TestDataset(folder_path=data_folder_path, transform=transform)\n\n# Create a data loader\nbatch_size = 64\ntestLoader = DataLoader(testing, batch_size=batch_size, shuffle=False)\n","metadata":{"execution":{"iopub.status.busy":"2023-08-31T17:26:07.180233Z","iopub.execute_input":"2023-08-31T17:26:07.180631Z","iopub.status.idle":"2023-08-31T17:26:07.193226Z","shell.execute_reply.started":"2023-08-31T17:26:07.180600Z","shell.execute_reply":"2023-08-31T17:26:07.192280Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4. Predicting the test data 😎","metadata":{}},{"cell_type":"code","source":"def test(model, training_data):\n    model.eval()\n    \n    output = []\n    with torch.no_grad(): # disable gradient tracking\n        for images in testLoader:\n            images = images.to(device)\n            \n            # Forward pass -> Outputs vector embeddings\n            embeddings = model(images)\n            output.append(embeddings)\n    \n    output = torch.cat(output, dim=0)\n    \n    # Classify using KNN\n    predictions = []\n    for o in output:\n        o = o.unsqueeze(0)\n        dist = torch.norm(training_data - o, dim=1, p=None)\n        knn = dist.topk(4, largest=False)\n        \n        votes = []\n        for i in range(len(knn.values)):\n            vote = idx_to_class[dataset.__getitem__(knn.indices[i].item())[1]]\n            votes.append(vote)\n            \n        pred = max(votes, key=votes.count)\n        predictions.append(pred)\n\n    return predictions","metadata":{"execution":{"iopub.status.busy":"2023-08-31T17:37:00.086450Z","iopub.execute_input":"2023-08-31T17:37:00.086851Z","iopub.status.idle":"2023-08-31T17:37:00.096317Z","shell.execute_reply.started":"2023-08-31T17:37:00.086817Z","shell.execute_reply":"2023-08-31T17:37:00.095110Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = test(model1, data)","metadata":{"execution":{"iopub.status.busy":"2023-08-31T17:39:35.948505Z","iopub.execute_input":"2023-08-31T17:39:35.948912Z","iopub.status.idle":"2023-08-31T17:40:57.415007Z","shell.execute_reply.started":"2023-08-31T17:39:35.948878Z","shell.execute_reply":"2023-08-31T17:40:57.413955Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"files = os.listdir('/kaggle/input/bioverse-hackathon-a/test')\nfiles","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5.2 Creating the Submission File 💾","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nsubmission = pd.DataFrame()\nsubmission['filename'] = files\nsubmission['class'] = preds\nsubmission.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-31T17:45:29.524486Z","iopub.execute_input":"2023-08-31T17:45:29.524969Z","iopub.status.idle":"2023-08-31T17:45:29.550789Z","shell.execute_reply.started":"2023-08-31T17:45:29.524929Z","shell.execute_reply":"2023-08-31T17:45:29.549811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv(\"solution.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2023-08-31T17:46:42.660054Z","iopub.execute_input":"2023-08-31T17:46:42.660483Z","iopub.status.idle":"2023-08-31T17:46:42.673536Z","shell.execute_reply.started":"2023-08-31T17:46:42.660446Z","shell.execute_reply":"2023-08-31T17:46:42.672354Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## References\n- https://ravimashru.dev/blog/2021-09-26-pytorch-subset/","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}],"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}}