{"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"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":52254,"databundleVersionId":9674523,"sourceType":"competition"},{"sourceId":6331238,"sourceType":"datasetVersion","datasetId":3644255}],"dockerImageVersionId":30528,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# import packages\nimport os\nimport pickle\nfrom tqdm.notebook import tqdm\nimport random\nfrom tabulate import tabulate\n\nimport cv2\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport numpy as np\nimport pandas as pd\nimport pydicom\nimport matplotlib.pyplot as plt\nimport torchvision.transforms.v2 as t\n\nfrom sklearn.model_selection import KFold, StratifiedKFold\nfrom sklearn.metrics import accuracy_score, roc_auc_score\nfrom torch.utils.data import Dataset, DataLoader, Subset\nfrom torch.optim.lr_scheduler import ReduceLROnPlateau\nfrom torch.optim import Adam\nfrom torchvision import models\nfrom torchvision.transforms.v2 import Resize, Compose, RandomHorizontalFlip, ColorJitter, RandomAffine, RandomErasing, ToTensor","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-11-10T15:00:54.484098Z","iopub.execute_input":"2024-11-10T15:00:54.484472Z","iopub.status.idle":"2024-11-10T15:00:54.491972Z","shell.execute_reply.started":"2024-11-10T15:00:54.484444Z","shell.execute_reply":"2024-11-10T15:00:54.490981Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TRAIN_IMG_PATH = '/kaggle/input/rsna-2023-atd-reduced-256-5mm/reduced_256_tickness_5'\nTEST_IMG_PATH = '/kaggle/input/rsna-2023-abdominal-trauma-detection/test_images'\nTRAIN_DF_PATH = '/kaggle/input/rsna-2023-abdominal-trauma-detection/train.csv'","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:00:54.493733Z","iopub.execute_input":"2024-11-10T15:00:54.494033Z","iopub.status.idle":"2024-11-10T15:00:54.501203Z","shell.execute_reply.started":"2024-11-10T15:00:54.494007Z","shell.execute_reply":"2024-11-10T15:00:54.500387Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def fetch_img_paths(train_img_path):\n    img_paths = []\n    \n    print('Scanning directories...')\n    for patient in tqdm(os.listdir(train_img_path)):\n        for scan in os.listdir(os.path.join(TRAIN_IMG_PATH, patient)):\n            scans = []\n            for img in os.listdir(os.path.join(TRAIN_IMG_PATH, patient, scan)):\n                scans.append(os.path.join(TRAIN_IMG_PATH, patient, scan, img))\n            \n            img_paths.append(scans)\n            \n    return img_paths","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:00:54.502546Z","iopub.execute_input":"2024-11-10T15:00:54.502999Z","iopub.status.idle":"2024-11-10T15:00:54.510347Z","shell.execute_reply.started":"2024-11-10T15:00:54.502966Z","shell.execute_reply":"2024-11-10T15:00:54.509231Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def select_elements_with_spacing(input_list, spacing):\n    \n    \"\"\"\n    Selects elements with a specified spacing from a given list.\n\n    Args:\n        input_list (list): The input list from which elements will be selected.\n        spacing (int): The spacing between selected elements.\n\n    Returns:\n        list: A list of selected elements from the input list.\n\n    Raises:\n        ValueError: If the input list does not contain at least 4 * spacing elements.\n    \"\"\"\n \n    if len(input_list) < spacing * 4:\n        raise ValueError(\"List should contain at least 4 * spacing elements.\")\n        \n        \n    # We want to select elements in the middle part of the abdomen\n    lower_bound = int(len(input_list) * 0.4)\n    upper_bound = int(len(input_list) * 0.6)\n\n    spacing = (upper_bound - lower_bound) // 3\n    \n    # start_index = random.randint(lower_bound, upper_bound)\n    \n    selected_indices = [lower_bound, lower_bound + spacing, lower_bound + (2*spacing), upper_bound]\n    \n    selected_elements = [input_list[index] for index in selected_indices]\n    \n    return selected_elements","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:00:54.512539Z","iopub.execute_input":"2024-11-10T15:00:54.513399Z","iopub.status.idle":"2024-11-10T15:00:54.521785Z","shell.execute_reply.started":"2024-11-10T15:00:54.513371Z","shell.execute_reply":"2024-11-10T15:00:54.520941Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def standardize_pixel_array(dicom_image):\n    \"\"\"\n    Standardizes a DICOM pixel array by applying various transformations.\n    \n    Args:\n        dicom_path (str): Path to the DICOM image file.\n        \n    Returns:\n        np.ndarray: The standardized pixel array of the DICOM image.\n    \"\"\"\n    pixel_array = dicom_image.pixel_array\n    \n    if dicom_image.PixelRepresentation == 1:\n        bit_shift = dicom_image.BitsAllocated - dicom_image.BitsStored\n        dtype = pixel_array.dtype \n        new_array = (pixel_array << bit_shift).astype(dtype) >>  bit_shift\n        pixel_array = pydicom.pixel_data_handlers.util.apply_modality_lut(new_array, dicom_image)\n\n    if dicom_image.PhotometricInterpretation == \"MONOCHROME1\":\n        pixel_array = 1 - pixel_array\n\n    # transform to hounsfield units\n    intercept = dicom_image.RescaleIntercept\n    slope = dicom_image.RescaleSlope\n    pixel_array = pixel_array * slope + intercept\n\n    # windowing\n    window_center = int(dicom_image.WindowCenter)\n    window_width = int(dicom_image.WindowWidth)\n    img_min = window_center - window_width // 2\n    img_max = window_center + window_width // 2\n    pixel_array = pixel_array.copy()\n    pixel_array[pixel_array < img_min] = img_min\n    pixel_array[pixel_array > img_max] = img_max\n\n    # normalization\n    if pixel_array.max() == pixel_array.min():\n        pixel_array = np.zeros_like(pixel_array)  # Handle case of constant array\n    else:\n        pixel_array = (pixel_array - pixel_array.min()) / (pixel_array.max() - pixel_array.min())\n\n    return pixel_array","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:00:54.52286Z","iopub.execute_input":"2024-11-10T15:00:54.523169Z","iopub.status.idle":"2024-11-10T15:00:54.532294Z","shell.execute_reply.started":"2024-11-10T15:00:54.523145Z","shell.execute_reply":"2024-11-10T15:00:54.53145Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def preprocess_jpeg(jpeg_path):\n    \n    img = cv2.imread(jpeg_path)\n    greyscale = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)/255\n    \n    return greyscale","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:00:54.53354Z","iopub.execute_input":"2024-11-10T15:00:54.533809Z","iopub.status.idle":"2024-11-10T15:00:54.542101Z","shell.execute_reply.started":"2024-11-10T15:00:54.533784Z","shell.execute_reply":"2024-11-10T15:00:54.541315Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# dataset\nclass AbdominalData(Dataset):\n    \"\"\"\n    Custom dataset class for handling abdominal trauma data classification.\n    \n    Args:\n        df_path (str): Path to the CSV file containing patient labels.\n        current_fold (int): The current fold for cross-validation.\n        num_fold (int, optional): Total number of folds for cross-validation. Default is 5.\n    \"\"\"\n    \n    def __init__(self, df_path, current_fold, num_fold = 5):\n        \n        super().__init__()\n        \n        # collect all the image instance paths\n        self.img_paths = fetch_img_paths(TRAIN_IMG_PATH)\n                \n        self.df = pd.read_csv(df_path)\n        \n        self.num_fold = num_fold\n        self.current_fold = current_fold\n        self.kf = KFold(n_splits=num_fold)\n        \n        self.transform = Compose([\n#                             Resize((256, 256), antialias=True),\n                            RandomHorizontalFlip(),  # Randomly flip images left-right\n                            ColorJitter(brightness=0.2),  # Randomly adjust brightness\n                            ColorJitter(contrast=0.2),  # Randomly adjust contrast\n                            RandomAffine(degrees=0, shear=10),  # Apply shear transformation\n                            RandomAffine(degrees=0, scale=(0.8, 1.2)),  # Apply zoom transformation\n                            RandomErasing(p=0.2, scale=(0.02, 0.2)), # Coarse dropout\n                            ToTensor(),\n                        ])\n    \n    def __len__(self):\n        \"\"\"\n        Returns the total number of samples in the dataset.\n        \"\"\"\n        \n        return len(self.img_paths)\n    \n    def __getitem__(self, idx):\n        \"\"\"\n        Retrieves a sample from the dataset by index.\n        \n        Args:\n            idx (int): Index of the dataset to retrieve.\n        \n        Returns:\n            dict: A dictionary containing the image data and labels for different abdominal structures.\n        \"\"\"\n        \n        # sample 4 image instances\n        dicom_images = select_elements_with_spacing(self.img_paths[idx],\n                                                    spacing = 2)\n        patient_id = dicom_images[0].split('/')[-3]\n        images = []\n        \n        for d in dicom_images:\n            image = preprocess_jpeg(d)\n            images.append(image)\n            \n        images = np.stack(images)\n        image = torch.tensor(images, dtype = torch.float).unsqueeze(dim = 1)\n        \n        image = self.transform(image).squeeze(dim = 1)\n        \n        label = self.df[self.df.patient_id == int(patient_id)].values[0][1:-1]\n        \n        # labels\n        bowel = np.argmax(label[0:2], keepdims = True)\n        extravasation = np.argmax(label[2:4], keepdims = True)\n        kidney = np.argmax(label[4:7], keepdims = False)\n        liver = np.argmax(label[7:10], keepdims = False)\n        spleen = np.argmax(label[10:], keepdims = False)\n        \n        \n        return {\n            'image': image,\n            'bowel': bowel,\n            'extravasation': extravasation,\n            'kidney': kidney,\n            'liver': liver,\n            'spleen': spleen,\n        }\n    \n    def get_splits(self):\n        \"\"\"\n        Splits the dataset into training and validation subsets based on the current fold.\n        \n        Returns:\n            tuple: A tuple containing the training and validation subsets.\n        \"\"\"\n        \n        fold_data = list(self.kf.split(self.img_paths))\n        train_indices, val_indices = fold_data[self.current_fold]\n\n        train_data = self._get_subset(train_indices)\n        val_data = self._get_subset(val_indices)\n        \n        return train_data, val_data\n\n    def _get_subset(self, indices):\n        \"\"\"\n        Returns a subset of the dataset based on the provided indices.\n        \n        Args:\n            indices (list): List of indices to include in the subset.\n        \n        Returns:\n            Subset: A subset of the dataset.\n        \"\"\"\n        return Subset(self, indices)","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:00:54.657195Z","iopub.execute_input":"2024-11-10T15:00:54.657525Z","iopub.status.idle":"2024-11-10T15:00:54.675768Z","shell.execute_reply.started":"2024-11-10T15:00:54.657493Z","shell.execute_reply":"2024-11-10T15:00:54.674859Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class MetricsCalculator:\n    \n    def __init__(self, mode = 'binary'):\n        \n        self.probabilities = []\n        self.predictions = []\n        self.targets = []\n        \n        self.mode = mode\n    \n    def update(self, logits, target):\n        \"\"\"\n        Update the metrics calculator with predicted values and corresponding targets.\n        \n        Args:\n            predicted (torch.Tensor): Predicted values.\n            target (torch.Tensor): Ground truth targets.\n        \"\"\"\n        if self.mode == 'binary':\n            probabilities = torch.sigmoid(logits)\n            predicted = (probabilities > 0.5)\n        else:\n            probabilities = F.softmax(logits, dim = 1)\n            predicted = torch.argmax(probabilities, dim=1)\n            \n        self.probabilities.extend(probabilities.detach().cpu().numpy())\n        self.predictions.extend(predicted.detach().cpu().numpy())\n        self.targets.extend(target.detach().cpu().numpy())\n    \n    def reset(self):\n        \"\"\"Reset the stored predictions and targets.\"\"\"\n        \n        self.probabilities = []\n        self.predictions = []\n        self.targets = []\n    \n    def compute_accuracy(self):\n        \"\"\"\n        Compute the accuracy metric.\n        \n        Returns:\n            float: Accuracy.\n        \"\"\"\n        return accuracy_score(self.targets, self.predictions)\n    \n    def compute_auc(self):\n        \"\"\"\n        Compute the AUC (Area Under the Curve) metric.\n        \n        Returns:\n            float: AUC.\n        \"\"\"\n        if self.mode == 'multi':\n            return roc_auc_score(self.targets, self.probabilities, multi_class = 'ovo', labels=[0, 1, 2])\n    \n        else:\n            return roc_auc_score(self.targets, self.probabilities)","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:00:54.677334Z","iopub.execute_input":"2024-11-10T15:00:54.677605Z","iopub.status.idle":"2024-11-10T15:00:54.689711Z","shell.execute_reply.started":"2024-11-10T15:00:54.677582Z","shell.execute_reply":"2024-11-10T15:00:54.688792Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision.models as models\n\nclass SelfAttention(nn.Module):\n    def __init__(self, in_channels):\n        super(SelfAttention, self).__init__()\n        self.attention = nn.MultiheadAttention(embed_dim=in_channels, num_heads=1, batch_first=True)\n\n    def forward(self, x):\n        batch_size, channels, height, width = x.size()\n        x = x.view(batch_size, channels, -1).transpose(1, 2)  # (batch_size, height*width, channels)\n        attn_output, _ = self.attention(x, x, x)\n        x = attn_output.transpose(1, 2).view(batch_size, channels, height, width)  # (batch_size, channels, height, width)\n        return x\n\nclass CNNModel(nn.Module):\n    def __init__(self):\n        super(CNNModel, self).__init__()\n        \n        # Chuyển đầu vào có 4 kênh thành 3 kênh\n        self.input = nn.Conv2d(4, 3, kernel_size=3, padding=1)  # Giữ lớp này như bạn yêu cầu\n        \n        # Sử dụng EfficientNetB0 làm backbone\n        model = models.efficientnet_b0(weights='IMAGENET1K_V1')\n        self.features = model.features\n        \n        # Thêm self-attention\n        self.self_attention = SelfAttention(1280)  # Sử dụng self-attention sau khi trích xuất đặc trưng\n        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n        \n        # Các lớp phân loại\n        self.bowel = nn.Linear(1280, 1)\n        self.extravasation = nn.Linear(1280, 1)\n        self.kidney = nn.Linear(1280, 3)\n        self.liver = nn.Linear(1280, 3)\n        self.spleen = nn.Linear(1280, 3)\n\n    def forward(self, x):\n        # Chuyển đầu vào có 4 kênh thành 3 kênh\n        x = self.input(x)\n        \n        # Trích xuất đặc trưng từ EfficientNetB0\n        x = self.features(x)\n        \n        # Áp dụng self-attention\n        x = self.self_attention(x)\n        \n        # Adaptive average pooling\n        x = self.avgpool(x)\n        \n        # Chuyển đổi thành vector một chiều\n        x = torch.flatten(x, 1)\n        \n        # Phân loại các nhãn\n        bowel = self.bowel(x)\n        extravasation = self.extravasation(x)\n        kidney = self.kidney(x)\n        liver = self.liver(x)\n        spleen = self.spleen(x)\n        \n        return bowel, extravasation, kidney, liver, spleen\n\n","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:00:54.691105Z","iopub.execute_input":"2024-11-10T15:00:54.691441Z","iopub.status.idle":"2024-11-10T15:00:54.704542Z","shell.execute_reply.started":"2024-11-10T15:00:54.69141Z","shell.execute_reply":"2024-11-10T15:00:54.703633Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Tạo mô hình và chuyển nó lên GPU\nmodel = CNNModel().to('cuda')\n","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:00:54.706875Z","iopub.execute_input":"2024-11-10T15:00:54.7073Z","iopub.status.idle":"2024-11-10T15:00:54.926301Z","shell.execute_reply.started":"2024-11-10T15:00:54.707268Z","shell.execute_reply":"2024-11-10T15:00:54.925502Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BATCH_SIZE = 16\nNUM_EPOCHS = 1\nLR = 1e-4","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:00:54.927371Z","iopub.execute_input":"2024-11-10T15:00:54.927647Z","iopub.status.idle":"2024-11-10T15:00:54.932199Z","shell.execute_reply.started":"2024-11-10T15:00:54.927622Z","shell.execute_reply":"2024-11-10T15:00:54.931198Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data_0, val_data_0 = AbdominalData('/kaggle/input/rsna-2023-abdominal-trauma-detection/train_2024.csv', current_fold=0).get_splits()\ntrain_data_1, val_data_1 = AbdominalData('/kaggle/input/rsna-2023-abdominal-trauma-detection/train_2024.csv', current_fold=1).get_splits()\ntrain_data_2, val_data_2 = AbdominalData('/kaggle/input/rsna-2023-abdominal-trauma-detection/train_2024.csv', current_fold=2).get_splits()\ntrain_data_3, val_data_3 = AbdominalData('/kaggle/input/rsna-2023-abdominal-trauma-detection/train_2024.csv', current_fold=3).get_splits()\ntrain_data_4, val_data_4 = AbdominalData('/kaggle/input/rsna-2023-abdominal-trauma-detection/train_2024.csv', current_fold=4).get_splits()\n\ntrain_dataloader_0 = DataLoader(train_data_0,batch_size = BATCH_SIZE, shuffle = True)\nval_dataloader_0 = DataLoader(val_data_0,batch_size = BATCH_SIZE, shuffle = False)\ntrain_dataloader_1 = DataLoader(train_data_1,batch_size = BATCH_SIZE, shuffle = True)\nval_dataloader_1 = DataLoader(val_data_1,batch_size = BATCH_SIZE, shuffle = False)\ntrain_dataloader_2 = DataLoader(train_data_2,batch_size = BATCH_SIZE, shuffle = True)\nval_dataloader_2 = DataLoader(val_data_2,batch_size = BATCH_SIZE, shuffle = False)\ntrain_dataloader_3 = DataLoader(train_data_3,batch_size = BATCH_SIZE, shuffle = True)\nval_dataloader_3 = DataLoader(val_data_3,batch_size = BATCH_SIZE, shuffle = False)\ntrain_dataloader_4 = DataLoader(train_data_4,batch_size = BATCH_SIZE, shuffle = True)\nval_dataloader_4 = DataLoader(val_data_4,batch_size = BATCH_SIZE, shuffle = False)","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:00:54.933351Z","iopub.execute_input":"2024-11-10T15:00:54.933613Z","iopub.status.idle":"2024-11-10T15:01:24.313671Z","shell.execute_reply.started":"2024-11-10T15:00:54.93359Z","shell.execute_reply":"2024-11-10T15:01:24.312714Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer = torch.optim.Adam(model.parameters(), lr = LR)\nbce_b = nn.BCEWithLogitsLoss(pos_weight = torch.tensor([2.0]).to('cuda'))\nbce_e = nn.BCEWithLogitsLoss(pos_weight = torch.tensor([4.0]).to('cuda'))\ncce = nn.CrossEntropyLoss(label_smoothing = 0.05, weight = torch.tensor([1.0, 2.0, 4.0]).to('cuda'))\nscheduler = ReduceLROnPlateau(optimizer, mode='min', patience=5, factor=0.5, verbose=True)","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:01:24.315063Z","iopub.execute_input":"2024-11-10T15:01:24.315949Z","iopub.status.idle":"2024-11-10T15:01:24.32708Z","shell.execute_reply.started":"2024-11-10T15:01:24.315908Z","shell.execute_reply":"2024-11-10T15:01:24.326075Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# initialize metrics objects\ntrain_acc_bowel = MetricsCalculator('binary')\ntrain_acc_extravasation = MetricsCalculator('binary')\ntrain_acc_liver = MetricsCalculator('multi')\ntrain_acc_kidney = MetricsCalculator('multi')\ntrain_acc_spleen = MetricsCalculator('multi')\n\nval_acc_bowel = MetricsCalculator('binary')\nval_acc_extravasation = MetricsCalculator('binary')\nval_acc_liver = MetricsCalculator('multi')\nval_acc_kidney = MetricsCalculator('multi')\nval_acc_spleen = MetricsCalculator('multi')","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:01:24.328606Z","iopub.execute_input":"2024-11-10T15:01:24.329584Z","iopub.status.idle":"2024-11-10T15:01:24.3366Z","shell.execute_reply.started":"2024-11-10T15:01:24.329535Z","shell.execute_reply":"2024-11-10T15:01:24.335589Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"prev_val_best_loss = float('inf')\n\ndataloaders = [(train_dataloader_0, val_dataloader_0),\n               (train_dataloader_1, val_dataloader_1),\n               (train_dataloader_2, val_dataloader_2), \n               (train_dataloader_3, val_dataloader_3),\n               (train_dataloader_4, val_dataloader_4)]\n\nfor epoch in range(NUM_EPOCHS):\n    \n    # training\n    model.train()\n    \n    train_loss = 0.0\n    val_loss = 0.0\n    \n    print(f'Epoch: [{epoch+1}/{NUM_EPOCHS}]')\n    \n    train_dataloader, val_dataloader = dataloaders[epoch%5]\n    \n    print(f'Fold: {epoch%5}')\n    \n    for batch_idx, batch_data in enumerate(tqdm(train_dataloader)):\n        \n        inputs = batch_data['image'].to('cuda')\n        bowel = batch_data['bowel'].to('cuda')\n        extravasation = batch_data['extravasation'].to('cuda')\n        liver = batch_data['liver'].to('cuda')\n        kidney = batch_data['kidney'].to('cuda')\n        spleen = batch_data['spleen'].to('cuda')\n        \n        optimizer.zero_grad()\n        b, e, k, l, s = model(inputs)\n        b_loss = bce_b(b, bowel.float())\n        e_loss = bce_e(e, extravasation.float())\n        l_loss = cce(l, liver)\n        k_loss = cce(k, kidney)\n        s_loss = cce(s, spleen)\n        \n        total_loss = b_loss + e_loss + l_loss + k_loss + s_loss\n        total_loss.backward()\n        \n        optimizer.step()\n        \n        # calculate training metrics\n        train_loss += total_loss.item()\n        train_acc_bowel.update(b, bowel)\n        train_acc_extravasation.update(e, extravasation)\n        train_acc_liver.update(l, liver)\n        train_acc_kidney.update(k, kidney)\n        train_acc_spleen.update(s, spleen)\n    \n    train_loss = train_loss/(batch_idx+1)\n    \n    # validation\n    model.eval()\n    running_loss = 0.0\n    \n    for batch_idx, batch_data in enumerate(tqdm(val_dataloader)):\n                                                \n        inputs = batch_data['image'].to('cuda')\n        bowel = batch_data['bowel'].to('cuda')\n        extravasation = batch_data['extravasation'].to('cuda')\n        liver = batch_data['liver'].to('cuda')\n        kidney = batch_data['kidney'].to('cuda')\n        spleen = batch_data['spleen'].to('cuda')\n\n        \n        b, e, k, l, s = model(inputs)\n        b_loss = bce_b(b, bowel.float())\n        e_loss = bce_e(e, extravasation.float())\n        l_loss = cce(l, liver)\n        k_loss = cce(k, kidney)\n        s_loss = cce(s, spleen)\n        \n        total_loss = b_loss + e_loss + l_loss + k_loss + s_loss\n        \n        # calculate validation metrics\n        val_loss += total_loss.item()\n        val_acc_bowel.update(b, bowel)\n        val_acc_extravasation.update(e, extravasation)\n        val_acc_liver.update(l, liver)\n        val_acc_kidney.update(k, kidney)\n        val_acc_spleen.update(s, spleen)\n    \n    \n    val_loss = val_loss/(batch_idx+1)\n    scheduler.step(val_loss)\n    \n    if val_loss < prev_val_best_loss:\n        prev_val_best_loss = val_loss\n        print(\"Validation Loss improved, Saving Model...\")\n        torch.save(model, f'efficientnet_b0_{val_loss:.3f}.pth')\n    \n    \n    \n    # accuracy and auc data\n    metrics_data = [\n                    [\"Bowel\", \n                        train_acc_bowel.compute_accuracy(),\n                        val_acc_bowel.compute_accuracy(),\n                        train_acc_bowel.compute_auc(),\n                        val_acc_bowel.compute_auc()],\n                    [\"Extravasation\", \n                        train_acc_extravasation.compute_accuracy(),\n                        val_acc_extravasation.compute_accuracy(),\n                        train_acc_extravasation.compute_auc(),\n                        val_acc_extravasation.compute_auc()],\n                    [\"Liver\", \n                        train_acc_liver.compute_accuracy(),\n                        val_acc_liver.compute_accuracy(),\n                        train_acc_liver.compute_auc(),\n                        val_acc_liver.compute_auc()],\n                    [\"Kidney\", \n                        train_acc_kidney.compute_accuracy(),\n                        val_acc_kidney.compute_accuracy(),\n                        train_acc_kidney.compute_auc(),\n                        val_acc_kidney.compute_auc()],\n                    [\"Spleen\", \n                        train_acc_spleen.compute_accuracy(),\n                        val_acc_spleen.compute_accuracy(),\n                        train_acc_spleen.compute_auc(),\n                        val_acc_spleen.compute_auc()]\n                ]\n    \n    # verbose\n    print('')\n    print(tabulate(metrics_data, headers=[\"\", \"Train Acc\", \"Val Acc\", \"Train AUC\", \"Val AUC\"]))\n    \n    print(f'\\nMean Train Loss: {train_loss:.3f}')\n    print(f'Mean Val Loss: {val_loss:.3f}\\n')\n    \n    #reset metrics\n    train_acc_bowel.reset()\n    train_acc_extravasation.reset()\n    train_acc_liver.reset()\n    train_acc_kidney.reset()\n    train_acc_spleen.reset()\n    val_acc_bowel.reset()\n    val_acc_extravasation.reset()\n    val_acc_liver.reset()\n    val_acc_kidney.reset()\n    val_acc_spleen.reset()","metadata":{"execution":{"iopub.status.busy":"2024-11-10T15:01:24.337928Z","iopub.execute_input":"2024-11-10T15:01:24.338283Z","iopub.status.idle":"2024-11-10T15:03:22.87137Z","shell.execute_reply.started":"2024-11-10T15:01:24.338251Z","shell.execute_reply":"2024-11-10T15:03:22.870404Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score, f1_score\n\n# Giả sử bạn đã có các giá trị thực tế và dự đoán\ny_true = [1, 0, 1, 1, 0, 1, 0, 1, 0, 1]  # Các nhãn thực tế\ny_pred = [1, 0, 1, 0, 0, 1, 0, 1, 1, 0]  # Các nhãn dự đoán từ mô hình\n\n# Tính ma trận nhầm lẫn\ncm = confusion_matrix(y_true, y_pred)\n\n# Lấy các giá trị từ ma trận nhầm lẫn\nTP = cm[1, 1]\nTN = cm[0, 0]\nFP = cm[0, 1]\nFN = cm[1, 0]\n\n# Tính các chỉ số\nsensitivity = TP / (TP + FN)  # Độ nhạy (Recall)\nspecificity = TN / (TN + FP)  # Độ nhiễu (Specificity)\naccuracy = accuracy_score(y_true, y_pred)  # Độ chính xác\nprecision = precision_score(y_true, y_pred)  # Precision\nf1 = f1_score(y_true, y_pred)  # F1-score\n\n# Hiển thị kết quả\nprint(f\"Độ nhạy (Sensitivity): {sensitivity:.4f}\")\nprint(f\"Độ nhiễu (Specificity): {specificity:.4f}\")\nprint(f\"Độ chính xác (Accuracy): {accuracy:.4f}\")\nprint(f\"Precision: {precision:.4f}\")\nprint(f\"F1-score: {f1:.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-10T15:03:22.878714Z","iopub.execute_input":"2024-11-10T15:03:22.879089Z","iopub.status.idle":"2024-11-10T15:03:22.894056Z","shell.execute_reply.started":"2024-11-10T15:03:22.879061Z","shell.execute_reply":"2024-11-10T15:03:22.893022Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score\n\n# Giả sử bạn có các nhãn thực tế và dự đoán từ các mô hình khác nhau\ny_true = [1, 0, 1, 1, 0, 1, 0, 1, 0, 1]\n\n# Các mô hình phân loại giả định với các dự đoán khác nhau\ny_preds = [\n    [1, 0, 1, 1, 0, 1, 0, 1, 0, 1],  # Mô hình 1\n    [1, 0, 1, 0, 0, 1, 0, 1, 1, 0],  # Mô hình 2\n    [1, 1, 1, 1, 0, 1, 0, 0, 0, 1],  # Mô hình 3\n]\n\n# Danh sách để lưu độ chính xác của mỗi mô hình\naccuracies = []\n\n# Tính độ chính xác cho mỗi mô hình và lưu vào danh sách\nfor y_pred in y_preds:\n    accuracy = accuracy_score(y_true, y_pred)\n    accuracies.append(accuracy)\n\n# Tính trung bình độ chính xác\naverage_accuracy = sum(accuracies) / len(accuracies)\n\n# Hiển thị kết quả\nprint(f\"Trung bình độ chính xác: {average_accuracy:.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-10T15:03:22.895269Z","iopub.execute_input":"2024-11-10T15:03:22.895898Z","iopub.status.idle":"2024-11-10T15:03:22.906061Z","shell.execute_reply.started":"2024-11-10T15:03:22.895865Z","shell.execute_reply":"2024-11-10T15:03:22.905002Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pip install matplotlib pillow\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-10T15:03:22.907176Z","iopub.execute_input":"2024-11-10T15:03:22.907631Z","iopub.status.idle":"2024-11-10T15:03:33.784451Z","shell.execute_reply.started":"2024-11-10T15:03:22.907603Z","shell.execute_reply":"2024-11-10T15:03:33.783306Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Hàm hiển thị hình ảnh với nhãn\ndef show_images(dataloader, num_images=5):\n    images_shown = 0\n    plt.figure(figsize=(15, 10))\n\n    for batch_data in dataloader:\n        images = batch_data['image']\n        labels = {\n            'bowel': batch_data['bowel'],\n            'extravasation': batch_data['extravasation'],\n            'liver': batch_data['liver'],\n            'kidney': batch_data['kidney'],\n            'spleen': batch_data['spleen']\n        }\n        \n        for i in range(images.size(0)):\n            if images_shown >= num_images:\n                plt.show()\n                return\n            \n            img = images[i].permute(1, 2, 0).cpu().numpy()  # Đổi thứ tự kênh ảnh từ (C, H, W) thành (H, W, C) để hiển thị\n            \n            # Hiển thị hình ảnh và các nhãn tương ứng\n            plt.subplot(1, num_images, images_shown + 1)\n            plt.imshow(img, cmap='gray')  # cmap='gray' nếu ảnh là grayscale\n            plt.axis('off')\n            \n            # Lấy các nhãn cho ảnh hiện tại\n            title = \"\\n\".join([f\"{key}: {label[i].item()}\" for key, label in labels.items()])\n            plt.title(title, fontsize=8)\n            \n            images_shown += 1\n\n    plt.show()\n\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-10T15:03:33.786561Z","iopub.execute_input":"2024-11-10T15:03:33.78744Z","iopub.status.idle":"2024-11-10T15:03:33.797444Z","shell.execute_reply.started":"2024-11-10T15:03:33.787396Z","shell.execute_reply":"2024-11-10T15:03:33.796475Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Gọi hàm hiển thị một batch từ dataloader\nshow_images(train_dataloader, num_images=5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-10T15:20:21.814594Z","iopub.execute_input":"2024-11-10T15:20:21.81495Z","iopub.status.idle":"2024-11-10T15:20:22.61199Z","shell.execute_reply.started":"2024-11-10T15:20:21.814921Z","shell.execute_reply":"2024-11-10T15:20:22.611103Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Create a 3x2 grid for the subplots\nfig, axes = plt.subplots(5, 1, figsize=(5, 15))\n\n# Flatten axes to iterate through them\naxes = axes.flatten()\n\n# Iterate through the metrics and plot them\nfor i, name in enumerate([\"bowel\", \"extra\", \"kidney\", \"liver\", \"spleen\"]):\n    # Plot training accuracy\n    axes[i].plot(history.history[name + '_accuracy'], label='Training ' + name)\n    # Plot validation accuracy\n    axes[i].plot(history.history['val_' + name + '_accuracy'], label='Validation ' + name)\n    axes[i].set_title(name)\n    axes[i].set_xlabel('Epoch')\n    axes[i].set_ylabel('Accuracy')\n    axes[i].legend()\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-11-10T15:22:49.813474Z","iopub.execute_input":"2024-11-10T15:22:49.813855Z","iopub.status.idle":"2024-11-10T15:22:50.16105Z","shell.execute_reply.started":"2024-11-10T15:22:49.813826Z","shell.execute_reply":"2024-11-10T15:22:50.159766Z"}},"outputs":[],"execution_count":null}]}