{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport torch\nfrom torch.utils.data import Dataset, DataLoader\nfrom glob import glob\nfrom torchvision import transforms\nfrom PIL import Image\nimport torch.optim as optim\nfrom torch import nn\nimport pydicom as dicom\n\nimport pandas as pd\n\nfrom matplotlib import pyplot as plt\nfrom matplotlib import style\nstyle.use(\"fivethirtyeight\")\n\nfrom sklearn.model_selection import train_test_split","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:20.826707Z","iopub.execute_input":"2023-10-10T05:47:20.827047Z","iopub.status.idle":"2023-10-10T05:47:25.956629Z","shell.execute_reply.started":"2023-10-10T05:47:20.827024Z","shell.execute_reply":"2023-10-10T05:47:25.955642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.__version__","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:40.295266Z","iopub.execute_input":"2023-10-10T05:47:40.295729Z","iopub.status.idle":"2023-10-10T05:47:40.301995Z","shell.execute_reply.started":"2023-10-10T05:47:40.295701Z","shell.execute_reply":"2023-10-10T05:47:40.301132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# set up device-agnostic code\ndevice = 'cuda' if torch.cuda.is_available() else 'cpu'","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:41.098591Z","iopub.execute_input":"2023-10-10T05:47:41.099249Z","iopub.status.idle":"2023-10-10T05:47:41.126292Z","shell.execute_reply.started":"2023-10-10T05:47:41.09922Z","shell.execute_reply":"2023-10-10T05:47:41.125393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Config:\n    SEED = 22\n    IMAGE_SIZE = [256, 256]\n    BATCH_SIZE = 16\n    EPOCHS = 10\n\nconfig = Config()","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:41.831201Z","iopub.execute_input":"2023-10-10T05:47:41.83151Z","iopub.status.idle":"2023-10-10T05:47:41.836564Z","shell.execute_reply.started":"2023-10-10T05:47:41.831485Z","shell.execute_reply":"2023-10-10T05:47:41.835424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.path.dirname(os.path.abspath(\"__file__\"))","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:42.461807Z","iopub.execute_input":"2023-10-10T05:47:42.462393Z","iopub.status.idle":"2023-10-10T05:47:42.468369Z","shell.execute_reply.started":"2023-10-10T05:47:42.462352Z","shell.execute_reply":"2023-10-10T05:47:42.467533Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import requests\nimport zipfile\nfrom pathlib import Path\n\n\ndata_path = Path(\"/kaggle/input/rsna-2023-abdominal-trauma-detection/\")","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:43.292907Z","iopub.execute_input":"2023-10-10T05:47:43.293226Z","iopub.status.idle":"2023-10-10T05:47:43.297647Z","shell.execute_reply.started":"2023-10-10T05:47:43.293201Z","shell.execute_reply":"2023-10-10T05:47:43.296728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dir = data_path / \"train_images\"\ntest_dir = data_path / \"test_images\"\nlabel_dir = data_path / \"train.csv\"\nseries_dir = data_path / \"train_series_meta.csv\"\nimage_level_dir = data_path / \"image_level_labels.csv\"\ntrain_dir, test_dir, label_dir, series_dir, image_level_dir","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:43.970796Z","iopub.execute_input":"2023-10-10T05:47:43.971185Z","iopub.status.idle":"2023-10-10T05:47:43.979802Z","shell.execute_reply.started":"2023-10-10T05:47:43.971155Z","shell.execute_reply":"2023-10-10T05:47:43.978919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_df = pd.read_csv(label_dir)\nlabel_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:44.642607Z","iopub.execute_input":"2023-10-10T05:47:44.642949Z","iopub.status.idle":"2023-10-10T05:47:44.677649Z","shell.execute_reply.started":"2023-10-10T05:47:44.642925Z","shell.execute_reply":"2023-10-10T05:47:44.676605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"series_df = pd.read_csv(series_dir)\nseries_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:45.556896Z","iopub.execute_input":"2023-10-10T05:47:45.557521Z","iopub.status.idle":"2023-10-10T05:47:45.577258Z","shell.execute_reply.started":"2023-10-10T05:47:45.55749Z","shell.execute_reply":"2023-10-10T05:47:45.576316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_level_df = pd.read_csv(image_level_dir)\nimage_level_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:46.150452Z","iopub.execute_input":"2023-10-10T05:47:46.15143Z","iopub.status.idle":"2023-10-10T05:47:46.177095Z","shell.execute_reply.started":"2023-10-10T05:47:46.151397Z","shell.execute_reply":"2023-10-10T05:47:46.176168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = label_df.merge(image_level_df, on=['patient_id'], how = 'right')\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:46.709682Z","iopub.execute_input":"2023-10-10T05:47:46.71072Z","iopub.status.idle":"2023-10-10T05:47:46.746777Z","shell.execute_reply.started":"2023-10-10T05:47:46.710683Z","shell.execute_reply":"2023-10-10T05:47:46.745841Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df[\"image_path\"] = f\"{data_path}/train_images\"\\\n                    + \"/\" + df.patient_id.astype(str)\\\n                    + \"/\" + df.series_id.astype(str)\\\n                    + \"/\" + df.instance_number.astype(str) +\".dcm\"\ndf = df.drop_duplicates()\ndf.head(), df.shape","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:47.412608Z","iopub.execute_input":"2023-10-10T05:47:47.413793Z","iopub.status.idle":"2023-10-10T05:47:47.45981Z","shell.execute_reply.started":"2023-10-10T05:47:47.413754Z","shell.execute_reply":"2023-10-10T05:47:47.458893Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_paths = glob('/kaggle/input/rsna-2023-abdominal-trauma-detection/test_images/*/*/*dcm')\n\ntest_df = pd.DataFrame(test_paths, columns=[\"image_path\"])\ntest_df['patient_id'] = test_df.image_path.map(lambda x: x.split('/')[-3]).astype(int)\ntest_df['series_id'] = test_df.image_path.map(lambda x: x.split('/')[-2]).astype(int)\ntest_df['instance_number'] = test_df.image_path.map(lambda x: x.split('/')[-1].replace('.dcm','')).astype(int)\nprint('Test:')\nprint(f'# Size: {len(test_df)}')\ndisplay(test_df.head())","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:48.310395Z","iopub.execute_input":"2023-10-10T05:47:48.311066Z","iopub.status.idle":"2023-10-10T05:47:48.338326Z","shell.execute_reply.started":"2023-10-10T05:47:48.311035Z","shell.execute_reply":"2023-10-10T05:47:48.337385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_df.columns[1:].tolist()","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:49.07562Z","iopub.execute_input":"2023-10-10T05:47:49.075977Z","iopub.status.idle":"2023-10-10T05:47:49.083033Z","shell.execute_reply.started":"2023-10-10T05:47:49.075951Z","shell.execute_reply":"2023-10-10T05:47:49.081967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = label_df.columns[1:].tolist()","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:49.686611Z","iopub.execute_input":"2023-10-10T05:47:49.687645Z","iopub.status.idle":"2023-10-10T05:47:49.692259Z","shell.execute_reply.started":"2023-10-10T05:47:49.687608Z","shell.execute_reply":"2023-10-10T05:47:49.691242Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\n# 切分 training set and validate set\n\n# 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 = config.SEED)\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 df.groupby(labels):\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":{"execution":{"iopub.status.busy":"2023-10-10T05:47:50.312925Z","iopub.execute_input":"2023-10-10T05:47:50.313351Z","iopub.status.idle":"2023-10-10T05:47:50.380558Z","shell.execute_reply.started":"2023-10-10T05:47:50.313322Z","shell.execute_reply":"2023-10-10T05:47:50.379728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_data.shape, val_data.shape","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:50.954121Z","iopub.execute_input":"2023-10-10T05:47:50.954435Z","iopub.status.idle":"2023-10-10T05:47:50.960809Z","shell.execute_reply.started":"2023-10-10T05:47:50.95441Z","shell.execute_reply":"2023-10-10T05:47:50.959858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Visualize an image","metadata":{}},{"cell_type":"code","source":"import random\nfrom PIL import Image\n\n# Set seed\nrandom.seed(config.SEED)","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:52.327012Z","iopub.execute_input":"2023-10-10T05:47:52.327627Z","iopub.status.idle":"2023-10-10T05:47:52.332514Z","shell.execute_reply.started":"2023-10-10T05:47:52.327596Z","shell.execute_reply":"2023-10-10T05:47:52.331299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# image_path_list = list(train_dir.glob(\"*/*/*.dcm\"))","metadata":{"_kg_hide-input":true,"_kg_hide-output":false,"execution":{"iopub.status.busy":"2023-10-10T05:47:52.947693Z","iopub.execute_input":"2023-10-10T05:47:52.948638Z","iopub.status.idle":"2023-10-10T05:47:52.953174Z","shell.execute_reply.started":"2023-10-10T05:47:52.948591Z","shell.execute_reply":"2023-10-10T05:47:52.952157Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # 2. Get random image path\n# random_image_path = random.choice(image_path_list)\n# random_image_path","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:53.440578Z","iopub.execute_input":"2023-10-10T05:47:53.441222Z","iopub.status.idle":"2023-10-10T05:47:53.445457Z","shell.execute_reply.started":"2023-10-10T05:47:53.441191Z","shell.execute_reply":"2023-10-10T05:47:53.444293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# random_image_path.parent.parent.stem","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:53.788363Z","iopub.execute_input":"2023-10-10T05:47:53.789319Z","iopub.status.idle":"2023-10-10T05:47:53.793499Z","shell.execute_reply.started":"2023-10-10T05:47:53.789279Z","shell.execute_reply":"2023-10-10T05:47:53.792229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import pydicom as dicom\n# ds = dicom.dcmread(random_image_path)\n# plt.imshow(ds.pixel_array, cmap = plt.cm.bone)  # set the color map to bone\n# plt.axis('off')\n# plt.colorbar()\n# plt.show()\n# print(f\"Random dic path: {random_image_path}\")","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:54.239683Z","iopub.execute_input":"2023-10-10T05:47:54.240002Z","iopub.status.idle":"2023-10-10T05:47:54.24417Z","shell.execute_reply.started":"2023-10-10T05:47:54.239979Z","shell.execute_reply":"2023-10-10T05:47:54.243257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nfrom torch.utils.data import DataLoader\nfrom torchvision import datasets, transforms\n\ndata_transform = transforms.Compose([\n    transforms.Resize(size = (256, 256)),\n    transforms.RandomHorizontalFlip(p = 0.5),\n    transforms.ColorJitter(brightness = 0.2, contrast = 0.3, saturation = 0.4, hue = 0.2),\n    transforms.ToTensor()\n])\ndata_transform","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:54.803334Z","iopub.execute_input":"2023-10-10T05:47:54.803854Z","iopub.status.idle":"2023-10-10T05:47:54.811456Z","shell.execute_reply.started":"2023-10-10T05:47:54.803824Z","shell.execute_reply":"2023-10-10T05:47:54.810428Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import random\nimport pydicom\nimport numpy as np\nfrom PIL import Image\nimport matplotlib.pyplot as plt\n\n# def plot_transformed_images(dicom_paths, transform, n = 3, seed = 42):\n#     \"\"\"Plots a series of random DICOM images from dicom_paths.\n\n#     Will open n DICOM paths from dicom_paths, transform them\n#     with transform and plot them side by side.\n\n#     Args:\n#         dicom_paths (list): List of DICOM file paths.\n#         transform (PyTorch Transforms): Transforms to apply to images.\n#         n (int, optional): Number of images to plot. Defaults to 3.\n#         seed (int, optional): Random seed for the random generator. Defaults to 42.\n#     \"\"\"\n#     random.seed(seed)\n#     # 從 dicom_paths 中隨機選擇 n 個 DICOM 檔案\n#     random_dicom_paths = random.sample(dicom_paths, k = n)\n#     for dicom_path in random_dicom_paths:\n#         # 使用 pydicom 開啟 DICOM 檔案，並使用 'with' 語句確保檔案在使用後被關閉\n#         with pydicom.dcmread(dicom_path) as dicom_data:\n#             dicom_image = dicom_data.pixel_array  # 從 DICOM 檔案中獲取像素數據\n\n#         # 將 NumPy 陣列轉換為 PIL 圖像\n#         pil_image = Image.fromarray(np.uint8(dicom_image))\n\n#         # 將 transform 應用於 PIL 圖像並去除單通道維度\n#         transformed_image = transform(pil_image).squeeze()  # 去除單通道維度\n#         print(transformed_image.shape)\n#         fig, ax = plt.subplots(1, 2)\n#         ax[0].imshow(pil_image, cmap = plt.cm.bone)\n#         ax[0].set_title(f\"Original \\nSize: {dicom_image.shape}\")\n#         ax[0].axis(\"off\")\n\n#         ax[1].imshow(transformed_image, cmap = plt.cm.bone)\n#         ax[1].set_title(f\"Transformed \\nSize: {transformed_image.shape}\")\n#         ax[1].axis(\"off\")\n\n#         fig.suptitle(f\"Patient ID: {dicom_data.PatientID}\", fontsize=16)\n\n# # 调用示例\n# plot_transformed_images(image_path_list,\n#                         transform = data_transform,\n#                         n = 5)","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:55.38796Z","iopub.execute_input":"2023-10-10T05:47:55.388285Z","iopub.status.idle":"2023-10-10T05:47:55.395709Z","shell.execute_reply.started":"2023-10-10T05:47:55.38826Z","shell.execute_reply":"2023-10-10T05:47:55.392962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_labels = train_data[labels].values\ntrain_labels, train_labels.shape","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:55.963011Z","iopub.execute_input":"2023-10-10T05:47:55.963655Z","iopub.status.idle":"2023-10-10T05:47:55.972075Z","shell.execute_reply.started":"2023-10-10T05:47:55.963626Z","shell.execute_reply":"2023-10-10T05:47:55.971133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val_labels = val_data[labels].values\nval_labels, val_labels.shape","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:56.380327Z","iopub.execute_input":"2023-10-10T05:47:56.380693Z","iopub.status.idle":"2023-10-10T05:47:56.388683Z","shell.execute_reply.started":"2023-10-10T05:47:56.380645Z","shell.execute_reply":"2023-10-10T05:47:56.387725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def standardize_pixel_array(dcm: pydicom.dataset.FileDataset) -> np.ndarray:\n    # Correct DICOM pixel_array if PixelRepresentation == 1.\n    pixel_array = dcm.pixel_array\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    return pixel_array","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:57.107553Z","iopub.execute_input":"2023-10-10T05:47:57.108551Z","iopub.status.idle":"2023-10-10T05:47:57.113813Z","shell.execute_reply.started":"2023-10-10T05:47:57.10851Z","shell.execute_reply":"2023-10-10T05:47:57.112903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import Dataset\n\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        # Read the DICOM file\n        dicom_file = pydicom.dcmread(self.paths[idx])\n\n        # Extract the image data from the DICOM file\n        # image = dicom_file.pixel_array\n\n        # Standardize the DICOM pixel_array\n        pixel_array = standardize_pixel_array(dicom_file)\n        \n        # Convert to PIL image\n        image = Image.fromarray(pixel_array)\n\n        # Convert to RGB if needed (some DICOMs are grayscale)\n        if image.mode != 'RGB':\n            image = image.convert('RGB')\n\n        if self.labels is not None:\n            label = torch.tensor(self.labels[idx], dtype=torch.float32)\n        else:\n            # 如果没有标签，可以返回一个虚拟的标签，例如全零\n            label = torch.zeros(1, dtype=torch.float32)\n\n        if self.transform:\n            image = self.transform(image)\n\n        return image, label","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:57.707943Z","iopub.execute_input":"2023-10-10T05:47:57.708267Z","iopub.status.idle":"2023-10-10T05:47:57.715485Z","shell.execute_reply.started":"2023-10-10T05:47:57.708241Z","shell.execute_reply":"2023-10-10T05:47:57.714504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_paths  = train_data.image_path.tolist()\nval_paths  = val_data.image_path.tolist()","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:58.356517Z","iopub.execute_input":"2023-10-10T05:47:58.357286Z","iopub.status.idle":"2023-10-10T05:47:58.362527Z","shell.execute_reply.started":"2023-10-10T05:47:58.357256Z","shell.execute_reply":"2023-10-10T05:47:58.361524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n    display(train_data['image_path'][0])","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:59.167353Z","iopub.execute_input":"2023-10-10T05:47:59.167707Z","iopub.status.idle":"2023-10-10T05:47:59.173555Z","shell.execute_reply.started":"2023-10-10T05:47:59.167649Z","shell.execute_reply":"2023-10-10T05:47:59.172734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Augment train data\ntrain_transforms = transforms.Compose([\n    transforms.Resize(size = (256, 256)),\n    transforms.RandomHorizontalFlip(p = 0.5),\n    transforms.ColorJitter(brightness = 0.2, contrast = 0.2, saturation = 0.2, hue = 0.1),\n    transforms.ToTensor()\n])\n\n# Don't augment test data, only reshape\ntest_transforms = transforms.Compose([\n    transforms.Resize((256, 256)),\n    transforms.ToTensor()\n])","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:47:59.732643Z","iopub.execute_input":"2023-10-10T05:47:59.73328Z","iopub.status.idle":"2023-10-10T05:47:59.738665Z","shell.execute_reply.started":"2023-10-10T05:47:59.73325Z","shell.execute_reply":"2023-10-10T05:47:59.737335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#torch dataset\nbatch_size = 32\n\n# Create the datasets\n\ndataset_train = CustomDataset(train_paths, train_labels, transform = train_transforms)\ndataset_val = CustomDataset(val_paths, val_labels, transform = test_transforms)","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:00.281178Z","iopub.execute_input":"2023-10-10T05:48:00.281792Z","iopub.status.idle":"2023-10-10T05:48:00.286185Z","shell.execute_reply.started":"2023-10-10T05:48:00.281762Z","shell.execute_reply":"2023-10-10T05:48:00.285351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(dataset_train), len(dataset_val)","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:00.809145Z","iopub.execute_input":"2023-10-10T05:48:00.810068Z","iopub.status.idle":"2023-10-10T05:48:00.816635Z","shell.execute_reply.started":"2023-10-10T05:48:00.810029Z","shell.execute_reply":"2023-10-10T05:48:00.81563Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataloader = DataLoader(dataset_train, batch_size = batch_size, shuffle = True, num_workers = os.cpu_count())\nval_dataloader = DataLoader(dataset_val, batch_size = batch_size, shuffle = True, num_workers = os.cpu_count())","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:01.980226Z","iopub.execute_input":"2023-10-10T05:48:01.980561Z","iopub.status.idle":"2023-10-10T05:48:01.985987Z","shell.execute_reply.started":"2023-10-10T05:48:01.980535Z","shell.execute_reply":"2023-10-10T05:48:01.984997Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pydicom\nfrom PIL import Image\n\nfor img, label in train_dataloader:\n  print(img.shape)\n  break","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:02.599578Z","iopub.execute_input":"2023-10-10T05:48:02.599948Z","iopub.status.idle":"2023-10-10T05:48:04.556895Z","shell.execute_reply.started":"2023-10-10T05:48:02.599923Z","shell.execute_reply":"2023-10-10T05:48:04.555872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport pydicom\nimport numpy as np\n\n# A function to display DICOM images with line breaks in labels\ndef show_dicom_images_with_linebreak(dicom_paths, labels):\n    num_images = len(dicom_paths)\n    fig, axes = plt.subplots(1, num_images, figsize = (15, 5))\n    \n    for idx, (dicom_path, label) in enumerate(zip(dicom_paths, labels)):\n        # Read the DICOM file\n        # 讀取 DICOM 文件\n        dicom_file = pydicom.dcmread(dicom_path)\n        \n        # Extract the pixel data from the DICOM file\n        #image = dicom_file.pixel_array\n         \n        # Standardize the DICOM pixel_array       \n        pixel_array = standardize_pixel_array(dicom_file)\n        \n        # Convert to PIL image\n        image = Image.fromarray(pixel_array) \n        \n        # Convert to uint8 for displaying\n        image = (image / np.max(image) * 255).astype(np.uint8)\n        \n        # Convert the label tensor to a string with line breaks\n        label_str = \"\\n\".join([str(val) for val in label])\n        \n        axes[idx].imshow(image, cmap ='gray')\n        axes[idx].set_title(f\"Labels:\\n{label_str}\", fontsize = 11)  # 使用換行符號分隔文本\n        axes[idx].axis(\"off\")\n    \n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:04.559025Z","iopub.execute_input":"2023-10-10T05:48:04.559415Z","iopub.status.idle":"2023-10-10T05:48:04.567158Z","shell.execute_reply.started":"2023-10-10T05:48:04.559377Z","shell.execute_reply":"2023-10-10T05:48:04.566248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load a few DICOM images for visualization\nnum_images_to_display = 7\nsample_indices = torch.randint(len(dataset_train), size = (num_images_to_display,))\nsample_dicom_paths = [dataset_train.paths[i] for i in sample_indices]\nsample_labels = [dataset_train.labels[i] for i in sample_indices]\n\n# Display the sample DICOM images with line breaks in labels\nshow_dicom_images_with_linebreak(sample_dicom_paths, sample_labels)","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:10.623268Z","iopub.execute_input":"2023-10-10T05:48:10.62372Z","iopub.status.idle":"2023-10-10T05:48:11.74933Z","shell.execute_reply.started":"2023-10-10T05:48:10.623635Z","shell.execute_reply":"2023-10-10T05:48:11.748321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## BUILD MODEL CNN with TinyVgg","metadata":{}},{"cell_type":"code","source":"class TinyVGG(nn.Module):\n    \"\"\"\n    Model architecture copying TinyVGG from: \n    https://poloclub.github.io/cnn-explainer/\n    \"\"\"\n    def __init__(self, input_shape: int, hidden_units: int, output_shape: int) -> None:\n        super().__init__()\n        self.conv_block_1 = nn.Sequential(\n            nn.Conv2d(in_channels=input_shape, \n                      out_channels=hidden_units, \n                      kernel_size=3, # how big is the square that's going over the image?\n                      stride=1, # default\n                      padding=1), # options = \"valid\" (no padding) or \"same\" (output has same shape as input) or int for specific number \n            nn.ReLU(),\n            nn.Conv2d(in_channels=hidden_units, \n                      out_channels=hidden_units,\n                      kernel_size=3,\n                      stride=1,\n                      padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(kernel_size=2,\n                         stride=2) # default stride value is same as kernel_size\n        )\n        self.conv_block_2 = nn.Sequential(\n            nn.Conv2d(hidden_units, hidden_units, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.Conv2d(hidden_units, hidden_units, kernel_size=3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2)\n        )\n        self.classifier = nn.Sequential(\n            nn.Flatten(),\n            # Where did this in_features shape come from? \n            # It's because each layer of our network compresses and changes the shape of our inputs data.\n            nn.Linear(in_features = hidden_units*64*64,\n                      out_features = output_shape)\n        )\n    \n    def forward(self, x: torch.Tensor):\n        x = self.conv_block_1(x)\n        # print(x.shape)\n        x = self.conv_block_2(x)\n        # print(x.shape)\n        x = self.classifier(x)\n        # print(x.shape)\n        return x\n        # return self.classifier(self.conv_block_2(self.conv_block_1(x))) # <- leverage the benefits of operator fusion\n\ntorch.manual_seed(42)\nmodel_0 = TinyVGG(input_shape = 3, # number of color channels (3 for RGB) \n                  hidden_units = 32, \n                  output_shape = len(train_labels[0])).to(device)\nmodel_0","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:14.745062Z","iopub.execute_input":"2023-10-10T05:48:14.745457Z","iopub.status.idle":"2023-10-10T05:48:17.900747Z","shell.execute_reply.started":"2023-10-10T05:48:14.745425Z","shell.execute_reply":"2023-10-10T05:48:17.899812Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Try a forward pass on a single image (to test the model)","metadata":{}},{"cell_type":"code","source":"img_batch, label_batch = next(iter(train_dataloader))","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:17.902413Z","iopub.execute_input":"2023-10-10T05:48:17.902785Z","iopub.status.idle":"2023-10-10T05:48:20.193448Z","shell.execute_reply.started":"2023-10-10T05:48:17.902754Z","shell.execute_reply":"2023-10-10T05:48:20.192206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_single, label_single = img_batch[0].unsqueeze(dim = 0), label_batch[0]\nprint(f\"Single image shape: {img_single.shape}\\n\")\n\n# 3. Perform a forward pass on a single image\nmodel_0.eval()\nwith torch.inference_mode():\n    pred = model_0(img_single.to(device))\n    \n# 4. Print out what's happening and convert model logits -> pred probs -> pred label\nprint(f\"Output logits:\\n{pred}\\n\")\nprint(f\"Output prediction probabilities:\\n{torch.softmax(pred, dim = 1)}\\n\")\nprint(f\"Output prediction label:\\n{(torch.softmax(pred, dim = 1) > 0.5).int()}\\n\")\nprint(f\"Actual label:\\n{label_single}\")","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:20.196148Z","iopub.execute_input":"2023-10-10T05:48:20.196842Z","iopub.status.idle":"2023-10-10T05:48:24.653274Z","shell.execute_reply.started":"2023-10-10T05:48:20.196804Z","shell.execute_reply":"2023-10-10T05:48:24.652294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_batch[0].unsqueeze(dim = 0).shape","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:24.654465Z","iopub.execute_input":"2023-10-10T05:48:24.655333Z","iopub.status.idle":"2023-10-10T05:48:24.662754Z","shell.execute_reply.started":"2023-10-10T05:48:24.6553Z","shell.execute_reply":"2023-10-10T05:48:24.661726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    import torchinfo\nexcept:\n    !pip install torchinfo\n    import torchinfo\n    \nfrom torchinfo import summary\nsummary(model_0, input_size = img_batch[0].unsqueeze(dim = 0).shape)","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:25.531004Z","iopub.execute_input":"2023-10-10T05:48:25.53137Z","iopub.status.idle":"2023-10-10T05:48:25.555568Z","shell.execute_reply.started":"2023-10-10T05:48:25.531339Z","shell.execute_reply":"2023-10-10T05:48:25.554545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_step(model: torch.nn.Module, \n               dataloader: torch.utils.data.DataLoader, \n               loss_fn: torch.nn.Module, \n               optimizer: torch.optim.Optimizer,\n               scheduler: torch.optim.lr_scheduler):\n    # Put model in train mode\n    model.train()\n    \n    # Setup train loss and train accuracy values\n    train_loss, train_acc = 0, 0\n    \n    # Loop through data loader data batches\n    for batch, (X, y) in enumerate(dataloader):\n        # Send data to target device\n        X, y = X.to(device), y.to(device)\n\n        # 1. Forward pass\n        y_pred = model(X)\n\n        # 2. Calculate  and accumulate loss\n        loss = loss_fn(y_pred, y)\n        train_loss += loss.item() \n\n        # 3. Optimizer zero grad\n        optimizer.zero_grad()\n\n        # 4. Loss backward\n        loss.backward()\n\n        # 5. Optimizer step\n        optimizer.step()\n        \n        # 6. Learning rate scheduler step\n        scheduler.step()  # 在优化器步骤之后调用学习率调度器        \n\n        # Calculate and accumulate accuracy metric across all batches\n        y_pred_class = (torch.softmax(y_pred, dim = 1) > 0.5).int()\n        batch_accuracy = (y_pred_class == y).float().mean().item()  # 计算每个 batch 的准确率\n        train_acc += batch_accuracy\n    \n    # Adjust metrics to get average loss and accuracy per batch \n    train_loss = train_loss / len(dataloader)\n    train_acc = train_acc / len(dataloader)\n    return train_loss, train_acc","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:26.923023Z","iopub.execute_input":"2023-10-10T05:48:26.923714Z","iopub.status.idle":"2023-10-10T05:48:26.931025Z","shell.execute_reply.started":"2023-10-10T05:48:26.923656Z","shell.execute_reply":"2023-10-10T05:48:26.929955Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def test_step(model: torch.nn.Module, \n              dataloader: torch.utils.data.DataLoader, \n              loss_fn: torch.nn.Module):\n    # Put model in eval mode\n    model.eval() \n    \n    # Setup test loss and test accuracy values\n    test_loss, test_acc, total_samples = 0, 0, 0\n    \n    # Turn on inference context manager\n    with torch.inference_mode():\n        # Loop through DataLoader batches\n        for batch, (X, y) in enumerate(dataloader):\n            # Send data to target device\n            X, y = X.to(device), y.to(device)\n    \n            # 1. Forward pass\n            test_pred_logits = model(X)\n\n            # 2. Calculate and accumulate loss\n            loss = loss_fn(test_pred_logits, y)\n            test_loss += loss.item()\n            \n            # Calculate and accumulate accuracy\n            test_pred_labels = (torch.softmax(test_pred_logits, dim = 1) > 0.5).int()\n            correct = (test_pred_labels == y).sum().item()\n            test_acc += correct\n            total_samples += len(y)\n            \n    # Adjust metrics to get average loss and accuracy per batch \n    test_loss = test_loss / len(dataloader)\n    test_acc = test_acc / total_samples\n    return test_loss, test_acc","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:27.778923Z","iopub.execute_input":"2023-10-10T05:48:27.779588Z","iopub.status.idle":"2023-10-10T05:48:27.786353Z","shell.execute_reply.started":"2023-10-10T05:48:27.779557Z","shell.execute_reply":"2023-10-10T05:48:27.785275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tqdm.auto import tqdm\n\n# 1. Take in various parameters required for training and test steps\ndef train(model: torch.nn.Module, \n          train_dataloader: torch.utils.data.DataLoader, \n          test_dataloader: torch.utils.data.DataLoader, \n          optimizer: torch.optim.Optimizer,\n          scheduler: torch.optim.lr_scheduler,\n          loss_fn: torch.nn.Module = nn.CrossEntropyLoss(),\n          epochs: int = 5):\n    \n    # 2. Create empty results dictionary\n    results = {\"train_loss\": [],\n        \"train_acc\": [],\n        \"test_loss\": [],\n        \"test_acc\": []\n    }\n    \n    # 3. Loop through training and testing steps for a number of epochs\n    for epoch in tqdm(range(epochs)):\n        train_loss, train_acc = train_step(model = model,\n                                           dataloader = train_dataloader,\n                                           loss_fn = loss_fn,\n                                           optimizer = optimizer,\n                                           scheduler = scheduler)\n        test_loss, test_acc = test_step(model = model,\n            dataloader=test_dataloader,\n            loss_fn=loss_fn)\n        \n        # 4. Print out what's happening\n        print(\n            f\"Epoch: {epoch+1} | \"\n            f\"train_loss: {train_loss:.4f} | \"\n            f\"train_acc: {train_acc:.4f} | \"\n            f\"test_loss: {test_loss:.4f} | \"\n            f\"test_acc: {test_acc:.4f}\"\n        )\n\n        # 5. Update results dictionary\n        results[\"train_loss\"].append(train_loss)\n        results[\"train_acc\"].append(train_acc)\n        results[\"test_loss\"].append(test_loss)\n        results[\"test_acc\"].append(test_acc)\n\n    # 6. Return the filled results at the end of the epochs\n    return results","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:28.38397Z","iopub.execute_input":"2023-10-10T05:48:28.384293Z","iopub.status.idle":"2023-10-10T05:48:28.458504Z","shell.execute_reply.started":"2023-10-10T05:48:28.384266Z","shell.execute_reply":"2023-10-10T05:48:28.457629Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set random seeds\ntorch.manual_seed(22) \ntorch.cuda.manual_seed(22)\n\n# Set number of epochs\nNUM_EPOCHS = 5\n\n# Recreate an instance of TinyVGG\nmodel_0 = TinyVGG(input_shape = 3, # number of color channels (3 for RGB) \n                  hidden_units = 32, \n                  output_shape = len(train_labels[0])).to(device)\n\n# Setup loss function and optimizer\nloss_fn = nn.BCEWithLogitsLoss()\noptimizer = torch.optim.Adam(params = model_0.parameters(), lr = 0.001)\nscheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max = 7)\n\n# Start the timer\nfrom timeit import default_timer as timer \nstart_time = timer()\n\n# Train model_0 \nmodel_0_results = train(model = model_0, \n                        train_dataloader = train_dataloader,\n                        test_dataloader = val_dataloader,\n                        optimizer = optimizer,\n                        scheduler = scheduler,\n                        loss_fn = loss_fn, \n                        epochs = NUM_EPOCHS)\n\n# End the timer and print out how long it took\nend_time = timer()\nprint(f\"Total training time: {end_time - start_time:.3f} seconds\")","metadata":{"execution":{"iopub.status.busy":"2023-10-10T05:48:28.992494Z","iopub.execute_input":"2023-10-10T05:48:28.993198Z","iopub.status.idle":"2023-10-10T06:03:02.188199Z","shell.execute_reply.started":"2023-10-10T05:48:28.993167Z","shell.execute_reply":"2023-10-10T06:03:02.187167Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\n\n# Set the model to evaluation mode\nmodel_0.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# Pass the image through the model\nwith torch.no_grad():\n\n    output = model_0(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":{"execution":{"iopub.status.busy":"2023-10-10T06:04:10.688814Z","iopub.execute_input":"2023-10-10T06:04:10.689181Z","iopub.status.idle":"2023-10-10T06:04:11.057051Z","shell.execute_reply.started":"2023-10-10T06:04:10.689151Z","shell.execute_reply":"2023-10-10T06:04:11.056223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"excluded_path = 'test_images/3124/5842/514.dcm'\ntest_paths  = [path for path in test_df.image_path.tolist() if path != excluded_path]\ntest_paths","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:06:34.078683Z","iopub.execute_input":"2023-10-10T06:06:34.079043Z","iopub.status.idle":"2023-10-10T06:06:34.085641Z","shell.execute_reply.started":"2023-10-10T06:06:34.079018Z","shell.execute_reply":"2023-10-10T06:06:34.084729Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_path_list = [path for path in test_dir.glob('*/*/*.dcm') if str(path) != 'test_images/3124/5842/514.dcm']","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:06:36.57391Z","iopub.execute_input":"2023-10-10T06:06:36.57424Z","iopub.status.idle":"2023-10-10T06:06:36.587589Z","shell.execute_reply.started":"2023-10-10T06:06:36.574212Z","shell.execute_reply":"2023-10-10T06:06:36.586557Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_path_list","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:06:37.209439Z","iopub.execute_input":"2023-10-10T06:06:37.210105Z","iopub.status.idle":"2023-10-10T06:06:37.216403Z","shell.execute_reply.started":"2023-10-10T06:06:37.210074Z","shell.execute_reply":"2023-10-10T06:06:37.215293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset_test = CustomDataset(test_paths, None, transform = train_transforms)","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:06:42.486545Z","iopub.execute_input":"2023-10-10T06:06:42.487537Z","iopub.status.idle":"2023-10-10T06:06:42.492172Z","shell.execute_reply.started":"2023-10-10T06:06:42.487493Z","shell.execute_reply":"2023-10-10T06:06:42.491114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport pydicom\nimport numpy as np\nfrom PIL import Image\n\n# 假设您的模型已经加载并位于适当的设备上\nmodel_0.eval()  # 将模型设置为评估模式\n\nall_predictions = []\n\n# Loop through the test dataset\nfor image, _ in dataset_test:\n    # Move the image to the GPU if available\n    image = image.to('cuda')\n\n    # Pass the image through the model\n    with torch.no_grad():\n        output = model_0(image.unsqueeze(0))  # Unsqueeze to add batch dimension\n\n    # Convert the output logits to probabilities using sigmoid function\n    predicted_probs = torch.sigmoid(output)[0]\n\n    # Append the prediction to the list\n    all_predictions.append(predicted_probs)\n\n# Convert the list of predictions to a tensor\nall_predictions = torch.stack(all_predictions)\n","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:06:43.238563Z","iopub.execute_input":"2023-10-10T06:06:43.238934Z","iopub.status.idle":"2023-10-10T06:06:43.303088Z","shell.execute_reply.started":"2023-10-10T06:06:43.238909Z","shell.execute_reply":"2023-10-10T06:06:43.302214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_predictions","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:06:43.925361Z","iopub.execute_input":"2023-10-10T06:06:43.925716Z","iopub.status.idle":"2023-10-10T06:06:43.935016Z","shell.execute_reply.started":"2023-10-10T06:06:43.925656Z","shell.execute_reply":"2023-10-10T06:06:43.934084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_prediction_df = pd.DataFrame(all_predictions.cpu().numpy(), columns = labels)\npd.options.display.float_format = '{:.20f}'.format\nfinal_prediction_df","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:06:44.826252Z","iopub.execute_input":"2023-10-10T06:06:44.826566Z","iopub.status.idle":"2023-10-10T06:06:44.841626Z","shell.execute_reply.started":"2023-10-10T06:06:44.826541Z","shell.execute_reply":"2023-10-10T06:06:44.840619Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df = pd.concat([test_df[['patient_id']], final_prediction_df], axis = \"columns\")\nsub_df","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:06:45.6794Z","iopub.execute_input":"2023-10-10T06:06:45.679736Z","iopub.status.idle":"2023-10-10T06:06:45.693704Z","shell.execute_reply.started":"2023-10-10T06:06:45.679706Z","shell.execute_reply":"2023-10-10T06:06:45.692722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df = sub_df.drop(labels = ['any_injury'], axis = 1)","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:06:46.435452Z","iopub.execute_input":"2023-10-10T06:06:46.436115Z","iopub.status.idle":"2023-10-10T06:06:46.441434Z","shell.execute_reply.started":"2023-10-10T06:06:46.436083Z","shell.execute_reply":"2023-10-10T06:06:46.440292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:06:47.131541Z","iopub.execute_input":"2023-10-10T06:06:47.132475Z","iopub.status.idle":"2023-10-10T06:06:47.145553Z","shell.execute_reply.started":"2023-10-10T06:06:47.132432Z","shell.execute_reply":"2023-10-10T06:06:47.144479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df2 = sub_df.groupby('patient_id').mean().reset_index()\nsub_df2 = sub_df2.fillna(0)\nsub_df2.head()","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:06:47.873227Z","iopub.execute_input":"2023-10-10T06:06:47.873845Z","iopub.status.idle":"2023-10-10T06:06:47.892519Z","shell.execute_reply.started":"2023-10-10T06:06:47.873813Z","shell.execute_reply":"2023-10-10T06:06:47.891566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df2.to_csv(\"submission.csv\", index = False, float_format='%.20f')","metadata":{"execution":{"iopub.status.busy":"2023-10-10T06:06:48.705917Z","iopub.execute_input":"2023-10-10T06:06:48.706238Z","iopub.status.idle":"2023-10-10T06:06:48.714836Z","shell.execute_reply.started":"2023-10-10T06:06:48.706213Z","shell.execute_reply":"2023-10-10T06:06:48.713938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# checkpoint = {'model': model_0,\n#               'state_dict': model_0.state_dict(),\n#               'optimizer' : optimizer.state_dict()}\n\n# torch.save(checkpoint, 'model_0.pth')","metadata":{"execution":{"iopub.status.busy":"2023-09-06T12:30:23.44614Z","iopub.execute_input":"2023-09-06T12:30:23.446617Z","iopub.status.idle":"2023-09-06T12:30:23.453064Z","shell.execute_reply.started":"2023-09-06T12:30:23.446485Z","shell.execute_reply":"2023-09-06T12:30:23.451836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def load_checkpoint(filepath):\n#     checkpoint = torch.load(filepath)\n#     model = checkpoint['model']\n#     model.load_state_dict(checkpoint['state_dict'])\n#     for parameter in model.parameters():\n#         parameter.requires_grad = False\n    \n#     model.eval()\n    \n#     return model","metadata":{"execution":{"iopub.status.busy":"2023-09-06T12:30:23.454857Z","iopub.execute_input":"2023-09-06T12:30:23.455324Z","iopub.status.idle":"2023-09-06T12:30:23.463938Z","shell.execute_reply.started":"2023-09-06T12:30:23.455287Z","shell.execute_reply":"2023-09-06T12:30:23.462906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# saved_model = load_checkpoint('base_model_0.pth')\n# print(saved_model)","metadata":{"execution":{"iopub.status.busy":"2023-09-06T12:30:23.467073Z","iopub.execute_input":"2023-09-06T12:30:23.467536Z","iopub.status.idle":"2023-09-06T12:30:23.476263Z","shell.execute_reply.started":"2023-09-06T12:30:23.467508Z","shell.execute_reply":"2023-09-06T12:30:23.47502Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import torch\n# import pydicom\n# import numpy as np\n# from PIL import Image\n\n# # 假设您的模型已经加载并位于适当的设备上\n# saved_model.eval()  # 将模型设置为评估模式\n\n# all_predictions = []\n\n# # Loop through the test dataset\n# for image, _ in dataset_test:\n#     # Move the image to the GPU if available\n#     image = image.to('cuda')\n\n#     # Pass the image through the model\n#     with torch.no_grad():\n#         output = saved_model(image.unsqueeze(0))  # Unsqueeze to add batch dimension\n\n#     # Convert the output logits to probabilities using sigmoid function\n#     predicted_probs = torch.sigmoid(output)[0]\n\n#     # Append the prediction to the list\n#     all_predictions.append(predicted_probs)\n\n# # Convert the list of predictions to a tensor\n# all_predictions = torch.stack(all_predictions)\n","metadata":{"execution":{"iopub.status.busy":"2023-09-06T12:30:23.477653Z","iopub.execute_input":"2023-09-06T12:30:23.47826Z","iopub.status.idle":"2023-09-06T12:30:23.488191Z","shell.execute_reply.started":"2023-09-06T12:30:23.478225Z","shell.execute_reply":"2023-09-06T12:30:23.48718Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# final_prediction_df = pd.DataFrame(all_predictions.cpu().numpy(), columns = labels)\n# pd.options.display.float_format = '{:.20f}'.format\n# final_prediction_df","metadata":{"execution":{"iopub.status.busy":"2023-09-06T12:30:23.490623Z","iopub.execute_input":"2023-09-06T12:30:23.490963Z","iopub.status.idle":"2023-09-06T12:30:23.50122Z","shell.execute_reply.started":"2023-09-06T12:30:23.490936Z","shell.execute_reply":"2023-09-06T12:30:23.500263Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# sub_df = pd.concat([test_df[['patient_id']], final_prediction_df], axis=\"columns\")","metadata":{"execution":{"iopub.status.busy":"2023-09-06T12:30:23.50294Z","iopub.execute_input":"2023-09-06T12:30:23.503247Z","iopub.status.idle":"2023-09-06T12:30:23.51271Z","shell.execute_reply.started":"2023-09-06T12:30:23.503216Z","shell.execute_reply":"2023-09-06T12:30:23.511757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# sub_df.to_csv(\"submission.csv\", index = False, float_format = '%.20f')","metadata":{"execution":{"iopub.status.busy":"2023-09-06T12:30:23.514108Z","iopub.execute_input":"2023-09-06T12:30:23.514895Z","iopub.status.idle":"2023-09-06T12:30:23.528057Z","shell.execute_reply.started":"2023-09-06T12:30:23.514861Z","shell.execute_reply":"2023-09-06T12:30:23.527058Z"},"trusted":true},"execution_count":null,"outputs":[]}]}