{"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":"gpu","dataSources":[{"sourceId":52254,"databundleVersionId":9674523,"sourceType":"competition"},{"sourceId":5838650,"sourceType":"datasetVersion","datasetId":3356068},{"sourceId":6211844,"sourceType":"datasetVersion","datasetId":3567114},{"sourceId":6267500,"sourceType":"datasetVersion","datasetId":3581068},{"sourceId":6367091,"sourceType":"datasetVersion","datasetId":3668143},{"sourceId":6437750,"sourceType":"datasetVersion","datasetId":3715314},{"sourceId":6440340,"sourceType":"datasetVersion","datasetId":3716919},{"sourceId":6501155,"sourceType":"datasetVersion","datasetId":3758078},{"sourceId":6504435,"sourceType":"datasetVersion","datasetId":3760213},{"sourceId":6533062,"sourceType":"datasetVersion","datasetId":3776927},{"sourceId":6605331,"sourceType":"datasetVersion","datasetId":3695414},{"sourceId":6642094,"sourceType":"datasetVersion","datasetId":3834301},{"sourceId":6666397,"sourceType":"datasetVersion","datasetId":3846730},{"sourceId":6670204,"sourceType":"datasetVersion","datasetId":3848762},{"sourceId":6673109,"sourceType":"datasetVersion","datasetId":3850050},{"sourceId":6673115,"sourceType":"datasetVersion","datasetId":3850054},{"sourceId":6675114,"sourceType":"datasetVersion","datasetId":3851220},{"sourceId":6678504,"sourceType":"datasetVersion","datasetId":3852993},{"sourceId":6678520,"sourceType":"datasetVersion","datasetId":3853000},{"sourceId":6679801,"sourceType":"datasetVersion","datasetId":3853474},{"sourceId":6680756,"sourceType":"datasetVersion","datasetId":3853894},{"sourceId":6681262,"sourceType":"datasetVersion","datasetId":3854158},{"sourceId":6681310,"sourceType":"datasetVersion","datasetId":3854197},{"sourceId":6681564,"sourceType":"datasetVersion","datasetId":3854378},{"sourceId":6694288,"sourceType":"datasetVersion","datasetId":3859591},{"sourceId":6694678,"sourceType":"datasetVersion","datasetId":3859765},{"sourceId":6695864,"sourceType":"datasetVersion","datasetId":3860267},{"sourceId":146649063,"sourceType":"kernelVersion"},{"sourceId":146650289,"sourceType":"kernelVersion"}],"dockerImageVersionId":30554,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!cp -r '/kaggle/input/contrails-libraries/pretrainedmodels-0.7.4/' './'\n!cp -r '/kaggle/input/contrails-libraries/efficientnet_pytorch-0.7.1/' './'\n\n!pip -q install /kaggle/input/dicomsdl--0-109-2/dicomsdl-0.109.2-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl\n!pip -q install '/kaggle/input/contrails-libraries/segmentation_models_pytorch-0.3.3-py3-none-any.whl' --no-deps\n!pip -q install /kaggle/input/contrails-model-def1/einops-0.6.1-py3-none-any.whl","metadata":{"execution":{"iopub.status.busy":"2024-12-01T21:44:10.32876Z","iopub.execute_input":"2024-12-01T21:44:10.329161Z","iopub.status.idle":"2024-12-01T21:44:30.613469Z","shell.execute_reply.started":"2024-12-01T21:44:10.329128Z","shell.execute_reply":"2024-12-01T21:44:30.612142Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import sys\nsys.path.append('./pretrainedmodels-0.7.4/pretrainedmodels-0.7.4/')\nsys.path.append('./efficientnet_pytorch-0.7.1/efficientnet_pytorch-0.7.1/')\nsys.path.append(\"/kaggle/input/rsna-abd-models-classes/\")\n","metadata":{"execution":{"iopub.status.busy":"2024-12-01T21:44:30.615285Z","iopub.execute_input":"2024-12-01T21:44:30.615579Z","iopub.status.idle":"2024-12-01T21:44:30.620234Z","shell.execute_reply.started":"2024-12-01T21:44:30.615554Z","shell.execute_reply":"2024-12-01T21:44:30.61948Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport random\nimport re\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom torch import nn, optim\nfrom PIL import Image\nfrom tqdm import tqdm\n\nimport pydicom as dicom\nimport nibabel as nib\nfrom sklearn.model_selection import train_test_split\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:30.621371Z","iopub.execute_input":"2024-12-01T21:44:30.621681Z","iopub.status.idle":"2024-12-01T21:44:33.048344Z","shell.execute_reply.started":"2024-12-01T21:44:30.621653Z","shell.execute_reply":"2024-12-01T21:44:33.04732Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"DS_RATE = 2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:33.051111Z","iopub.execute_input":"2024-12-01T21:44:33.05181Z","iopub.status.idle":"2024-12-01T21:44:33.056349Z","shell.execute_reply.started":"2024-12-01T21:44:33.051767Z","shell.execute_reply":"2024-12-01T21:44:33.055414Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport gc\nimport copy\nimport time\nimport numpy as np\nimport pandas as pd\nfrom glob import glob\nfrom tqdm import tqdm\n\nimport cv2\nfrom PIL import Image\nimport pydicom\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nimport matplotlib.pyplot as plt\n\nimport torch\nfrom torch import nn\nimport torch.nn.functional as F\n\nimport timm\nimport segmentation_models_pytorch as smp\nfrom models import *\n\nimport dicomsdl\ndef __dataset__to_numpy_image(self, index=0):\n    info = self.getPixelDataInfo()\n    dtype = info['dtype']\n    if info['SamplesPerPixel'] != 1:\n        raise RuntimeError('SamplesPerPixel != 1')\n    else:\n        shape = [info['Rows'], info['Cols']]\n    outarr = np.empty(shape, dtype=dtype)\n    self.copyFrameData(index, outarr)\n    return outarr\ndicomsdl._dicomsdl.DataSet.to_numpy_image = __dataset__to_numpy_image   \n\n\ntorch.cuda.set_device('cuda:0')","metadata":{"execution":{"iopub.status.busy":"2024-12-01T21:44:33.057468Z","iopub.execute_input":"2024-12-01T21:44:33.057788Z","iopub.status.idle":"2024-12-01T21:44:35.25481Z","shell.execute_reply.started":"2024-12-01T21:44:33.057764Z","shell.execute_reply":"2024-12-01T21:44:35.25388Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Config:\n    SEED = 42\n    IMAGE_SIZE = [256, 256]\n    BATCH_SIZE = 32\n    EPOCHS = 200\n    TARGET_COLS  = [\n        \"bowel_injury\", \"extravasation_injury\",\n        \"kidney_healthy\", \"kidney_low\", \"kidney_high\",\n        \"liver_healthy\", \"liver_low\", \"liver_high\",\n        \"spleen_healthy\", \"spleen_low\", \"spleen_high\",\n    ]\n\nconfig = Config()\nprint(f\"Số lượng nhãn mục tiêu: {len(Config.TARGET_COLS)}\")\ntorch.manual_seed(Config.SEED)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:35.255863Z","iopub.execute_input":"2024-12-01T21:44:35.256122Z","iopub.status.idle":"2024-12-01T21:44:35.265225Z","shell.execute_reply.started":"2024-12-01T21:44:35.256099Z","shell.execute_reply":"2024-12-01T21:44:35.264397Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BASE_PATH = f\"/kaggle/input/rsna-atd-512x512-png-v2-dataset\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:35.266344Z","iopub.execute_input":"2024-12-01T21:44:35.266611Z","iopub.status.idle":"2024-12-01T21:44:35.272Z","shell.execute_reply.started":"2024-12-01T21:44:35.26659Z","shell.execute_reply":"2024-12-01T21:44:35.271158Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# train\ndataframe = pd.read_csv(f\"{BASE_PATH}/train.csv\")\ndataframe[\"image_path\"] = f\"{BASE_PATH}/train_images\"\\\n                    + \"/\" + dataframe.patient_id.astype(str)\\\n                    + \"/\" + dataframe.series_id.astype(str)\\\n                    + \"/\" + dataframe.instance_number.astype(str) +\".png\"\ndataframe = dataframe.drop_duplicates()\n\ndataframe.head(10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:35.273037Z","iopub.execute_input":"2024-12-01T21:44:35.273312Z","iopub.status.idle":"2024-12-01T21:44:35.374759Z","shell.execute_reply.started":"2024-12-01T21:44:35.273292Z","shell.execute_reply":"2024-12-01T21:44:35.373869Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Function to handle the split for each group\ndef split_group(group, test_size=0.2):\n    if len(group) == 1:\n        return (group, pd.DataFrame()) if np.random.rand() < test_size else (pd.DataFrame(), group)\n    else:\n        return train_test_split(group, test_size=test_size, random_state=42)\n\n# Initialize the train and validation datasets\ntrain_data = pd.DataFrame()\nval_data = pd.DataFrame()\n\n# Iterate through the groups and split them, handling single-sample groups\nfor _, group in dataframe.groupby(config.TARGET_COLS):\n    train_group, val_group = split_group(group)\n    train_data = pd.concat([train_data, train_group], ignore_index=True)\n    val_data = pd.concat([val_data, val_group], ignore_index=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:35.375987Z","iopub.execute_input":"2024-12-01T21:44:35.376269Z","iopub.status.idle":"2024-12-01T21:44:35.454207Z","shell.execute_reply.started":"2024-12-01T21:44:35.376245Z","shell.execute_reply":"2024-12-01T21:44:35.453454Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data.shape, val_data.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:35.457077Z","iopub.execute_input":"2024-12-01T21:44:35.457388Z","iopub.status.idle":"2024-12-01T21:44:35.463189Z","shell.execute_reply.started":"2024-12-01T21:44:35.457362Z","shell.execute_reply":"2024-12-01T21:44:35.462228Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"paths  = train_data.image_path.tolist()\nlabels = train_data[config.TARGET_COLS].values\n\nclass CustomDataset(Dataset):\n    def __init__(self, paths, labels, transform=None):\n        self.paths = paths\n        self.labels = labels\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.paths)\n\n    def __getitem__(self, idx):\n        image = Image.open(self.paths[idx]).convert('RGB')\n        label = torch.tensor(self.labels[idx], dtype=torch.float32)\n\n        if self.transform:\n            image = self.transform(image)\n\n        return image, label\n\n# Define any image transformations you want to apply, here we also add augmentation. \ntransform = transforms.Compose([\n    transforms.Resize((256, 256)),\n    transforms.RandomResizedCrop(256),   # Random crop and resize\n    transforms.RandomHorizontalFlip(),    # Random horizontal flip\n    transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),  # Color jitter\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:35.464407Z","iopub.execute_input":"2024-12-01T21:44:35.464693Z","iopub.status.idle":"2024-12-01T21:44:35.474573Z","shell.execute_reply.started":"2024-12-01T21:44:35.464671Z","shell.execute_reply":"2024-12-01T21:44:35.473771Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# get image_paths and labels\nprint(\"[INFO] Building the dataset...\")\n\ntrain_paths  = train_data.image_path.tolist()\ntrain_labels = train_data[config.TARGET_COLS].values\n\nval_paths  = val_data.image_path.tolist()\nval_labels = val_data[config.TARGET_COLS].values\n\n\n#torch dataset\nbatch_size = 32\n\n# Create the datasets\n\ndataset_train = CustomDataset(train_paths, train_labels, transform=transform)\ntrain_dataloader = DataLoader(dataset_train, batch_size=batch_size, shuffle=True)\n\n\ndataset_val = CustomDataset(val_paths, val_labels, transform=transform)\nval_dataloader = DataLoader(dataset_val, batch_size=batch_size, shuffle=True)\n\n\n# Define your dataset size and other configuration parameters\ndataset_size = len(dataset_train)  # Assuming you have defined 'dataset' earlier\nbatch_size = 32  # Your batch size\ntotal_epochs = 50  # Total number of epochs\n\n# Calculate total train steps\ntotal_train_steps = dataset_size * batch_size * total_epochs\n\n# Define warmup steps as 10% of total train steps\nwarmup_steps = int(total_train_steps * 0.10)\n\n# Define decay steps as the remaining steps after warmup\ndecay_steps = total_train_steps - warmup_steps\n\nprint(f\"Total Train Steps: {total_train_steps}\")\nprint(f\"Warmup Steps: {warmup_steps}\")\nprint(f\"Decay Steps: {decay_steps}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:35.475575Z","iopub.execute_input":"2024-12-01T21:44:35.475847Z","iopub.status.idle":"2024-12-01T21:44:35.490222Z","shell.execute_reply.started":"2024-12-01T21:44:35.475797Z","shell.execute_reply":"2024-12-01T21:44:35.48948Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for img, label in train_dataloader:\n  print(img.shape)\n  break","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:35.491273Z","iopub.execute_input":"2024-12-01T21:44:35.491543Z","iopub.status.idle":"2024-12-01T21:44:35.894373Z","shell.execute_reply.started":"2024-12-01T21:44:35.491523Z","shell.execute_reply":"2024-12-01T21:44:35.893124Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#a function to display images\ndef show_images(images, labels):\n    fig, axes = plt.subplots(1, len(images), figsize=(15, 5))\n    for idx, (image, label) in enumerate(zip(images, labels)):\n        image = image.permute(1, 2, 0)  # Convert from (C, H, W) to (H, W, C) for displaying\n        axes[idx].imshow(image)\n        label_str = \", \".join([str(val) for val in label])  # Convert label tensor to string\n        axes[idx].set_title(f\"Labels: {label_str}\")\n        axes[idx].axis(\"off\")\n    plt.show()\n\n# Load a few images for visualization\nnum_images_to_display = 5\nsample_indices = torch.randint(len(dataset_train), size=(num_images_to_display,))\nsample_images = [dataset_train[i][0] for i in sample_indices]\nsample_labels = [dataset_train[i][1] for i in sample_indices]\n\n# Convert label tensors to numpy arrays for display\nsample_labels_np = [label.numpy() for label in sample_labels]\n\n# Display the sample images\nshow_images(sample_images, sample_labels_np)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:35.895517Z","iopub.execute_input":"2024-12-01T21:44:35.895792Z","iopub.status.idle":"2024-12-01T21:44:36.457946Z","shell.execute_reply.started":"2024-12-01T21:44:35.895768Z","shell.execute_reply":"2024-12-01T21:44:36.457101Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\nclass ChannelAttention(nn.Module):\n    def __init__(self, channel):\n        super(ChannelAttention, self).__init__()\n        self.fc = nn.Linear(channel, channel)  # Lớp fully connected duy nhất\n\n    def forward(self, x):\n        avg_pool = x.mean(dim=(2, 3))  # Kích thước: (batch_size, channels)\n        max_pool = x.max(dim=2)[0].max(dim=2)[0]  # Kích thước: (batch_size, channels)\n        \n        # Tính toán trọng số kênh\n        channel_attention = torch.sigmoid(self.fc(avg_pool) + self.fc(max_pool))\n        \n        return x * channel_attention.view(x.size(0), -1, 1, 1)\n\nclass SpatialAttention(nn.Module):\n    def __init__(self):\n        super(SpatialAttention, self).__init__()\n        self.conv1 = nn.Conv2d(2, 1, kernel_size=7, padding=3)  # Lớp tích chập đầu tiên\n        self.conv2 = nn.Conv2d(1, 1, kernel_size=5, padding=2)  # Lớp tích chập thứ hai\n\n    def forward(self, x):\n        avg_pool = x.mean(dim=1, keepdim=True)  # Tính trung bình theo chiều kênh\n        max_pool = x.max(dim=1, keepdim=True)[0]  # Tính giá trị lớn nhất theo chiều kênh\n        concat = torch.cat([avg_pool, max_pool], dim=1)  # Kết hợp hai đầu ra\n        \n        # Áp dụng 2 lớp tích chập\n        spatial_attention = torch.sigmoid(self.conv1(concat))  # Lớp tích chập đầu tiên\n        spatial_attention = torch.sigmoid(self.conv2(spatial_attention))  # Lớp tích chập thứ hai\n        \n        return x * spatial_attention  # Nhân đầu vào với trọng số chú ý không gian\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:36.459232Z","iopub.execute_input":"2024-12-01T21:44:36.459554Z","iopub.status.idle":"2024-12-01T21:44:36.469285Z","shell.execute_reply.started":"2024-12-01T21:44:36.459524Z","shell.execute_reply":"2024-12-01T21:44:36.468424Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class SimpleCNN(nn.Module):\n    def __init__(self, num_classes=11):\n        super(SimpleCNN, self).__init__()\n\n        # Khối tích chập 1\n        self.conv1 = nn.Sequential(\n            nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=1, padding=1),  # 3 kênh cho ảnh RGB\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2, stride=2),\n        )\n\n        # Channel Attention và Spatial Attention cho khối 1\n        self.channel_attention1 = ChannelAttention(32)\n        self.spatial_attention1 = SpatialAttention()\n\n        # Khối tích chập 2\n        self.conv2 = nn.Sequential(\n            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1),  \n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2, stride=2),\n        )\n        self.channel_attention2 = ChannelAttention(64)\n        self.spatial_attention2 = SpatialAttention()\n\n        # Khối tích chập 3\n        self.conv3 = nn.Sequential(\n            nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, stride=1, padding=1),  \n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2, stride=2),\n        )\n        self.channel_attention3 = ChannelAttention(128)\n        self.spatial_attention3 = SpatialAttention()\n\n        # Tính toán kích thước sau các lớp tích chập\n        dummy_input = torch.randn(1, 3, 256, 256)  # Đảm bảo đầu vào giả có 3 kênh\n        conv_output = self.conv3(self.conv2(self.conv1(dummy_input)))  # Qua ba khối tích chập\n        flattened_size = conv_output.view(1, -1).size(1)  # Kích thước sau khi flatten\n\n        # Fully connected layers\n        self.fc_layers = nn.Sequential(\n            nn.Linear(flattened_size, 128),  # Kích thước đầu vào là flattened_size\n            nn.ReLU(),\n            nn.Linear(128, num_classes)\n        )\n\n    def forward(self, x):\n        # Conv1 + Attention\n        x = self.conv1(x)\n        x = self.channel_attention1(x)\n        x = self.spatial_attention1(x)\n\n        # Conv2 + Attention\n        x = self.conv2(x)\n        x = self.channel_attention2(x)\n        x = self.spatial_attention2(x)\n\n        # Conv3 + Attention\n        x = self.conv3(x)\n        x = self.channel_attention3(x)\n        x = self .spatial_attention3(x)\n\n        # Flatten and fully connected\n        x = x.view(x.size(0), -1)  # Flatten\n        x = self.fc_layers(x)  # Fully connected\n        return x","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:36.470421Z","iopub.execute_input":"2024-12-01T21:44:36.470664Z","iopub.status.idle":"2024-12-01T21:44:36.483871Z","shell.execute_reply.started":"2024-12-01T21:44:36.470643Z","shell.execute_reply":"2024-12-01T21:44:36.483044Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import KFold\n# Số lượng folds\nK = 4  # Bạn có thể chọn 5 hoặc 10 tùy ý\n\n# Khởi tạo K-Fold splitter\nkf = KFold(n_splits=K, shuffle=True, random_state=config.SEED)\n\n# Chuẩn bị dữ liệu\nX = dataframe.image_path.values\ny = dataframe[config.TARGET_COLS].values\n\n# Khởi tạo danh sách để lưu trữ các chỉ số và metric của từng fold\nfold_train_losses = []\nfold_val_losses = []\nfold_val_accuracies = []\nfold_val_f1_scores = []","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:36.484938Z","iopub.execute_input":"2024-12-01T21:44:36.485214Z","iopub.status.idle":"2024-12-01T21:44:36.500535Z","shell.execute_reply.started":"2024-12-01T21:44:36.485184Z","shell.execute_reply":"2024-12-01T21:44:36.499796Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Chia dữ liệu cho từng fold\nfor fold, (train_idx, val_idx) in enumerate(kf.split(X)):\n    X_train, X_val = X[train_idx], X[val_idx]\n    y_train, y_val = y[train_idx], y[val_idx]\n\n    # Tạo dataset và dataloader cho fold hiện tại\n    train_dataset = CustomDataset(paths=X_train, labels=y_train, transform=transform)\n    val_dataset = CustomDataset(paths=X_val, labels=y_val, transform=transform)\n\n    train_dataloader = DataLoader(train_dataset, batch_size=16, shuffle=True, num_workers=4, pin_memory=True)\n    val_dataloader = DataLoader(val_dataset, batch_size=16, shuffle=False, num_workers=4, pin_memory=True)\n\n    # Huấn luyện và đánh giá cho fold hiện tại\n    for epoch in range(config.EPOCHS):\n        # Vòng lặp huấn luyện và validation tương tự như trước\n        ...\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:36.501513Z","iopub.execute_input":"2024-12-01T21:44:36.501803Z","iopub.status.idle":"2024-12-01T21:44:36.518734Z","shell.execute_reply.started":"2024-12-01T21:44:36.501771Z","shell.execute_reply":"2024-12-01T21:44:36.517703Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Kiểm tra nếu có GPU thì sử dụng, nếu không sẽ sử dụng CPU\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(f\"Using device: {device}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:36.51981Z","iopub.execute_input":"2024-12-01T21:44:36.520156Z","iopub.status.idle":"2024-12-01T21:44:36.525407Z","shell.execute_reply.started":"2024-12-01T21:44:36.520102Z","shell.execute_reply":"2024-12-01T21:44:36.52458Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.cuda.amp import GradScaler\n\nmodel = SimpleCNN(num_classes=len(config.TARGET_COLS)).to(device)\ncriterion = nn.BCEWithLogitsLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=1e-3)\nscheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=config.EPOCHS)\n\n# Correct initialization\nscaler = GradScaler()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:36.526363Z","iopub.execute_input":"2024-12-01T21:44:36.526891Z","iopub.status.idle":"2024-12-01T21:44:36.815586Z","shell.execute_reply.started":"2024-12-01T21:44:36.526823Z","shell.execute_reply":"2024-12-01T21:44:36.814899Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"accumulation_steps = 4  # ví dụ: cập nhật sau mỗi 4 batch\nfor i, (images, labels) in enumerate(train_dataloader):\n    images, labels = images.to(device), labels.to(device)\n    with torch.amp.autocast(device_type=device.type):\n        outputs = model(images)\n        loss = criterion(outputs, labels) / accumulation_steps\n    scaler.scale(loss).backward()\n\n    if (i + 1) % accumulation_steps == 0:\n        scaler.step(optimizer)\n        scaler.update()\n        optimizer.zero_grad()  # reset lại gradient","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:44:36.81657Z","iopub.execute_input":"2024-12-01T21:44:36.816785Z","iopub.status.idle":"2024-12-01T21:45:24.033621Z","shell.execute_reply.started":"2024-12-01T21:44:36.816766Z","shell.execute_reply":"2024-12-01T21:45:24.032429Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch.utils.checkpoint as checkpoint\n\ndef forward(self, x):\n    x = checkpoint.checkpoint(self.conv_layers, x)\n    x = x.view(x.size(0), -1)\n    x = checkpoint.checkpoint(self.fc_layers, x)\n    return x\nif (epoch + 1) % 10 == 0:  # Lưu sau mỗi 10 epoch\n    torch.save(model.state_dict(), f\"model_checkpoint_epoch_{epoch+1}.pth\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:45:24.03521Z","iopub.execute_input":"2024-12-01T21:45:24.035566Z","iopub.status.idle":"2024-12-01T21:45:24.189164Z","shell.execute_reply.started":"2024-12-01T21:45:24.035531Z","shell.execute_reply":"2024-12-01T21:45:24.188201Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import f1_score, confusion_matrix\n\n# Vòng lặp huấn luyện cho mỗi fold\nfor epoch in range(config.EPOCHS):\n    model.train()\n    running_loss = 0.0\n    optimizer.zero_grad()  # Reset optimizer\n\n    # Training loop\n    for i, (images, labels) in enumerate(train_dataloader):\n        images, labels = images.to(device), labels.to(device)\n\n        # In kích thước batch chỉ một lần\n        if i == 0:  # Chỉ in cho batch đầu tiên\n            print(\"Kích thước batch trong training:\", images.size())\n        \n        # Sử dụng cú pháp mới của autocast\n        with torch.amp.autocast(device_type=device.type):\n            outputs = model(images)\n            loss = criterion(outputs, labels) / accumulation_steps  # Chia loss theo accumulation steps\n        \n        scaler.scale(loss).backward()  # Tích lũy gradient\n        \n        # Thực hiện bước optimizer mỗi accumulation_steps batch\n        if (i + 1) % accumulation_steps == 0:\n            scaler.step(optimizer)\n            scaler.update()\n            optimizer.zero_grad()  # Reset lại gradient\n\n        running_loss += loss.item() * images.size(0)  # Không nhân với accumulation_steps ở đây\n\n    # Lưu lại train loss\n    epoch_train_loss = running_loss / len(train_dataloader.dataset)\n    fold_train_losses.append(epoch_train_loss)\n\n    # Cập nhật learning rate\n    scheduler.step()\n\n    # Validation loop\n    model.eval()\n    val_loss, correct, total = 0.0, 0, 0\n    all_preds, all_targets = [], []\n\n    with torch.no_grad():\n        for images, labels in val_dataloader:\n            images, labels = images.to(device), labels.to(device)\n\n            # In kích thước batch chỉ một lần\n            if total == 0:  # Chỉ in cho batch đầu tiên\n                print(\"Kích thước batch trong validation:\", images.size())\n\n            # Sử dụng cú pháp mới của autocast trong validation\n            with torch.amp.autocast(device_type=device.type):\n                outputs = model(images)\n                loss = criterion(outputs, labels)\n\n            val_loss += loss.item() * images.size(0)\n\n            preds = torch.sigmoid(outputs) > 0.5\n            correct += (preds.int() == labels.int()).sum().item()\n            total += labels.numel()\n\n            all_preds.append(preds.cpu().numpy())\n            all_targets.append(labels.cpu().numpy())\n\n    # Lưu lại validation loss và accuracy\n    epoch_val_loss = val_loss / len(val_dataloader.dataset)\n    fold_val_losses.append(epoch_val_loss)\n\n    epoch_val_accuracy = 100.0 * correct / total\n    fold_val_accuracies.append(epoch_val_accuracy)\n\n    # Tính F1 score\n    all_preds_np = np.vstack(all_preds)\n    all_targets_np = np.vstack(all_targets)\n    epoch_f1 = f1_score(all_targets_np, all_preds_np, average='macro')\n    fold_val_f1_scores.append(epoch_f1)\n\n    # Tính các chỉ số khác: độ nhạy và độ đặc hiệu cho từng nhãn\n    sensitivity_per_class = []\n    specificity_per_class = []\n\n    for class_idx in range(all_targets_np.shape[1]):\n        tn, fp, fn, tp = confusion_matrix(all_targets_np[:, class_idx], all_preds_np[:, class_idx]).ravel()\n\n        sensitivity = tp / (tp + fn) if (tp + fn) > 0 else 0\n        specificity = tn / (tn + fp) if (tn + fp) > 0 else 0\n\n        sensitivity_per_class.append(sensitivity * 100)\n        specificity_per_class.append(specificity * 100)\n\n    # In các chỉ số sau mỗi epoch\n    print(f\"Epoch [{epoch + 1}/{config.EPOCHS}] - Train Loss: {epoch_train_loss:.4f} - Val Loss: {epoch_val_loss:.4f} - Val Acc: {epoch_val_accuracy:.2f}% - Val F1: {epoch_f1:.4f}\")\n    \n    for class_idx, organ in enumerate([\"Bowel\", \"Extravasation\", \"Liver\", \"Kidney\", \"Spleen\"]):\n        print(f\"{organ} - Sensitivity: {sensitivity_per_class[class_idx]:.2f}%, Specificity: {specificity_per_class[class_idx]:.2f}%\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T21:45:24.190402Z","iopub.execute_input":"2024-12-01T21:45:24.190677Z","iopub.status.idle":"2024-12-02T01:09:07.977461Z","shell.execute_reply.started":"2024-12-01T21:45:24.190654Z","shell.execute_reply":"2024-12-02T01:09:07.976277Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Calculate and print average metrics\navg_sensitivity = np.mean(sensitivity_per_class)\navg_specificity = np.mean(specificity_per_class)\navg_accuracy = epoch_val_accuracy  # Average accuracy for this epoch\navg_f1 = epoch_f1  # Macro F1 score for this epoch\n\n# Print average values\nprint(f\"Average Sensitivity: {avg_sensitivity:.2f}%\")\nprint(f\"Average Specificity: {avg_specificity:.2f}%\")\nprint(f\"Average Accuracy: {avg_accuracy:.2f}%\")\nprint(f\"Average F1 Score (Macro): {avg_f1:.2f}%\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:07.978992Z","iopub.execute_input":"2024-12-02T01:09:07.979308Z","iopub.status.idle":"2024-12-02T01:09:07.985628Z","shell.execute_reply.started":"2024-12-02T01:09:07.97928Z","shell.execute_reply":"2024-12-02T01:09:07.984478Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Giả sử có dữ liệu cho các giá trị accuracy theo từng epoch\nepochs = range(1, config.EPOCHS + 1)\n\n# Đồ thị cho accuracy và F1 score\nplt.figure(figsize=(8, 6))  # Đặt kích thước cho đồ thị\n\n# Vẽ đồ thị cho accuracy\nplt.plot(epochs, fold_val_accuracies, label='Validation Accuracy', color='blue', linewidth=2)\n\n# Đặt tiêu đề và nhãn cho trục\nplt.title('Validation Accuracy over Epochs', fontsize=16)\nplt.xlabel('Epochs', fontsize=12)\nplt.ylabel('Accuracy (%)', fontsize=12)\n\n# Hiển thị lưới (grid)\nplt.grid(True)\n\n# Hiển thị chú giải (legend)\nplt.legend()\n\n# Hiển thị biểu đồ\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:07.98693Z","iopub.execute_input":"2024-12-02T01:09:07.987325Z","iopub.status.idle":"2024-12-02T01:09:08.298653Z","shell.execute_reply.started":"2024-12-02T01:09:07.987296Z","shell.execute_reply":"2024-12-02T01:09:08.297815Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Khởi tạo fold_organ_accuracies ngoài vòng lặp epoch để chỉ khởi tạo một lần\nfold_organ_accuracies = { organ: [] for organ in [\"Bowel\", \"Extravasation\", \"Liver\", \"Kidney\", \"Spleen\"] }\n\n# Validation loop\nmodel.eval()\nval_loss, correct, total = 0.0, 0, 0\ncorrect_per_organ = { \"Bowel\": 0, \"Extravasation\": 0, \"Liver\": 0, \"Kidney\": 0, \"Spleen\": 0 }\ntotal_per_organ = { \"Bowel\": 0, \"Extravasation\": 0, \"Liver\": 0, \"Kidney\": 0, \"Spleen\": 0 }\n\nwith torch.no_grad():\n    for images, labels in val_dataloader:\n        images, labels = images.to(device), labels.to(device)\n\n        # Sử dụng cú pháp mới của autocast trong validation\n        with torch.amp.autocast(device_type=device.type):\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n\n        val_loss += loss.item() * images.size(0)\n\n        preds = torch.sigmoid(outputs) > 0.5\n\n        # Cập nhật đúng và tổng số cho từng bộ phận\n        for organ_idx, organ_name in enumerate([\"Bowel\", \"Extravasation\", \"Liver\", \"Kidney\", \"Spleen\"]):\n            correct_per_organ[organ_name] += (preds[:, organ_idx].int() == labels[:, organ_idx].int()).sum().item()\n            total_per_organ[organ_name] += labels[:, organ_idx].numel()\n\n# Tính toán accuracy cho từng bộ phận\naccuracies_per_organ = { organ: 100.0 * correct_per_organ[organ] / total_per_organ[organ] for organ in correct_per_organ }\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:08.299884Z","iopub.execute_input":"2024-12-02T01:09:08.300242Z","iopub.status.idle":"2024-12-02T01:09:22.553438Z","shell.execute_reply.started":"2024-12-02T01:09:08.30021Z","shell.execute_reply":"2024-12-02T01:09:22.552368Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# In ra độ chính xác (accuracy) cho từng bộ phận sau mỗi epoch\nfor organ, accuracy in accuracies_per_organ.items():\n    print(f\"{organ} Accuracy: {accuracy:.2f}%\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:22.554968Z","iopub.execute_input":"2024-12-02T01:09:22.555379Z","iopub.status.idle":"2024-12-02T01:09:22.560974Z","shell.execute_reply.started":"2024-12-02T01:09:22.555353Z","shell.execute_reply":"2024-12-02T01:09:22.56004Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\n\n# Set the model to evaluation mode\nmodel.eval()\n\n# Select a random image from the validation dataset\nrandom_index = np.random.randint(len(dataset_val))\nimage, label = dataset_val[random_index]\n\n# Move the image to the GPU if available\nimage = image.to('cuda')\n\n# Pass the image through the model\nwith torch.no_grad():\n    output = model(image.unsqueeze(0))  # Unsqueeze to add batch dimension\n\n# Convert the output logits to probabilities using sigmoid function\npredicted_probs = torch.sigmoid(output)[0]\n\n# Convert predicted probabilities to binary predictions\npredicted_labels = (predicted_probs > 0.5).int()\n\n\n# Display the image, actual labels, and predicted labels\nplt.imshow(image.permute(1, 2, 0).cpu())  # Move image to CPU and change channel order\n#plt.title(f\"Actual Labels: {label}\\nPredicted Labels: {predicted_labels}\")\nplt.title(f\"Actual Labels: {label}\\nPredicted Labels: {predicted_labels}\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:22.565933Z","iopub.execute_input":"2024-12-02T01:09:22.566205Z","iopub.status.idle":"2024-12-02T01:09:22.856539Z","shell.execute_reply.started":"2024-12-02T01:09:22.566184Z","shell.execute_reply":"2024-12-02T01:09:22.855825Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def create_3D_scans(folder, downsample_rate=1): \n    filenames = os.listdir(folder)\n    filenames = [int(filename.split('.')[0]) for filename in filenames]\n    filenames = sorted(filenames)\n    filenames = [str(filename) + '.dcm' for filename in filenames]\n        \n    volume = []\n    for filename in tqdm(filenames[::downsample_rate]):\n        filepath = os.path.join(folder, filename)\n        ds = dicom.dcmread(filepath)\n        image = ds.pixel_array\n        \n        # find rescale params\n        if (\"RescaleIntercept\" in ds) and (\"RescaleSlope\" in ds):\n            intercept = float(ds.RescaleIntercept)\n            slope = float(ds.RescaleSlope)\n    \n        # find clipping params\n        center = int(ds.WindowCenter)\n        width = int(ds.WindowWidth)\n        low = center - width / 2\n        high = center + width / 2    \n        \n        \n        image = (image * slope) + intercept\n        image = np.clip(image, low, high)\n\n        image = (image / np.max(image) * 255).astype(np.int16)\n        image = image[::downsample_rate, ::downsample_rate]\n        volume.append( image )\n    \n    volume = np.stack(volume, axis=0)\n    return volume\n\n\ndef create_3D_segmentations(filepath, downsample_rate=1):\n    img = nib.load(filepath).get_fdata()\n    img = np.transpose(img, [1, 0, 2])\n    img = np.rot90(img, 1, (1,2))\n    img = img[::-1,:,:]\n    img = np.transpose(img, [1, 0, 2])\n    img = img[::downsample_rate, ::downsample_rate, ::downsample_rate]\n    return img\n\n\n\nfilepath = '/kaggle/input/rsna-2023-abdominal-trauma-detection/segmentations/21057.nii'\nvolume_seg = create_3D_segmentations(filepath, downsample_rate=DS_RATE)\nprint(f'3D segmentation file shape: {volume_seg.shape}')\n\nfilepath = '/kaggle/input/rsna-2023-abdominal-trauma-detection/train_images/10004/21057'\nvolume = create_3D_scans(filepath, downsample_rate=DS_RATE)\nprint(f'3D Image file shape: {volume.shape}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:22.857547Z","iopub.execute_input":"2024-12-02T01:09:22.8578Z","iopub.status.idle":"2024-12-02T01:09:29.026089Z","shell.execute_reply.started":"2024-12-02T01:09:22.857778Z","shell.execute_reply":"2024-12-02T01:09:29.025217Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def plot_image_with_seg(volume, volume_seg=[], orientation='Coronal', num_subplots=20):\n    # simply copy\n    if len(volume_seg) == 0:\n        plot_mask = 0\n    else:\n        plot_mask = 1\n        \n    if orientation == 'Coronal':\n        slices = np.linspace(0, volume.shape[2]-1, num_subplots).astype(np.int16)\n        volume = volume.transpose([1, 0, 2])\n        if plot_mask:\n            volume_seg = volume_seg.transpose([1, 0, 2])\n        \n    elif orientation == 'Sagittal':\n        slices = np.linspace(0, volume.shape[2]-1, num_subplots).astype(np.int16)\n        volume = volume.transpose([2, 0, 1])\n        if plot_mask:\n            volume_seg = volume_seg.transpose([2, 0, 1])\n\n    elif orientation == 'Axial':\n        slices = np.linspace(0, volume.shape[0]-1, num_subplots).astype(np.int16)\n           \n    rows = np.max( [np.floor(np.sqrt(num_subplots)).astype(int) - 2, 1])\n    cols = np.ceil(num_subplots/rows).astype(int)\n    \n    fig, ax = plt.subplots(rows, cols, figsize=(cols * 2, rows * 4))\n    fig.tight_layout(h_pad=0.01, w_pad=0)\n    \n    ax = ax.ravel()\n    for this_ax in ax:\n        this_ax.axis('off')\n\n    for counter, this_slice in enumerate( slices ):\n        plt.sca(ax[counter])\n        \n        image = volume[this_slice, :, :]\n        plt.imshow(image, cmap='gray')\n        \n        if plot_mask:\n            mask = np.where(volume_seg[this_slice, :, :], volume_seg[this_slice, :, :], np.nan)\n            plt.imshow(mask, cmap='Set1', alpha=0.5)        \n        \n        \n        \n        \nplot_image_with_seg(volume, volume_seg, orientation='Coronal', num_subplots=10)\nplot_image_with_seg(volume, volume_seg, orientation='Sagittal', num_subplots=10)\nplot_image_with_seg(volume, volume_seg, orientation='Axial', num_subplots=10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:29.02715Z","iopub.execute_input":"2024-12-02T01:09:29.027423Z","iopub.status.idle":"2024-12-02T01:09:31.914371Z","shell.execute_reply.started":"2024-12-02T01:09:29.027399Z","shell.execute_reply":"2024-12-02T01:09:31.913469Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def glob_sorted(path):\n    return sorted(glob(path), key=lambda x: int(x.split('/')[-1].split('.')[0]))\n\ndef get_rescaled_image(dcm, img):\n    resI, resS = dcm.RescaleIntercept, dcm.RescaleSlope\n    img = resS * img + resI\n    return img\n\ndef get_windowed_image(img, WL=50, WW=400):\n    upper, lower = WL+WW//2, WL-WW//2\n    X = np.clip(img.copy(), lower, upper)\n    X = X - np.min(X)\n    X = X / np.max(X)\n    X = (X*255.0).astype('uint8')\n    \n    return X\n\ndef standardize_pixel_array(dcm, pixel_array):\n    \"\"\"\n    Source : https://www.kaggle.com/competitions/rsna-2023-abdominal-trauma-detection/discussion/427217\n    \"\"\"\n    # Correct DICOM pixel_array if PixelRepresentation == 1.\n    #pixel_array = dcm.pixel_array\n    \n    if dcm.PixelRepresentation == 1:\n        bit_shift = dcm.BitsAllocated - dcm.BitsStored\n        dtype = pixel_array.dtype \n        pixel_array = (pixel_array << bit_shift).astype(dtype) >>  bit_shift\n\n    intercept = float(dcm.RescaleIntercept)\n    slope = float(dcm.RescaleSlope)\n    center = int(dcm.WindowCenter)\n    width = int(dcm.WindowWidth)\n    low = center - width / 2\n    high = center + width / 2    \n    \n    pixel_array = (pixel_array * slope) + intercept\n    pixel_array = np.clip(pixel_array, low, high)\n\n    return pixel_array\n\ndef load_volume(dcms):\n    volume = []\n    pos_zs = []\n    \n    for dcm_path in dcms:\n        pydcm = pydicom.dcmread(dcm_path)\n        \n        pos_z = pydcm[(0x20, 0x32)].value[-1]\n        pos_zs.append(pos_z)\n        \n        dcm = dicomsdl.open(dcm_path)\n        \n        orig_image = dcm.to_numpy_image()\n        image = get_rescaled_image(dcm, orig_image)\n        image = get_windowed_image(image)\n        \n        if np.min(image)<0:\n            image = image + np.abs(np.min(image))\n        \n        image = image / image.max()\n        image = (image * 255).astype(np.uint8)\n        volume.append(image)\n    \n    return np.stack(volume)\n\n\ndef process_volume(volume):\n    volume = np.stack([cv2.resize(x, (128, 128)) for x in volume])\n    \n    volumes = []\n    cuts = [(x, x+32) for x in np.arange(0, volume.shape[0], 32)[:-1]]\n    \n    if cuts:\n        for cut in cuts:\n            volumes.append(volume[cut[0]:cut[1]])\n        volumes = np.stack(volumes)\n    else:\n        volumes = np.zeros((1, 32, 128, 128), dtype=np.uint8)\n        volumes[0, :len(volume)] = volume\n    \n    if cuts:\n        last_volume = np.zeros((1, 32, 128, 128), dtype=np.uint8)\n        last_volume[0, :volume[cuts[-1][1]:].shape[0]] =  volume[cuts[-1][1]:]\n        volumes = np.concatenate([volumes, last_volume])\n    \n    volumes = torch.as_tensor(volumes).float()\n    \n    return volumes\n\n\ndef get_volume_data(grd, step=96, stride=1, stride_cutoff=200):\n    volumes = []\n    \n    if len(grd)>stride_cutoff:\n        grd = grd[::stride]\n\n    take_last = False\n    if not str(len(grd)/step).endswith('.0'):\n        take_last = True\n\n    started = False\n    for i in range(len(grd)//step):\n        rows = grd[i*step:(i+1)*step]\n\n        if len(rows)!=step:\n            rows = pd.DataFrame([rows.iloc[int(x*len(rows))] for x in np.arange(0, 1, 1/step)])\n\n        volumes.append(rows)\n\n        started = True\n\n    if not started:\n        rows = grd\n        rows = pd.DataFrame([rows.iloc[int(x*len(rows))] for x in np.arange(0, 1, 1/step)])\n        volumes.append(rows)\n\n    if take_last:\n        rows = grd[-step:]\n        if len(rows)==step:\n            volumes.append(rows)\n\n    return volumes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:31.915771Z","iopub.execute_input":"2024-12-02T01:09:31.91607Z","iopub.status.idle":"2024-12-02T01:09:31.931517Z","shell.execute_reply.started":"2024-12-02T01:09:31.916047Z","shell.execute_reply":"2024-12-02T01:09:31.930614Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Config","metadata":{}},{"cell_type":"code","source":"IMAGE_FOLDER = '/kaggle/input/rsna-2023-abdominal-trauma-detection/train_images/'\n\npatient = '10007'  # We only predict a single patient in this notebook\n\ntest_augs = A.Compose([\n    A.Resize(384, 384),\n    ToTensorV2()\n])\n\npatient","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:31.932392Z","iopub.execute_input":"2024-12-02T01:09:31.932632Z","iopub.status.idle":"2024-12-02T01:09:31.947262Z","shell.execute_reply.started":"2024-12-02T01:09:31.932611Z","shell.execute_reply":"2024-12-02T01:09:31.946587Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"path = f'/kaggle/input/rsna-abd-models/try3_seg_resnet18d_v3/zip/0.pth'\nst = torch.load(path, map_location='cpu')\nmodel_3dseg = convert_3d(SegmentationModel())\nmodel_3dseg.load_state_dict(st)\nmodel_3dseg.eval()\nmodel_3dseg.cuda()\n    \n    \npath = f\"/kaggle/input/coatmed384ourdataseed6969/3.pth\"\nst = torch.load(path, map_location='cpu')\nmodel_organs = Model4(num_classes=10, seg_classes=4, arch='medium', mask_head=False)\nmodel_organs.load_state_dict(st)\nmodel_organs.cuda()\nmodel_organs.eval()\n\n\npath = f\"/kaggle/input/coatsmall384extravast4funet/3.pth\"\nst = torch.load(path, map_location='cpu')\nmodel_extrav = Model4(num_classes=2, seg_classes=4, arch='small', mask_head=False)\nmodel_extrav.load_state_dict(st)\nmodel_extrav.cuda()\nmodel_extrav.eval()\n\nprint('''We load 3 models here:\n1: 3d semantic segmentation model for segment organs\n2: 2.5d classification model for classify organs\n3: 2.5d classification model for classify extravasation\n''')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:31.94826Z","iopub.execute_input":"2024-12-02T01:09:31.948521Z","iopub.status.idle":"2024-12-02T01:09:34.334964Z","shell.execute_reply.started":"2024-12-02T01:09:31.948494Z","shell.execute_reply":"2024-12-02T01:09:34.334109Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Predict","metadata":{}},{"cell_type":"code","source":"PATIENT_TO_PREDICTION = {}\nPATIENT_TO_PREDICTION2 = {}\n\nfinal_outputs = []\nfinal_outputs2 = []\n\nstudies = os.listdir(f'{IMAGE_FOLDER}/{patient}')\nfor study in studies:\n\n    files = glob_sorted(f\"{IMAGE_FOLDER}/{patient}/{study}/*\")\n\n    volume = load_volume(files)\n    file_to_volume = {file: vol for file, vol in zip(files, volume)}\n\n    volumes = process_volume(volume)\n    volumes_seg = predict_segmentation(volumes, [model_3dseg])\n    volume_seg = np.concatenate(volumes_seg.transpose(0, 2, 1, 3, 4))[:len(volume)]\n    \n    vis_seg_0 = volumes[volumes.shape[0]//2, 16].numpy().astype(np.uint8)\n    vis_seg_1 = volumes_seg[volumes_seg.shape[0]//2, :, 16]\n    vis_seg_1[0] += vis_seg_1[3]\n    vis_seg_1[1] += vis_seg_1[4]\n    vis_seg_1 = (vis_seg_1[:3].transpose(1,2,0).clip(0, 1) * 255).astype(np.uint8)\n\n#     print(volumes.shape, volumes_seg.shape)  # torch.Size([7, 32, 128, 128]) (7, 5, 32, 128, 128)\n\n    msk = volume_seg.max(0).max(0)\n    ys, xs = np.where(msk)\n    y1, y2, x1, x2 = np.min(ys) / 128, np.max(ys) / 128, np.min(xs) / 128, np.max(xs) / 128\n\n    files = pd.DataFrame({\"file\": files})\n    files_volumes = get_volume_data(files, step=96, stride=2, stride_cutoff=400)\n\n    first = True\n\n    del volumes, volumes_seg, volume_seg, volume\n    gc.collect()\n\n    for file_volume in files_volumes:\n        volume = np.stack([file_to_volume[file] for file in file_volume.file])\n\n        if first:\n            h, w = volume.shape[1:]\n            y1, y2, x1, x2 = int(y1*h), int(y2*h), int(x1*w), int(x2*w)\n        volume2 = volume\n        \n        #### CROPPED #####\n        volume = volume[:, y1:y2, x1:x2]\n\n        vols = []\n        NC = 3\n        for i in range(len(volume)//NC):\n            vols.append(volume[i*NC:(i+1)*NC])\n        vol = np.stack(vols, 0).transpose(0, 2, 3, 1)\n\n        volume_ = []\n        for image in vol:\n            image = image.astype(np.float32) / 255\n            transformed = test_augs(image=image)\n            image = transformed['image']\n            volume_.append(image)\n        volume = torch.stack(volume_).float()\n        volume = volume.cuda()\n\n        #### UNCROPPED #####\n        vols = []\n        NC = 3\n        for i in range(len(volume2)//NC):\n            vols.append(volume2[i*NC:(i+1)*NC])\n        vol = np.stack(vols, 0).transpose(0, 2, 3, 1)\n\n        volume_ = []\n        for image in vol:\n            image = image.astype(np.float32) / 255\n            transformed = test_augs(image=image)\n            image = transformed['image']\n            volume_.append(image)\n\n        volume2 = torch.stack(volume_).float()\n        volume2 = volume2.cuda()\n\n        outputs = []\n        outputs2 = []\n\n        with torch.no_grad():\n            with torch.cuda.amp.autocast(enabled=True):\n\n                outs = model_organs(volume.unsqueeze(0))\n                outs = outs.float().sigmoid()\n                outputs.append(outs)\n\n                outs = model_extrav(volume2.unsqueeze(0))[:, :, [1, 0]]\n                outs = outs.float().sigmoid()\n                outputs2.append(outs)\n\n        torch.cuda.empty_cache()\n\n        outputs = torch.stack(outputs)[:, 0].mean(0)\n        outputs2 = torch.stack(outputs2)[:, 0].mean(0)\n\n        final_outputs.append(outputs.detach().cpu().numpy())\n        final_outputs2.append(outputs2.detach().cpu().numpy())\n\n        first = False\n\n        torch.cuda.empty_cache()\n\n\nlast_final_outputs = final_outputs.copy()\nlast_final_outputs2 = final_outputs2.copy()\n\nfinal_outputs = np.concatenate(final_outputs)\nfinal_outputs2 = np.concatenate(final_outputs2)\n\nfinal_predictions = final_outputs.max(0)\nfinal_predictions2 = final_outputs2.max(0)\n\nPATIENT_TO_PREDICTION[patient] = final_predictions\nPATIENT_TO_PREDICTION2[patient] = final_predictions2\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:34.336068Z","iopub.execute_input":"2024-12-02T01:09:34.336322Z","iopub.status.idle":"2024-12-02T01:09:38.418056Z","shell.execute_reply.started":"2024-12-02T01:09:34.3363Z","shell.execute_reply":"2024-12-02T01:09:38.417305Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fig, axarr = plt.subplots(1, 2, figsize=(10, 4))\n\naxarr[0].imshow(vis_seg_0)\naxarr[0].axis('off') \n\naxarr[1].imshow(vis_seg_1)\naxarr[1].axis('off') \n\nplt.tight_layout() \nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:38.419228Z","iopub.execute_input":"2024-12-02T01:09:38.419525Z","iopub.status.idle":"2024-12-02T01:09:38.65743Z","shell.execute_reply.started":"2024-12-02T01:09:38.419499Z","shell.execute_reply":"2024-12-02T01:09:38.656305Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Postprocess","metadata":{}},{"cell_type":"code","source":"bowel_w = 2\nextrav_w = 6\nlow_w = 2\nhigh_w = 4\n\nFINAL_SUB = {'patient_id': [], 'bowel_healthy': [], 'bowel_injury': [], \n             'extravasation_healthy': [], 'extravasation_injury': [], \n             'kidney_healthy': [], 'kidney_low': [], 'kidney_high': [],\n             'liver_healthy': [], 'liver_low': [], 'liver_high': [],\n             'spleen_healthy': [], 'spleen_low': [], 'spleen_high': [],}\n\nfor patient in PATIENT_TO_PREDICTION:\n    prediction = PATIENT_TO_PREDICTION[patient].copy()\n    prediction2 = PATIENT_TO_PREDICTION2[patient].copy()\n    \n    prediction[9] = (prediction[9] * 0.666) + (prediction2[1]*0.334)\n    \n    FINAL_SUB['patient_id'].append(patient)\n    \n    FINAL_SUB['bowel_healthy'].append(1 - prediction[9])\n    FINAL_SUB['bowel_injury'].append(prediction[9] * bowel_w)\n    FINAL_SUB['extravasation_healthy'].append(1 - prediction2[0])\n    FINAL_SUB['extravasation_injury'].append(0.06355258976803305 + (prediction2[0] * extrav_w))\n    \n    FINAL_SUB['liver_healthy'].append(1 - prediction[0])\n    FINAL_SUB['liver_low'].append(prediction[3]*low_w)\n    FINAL_SUB['liver_high'].append(prediction[4]*high_w)\n\n    FINAL_SUB['spleen_healthy'].append(1 - prediction[1])\n    FINAL_SUB['spleen_low'].append(prediction[5]*low_w)\n    FINAL_SUB['spleen_high'].append(prediction[6]*high_w)\n\n    FINAL_SUB['kidney_healthy'].append(1 - prediction[2])\n    FINAL_SUB['kidney_low'].append((prediction[7])*low_w)\n    FINAL_SUB['kidney_high'].append(prediction[8]*high_w)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:38.658945Z","iopub.execute_input":"2024-12-02T01:09:38.659811Z","iopub.status.idle":"2024-12-02T01:09:38.669123Z","shell.execute_reply.started":"2024-12-02T01:09:38.659786Z","shell.execute_reply":"2024-12-02T01:09:38.668235Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nsubmission = pd.DataFrame(FINAL_SUB)\nsubmission","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:38.670289Z","iopub.execute_input":"2024-12-02T01:09:38.670546Z","iopub.status.idle":"2024-12-02T01:09:38.694454Z","shell.execute_reply.started":"2024-12-02T01:09:38.670525Z","shell.execute_reply":"2024-12-02T01:09:38.693513Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"patient_id = submission['patient_id'].iloc[0]\ndata_to_plot = submission.drop(columns=['patient_id'])\nenglish_column_names = {\n    \"bowel_healthy\": \"Bowel Healthy\",\n    \"bowel_injury\": \"Bowel Injury\",\n    \"extravasation_healthy\": \"Extravasation Healthy\",\n    \"extravasation_injury\": \"Extravasation Injury\",\n    \"kidney_healthy\": \"Kidney Healthy\",\n    \"kidney_low\": \"Kidney Low\",\n    \"kidney_high\": \"Kidney High\",\n    \"liver_healthy\": \"Liver Healthy\",\n    \"liver_low\": \"Liver Low\",\n    \"liver_high\": \"Liver High\",\n    \"spleen_healthy\": \"Spleen Healthy\",\n    \"spleen_low\": \"Spleen Low\",\n    \"spleen_high\": \"Spleen High\"\n}\n\ndata_to_plot.columns = [english_column_names[col] for col in data_to_plot.columns]\n\nplt.figure(figsize=(15, 7))\ndata_to_plot.T.plot(kind='bar', legend=False, ax=plt.gca())\nplt.title(f\"Probability of Diseases for Patient {patient_id}\")\nplt.ylabel(\"Probability\")\nplt.xticks(rotation=45, ha='right')\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:38.695542Z","iopub.execute_input":"2024-12-02T01:09:38.695772Z","iopub.status.idle":"2024-12-02T01:09:39.102872Z","shell.execute_reply.started":"2024-12-02T01:09:38.69575Z","shell.execute_reply":"2024-12-02T01:09:39.101968Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!rm -rf /kaggle/working/*","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:39.104112Z","iopub.execute_input":"2024-12-02T01:09:39.104386Z","iopub.status.idle":"2024-12-02T01:09:40.192235Z","shell.execute_reply.started":"2024-12-02T01:09:39.104364Z","shell.execute_reply":"2024-12-02T01:09:40.19113Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission.to_csv('./submission.csv', index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:40.19398Z","iopub.execute_input":"2024-12-02T01:09:40.194486Z","iopub.status.idle":"2024-12-02T01:09:40.203321Z","shell.execute_reply.started":"2024-12-02T01:09:40.194445Z","shell.execute_reply":"2024-12-02T01:09:40.202518Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom sklearn.metrics import confusion_matrix\nimport seaborn as sns\nimport numpy as np\n\n# Convert targets and predictions to numpy arrays\nall_preds_np = np.vstack(all_preds)\nall_targets_np = np.vstack(all_targets)\n\n# Các bộ phận cần tính ma trận nhầm lẫn\norgans = [\"Bowel\", \"Extravasation\", \"Liver\", \"Kidney\", \"Spleen\"]\n\n# Lặp qua từng bộ phận và tính toán ma trận nhầm lẫn\nfor i, organ in enumerate(organs):\n    # Tạo ma trận nhầm lẫn cho từng bộ phận (sử dụng lớp tương ứng)\n    conf_matrix = confusion_matrix(all_targets_np[:, i], all_preds_np[:, i])\n    \n    # Hiển thị ma trận nhầm lẫn dưới dạng heatmap\n    plt.figure(figsize=(8, 6))\n    sns.heatmap(conf_matrix, annot=True, fmt=\"d\", cmap=\"Blues\", xticklabels=[\"Healthy\", \"Injury\"], yticklabels=[\"Healthy\", \"Injury\"])\n    plt.title(f'{organ} Confusion Matrix', fontsize=16)\n    plt.xlabel('Predicted', fontsize=12)\n    plt.ylabel('True', fontsize=12)\n    plt.show()\n\n    # In ra ma trận nhầm lẫn cho từng bộ phận\n    print(f\"{organ} Confusion Matrix:\")\n    print(conf_matrix)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:40.204243Z","iopub.execute_input":"2024-12-02T01:09:40.204554Z","iopub.status.idle":"2024-12-02T01:09:41.409448Z","shell.execute_reply.started":"2024-12-02T01:09:40.204531Z","shell.execute_reply":"2024-12-02T01:09:41.408533Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Vẽ đồ thị cho độ chính xác của validation qua các epoch\nplt.figure(figsize=(14, 6))\n\n# Độ chính xác validation\nplt.subplot(2, 2, 1)\nplt.plot(range(1, config.EPOCHS + 1), fold_val_accuracies, label=\"Val Accuracy\", color=\"blue\", linewidth=2)\nplt.title(\"Validation Accuracy Over Epochs\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Accuracy (%)\")\nplt.grid(True)\n\n# F1 Score\nplt.subplot(2, 2, 2)\nplt.plot(range(1, config.EPOCHS + 1), fold_val_f1_scores, label=\"Val F1 Score\", color=\"green\", linewidth=2)\nplt.title(\"Validation F1 Score Over Epochs\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"F1 Score\")\nplt.grid(True)\n\n# Sensitivity (Average over all classes)\navg_sensitivity = [np.mean(sensitivity_per_class[:epoch+1]) for epoch in range(config.EPOCHS)]\nplt.subplot(2, 2, 3)\nplt.plot(range(1, config.EPOCHS + 1), avg_sensitivity, label=\"Avg Sensitivity\", color=\"red\", linewidth=2)\nplt.title(\"Average Sensitivity Over Epochs\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Sensitivity (%)\")\nplt.grid(True)\n\n# Specificity (Average over all classes)\navg_specificity = [np.mean(specificity_per_class[:epoch+1]) for epoch in range(config.EPOCHS)]\nplt.subplot(2, 2, 4)\nplt.plot(range(1, config.EPOCHS + 1), avg_specificity, label=\"Avg Specificity\", color=\"purple\", linewidth=2)\nplt.title(\"Average Specificity Over Epochs\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Specificity (%)\")\nplt.grid(True)\n\n# Hiển thị tất cả các đồ thị\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:41.410907Z","iopub.execute_input":"2024-12-02T01:09:41.411255Z","iopub.status.idle":"2024-12-02T01:09:42.227231Z","shell.execute_reply.started":"2024-12-02T01:09:41.411224Z","shell.execute_reply":"2024-12-02T01:09:42.226409Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Vẽ đồ thị cho độ chính xác của validation qua các epoch\nplt.figure(figsize=(14, 6))\n\n# Độ chính xác validation\nplt.subplot(2, 2, 1)\nplt.plot(range(1, config.EPOCHS + 1), fold_val_accuracies, label=\"Val Accuracy\", color=\"blue\", linewidth=2)\nplt.title(\"Validation Accuracy Over Epochs\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Accuracy (%)\")\nplt.grid(True)\n\n# F1 Score\nplt.subplot(2, 2, 2)\nplt.plot(range(1, config.EPOCHS + 1), fold_val_f1_scores, label=\"Val F1 Score\", color=\"green\", linewidth=2)\nplt.title(\"Validation F1 Score Over Epochs\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"F1 Score\")\nplt.grid(True)\n\n# Sensitivity (Average over all classes)\navg_sensitivity = [np.mean(sensitivity_per_class[:epoch+1]) for epoch in range(config.EPOCHS)]\nplt.subplot(2, 2, 3)\nplt.plot(range(1, config.EPOCHS + 1), avg_sensitivity, label=\"Avg Sensitivity\", color=\"red\", linewidth=2)\nplt.title(\"Average Sensitivity Over Epochs\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Sensitivity (%)\")\nplt.grid(True)\n\n# Specificity (Average over all classes)\navg_specificity = [np.mean(specificity_per_class[:epoch+1]) for epoch in range(config.EPOCHS)]\nplt.subplot(2, 2, 4)\nplt.plot(range(1, config.EPOCHS + 1), avg_specificity, label=\"Avg Specificity\", color=\"purple\", linewidth=2)\nplt.title(\"Average Specificity Over Epochs\")\nplt.xlabel(\"Epochs\")\nplt.ylabel(\"Specificity (%)\")\nplt.grid(True)\n\n# Hiển thị tất cả các đồ thị\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:42.228524Z","iopub.execute_input":"2024-12-02T01:09:42.229121Z","iopub.status.idle":"2024-12-02T01:09:43.032009Z","shell.execute_reply.started":"2024-12-02T01:09:42.229089Z","shell.execute_reply":"2024-12-02T01:09:43.031161Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Khởi tạo fold_organ_accuracies ngoài vòng lặp epoch\nfold_organ_accuracies = {organ: [] for organ in [\"Bowel\", \"Extravasation\", \"Liver\", \"Kidney\", \"Spleen\"]}\n\nfor epoch in range(config.EPOCHS):\n    model.eval()\n    val_loss, correct, total = 0.0, 0, 0\n    correct_per_organ = {organ: 0 for organ in fold_organ_accuracies}\n    total_per_organ = {organ: 0 for organ in fold_organ_accuracies}\n\n    with torch.no_grad():\n        for images, labels in val_dataloader:\n            images, labels = images.to(device), labels.to(device)\n\n            with torch.amp.autocast(device_type=device.type):\n                outputs = model(images)\n                loss = criterion(outputs, labels)\n\n            val_loss += loss.item() * images.size(0)\n\n            preds = torch.sigmoid(outputs) > 0.5\n\n            for organ_idx, organ_name in enumerate(fold_organ_accuracies):\n                correct_per_organ[organ_name] += (preds[:, organ_idx].int() == labels[:, organ_idx].int()).sum().item()\n                total_per_organ[organ_name] += labels[:, organ_idx].numel()\n\n    # Tính toán và lưu accuracy cho từng bộ phận trong fold_organ_accuracies\n    for organ in fold_organ_accuracies:\n        accuracy = 100.0 * correct_per_organ[organ] / total_per_organ[organ]\n        fold_organ_accuracies[organ].append(accuracy)\n\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-02T01:09:43.033073Z","iopub.execute_input":"2024-12-02T01:09:43.03331Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Vẽ đồ thị độ chính xác cho từng bộ phận\nplt.figure(figsize=(14, 10))\n\n# Duyệt qua từng bộ phận và vẽ đồ thị\nfor organ, accuracies in fold_organ_accuracies.items():\n    plt.plot(range(1, config.EPOCHS + 1), accuracies, label=f'{organ} Accuracy', linewidth=2)\n\nplt.title('Accuracy for Each Organ Over Epochs', fontsize=16)\nplt.xlabel('Epochs', fontsize=12)\nplt.ylabel('Accuracy (%)', fontsize=12)\nplt.grid(True)\nplt.legend()\n\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Đảm bảo rằng bạn đã tính toán và lưu trữ giá trị loss qua các epoch\nepochs = range(1, config.EPOCHS + 1)\n\n# Vẽ đồ thị cho Train Loss và Validation Loss\nplt.figure(figsize=(10, 6))\n\n# Vẽ Train Loss\nplt.plot(epochs, fold_train_losses, label='Train Loss', color='blue', linestyle='-', marker='o')\n\n# Vẽ Validation Loss\nplt.plot(epochs, fold_val_losses, label='Validation Loss', color='red', linestyle='-', marker='x')\n\n# Thêm tiêu đề và nhãn cho các trục\nplt.title('Train Loss and Validation Loss over Epochs', fontsize=16)\nplt.xlabel('Epochs', fontsize=12)\nplt.ylabel('Loss', fontsize=12)\n\n# Thêm lưới cho dễ nhìn\nplt.grid(True)\n\n# Hiển thị chú thích để phân biệt giữa Train Loss và Validation Loss\nplt.legend()\n\n# Hiển thị đồ thị\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\n\n# Dữ liệu lưu trữ độ chính xác cho từng bộ phận qua các epoch\n# Giả sử bạn đã tính toán accuracies trong fold_organ_accuracies trước đó\n\n# Tạo dữ liệu từ các danh sách lưu trữ độ chính xác của từng bộ phận\naccuracies_data = [\n    fold_organ_accuracies['Bowel'],\n    fold_organ_accuracies['Extravasation'],\n    fold_organ_accuracies['Liver'],\n    fold_organ_accuracies['Kidney'],\n    fold_organ_accuracies['Spleen']\n]\n\n# Tạo nhãn cho mỗi bộ phận\norgan_names = ['Bowel', 'Extravasation', 'Liver', 'Kidney', 'Spleen']\n\n# Tạo đồ thị boxplot\nplt.figure(figsize=(10, 6))\nsns.boxplot(data=accuracies_data)\n\n# Thêm tiêu đề và nhãn cho trục\nplt.title('Boxplot of Accuracy for Different Organs')\nplt.ylabel('Accuracy (%)')\nplt.xticks(ticks=range(len(organ_names)), labels=organ_names)\n\n# Hiển thị đồ thị\nplt.show()\n","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}