{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.10","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":29653,"databundleVersionId":2420395,"sourceType":"competition"},{"sourceId":8020149,"sourceType":"datasetVersion","datasetId":4725819}],"dockerImageVersionId":30120,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"seed = 42","metadata":{"execution":{"iopub.status.busy":"2024-04-03T14:59:39.844523Z","iopub.execute_input":"2024-04-03T14:59:39.844914Z","iopub.status.idle":"2024-04-03T14:59:39.855765Z","shell.execute_reply.started":"2024-04-03T14:59:39.844834Z","shell.execute_reply":"2024-04-03T14:59:39.854463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport io\nimport glob\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom time import time\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nimport cv2\nfrom sklearn.model_selection import train_test_split\n\nimport torch \nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms, utils\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-04-03T14:59:42.336983Z","iopub.execute_input":"2024-04-03T14:59:42.337330Z","iopub.status.idle":"2024-04-03T14:59:44.935096Z","shell.execute_reply.started":"2024-04-03T14:59:42.337301Z","shell.execute_reply":"2024-04-03T14:59:44.934304Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install git+https://github.com/shijianjian/EfficientNet-PyTorch-3D ","metadata":{"execution":{"iopub.status.busy":"2024-04-03T14:59:44.936531Z","iopub.execute_input":"2024-04-03T14:59:44.936893Z","iopub.status.idle":"2024-04-03T14:59:56.489963Z","shell.execute_reply.started":"2024-04-03T14:59:44.936855Z","shell.execute_reply":"2024-04-03T14:59:56.488951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from efficientnet_pytorch_3d import EfficientNet3D","metadata":{"execution":{"iopub.status.busy":"2024-04-03T14:59:58.248358Z","iopub.execute_input":"2024-04-03T14:59:58.248716Z","iopub.status.idle":"2024-04-03T14:59:58.259954Z","shell.execute_reply.started":"2024-04-03T14:59:58.248682Z","shell.execute_reply":"2024-04-03T14:59:58.258823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"path = '../input/rsna-miccai-brain-tumor-radiogenomic-classification'\n\ndf = pd.read_csv(os.path.join(path, 'train_labels.csv'))","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:00:00.478157Z","iopub.execute_input":"2024-04-03T15:00:00.478487Z","iopub.status.idle":"2024-04-03T15:00:00.496283Z","shell.execute_reply.started":"2024-04-03T15:00:00.478460Z","shell.execute_reply":"2024-04-03T15:00:00.495490Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train, df_aux = train_test_split(df, test_size=0.2, stratify=df['MGMT_value'], random_state=seed)\n\ndf_val, df_test = train_test_split(df_aux, test_size=0.5, stratify=df_aux['MGMT_value'], random_state=seed)","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:00:02.066730Z","iopub.execute_input":"2024-04-03T15:00:02.067095Z","iopub.status.idle":"2024-04-03T15:00:02.085819Z","shell.execute_reply.started":"2024-04-03T15:00:02.067042Z","shell.execute_reply":"2024-04-03T15:00:02.085044Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train.drop(df_train.loc[df_train['BraTS21ID']==109].index, inplace=True)\ndf_train.drop(df_train.loc[df_train['BraTS21ID']==123].index, inplace=True)\ndf_train.drop(df_train.loc[df_train['BraTS21ID']==709].index, inplace=True)","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:00:03.248677Z","iopub.execute_input":"2024-04-03T15:00:03.249013Z","iopub.status.idle":"2024-04-03T15:00:03.271145Z","shell.execute_reply.started":"2024-04-03T15:00:03.248983Z","shell.execute_reply":"2024-04-03T15:00:03.270385Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_sequence_images_npy(path: str, seq_len: int) -> list:\n    images = []\n    # Encuentra todos los archivos .npy en el directorio especificado\n    image_path_list = glob.glob(path + '/*.npy')\n    # Ordena la lista de rutas por número de imagen\n    image_path_list.sort(key=lambda x: int(x.split('/')[-1].split('_')[-1].split('.')[0]))\n    \n    if len(image_path_list) >= seq_len:\n        start = (len(image_path_list)//2)-int(seq_len/2)\n        end = (len(image_path_list)//2)+int(seq_len/2)\n        imgs_path_list = image_path_list[start:end]\n        for p in imgs_path_list:\n            img = np.load(p)\n            images.append(img)\n        images = np.array(images).T\n    else:\n        for p in image_path_list:\n            img = np.load(p)\n            images.append(img)\n        diff = seq_len - len(image_path_list)\n        images = np.concatenate((np.array(images).T, np.zeros((256,256,diff))),axis=-1)\n            \n    return images","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:25:40.058764Z","iopub.execute_input":"2024-04-03T15:25:40.059133Z","iopub.status.idle":"2024-04-03T15:25:40.068356Z","shell.execute_reply.started":"2024-04-03T15:25:40.059102Z","shell.execute_reply":"2024-04-03T15:25:40.067462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Processing and Loading","metadata":{}},{"cell_type":"code","source":"# helper function to process DICOM images. \ndef get_patient_images(path, seq_len):\n    \n    # get the path of MRI seq subfolder\n    flair_path = os.path.join(path, 'FLAIR')\n    t1w_path = os.path.join(path, 'T1w')\n    t1wce_path = os.path.join(path, 'T1wCE')\n    t2w_path = os.path.join(path, 'T2w')\n    \n    # get the images in each sequence\n    # FLAIR\n    flair_imgs = get_sequence_images_npy(flair_path, seq_len)\n    \n    # T1w\n    t1w_imgs = get_sequence_images_npy(t1w_path, seq_len)\n    \n    # T1wCE\n    t1wce_imgs = get_sequence_images_npy(t1wce_path, seq_len)\n    \n    # T2w\n    t2w_imgs = get_sequence_images_npy(t2w_path, seq_len)\n    \n    return np.moveaxis(np.array((flair_imgs, t1w_imgs, t1wce_imgs, t2w_imgs)), 0, -1)","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:26:01.900883Z","iopub.execute_input":"2024-04-03T15:26:01.901250Z","iopub.status.idle":"2024-04-03T15:26:01.907672Z","shell.execute_reply.started":"2024-04-03T15:26:01.901218Z","shell.execute_reply":"2024-04-03T15:26:01.906707Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create a PyTorch Dataset","metadata":{}},{"cell_type":"code","source":"class BrainScanDataset(Dataset):\n    \n    def __init__(self, df, seq_len, transform=None):\n        \n        self.df = df\n        self.seq_len = seq_len\n        \n        label_id = self.df[self.df.columns[0]] # BraTS21ID\n        label_y = self.df[self.df.columns[1]] # MGMT_value\n        self.labels_dict = {str(l_id).zfill(5): y for l_id, y in zip(label_id, label_y)}\n        \n        self.data_path = '/kaggle/input/pruebaprep/dataset_preprocessed'\n        \n        # get patient ids\n        self.id_path_list = [path for path in sorted(glob.glob(self.data_path + '/*')) \n                             if path.split('/')[-1] in self.labels_dict]\n        self.id_list = [path.split('/')[-1] for path in sorted(glob.glob(self.data_path + '/*'))\n                        if path.split('/')[-1] in self.labels_dict]\n        \n        # TODO: image transforms\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.id_path_list)\n    \n    def __getitem__(self, idx):\n        if torch.is_tensor(idx):\n            idx = idx.tolist()\n            \n        images = get_patient_images(self.id_path_list[idx], self.seq_len)\n        labels = self.labels_dict[self.id_list[idx]]\n        \n        imgs_tensor = torch.tensor(images, dtype=torch.float32).permute(-1, 0, 1, 2) # need to reshape\n#         print(imgs_tensor.shape)\n        labels_tensor = torch.tensor(labels)\n        \n        return imgs_tensor, labels_tensor","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:26:02.775421Z","iopub.execute_input":"2024-04-03T15:26:02.775786Z","iopub.status.idle":"2024-04-03T15:26:02.787658Z","shell.execute_reply.started":"2024-04-03T15:26:02.775751Z","shell.execute_reply":"2024-04-03T15:26:02.786664Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create PyTorch DataLoader","metadata":{}},{"cell_type":"code","source":"batch_size = 8\n\ntrain_dataset = BrainScanDataset(df_train, 64)\nvalid_dataset = BrainScanDataset(df_val, 64)\n\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, drop_last=True)\nvalid_loader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=True, drop_last=True)","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:44:22.136626Z","iopub.execute_input":"2024-04-03T15:44:22.137005Z","iopub.status.idle":"2024-04-03T15:44:22.155930Z","shell.execute_reply.started":"2024-04-03T15:44:22.136972Z","shell.execute_reply":"2024-04-03T15:44:22.155238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for img, label in train_loader:\n    print('--- Train Data ---')\n    print('Image shape: ', img.shape)\n    print('Class label shape:', label.shape)\n    print('Class label: ', label)\n    break\n    \nfor img, label in valid_loader:\n    print('--- Valid Data ---')\n    print('Image shape: ', img.shape)\n    print('Class label shape:', label.shape)\n    print('Class label: ', label)\n    break","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:44:22.279203Z","iopub.execute_input":"2024-04-03T15:44:22.279541Z","iopub.status.idle":"2024-04-03T15:44:27.979349Z","shell.execute_reply.started":"2024-04-03T15:44:22.279513Z","shell.execute_reply":"2024-04-03T15:44:27.978389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_info = {'model_name': 'efficientnet-b5',\n              'input_dim': 4,\n              'output_dim': {'num_classes': 1}}","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:44:27.980753Z","iopub.execute_input":"2024-04-03T15:44:27.981115Z","iopub.status.idle":"2024-04-03T15:44:27.985298Z","shell.execute_reply.started":"2024-04-03T15:44:27.981074Z","shell.execute_reply":"2024-04-03T15:44:27.984216Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = EfficientNet3D.from_name(model_name=model_info['model_name'], \n                                 override_params=model_info['output_dim'], \n                                 in_channels=model_info['input_dim']) ","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:44:27.987007Z","iopub.execute_input":"2024-04-03T15:44:27.987357Z","iopub.status.idle":"2024-04-03T15:44:28.256636Z","shell.execute_reply.started":"2024-04-03T15:44:27.987328Z","shell.execute_reply":"2024-04-03T15:44:28.255714Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(f\"Usando el dispositivo: {device}\")\n\nmodel = model.to(device)","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:44:28.258088Z","iopub.execute_input":"2024-04-03T15:44:28.258389Z","iopub.status.idle":"2024-04-03T15:44:28.332345Z","shell.execute_reply.started":"2024-04-03T15:44:28.258359Z","shell.execute_reply":"2024-04-03T15:44:28.331444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion = torch.nn.BCEWithLogitsLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=0.001)\nscaler = torch.cuda.amp.GradScaler()","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:44:28.333568Z","iopub.execute_input":"2024-04-03T15:44:28.333869Z","iopub.status.idle":"2024-04-03T15:44:28.350404Z","shell.execute_reply.started":"2024-04-03T15:44:28.333838Z","shell.execute_reply":"2024-04-03T15:44:28.349502Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tqdm\nfrom sklearn.metrics import roc_auc_score","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:44:28.351355Z","iopub.execute_input":"2024-04-03T15:44:28.351622Z","iopub.status.idle":"2024-04-03T15:44:28.360753Z","shell.execute_reply.started":"2024-04-03T15:44:28.351596Z","shell.execute_reply":"2024-04-03T15:44:28.359914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_epochs = 10  # Define el número de épocas\n\nfor epoch in range(num_epochs):\n    print(\"Epoch {}/{}\".format(epoch + 1, num_epochs))\n    # Entrenamiento\n    model.train()\n    for images, labels in tqdm.tqdm(train_loader, desc='Entrenamiento'):\n        images = images.to(device)\n        labels = labels.to(device).float()\n        \n        optimizer.zero_grad()\n        with torch.cuda.amp.autocast():\n            outputs = model(images).squeeze()\n            loss = criterion(outputs, labels)\n            \n        scaler.scale(loss).backward()\n        scaler.step(optimizer)\n        scaler.update()\n    \n    # Validación\n    model.eval()\n    val_loss = 0\n    all_labels = []\n    all_predictions = []\n    with torch.no_grad():\n        total, correct = 0, 0\n        for images, labels in tqdm.tqdm(valid_loader, desc='Validación'):\n            images = images.to(device)\n            labels = labels.to(device).float()\n            with torch.cuda.amp.autocast():\n                outputs = model(images)\n                val_loss += criterion(outputs.squeeze(), labels).item()\n            probabilities = torch.sigmoid(outputs).squeeze()\n            all_labels.extend(labels.cpu().numpy())\n            all_predictions.extend(probabilities.cpu().numpy()>0.5)\n        \n    val_loss /= len(valid_loader)\n    auc = roc_auc_score(all_labels, all_predictions)\n    print(f\"Epoch {epoch+1}/{num_epochs}, Train Loss: {loss.item()}, Val Loss: {val_loss}, Val AUC: {auc}\")","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:52:28.383187Z","iopub.execute_input":"2024-04-03T15:52:28.383545Z","iopub.status.idle":"2024-04-03T15:53:41.948887Z","shell.execute_reply.started":"2024-04-03T15:52:28.383515Z","shell.execute_reply":"2024-04-03T15:53:41.946484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.save(model.state_dict(), 'model_efficientnet3d.pth')","metadata":{"execution":{"iopub.status.busy":"2024-04-03T15:36:06.940038Z","iopub.status.idle":"2024-04-03T15:36:06.940450Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}