{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.12"},"papermill":{"default_parameters":{},"duration":26.601064,"end_time":"2023-11-13T02:44:18.358611","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2023-11-13T02:43:51.757547","version":"2.4.0"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":61446,"databundleVersionId":6962461,"sourceType":"competition"},{"sourceId":6640479,"sourceType":"datasetVersion","datasetId":3833517},{"sourceId":6746686,"sourceType":"datasetVersion","datasetId":3884593},{"sourceId":6827935,"sourceType":"datasetVersion","datasetId":3926155},{"sourceId":6874344,"sourceType":"datasetVersion","datasetId":3950227},{"sourceId":7259757,"sourceType":"datasetVersion","datasetId":4207197},{"sourceId":7270449,"sourceType":"datasetVersion","datasetId":4214573},{"sourceId":147635265,"sourceType":"kernelVersion"}],"dockerImageVersionId":30627,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## 📂 Importing necessary libraries\n\n\nFork from https://www.kaggle.com/code/zulqarnainali/fork-of-lb-0-57/notebook","metadata":{}},{"cell_type":"code","source":"# 📂 Operating System and Garbage Collection\nimport os\nimport gc\n\n# 📷 Computer Vision Library for image processing\nimport cv2\n\n# 📊 Mathematical functions\nimport math\n\n# 📦 Python's built-in library for shallow and deep copy operations\nimport copy\n\n# ⏰ Time-related functions\nimport time\n\n# 🎲 Random number generation\nimport random\n\n# 🔍 File globbing utility\nimport glob\n\n# 🖼️ Image processing library\nfrom PIL import Image\n\n# 📊 Data manipulation library\nimport numpy as np\nimport pandas as pd\n\n# 🚀 Deep Learning Library - PyTorch\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torch.nn.functional as F\nfrom torch.optim import lr_scheduler\nfrom torch.utils.data import Dataset, DataLoader\nfrom torch.cuda import amp\nimport torchvision\n\n# 🛠️ Utility functions\nimport joblib\nfrom tqdm import tqdm\nfrom collections import defaultdict\n\n# 🧱 Sklearn - Machine learning library\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.model_selection import StratifiedKFold\n\n# 🌐 Image Models from torchvision and timm\nimport timm\n\n# 🌈 Augmentation library for image data\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\n# 🎨 Colored terminal text\nfrom colorama import Fore, Back, Style\nb_ = Fore.BLUE\nsr_ = Style.RESET_ALL\n\n# ⚠️ Ignore warnings\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\n# 🚨 For descriptive error messages during CUDA operations\nos.environ['CUDA_LAUNCH_BLOCKING'] = \"1\"\n","metadata":{"papermill":{"duration":8.038554,"end_time":"2023-11-13T02:44:03.310789","exception":false,"start_time":"2023-11-13T02:43:55.272235","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:28:09.418526Z","iopub.execute_input":"2023-12-28T12:28:09.419411Z","iopub.status.idle":"2023-12-28T12:28:15.892013Z","shell.execute_reply.started":"2023-12-28T12:28:09.419358Z","shell.execute_reply":"2023-12-28T12:28:15.891016Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 🛠️ Configuration parameters for the model and training process.\n\nCONFIG = {\n    \"seed\": 40,  # 🌱 Seed for reproducibility\n    \"img_size\": 2054,  # 🖼️ Image size for training\n    \"model_name\": \"tf_efficientnetv2_s_in21ft1k\",  # 🧠 Model architecture name\n    \"num_classes\": 5,  # 🎯 Number of output classes\n    \"valid_batch_size\": 4,  # 🚚 Batch size for validation\n    \"device\": torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\"),  # 🧭 Device for training (GPU if available, else CPU)\n}\n","metadata":{"papermill":{"duration":0.071669,"end_time":"2023-11-13T02:44:03.4033","exception":false,"start_time":"2023-11-13T02:44:03.331631","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:28:15.893671Z","iopub.execute_input":"2023-12-28T12:28:15.894109Z","iopub.status.idle":"2023-12-28T12:28:15.922566Z","shell.execute_reply.started":"2023-12-28T12:28:15.894078Z","shell.execute_reply":"2023-12-28T12:28:15.921709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 🌱 Function to set seed for random number generators, ensuring reproducibility.\n\ndef set_seed(seed=42):\n    np.random.seed(seed)  # 🎲 Set seed for NumPy\n    torch.manual_seed(seed)  # 🚀 Set seed for PyTorch on CPU\n    torch.cuda.manual_seed(seed)  # 🚀 Set seed for PyTorch on GPU\n    \n    # ⚙️ When running on the CuDNN backend, two further options must be set\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = False\n    \n    # 🔏 Set a fixed value for the hash seed\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    \n# 🌱 Set seed using the configured seed value\nset_seed(CONFIG['seed'])\n","metadata":{"papermill":{"duration":0.019962,"end_time":"2023-11-13T02:44:03.43038","exception":false,"start_time":"2023-11-13T02:44:03.410418","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:28:15.923765Z","iopub.execute_input":"2023-12-28T12:28:15.924067Z","iopub.status.idle":"2023-12-28T12:28:15.948104Z","shell.execute_reply.started":"2023-12-28T12:28:15.924041Z","shell.execute_reply":"2023-12-28T12:28:15.947327Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 🗂️ Directory paths and file locations for data and model-related files.\n\nROOT_DIR = '/kaggle/input/UBC-OCEAN'  # 📁 Root directory containing the dataset\n# TEST_DIR = '/kaggle/input/UBC-OCEAN/test_thumbnails'  # 📁 Test thumbnails directory\n# ALT_TEST_DIR = '/kaggle/input/UBC-OCEAN/test_images'  # 📁 Alternative test images directory\nTEST_DIR = '/kaggle/input/UBC-OCEAN/train_thumbnails'  # 📁 Test thumbnails directory\nALT_TEST_DIR = '/kaggle/input/UBC-OCEAN/train_images'  # 📁 Alternative test images directory\nModel_predict = '/kaggle/input/check-ponit007'  # 📁 Model prediction directory\nLABEL_ENCODER_BIN = \"/kaggle/input/ubcpytorchwith-classweights-training-fold1of5/label_encoder.pkl\"  # 📄 Label encoder binary file\nBEST_WEIGHT = \"/kaggle/input/baseline-0-36/Acc0.70_Loss1.0140_epoch29_tf_efficientnetv2_s_in21ft1k_0.36.bin\"  # 📄 Best weight file 1\nBEST_WEIGHT2 = \"/kaggle/input/ubc-efficienetnetb0-fold1of10-2048pix-thumbnails/Recall0.9178_Acc0.9437_Loss0.1685_epoch9.bin\"  # 📄 Best weight file 2\nBEST_WEIGHT3 = \"/kaggle/input/ubc-efficienetnetb0-fold1of10-2048pix-thumbnails/Recall0.8858_Acc0.9155_Loss0.2106_epoch1.bin\"  # 📄 Best weight file 3\nBEST_WEIGHT4 = \"/kaggle/input/ver-21-10/Acc0.50_Loss1.2095_epoch4.bin\"  # 📄 Best weight file 4\n","metadata":{"papermill":{"duration":0.014908,"end_time":"2023-11-13T02:44:03.452122","exception":false,"start_time":"2023-11-13T02:44:03.437214","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:28:15.950097Z","iopub.execute_input":"2023-12-28T12:28:15.950804Z","iopub.status.idle":"2023-12-28T12:28:15.956214Z","shell.execute_reply.started":"2023-12-28T12:28:15.950777Z","shell.execute_reply":"2023-12-28T12:28:15.955423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 📄 Function to get the file path for a test image given its ID.\n\ndef get_test_file_path(image_id):\n    # 📄 Check if the thumbnail file exists in the primary test directory\n    if os.path.exists(f\"{TEST_DIR}/{image_id}_thumbnail.png\"):\n        return f\"{TEST_DIR}/{image_id}_thumbnail.png\", 0  # 📄 Return the thumbnail file path\n    else:\n        return f\"{ALT_TEST_DIR}/{image_id}.png\", 1  # 📄 Return the alternative image file path\n","metadata":{"papermill":{"duration":0.015472,"end_time":"2023-11-13T02:44:03.47424","exception":false,"start_time":"2023-11-13T02:44:03.458768","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:28:15.957332Z","iopub.execute_input":"2023-12-28T12:28:15.957699Z","iopub.status.idle":"2023-12-28T12:28:15.97002Z","shell.execute_reply.started":"2023-12-28T12:28:15.957666Z","shell.execute_reply":"2023-12-28T12:28:15.969017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 📊 Reading test data from a CSV file and adding additional columns.\n\n# 📊 Read the test data CSV file into a DataFrame\ndf = pd.read_csv(f\"{ROOT_DIR}/train.csv\")\n\nimage_type = []\n\n# 🖼️ Add a new column 'file_path' by applying the get_test_file_path function to the 'image_id' column\nfor idx, row in df.iterrows():\n    result = get_test_file_path(row['image_id'])\n    df.loc[idx, 'file_path'] = result[0]\n    image_type.append(result[1])\n# df['file_path'] = df['image_id'].apply(get_test_file_path)\n\n# 🏷️ Add a dummy 'label' column with all values set to 0\ndf['label'] = 0  # 🤖 Dummy label for test data\n","metadata":{"papermill":{"duration":0.041286,"end_time":"2023-11-13T02:44:03.522376","exception":false,"start_time":"2023-11-13T02:44:03.48109","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:28:15.97115Z","iopub.execute_input":"2023-12-28T12:28:15.971429Z","iopub.status.idle":"2023-12-28T12:28:17.197409Z","shell.execute_reply.started":"2023-12-28T12:28:15.971401Z","shell.execute_reply":"2023-12-28T12:28:17.196632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2023-12-28T12:28:17.198801Z","iopub.execute_input":"2023-12-28T12:28:17.199064Z","iopub.status.idle":"2023-12-28T12:28:17.212418Z","shell.execute_reply.started":"2023-12-28T12:28:17.199041Z","shell.execute_reply":"2023-12-28T12:28:17.211525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 📊 Reading the sample submission data from a CSV file.\n\n# 📊 Read the sample submission CSV file into a DataFrame\ndf_sub = pd.read_csv(f\"{ROOT_DIR}/sample_submission.csv\")\n","metadata":{"papermill":{"duration":0.022531,"end_time":"2023-11-13T02:44:03.552076","exception":false,"start_time":"2023-11-13T02:44:03.529545","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:28:17.213425Z","iopub.execute_input":"2023-12-28T12:28:17.213691Z","iopub.status.idle":"2023-12-28T12:28:17.222311Z","shell.execute_reply.started":"2023-12-28T12:28:17.213668Z","shell.execute_reply":"2023-12-28T12:28:17.221415Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 📄 Loading the label encoder using joblib.\n\n# 📄 Load the label encoder from the specified binary file\nencoder = joblib.load(LABEL_ENCODER_BIN)\n","metadata":{"papermill":{"duration":0.017015,"end_time":"2023-11-13T02:44:03.575976","exception":false,"start_time":"2023-11-13T02:44:03.558961","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:28:17.223506Z","iopub.execute_input":"2023-12-28T12:28:17.223841Z","iopub.status.idle":"2023-12-28T12:28:17.2325Z","shell.execute_reply.started":"2023-12-28T12:28:17.223817Z","shell.execute_reply":"2023-12-28T12:28:17.231599Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 📄 Function to get cropped images based on specified conditions.\n\ndef get_cropped_images(file_path, image_id, th_area=1000):\n    # 🖼️ Open the image using the PIL library\n    image = Image.open(file_path)\n    \n    # 🔄 Calculate the aspect ratio\n    as_ratio = image.size[0] / image.size[1]\n    \n    sxs, exs, sys, eys = [], [], [], []\n    \n    if as_ratio >= 1.5:\n        # 💡 If aspect ratio is greater than or equal to 1.5, perform cropping\n        \n        # 🎭 Create a mask using maximum value condition\n        mask = np.max(np.array(image) > 0, axis=-1).astype(np.uint8)\n        \n        # 🖼️ Find connected components in the mask\n        retval, labels = cv2.connectedComponents(mask)\n        \n        if retval >= as_ratio:\n            # 🔄 Loop through connected components\n            x, y = np.meshgrid(np.arange(image.size[0]), np.arange(image.size[1]))\n            for label in range(1, retval):\n                # 🚫 Skip small components\n                area = np.sum(labels == label)\n                if area < th_area:\n                    continue\n                \n                # 🔄 Get coordinates of connected components\n                xs, ys = x[labels == label], y[labels == label]\n                \n                # 🎯 Calculate cropping boundaries\n                sx, ex = np.min(xs), np.max(xs)\n                cx = (sx + ex) // 2\n                crop_size = image.size[1]\n                sx = max(0, cx - crop_size // 2)\n                ex = min(sx + crop_size - 1, image.size[0] - 1)\n                sx = ex - crop_size + 1\n                sy, ey = 0, image.size[1] - 1\n                \n                # 📊 Append cropping boundaries to lists\n                sxs.append(sx)\n                exs.append(ex)\n                sys.append(sy)\n                eys.append(ey)\n        else:\n            # 🎯 If no connected components found, divide the image into equal parts\n            crop_size = image.size[1]\n            for i in range(int(as_ratio)):\n                sxs.append(i * crop_size)\n                exs.append((i + 1) * crop_size - 1)\n                sys.append(0)\n                eys.append(crop_size - 1)\n    else:\n        # 🎯 If aspect ratio is less than 1.5, use the entire image without cropping\n        sxs, exs, sys, eys = [0,], [image.size[0] - 1], [0,], [image.size[1] - 1]\n\n    # 📊 Create a DataFrame with image_id, file_path, and cropping boundaries\n    df_crop = pd.DataFrame()\n    df_crop[\"image_id\"] = [image_id] * len(sxs)\n    df_crop[\"file_path\"] = [file_path] * len(sxs)\n    df_crop[\"sx\"] = sxs\n    df_crop[\"ex\"] = exs\n    df_crop[\"sy\"] = sys\n    df_crop[\"ey\"] = eys\n    \n    return df_crop\n","metadata":{"papermill":{"duration":0.024171,"end_time":"2023-11-13T02:44:03.607376","exception":false,"start_time":"2023-11-13T02:44:03.583205","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:28:17.236062Z","iopub.execute_input":"2023-12-28T12:28:17.236312Z","iopub.status.idle":"2023-12-28T12:28:17.250557Z","shell.execute_reply.started":"2023-12-28T12:28:17.236291Z","shell.execute_reply":"2023-12-28T12:28:17.249619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 🔄 Loop through each row in the 'df' DataFrame and apply the get_cropped_images function.\n\n# 📊 Initialize an empty list to store the DataFrames returned by get_cropped_images\ndfs = []\n\nnew_image_type = []\n\n# 🔄 Loop through each row in the 'df' DataFrame\nndx = 0\nfor (file_path, image_id) in zip(df[\"file_path\"], df[\"image_id\"]):\n    # 📊 Append the DataFrame returned by get_cropped_images to the list\n    result = get_cropped_images(file_path, image_id)\n    dfs.append(result)\n    for i in range(len(result)):\n        new_image_type.append(image_type[ndx])\n    ndx += 1 \n\n# 📊 Concatenate the list of DataFrames into a single DataFrame\ndf_crop = pd.concat(dfs)\n\n# 🏷️ Add a dummy 'label' column with all values set to 0\ndf_crop[\"label\"] = 0  # 🤖 Dummy label for cropped images\n","metadata":{"papermill":{"duration":0.585144,"end_time":"2023-11-13T02:44:04.199892","exception":false,"start_time":"2023-11-13T02:44:03.614748","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:28:17.251672Z","iopub.execute_input":"2023-12-28T12:28:17.251931Z","iopub.status.idle":"2023-12-28T12:30:19.12402Z","shell.execute_reply.started":"2023-12-28T12:28:17.251908Z","shell.execute_reply":"2023-12-28T12:30:19.123148Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(df_crop)","metadata":{"execution":{"iopub.status.busy":"2023-12-28T12:30:19.125188Z","iopub.execute_input":"2023-12-28T12:30:19.125487Z","iopub.status.idle":"2023-12-28T12:30:19.131181Z","shell.execute_reply.started":"2023-12-28T12:30:19.125462Z","shell.execute_reply":"2023-12-28T12:30:19.130326Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(new_image_type)","metadata":{"execution":{"iopub.status.busy":"2023-12-28T12:30:19.132344Z","iopub.execute_input":"2023-12-28T12:30:19.132898Z","iopub.status.idle":"2023-12-28T12:30:19.142862Z","shell.execute_reply.started":"2023-12-28T12:30:19.132863Z","shell.execute_reply":"2023-12-28T12:30:19.141979Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 🔄 Remove duplicate rows based on specified columns and reset the index.\n\n# 📊 Drop duplicate rows in the 'df_crop' DataFrame based on the specified subset of columns\ndf_crop = df_crop.drop_duplicates(subset=[\"image_id\", \"sx\", \"ex\", \"sy\", \"ey\"]).reset_index(drop=True)\n","metadata":{"papermill":{"duration":0.026989,"end_time":"2023-11-13T02:44:04.23431","exception":false,"start_time":"2023-11-13T02:44:04.207321","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:30:19.143917Z","iopub.execute_input":"2023-12-28T12:30:19.144182Z","iopub.status.idle":"2023-12-28T12:30:19.161795Z","shell.execute_reply.started":"2023-12-28T12:30:19.14416Z","shell.execute_reply":"2023-12-28T12:30:19.160889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 📦 Custom dataset class for the UBC dataset.\n\nclass UBCDataset(Dataset):\n    def __init__(self, df, transforms=None):\n        # 📊 Initialize the dataset with DataFrame, file names, labels, and transformations\n        self.df = df\n        self.file_names = df['file_path'].values\n        self.labels = df['label'].values\n        self.transforms = transforms\n        self.sxs = df[\"sx\"].values\n        self.exs = df[\"ex\"].values\n        self.sys = df[\"sy\"].values\n        self.eys = df[\"ey\"].values\n        \n    def __len__(self):\n        # 🔄 Return the length of the dataset\n        return len(self.df)\n    \n    def __getitem__(self, index):\n        # 🔍 Get an item from the dataset based on the index\n        \n        # 📄 Get image path, cropping boundaries, and label\n        img_path = self.file_names[index]\n        sx, ex, sy, ey = self.sxs[index], self.exs[index], self.sys[index], self.eys[index]\n        \n        # 🖼️ Read and convert the image to RGB\n        img = cv2.imread(img_path)\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        \n        # 🔄 Crop the image based on cropping boundaries\n        img = img[sy:ey, sx:ex, :]\n        \n        # 🔍 Get the label\n        label = self.labels[index]\n        \n        # 🔄 Apply transformations if specified\n        if self.transforms:\n            img = self.transforms(image=img)[\"image\"]\n            \n        # 🔍 Return a dictionary containing the image and label as torch tensors\n        return {\n            'image': img,\n            'label': torch.tensor(label, dtype=torch.long)\n        }\n","metadata":{"papermill":{"duration":0.020623,"end_time":"2023-11-13T02:44:04.262244","exception":false,"start_time":"2023-11-13T02:44:04.241621","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:30:19.162955Z","iopub.execute_input":"2023-12-28T12:30:19.163222Z","iopub.status.idle":"2023-12-28T12:30:19.175681Z","shell.execute_reply.started":"2023-12-28T12:30:19.163199Z","shell.execute_reply":"2023-12-28T12:30:19.174682Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 🔄 Data transformations dictionary for validation images.\n\ndata_transforms = {\n    \"valid\": A.Compose([\n        # 🔄 Resize images to the specified size\n        A.Resize(CONFIG['img_size'], CONFIG['img_size']),\n        \n        # 🚀 Normalize pixel values of the image\n        A.Normalize(\n            mean=[0.485, 0.456, 0.406], \n            std=[0.229, 0.224, 0.225], \n            max_pixel_value=255.0, \n            p=1.0\n        ),\n        \n        # 🚀 Convert the image to a PyTorch tensor\n        ToTensorV2()\n    ], p=1.)\n}","metadata":{"papermill":{"duration":0.01697,"end_time":"2023-11-13T02:44:04.287059","exception":false,"start_time":"2023-11-13T02:44:04.270089","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:30:19.176705Z","iopub.execute_input":"2023-12-28T12:30:19.176951Z","iopub.status.idle":"2023-12-28T12:30:19.185832Z","shell.execute_reply.started":"2023-12-28T12:30:19.176929Z","shell.execute_reply":"2023-12-28T12:30:19.185021Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 🚀 Implementation of Generalized Mean Pooling (GeM) layer as a PyTorch module.\n\nclass GeM(nn.Module):\n    def __init__(self, p=3, eps=1e-6):\n        # 🔄 Initialize the GeM layer with parameters p and eps\n        super(GeM, self).__init__()\n        self.p = nn.Parameter(torch.ones(1) * p)\n        self.eps = eps\n\n    def forward(self, x):\n        # 🔍 Forward pass through the GeM layer\n        return self.gem(x, p=self.p, eps=self.eps)\n        \n    def gem(self, x, p=3, eps=1e-6):\n        # 🚀 Generalized Mean Pooling function\n        return F.avg_pool2d(x.clamp(min=eps).pow(p), (x.size(-2), x.size(-1))).pow(1./p)\n        \n    def __repr__(self):\n        # 🔤 Representation of the GeM layer\n        return self.__class__.__name__ + \\\n                '(' + 'p=' + '{:.4f}'.format(self.p.data.tolist()[0]) + \\\n                ', ' + 'eps=' + str(self.eps) + ')'\n","metadata":{"papermill":{"duration":0.019491,"end_time":"2023-11-13T02:44:04.313901","exception":false,"start_time":"2023-11-13T02:44:04.29441","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:30:19.186835Z","iopub.execute_input":"2023-12-28T12:30:19.187097Z","iopub.status.idle":"2023-12-28T12:30:19.19939Z","shell.execute_reply.started":"2023-12-28T12:30:19.187074Z","shell.execute_reply":"2023-12-28T12:30:19.198631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 🚀 Custom model class for UBC dataset based on the EfficientNet architecture.\n\nclass UBCModel(nn.Module):\n    def __init__(self, model_name, num_classes, pretrained=False, checkpoint_path=None):\n        # 🔄 Initialize the UBCModel with specified parameters\n        super(UBCModel, self).__init__()\n        \n        # 🚀 Create the specified model with or without pretraining\n        self.model = timm.create_model(model_name, pretrained=pretrained)\n\n        # 📏 Get the number of input features for the linear layer\n        in_features = self.model.classifier.in_features\n        \n        # 🔄 Replace the classifier and global pooling layers with Identity\n        self.model.classifier = nn.Identity()\n        self.model.global_pool = nn.Identity()\n        \n        # 🚀 Add Generalized Mean Pooling (GeM) layer\n        self.pooling = GeM()\n        \n        # 📏 Linear layer for final classification\n        self.linear = nn.Linear(in_features, num_classes)\n        \n        # 🔍 Softmax layer for probability distribution\n        self.softmax = nn.Softmax(dim=1)\n\n    def forward(self, images):\n        # 🔍 Forward pass through the UBCModel\n        features = self.model(images)\n        pooled_features = self.pooling(features).flatten(1)\n        output = self.linear(pooled_features)\n        return output\n\n# 🚀 Instantiate UBCModel instances with different weights\n# model = UBCModel('tf_efficientnetv2_s_in21ft1k', CONFIG['num_classes'])\n# model2 = UBCModel('tf_efficientnet_b0_ns', CONFIG['num_classes'])\n# model3 = UBCModel('tf_efficientnet_b0_ns', CONFIG['num_classes'])\n# model4 = UBCModel('tf_efficientnet_b0_ns', CONFIG['num_classes'])\n\n# # 📄 Load the weights into the models\n# model.load_state_dict(torch.load(BEST_WEIGHT))\n# model2.load_state_dict(torch.load(BEST_WEIGHT2))\n# model3.load_state_dict(torch.load(BEST_WEIGHT3))\n# model4.load_state_dict(torch.load(BEST_WEIGHT3))\n\n# # 🔄 Move models to the specified device (GPU if available, else CPU)\n# model.to(CONFIG['device'])\n# model2.to(CONFIG['device'])\n# model3.to(CONFIG['device'])\n# model4.to(CONFIG['device'])\nmodel = UBCModel('tf_efficientnet_b0_ns', CONFIG['num_classes'])\nmodel.load_state_dict(torch.load(\"/kaggle/input/ubc-efficienetnetb0-fold1of10-2048pix-thumbnails/Recall0.8858_Acc0.9155_Loss0.2106_epoch1.bin\"))\nmodel.to(CONFIG['device'])\n\nmodel1 = UBCModel('tf_efficientnet_b0_ns', CONFIG['num_classes'])\nmodel1.load_state_dict(torch.load(\"/kaggle/input/ubc-efficienetnetb0-fold1of10-2048pix-thumbnails/Recall0.9052_Acc0.9296_Loss0.1574_epoch5.bin\"))\nmodel1.to(CONFIG['device'])\n\nmodel2 = UBCModel('tf_efficientnet_b0_ns', CONFIG['num_classes'])\nmodel2.load_state_dict(torch.load(\"/kaggle/input/ubc-efficienetnetb0-fold1of10-2048pix-thumbnails/Recall0.9178_Acc0.9437_Loss0.1685_epoch9.bin\"))\nmodel2.to(CONFIG['device'])\n\nmodel3 = UBCModel('tf_efficientnet_b0_ns', CONFIG['num_classes'])\nmodel3.load_state_dict(torch.load(\"/kaggle/input/ubcpytorchwith-classweights-training-fold1of5/Acc0.63_Loss1.0573_epoch8.bin\"))\nmodel3.to(CONFIG['device'])\n\nmodel4 = UBCModel('tf_efficientnet_b0_ns', CONFIG['num_classes'])\nmodel4.load_state_dict(torch.load(\"/kaggle/input/ubcpytorchwith-classweights-training-fold1of5/Acc0.65_Loss1.0547_epoch12.bin\"))\nmodel4.to(CONFIG['device'])\n\n\nmodel5 = UBCModel('tf_efficientnet_b0_ns', CONFIG['num_classes'])\nmodel5.load_state_dict(torch.load(\"/kaggle/input/ubcpytorchwith-classweights-training-fold1of5/Acc0.66_Loss1.0244_epoch16.bin\"))\nmodel5.to(CONFIG['device'])","metadata":{"papermill":{"duration":5.537674,"end_time":"2023-11-13T02:44:09.859078","exception":false,"start_time":"2023-11-13T02:44:04.321404","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:30:19.200656Z","iopub.execute_input":"2023-12-28T12:30:19.200972Z","iopub.status.idle":"2023-12-28T12:30:24.841141Z","shell.execute_reply.started":"2023-12-28T12:30:19.200943Z","shell.execute_reply":"2023-12-28T12:30:24.840197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_crop","metadata":{"execution":{"iopub.status.busy":"2023-12-28T12:30:24.845607Z","iopub.execute_input":"2023-12-28T12:30:24.845955Z","iopub.status.idle":"2023-12-28T12:30:24.859234Z","shell.execute_reply.started":"2023-12-28T12:30:24.845929Z","shell.execute_reply":"2023-12-28T12:30:24.858408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(new_image_type)","metadata":{"execution":{"iopub.status.busy":"2023-12-28T12:30:24.860405Z","iopub.execute_input":"2023-12-28T12:30:24.860706Z","iopub.status.idle":"2023-12-28T12:30:24.874674Z","shell.execute_reply.started":"2023-12-28T12:30:24.860674Z","shell.execute_reply":"2023-12-28T12:30:24.873819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 创建空的 DataFrame\ndf_crop_0 = pd.DataFrame()\ndf_crop_1 = pd.DataFrame()\n\n# 根据 new_image_type 列的值将 df_crop 分割成两个 DataFrame\nfor i in range(len(df_crop)):\n    if new_image_type[i] == 0:\n        df_crop_0 = pd.concat([df_crop_0, df_crop.iloc[[i]]])\n    elif new_image_type[i] == 1:\n        df_crop_1 = pd.concat([df_crop_1, df_crop.iloc[[i]]])\n","metadata":{"execution":{"iopub.status.busy":"2023-12-28T12:30:24.875941Z","iopub.execute_input":"2023-12-28T12:30:24.876294Z","iopub.status.idle":"2023-12-28T12:30:25.294174Z","shell.execute_reply.started":"2023-12-28T12:30:24.876242Z","shell.execute_reply":"2023-12-28T12:30:25.293174Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_crop_0","metadata":{"execution":{"iopub.status.busy":"2023-12-28T12:30:25.295415Z","iopub.execute_input":"2023-12-28T12:30:25.296627Z","iopub.status.idle":"2023-12-28T12:30:25.314029Z","shell.execute_reply.started":"2023-12-28T12:30:25.29659Z","shell.execute_reply":"2023-12-28T12:30:25.313088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if df_crop_1.empty:\n    df_crop_1 = pd.DataFrame(columns=df_crop_0.columns)","metadata":{"execution":{"iopub.status.busy":"2023-12-28T12:30:25.315484Z","iopub.execute_input":"2023-12-28T12:30:25.315956Z","iopub.status.idle":"2023-12-28T12:30:25.321358Z","shell.execute_reply.started":"2023-12-28T12:30:25.31592Z","shell.execute_reply":"2023-12-28T12:30:25.320276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_crop_1","metadata":{"execution":{"iopub.status.busy":"2023-12-28T12:30:25.322612Z","iopub.execute_input":"2023-12-28T12:30:25.322958Z","iopub.status.idle":"2023-12-28T12:30:25.340049Z","shell.execute_reply.started":"2023-12-28T12:30:25.322928Z","shell.execute_reply":"2023-12-28T12:30:25.339017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 🚀 Create a DataLoader for the UBC test dataset using the UBCDataset class.\n\n# 🚀 Instantiate the UBCDataset with the cropped DataFrame and validation transforms\n\n# test_dataset = UBCDataset(df_crop, transforms=data_transforms[\"valid\"])\ntest_dataset_0 = UBCDataset(df_crop_0, transforms=data_transforms[\"valid\"])\ntest_dataset_1 = UBCDataset(df_crop_1, transforms=data_transforms[\"valid\"])\n\n# 🚚 Create a DataLoader for the test dataset with specified batch size and other settings\n# test_loader = DataLoader(\n#     test_dataset, \n#     batch_size=CONFIG['valid_batch_size'], \n#     num_workers=2,  # 🔍 Number of workers for data loading\n#     shuffle=False,   # 🔄 Do not shuffle the data for test set\n#     pin_memory=True  # 🚀 Pin the memory for faster GPU data transfer\n# )\ntest_loader_0 = DataLoader(\n    test_dataset_0, \n    batch_size=CONFIG['valid_batch_size'], \n    num_workers=2,  # 🔍 Number of workers for data loading\n    shuffle=False,   # 🔄 Do not shuffle the data for test set\n    pin_memory=True  # 🚀 Pin the memory for faster GPU data transfer\n)\ntest_loader_1 = DataLoader(\n    test_dataset_1, \n    batch_size=CONFIG['valid_batch_size'], \n    num_workers=2,  # 🔍 Number of workers for data loading\n    shuffle=False,   # 🔄 Do not shuffle the data for test set\n    pin_memory=True  # 🚀 Pin the memory for faster GPU data transfer\n)\n\n","metadata":{"papermill":{"duration":0.017005,"end_time":"2023-11-13T02:44:09.884413","exception":false,"start_time":"2023-11-13T02:44:09.867408","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:30:25.341246Z","iopub.execute_input":"2023-12-28T12:30:25.342191Z","iopub.status.idle":"2023-12-28T12:30:25.353701Z","shell.execute_reply.started":"2023-12-28T12:30:25.342157Z","shell.execute_reply":"2023-12-28T12:30:25.352795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 🔍 Inference loop for making predictions on the test set.\n\n# 📊 Initialize an empty list to store the predictions\npreds_0 = []\n\n# 🔍 Iterate through the test DataLoader\nwith torch.no_grad():\n    bar = tqdm(enumerate(test_loader_0), total=len(test_loader_0))\n    for step, data in bar:\n        # 🔄 Move the input images to the specified device\n        images = data['image'].to(CONFIG[\"device\"], dtype=torch.float)\n        \n        # 🔍 Forward pass through the models and combine the outputs\n        outputs3 = model3(images)\n        outputs4 = model4(images)\n        outputs5 = model5(images)\n        \n#         outputs = (outputs3 + outputs4 + outputs5) / 3\n        outputs = (outputs3 + outputs4) / 2\n        \n        # 🔄 Combine the model outputs using specified weights\n#         outputs = 0.66 * (0.34 * outputs4 + 0.7 * outputs2) + 0.322 * (0.4 * outputs1 + 0.6 * outputs3)\n        \n        # 🚀 Apply softmax to obtain probability distribution\n        outputs = model.softmax(outputs)\n        \n        # 📊 Append the predictions to the list\n        preds_0.append(outputs.detach().cpu().numpy())\n\n# 📊 Stack the predictions into a single NumPy array\npreds_0 = np.vstack(preds_0)\nprint(preds_0.shape)\n","metadata":{"papermill":{"duration":5.8547,"end_time":"2023-11-13T02:44:15.747075","exception":false,"start_time":"2023-11-13T02:44:09.892375","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T12:30:25.354993Z","iopub.execute_input":"2023-12-28T12:30:25.356036Z","iopub.status.idle":"2023-12-28T12:33:31.010908Z","shell.execute_reply.started":"2023-12-28T12:30:25.356003Z","shell.execute_reply":"2023-12-28T12:33:31.009774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 🔍 Inference loop for making predictions on the test set.\n\n# 📊 Initialize an empty list to store the predictions\npreds_1 = []\n\n# 🔍 Iterate through the test DataLoader\nwith torch.no_grad():\n    bar = tqdm(enumerate(test_loader_1), total=len(test_loader_1))\n    for step, data in bar:\n        # 🔄 Move the input images to the specified device\n        images = data['image'].to(CONFIG[\"device\"], dtype=torch.float)\n        data['']\n        \n        # 🔍 Forward pass through the models and combine the outputs\n        outputs = model(images)\n        outputs1 = model1(images)\n        outputs2 = model2(images)\n        \n#         outputs = (outputs + outputs1 + outputs2) / 3\n        outputs = (outputs + outputs1) / 2\n        \n        # 🔄 Combine the model outputs using specified weights\n#         outputs = 0.66 * (0.34 * outputs4 + 0.7 * outputs2) + 0.322 * (0.4 * outputs1 + 0.6 * outputs3)\n        \n        # 🚀 Apply softmax to obtain probability distribution\n        outputs = model.softmax(outputs)\n        \n        # 📊 Append the predictions to the list\n        preds_1.append(outputs.detach().cpu().numpy())\n\n# 📊 Stack the predictions into a single NumPy array\nif len(preds_1) == 0:\n    preds_1 = np.array(preds_1)\nelse:\n    preds_1 = np.vstack(preds_1)\nprint(preds_1.shape)","metadata":{"execution":{"iopub.status.busy":"2023-12-28T12:33:31.012594Z","iopub.execute_input":"2023-12-28T12:33:31.013014Z","iopub.status.idle":"2023-12-28T12:33:39.62258Z","shell.execute_reply.started":"2023-12-28T12:33:31.012973Z","shell.execute_reply":"2023-12-28T12:33:39.621428Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 🔄 Post-processing to get final predictions from the softmax outputs.\n\n# 📊 Create columns for each category in the DataFrame based on predictions\n# for i in range(preds.shape[-1]):\n#     df_crop[f\"cat{i}\"] = preds[:, i]\nfor i in range(preds_0.shape[-1]):\n    df_crop_0[f\"cat{i}\"] = preds_0[:, i]\nfor i in range(preds_1.shape[-1]):\n    df_crop_1[f\"cat{i}\"] = preds_1[:, i]\n# df_crop = pd.concat([df_crop_0, df_crop_1])\n# df_crop = df_crop.sort_values('image_id') \n\n# 📊 Create a dictionary to store the final label for each image\ndict_label_0 = {}\n\n# 🔍 Iterate through the DataFrame grouped by \"image_id\"\nfor image_id, gdf in df_crop_0.groupby(\"image_id\"):\n    # 🔄 Assign the final label as the index of the maximum value in each category\n    dict_label_0[image_id] = np.argmax(gdf[[f\"cat{i}\" for i in range(preds_0.shape[-1])]].values.max(axis=0))\n\ndict_label_1 = {}\n\n# 🔍 Iterate through the DataFrame grouped by \"image_id\"\nfor image_id, gdf in df_crop_1.groupby(\"image_id\"):\n    # 🔄 Assign the final label as the index of the maximum value in each category\n    dict_label_1[image_id] = np.argmax(gdf[[f\"cat{i}\" for i in range(preds_1.shape[-1])]].values.max(axis=0))\n\n\npreds = []\n# 📊 Update the 'preds' array with the final labels for each image\nfor image_id in df['image_id'].values:\n    if image_id in dict_label_0:\n        preds.append(dict_label_0[image_id])\n    elif image_id in dict_label_1:\n        preds.append(dict_label_1[image_id])\n# preds_0 = np.array([dict_label_0[image_id] for image_id in df[\"image_id\"].values])\n# preds_1 = np.array([dict_label_1[image_id] for image_id in df[\"image_id\"].values])\npreds = np.array(preds)","metadata":{"papermill":{"duration":0.027482,"end_time":"2023-11-13T02:44:15.783349","exception":false,"start_time":"2023-11-13T02:44:15.755867","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T07:15:58.403815Z","iopub.execute_input":"2023-12-28T07:15:58.404582Z","iopub.status.idle":"2023-12-28T07:15:58.421899Z","shell.execute_reply.started":"2023-12-28T07:15:58.404543Z","shell.execute_reply":"2023-12-28T07:15:58.42105Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_sub","metadata":{"execution":{"iopub.status.busy":"2023-12-28T07:15:58.422973Z","iopub.execute_input":"2023-12-28T07:15:58.423269Z","iopub.status.idle":"2023-12-28T07:15:58.440489Z","shell.execute_reply.started":"2023-12-28T07:15:58.423244Z","shell.execute_reply":"2023-12-28T07:15:58.438904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder\nOther = [\"Other\"]\nencoder_other = LabelEncoder()\nOther = encoder_other.fit_transform(Other)\nprediction = []\nfor pred in tqdm(preds):\n    if pred.max() > 0.5:\n        pred_labels = encoder.inverse_transform(np.argmax([pred], 1)).item()\n        prediction.append(pred_labels)\n    else:\n        pred_labels = encoder_other.inverse_transform([0]).item()\n        prediction.append(pred_labels)\nprediction","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 📊 Inverse transform the predicted labels using the label encoder and create the submission CSV.\n\n# 📊 Inverse transform the predicted labels using the label encoder\n# pred_labels = encoder.inverse_transform(preds)\n\n# 📊 Update the 'label' column in the submission DataFrame\ndf_sub[\"label\"] = prediction\n\n# 📄 Save the submission DataFrame to a CSV file\ndf_sub.to_csv(\"submission.csv\", index=False)\n","metadata":{"papermill":{"duration":0.020861,"end_time":"2023-11-13T02:44:15.812793","exception":false,"start_time":"2023-11-13T02:44:15.791932","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-12-28T07:15:58.442084Z","iopub.execute_input":"2023-12-28T07:15:58.442707Z","iopub.status.idle":"2023-12-28T07:15:58.449931Z","shell.execute_reply.started":"2023-12-28T07:15:58.44267Z","shell.execute_reply":"2023-12-28T07:15:58.449036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}