{"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":"markdown","source":"# Importe Librerias","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-06-28T05:25:16.6468Z","iopub.execute_input":"2023-06-28T05:25:16.64728Z","iopub.status.idle":"2023-06-28T05:25:21.913978Z","shell.execute_reply.started":"2023-06-28T05:25:16.647175Z","shell.execute_reply":"2023-06-28T05:25:21.912968Z"}}},{"cell_type":"code","source":"# Importaciones generales\nimport math\nimport os\nimport random\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport tensorflow as tf\nimport pydicom\nimport time\nfrom IPython.display import display, FileLink\n\n# Importaciones de TensorFlow y Keras\nimport tensorflow_hub as tfhub\nfrom kaggle_datasets import KaggleDatasets\nfrom tensorflow.keras import Model\nfrom tensorflow.keras.applications import EfficientNetB3, DenseNet121\nfrom tensorflow.keras.callbacks import EarlyStopping, LearningRateScheduler, ModelCheckpoint, ReduceLROnPlateau\nfrom tensorflow.keras.layers import (\n    BatchNormalization, Conv2D, Dense, Dropout, Flatten, GlobalAveragePooling2D,\n    InputLayer, MaxPooling2D\n)\nfrom tensorflow.keras.metrics import AUC, Recall, Precision\nfrom tensorflow.keras.optimizers import RMSprop, Adam\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.layers import GlobalAveragePooling2D\n\n# Importaciones de scikit-learn\nfrom sklearn.metrics import f1_score, matthews_corrcoef, brier_score_loss\nfrom sklearn.model_selection import train_test_split\n\n# Otras importaciones\nimport cupy as cp\nimport torch\nimport torch.nn as nn\nfrom torchvision import models\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, matthews_corrcoef, confusion_matrix\nimport pydicom\nimport cv2\nimport pandas as pd\nimport numpy as np\n\nimport torch\nimport torch.nn as nn\nfrom torchvision import models\n\nimport pydicom\nimport cv2\nimport pandas as pd\nimport numpy as np\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader\nfrom PIL import Image\n\n# Confirmar si tenemos activa la GPU. Si hay una GPU disponible se imprime un mensaje indicando que está disponible; si no se encontró una GPU se imprime un mensaje indicando que no se encontró una GPU.\n#tf.config.set_visible_devices(tf.config.list_physical_devices('GPU'), 'GPU')\n\nif tf.test.is_gpu_available():\n    print('Se encontró al menos una GPU')\n    print('Dispositivos GPU disponibles:')\n    gpu_devices = tf.config.list_physical_devices('GPU')\n    for device in gpu_devices:\n        print(device)\nelse:\n    print('No se encontró GPU')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-09-24T17:10:03.602903Z","iopub.execute_input":"2023-09-24T17:10:03.603528Z","iopub.status.idle":"2023-09-24T17:10:22.731683Z","shell.execute_reply.started":"2023-09-24T17:10:03.603486Z","shell.execute_reply":"2023-09-24T17:10:22.730125Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Establecer la ruta de la base de datos\nbase_datos = '/kaggle/input/rsna-miccai-brain-tumor-radiogenomic-classification/'\n# Listar los archivos y directorios en la ruta de la base de datos\nos.listdir(base_datos)\n# Establecer las rutas para los conjuntos de datos de entrenamiento y prueba\ntrain = base_datos+'train'\ntest  = base_datos+'test'\n# Leer los archivos CSV para los conjuntos de datos de entrenamiento y prueba utilizando la biblioteca pandas\ntrain_csv = pd.read_csv(base_datos+'train_labels.csv')\ntest_csv  = pd.read_csv(base_datos+'sample_submission.csv')\n# Imprimir las primeras 10 filas de los DataFrames de entrenamiento y prueba\nprint('\\033[1;32;48;5;82m' + '\\033[1m' + '--------------TRAIN--------------' + '\\033[0m')\ndisplay(train_csv)\nprint('\\033[1;32;48;5;82m' + '\\033[1m' + '--------------TEST--------------' + '\\033[0m')\ndisplay(test_csv)","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:10:22.734331Z","iopub.execute_input":"2023-09-24T17:10:22.735558Z","iopub.status.idle":"2023-09-24T17:10:22.774166Z","shell.execute_reply.started":"2023-09-24T17:10:22.735517Z","shell.execute_reply":"2023-09-24T17:10:22.773085Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Obtener el número de valores faltantes por columna en el DataFrame de entrenamiento utilizando el método isnull() y sum()\nvalores_faltantes_train = train_csv.isnull().sum()\n# Imprimir el número de valores faltantes en las primeras dos columnas del DataFrame de entrenamiento\nvalores_faltantes_train[0:2]","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:10:22.775862Z","iopub.execute_input":"2023-09-24T17:10:22.776562Z","iopub.status.idle":"2023-09-24T17:10:22.785603Z","shell.execute_reply.started":"2023-09-24T17:10:22.776525Z","shell.execute_reply":"2023-09-24T17:10:22.784643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Definir una función para completar los IDs con ceros a la izquierda hasta tener una longitud de 5 caracteres\ndef full_ids(data):\n    return str(data).zfill(5)\n\n# Aplicar la función full_ids a la columna 'BraTS21ID' del DataFrame de entrenamiento y guardar el resultado en una nueva columna llamada 'BraTS21ID_full'\ntrain_csv['BraTS21ID_full'] = train_csv['BraTS21ID'].apply(full_ids)\n# Establecer la ruta base para los datos de entrenamiento\nbase_path = base_datos + 'train/'\n# Crear nuevas columnas en el DataFrame de entrenamiento para las rutas completas a diferentes tipos de secuencias de imágenes para cada ID\ntrain_csv['flair'] = base_path + train_csv['BraTS21ID_full'] + '/FLAIR/'\ntrain_csv['t1w'] = base_path + train_csv['BraTS21ID_full'] + '/T1w/'\ntrain_csv['t1wce'] = base_path + train_csv['BraTS21ID_full'] + '/T1wCE/'\ntrain_csv['t2w'] = base_path + train_csv['BraTS21ID_full'] + '/T2w/'\n#train_csv.to_csv('nuevo_train_labels.csv', index=False)\nprint('\\033[1;32;48;5;82m' + '\\033[1m' + '                                                   TRAIN                                                                         ' + '\\033[0m')\ndisplay(train_csv)\n\n#test_csv\n\n# Aplicar la función full_ids a la columna 'BraTS21ID' del DataFrame de prueba y guardar el resultado en una nueva columna llamada 'BraTS21ID_full'\ntest_csv['BraTS21ID_full'] = test_csv['BraTS21ID'].apply(full_ids)\n# Establecer la ruta base para los datos de prueba\nbase_path = base_datos + 'test/'\n# Crear nuevas columnas en el DataFrame de prueba para las rutas completas a diferentes tipos de secuencias de imágenes para cada ID\ntest_csv['flair'] = base_path + test_csv['BraTS21ID_full'] + '/FLAIR/'\ntest_csv['t1w'] = base_path + test_csv['BraTS21ID_full'] + '/T1w/'\ntest_csv['t1wce'] = base_path + test_csv['BraTS21ID_full'] + '/T1wCE/'\ntest_csv['t2w'] = base_path + test_csv['BraTS21ID_full'] + '/T2w/'\n\nprint('\\033[1;32;48;5;82m' + '\\033[1m' + '                                                     TEST                                                        ' + '\\033[0m')\ndisplay(test_csv)","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:10:22.789032Z","iopub.execute_input":"2023-09-24T17:10:22.789397Z","iopub.status.idle":"2023-09-24T17:10:22.833848Z","shell.execute_reply.started":"2023-09-24T17:10:22.789371Z","shell.execute_reply":"2023-09-24T17:10:22.832597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_dataframe(train_csv, mt):\n    all_img_files = []\n    all_img_labels = []\n    all_img_patient_ids = []\n    \n    for index, row in train_csv.iterrows():\n        img_dir = row[mt]\n        img_files = os.listdir(img_dir)\n        \n        img_paths = [os.path.join(img_dir, img_file) for img_file in img_files]\n        img_labels = [row['MGMT_value']] * len(img_paths)\n        img_patient_ids = [row['BraTS21ID']] * len(img_paths)\n\n        all_img_files.extend(img_paths)\n        all_img_labels.extend(img_labels)\n        all_img_patient_ids.extend(img_patient_ids)\n        \n    train_original = pd.DataFrame({\n        'patient_ids': all_img_patient_ids,\n        'labels': all_img_labels,\n        'file_paths': all_img_files\n    })\n    \n    train_original['labels'] = train_original['labels'].map({1: '1', 0: '0'})\n       \n    return train_original","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:10:22.835198Z","iopub.execute_input":"2023-09-24T17:10:22.836327Z","iopub.status.idle":"2023-09-24T17:10:22.845449Z","shell.execute_reply.started":"2023-09-24T17:10:22.836288Z","shell.execute_reply":"2023-09-24T17:10:22.844585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def analyze_and_remove_zero_sum_images(train_original, mt):\n    # Carpeta predeterminada donde se encuentran los archivos CSV\n    dataset_dir = '/kaggle/input/datos-negros/'\n\n    # Validar que mt sea una de las secuencias de IRM válidas\n    valid_mt_values = ['flair', 't1w', 't2w', 't1wce']\n\n    # Obtener el nombre del archivo CSV correspondiente a la secuencia de IRM\n    csv_filename = f\"{mt}.csv\"\n    csv_path = os.path.join(dataset_dir, csv_filename)\n\n    # Cargar el DataFrame del archivo CSV\n    df = pd.read_csv(csv_path)\n\n    # Obtener una lista de las URLs de imágenes en la columna correspondiente a mt\n    mt_urls = df['file_paths'].tolist()\n    \n    # Filtrar las filas de train_val_df_all que no contienen las URLs en mt_urls\n    remaining_df = train_original[~train_original['file_paths'].isin(mt_urls)]\n \n   # Mostrar estadísticas\n    removed_count = len(train_original) - len(remaining_df)\n    remaining_count = len(remaining_df)\n       \n    return remaining_df","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:10:22.846895Z","iopub.execute_input":"2023-09-24T17:10:22.847603Z","iopub.status.idle":"2023-09-24T17:10:22.857504Z","shell.execute_reply.started":"2023-09-24T17:10:22.847566Z","shell.execute_reply":"2023-09-24T17:10:22.856742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def split_train_val_data(train_val_df, porcentaje, semilla):\n    # Divide el DataFrame en conjuntos de entrenamiento y validación según el porcentaje y la semilla\n    train_df, val_df = train_test_split(train_val_df, train_size=porcentaje, random_state=semilla)  \n    return train_df, val_df","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:10:22.859983Z","iopub.execute_input":"2023-09-24T17:10:22.860936Z","iopub.status.idle":"2023-09-24T17:10:22.872026Z","shell.execute_reply.started":"2023-09-24T17:10:22.860885Z","shell.execute_reply":"2023-09-24T17:10:22.871130Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def porcentaje_entrenamiento(train_1, percentage, random_seed=None):\n    # Verifica que el porcentaje esté en el rango correcto (0 <= percentage <= 1)\n    if percentage < 0 or percentage > 1:\n        raise ValueError(\"El porcentaje debe estar en el rango de 0 a 1.\")\n    # Define una semilla aleatoria si se proporciona\n    if random_seed is not None:\n        random_state = random_seed\n    else:\n        random_state = None\n    # Calcula cuántas filas se deben seleccionar\n    num_rows = int(len(train_1) * percentage)\n    # Selecciona un subconjunto de filas del DataFrame con la semilla aleatoria\n    train_2 = train_1.sample(n=num_rows, random_state=random_state)    \n    return train_2","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:10:22.873571Z","iopub.execute_input":"2023-09-24T17:10:22.874336Z","iopub.status.idle":"2023-09-24T17:10:22.884286Z","shell.execute_reply.started":"2023-09-24T17:10:22.874298Z","shell.execute_reply":"2023-09-24T17:10:22.883302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def is_image_empty(image_path):\n    # Cargar la imagen DICOM\n    ds = pydicom.dcmread(image_path)\n    \n    # Obtener la matriz de píxeles\n    pixel_array = ds.pixel_array\n    \n    # Calcular la suma de píxeles en la imagen\n    pixel_sum = np.sum(pixel_array)\n    \n    # Devolver True si la suma de píxeles es igual a cero, lo que significa que la imagen está vacía\n    return pixel_sum == 0\n\ndef get_test_dataframe(mri_type):\n    # Registra el tiempo de inicio\n    start_time = time.time()\n    \n    # Crear listas vacías para almacenar los archivos de imagen, etiquetas e ID de pacientes\n    all_test_img_files = []\n    all_test_img_labels = []\n    all_test_img_patient_ids = []\n    empty_image_count = 0\n    \n    # Iterar sobre cada fila del DataFrame de prueba\n    for _, row in test_csv.iterrows():\n        # Obtener el directorio de imágenes para el tipo de MRI especificado\n        img_dir = row[mri_type]\n        \n        # Enumerar los archivos en el directorio de imágenes\n        img_files = os.listdir(img_dir)\n        \n        # Generar los nombres de archivo para todas las imágenes en el directorio\n        img_names = [f'Image-{int(ele.replace(\"Image-\", \"\").replace(\".dcm\", \"\"))}.dcm' for ele in img_files]\n        \n        # Concatenar la ruta del directorio con los nombres de archivo para obtener las rutas completas a las imágenes\n        img_paths = [os.path.join(img_dir, ele) for ele in img_names]\n        \n        # Verificar si las imágenes están vacías y contarlas\n        for img_path in img_paths:\n            if is_image_empty(img_path):\n                empty_image_count += 1\n        \n        # Generar listas de etiquetas e ID de pacientes para todas las imágenes\n        img_labels = [row['MGMT_value']] * len(img_paths)\n        img_patient_ids = [row['BraTS21ID']] * len(img_paths)\n        \n        # Agregar las listas a las listas all_test_img_files, all_test_img_labels y all_test_img_patient_ids\n        all_test_img_files.extend(img_paths)\n        all_test_img_labels.extend(img_labels)\n        all_test_img_patient_ids.extend(img_patient_ids)\n    \n    # Crear un DataFrame con las listas all_test_img_patient_ids, all_test_img_labels y all_test_img_files\n    test_df = pd.DataFrame({'patient_ids': all_test_img_patient_ids,\n                            'labels': all_test_img_labels,\n                            'file_paths': all_test_img_files})\n    \n    # Establecer la columna 'labels' a una lista de unos seguida por un cero (solución temporal para generar datos de prueba)\n    test_df['labels'] = ['1'] * (len(test_df) - 1) + ['0']\n       \n    # Devolver el DataFrame de prueba como salida\n    return test_df","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:10:22.885966Z","iopub.execute_input":"2023-09-24T17:10:22.886690Z","iopub.status.idle":"2023-09-24T17:10:22.898702Z","shell.execute_reply.started":"2023-09-24T17:10:22.886654Z","shell.execute_reply":"2023-09-24T17:10:22.897582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for mt in ['flair']:\n\n    # HIPERPARÁMETROS\n    porcentaje = 0.01\n    class_prop = 0.90\n    semilla=50  #Semilla divicio para conseguir train y val\n    epochs=1\n    SEED = 500  \n    BATCH_SIZE = 350  \n    TARGET_SIZE = (300, 300)\n    brightness_range = [0.8, 1.2]  \n    learning_rate = 1  \n    top_dropout_rate = 0.2  \n    patience = 1  \n    factor = 0.2  \n    min_lr = 1e-4  \n    semilla_2 = 42  #Para extrer porcentaje de dataframe de entrenamiento \n    \n    \n    train_original = create_dataframe(train_csv, mt)  \n    test_df = get_test_dataframe(mt)\n    remaining_df  = analyze_and_remove_zero_sum_images(train_original, mt)   \n    train_df_2, val_df = split_train_val_data(remaining_df, class_prop, semilla)\n    train_df = porcentaje_entrenamiento(train_df_2, porcentaje, semilla_2) \n    \n    pd.set_option('display.max_colwidth', None)\n    print('\\033[1;32;48;5;82m' + '\\033[1m' + '                 Entrenamiento                       ' + '\\033[0m')\n    display(train_df)\n    \n    pd.set_option('display.max_colwidth', None)\n    print('\\033[1;32;48;5;82m' + '\\033[1m' + '                 Validacion                       ' + '\\033[0m')\n    display(val_df)\n    \n    pd.set_option('display.max_colwidth', None)\n    print('\\033[1;32;48;5;82m' + '\\033[1m' + '                 Testeo                      ' + '\\033[0m')\n    display(test_df)","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:10:22.904185Z","iopub.execute_input":"2023-09-24T17:10:22.904512Z","iopub.status.idle":"2023-09-24T17:11:03.193458Z","shell.execute_reply.started":"2023-09-24T17:10:22.904486Z","shell.execute_reply":"2023-09-24T17:11:03.192488Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"T1W\n* Área de información más grande en el conjunto de entrenamiento: 90759\n* Área de información más grande en el conjunto de validación: 90196\n* Área de información más grande en el conjunto de prueba: 75838\n\nT2W\n* Área de información más grande en el conjunto de entrenamiento: 190239\n* Área de información más grande en el conjunto de validación: 89450\n* Área de información más grande en el conjunto de prueba: 83962\n\nt1wce\n* Área de información más grande en el conjunto de entrenamiento: 96026\n* Área de información más grande en el conjunto de validación: 94395\n* Área de información más grande en el conjunto de prueba: 8545\n\nflair\n* Área de información más grande en el conjunto de entrenamiento: 96026\n* Área de información más grande en el conjunto de validación: 94395\n* Área de información más grande en el conjunto de prueba: 8545","metadata":{}},{"cell_type":"code","source":"from torch.utils.data import DataLoader\n# Define el modelo (puedes reemplazar esto con tu propia definición de modelo)\nclass CustomModel(nn.Module):\n    def __init__(self):\n        super(CustomModel, self).__init__()\n        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, padding=1)\n        self.fc1 = nn.Linear(64 * 64 * 64, 1)\n\n    def forward(self, x):\n        x = self.conv1(x)\n        x = x.view(x.size(0), -1)\n        x = self.fc1(x)\n        return x\n\n# Crear una instancia del modelo\nmodel = CustomModel()\n\n# Definir el umbral de área de información deseado\numbral_deseado = 100  # Ajusta este umbral según tus necesidades\n\n# Función para calcular el área de información en una imagen DICOM\ndef calcular_area_informacion(imagen_path, umbral):\n    dcm = pydicom.dcmread(imagen_path)\n    imagen = dcm.pixel_array\n    _, imagen_umbral = cv2.threshold(imagen, umbral, 255, cv2.THRESH_BINARY)\n    area_informacion = cv2.countNonZero(imagen_umbral)\n    return area_informacion\n\n# Definir la clase del conjunto de datos personalizado\nclass CustomDataset(Dataset):\n    def __init__(self, dataframe, umbral):\n        self.dataframe = dataframe\n        self.umbral = umbral\n\n    def __len__(self):\n        return len(self.dataframe)\n\n    def __getitem__(self, idx):\n        imagen_path = self.dataframe.iloc[idx]['file_paths']\n        area_informacion = calcular_area_informacion(imagen_path, self.umbral)\n        return imagen_path, area_informacion\n\n# Crear instancias de DataFrames (train_df, val_df, test_df)\n# ...\n\n# Crear instancias de conjuntos de datos personalizados\ntrain_dataset = CustomDataset(train_df, umbral_deseado)\nval_dataset = CustomDataset(val_df, umbral_deseado)\ntest_dataset = CustomDataset(test_df, umbral_deseado)\n\n# Crear DataLoaders para datos de entrenamiento y validación\ntrain_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=2)\nval_loader = torch.utils.data.DataLoader(val_dataset, batch_size=32, num_workers=2)\n\n# Definir el dispositivo (utilizar ambas GPUs si disponibles)\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nif torch.cuda.device_count() > 1:\n    print(\"Usando\", torch.cuda.device_count(), \"GPUs\")\n    model = nn.DataParallel(model)\n\n# ... Define el modelo y el optimizador ...\n\n# Iterar sobre las filas de los DataFrames y filtrar las imágenes\ndef filtrar_imagenes_por_area(df, umbral):\n    imagenes_filtradas = []\n    for _, fila in df.iterrows():\n        imagen_path = fila['file_paths']\n        area_informacion = calcular_area_informacion(imagen_path, umbral)\n        if area_informacion >= umbral:\n            imagenes_filtradas.append(fila.values.tolist())\n    return pd.DataFrame(imagenes_filtradas, columns=df.columns)\n\n# Filtrar las imágenes en los DataFrames train_df, val_df y test_df\ntrain_df_filtrado = filtrar_imagenes_por_area(train_df, umbral_deseado)\nval_df_filtrado = filtrar_imagenes_por_area(val_df, umbral_deseado)\ntest_df_filtrado = filtrar_imagenes_por_area(test_df, umbral_deseado)\n\npd.set_option('display.max_colwidth', None)\nprint('\\033[1;32;48;5;82m' + '\\033[1m' + '                 Entrenamiento  filtrado                     ' + '\\033[0m')\ndisplay(train_df_filtrado)\n    \npd.set_option('display.max_colwidth', None)\nprint('\\033[1;32;48;5;82m' + '\\033[1m' + '                 Validacion filtrado                      ' + '\\033[0m')\ndisplay(val_df_filtrado)\n    \npd.set_option('display.max_colwidth', None)\nprint('\\033[1;32;48;5;82m' + '\\033[1m' + '                 Testeo filtrado                     ' + '\\033[0m')\ndisplay(test_df_filtrado)\n","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:11:03.195266Z","iopub.execute_input":"2023-09-24T17:11:03.195671Z","iopub.status.idle":"2023-09-24T17:11:42.665527Z","shell.execute_reply.started":"2023-09-24T17:11:03.195635Z","shell.execute_reply":"2023-09-24T17:11:42.662280Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchvision import transforms\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import DataLoader\nfrom PIL import Image\n\n# Define una transformación para redimensionar las imágenes a 224x224\ntransform = transforms.Compose([\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\nclass BrainTumorDataset(Dataset):\n    def __init__(self, dataframe, transform=None):\n        self.dataframe = dataframe\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.dataframe)\n\n    def __getitem__(self, idx):\n        img_path = self.dataframe.iloc[idx]['file_paths']\n        dcm = pydicom.dcmread(img_path)\n        image = dcm.pixel_array\n\n        if image.min() != image.max():\n           image = (image - image.min()) / (image.max() - image.min())\n        else:\n            if image.max() > 0:\n                image = image / image.max()\n\n        image = image.astype(np.uint8)\n        image_rgb = np.stack((image,) * 3, axis=-1)\n        image_pil = Image.fromarray(image_rgb)\n\n        if self.transform:\n            image_pil = self.transform(image_pil)\n\n        label = int(self.dataframe.iloc[idx]['labels'])\n        return image_pil, label\n\n# Crear conjuntos de datos y dataloaders para entrenamiento y validación\ntrain_dataset = BrainTumorDataset(train_df, transform=transform)\ntrain_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)\n\nval_dataset = BrainTumorDataset(val_df, transform=transform)\nval_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)\n\ntest_dataset = BrainTumorDataset(test_df, transform=transform)\ntest_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)\n\nclass CheXNetRGB(nn.Module):\n    def __init__(self):\n        super(CheXNetRGB, self).__init__()\n        self.model = models.densenet121(pretrained=False)  \n        num_features = self.model.classifier.in_features\n        self.model.classifier = nn.Sequential(\n            nn.Linear(num_features, 512),\n            nn.ReLU(),\n            nn.BatchNorm1d(512),\n            nn.Dropout(0.5),\n            nn.Linear(512, 256),\n            nn.ReLU(),\n            nn.BatchNorm1d(256),\n            nn.Dropout(0.5),\n            nn.Linear(256, 128),\n            nn.ReLU(),\n            nn.BatchNorm1d(128),\n            nn.Dropout(0.5),\n            nn.Linear(128, 1),\n            nn.Sigmoid()\n        )\n\n    def forward(self, x):\n        return self.model(x)\n\n# Definir el dispositivo (utilizar ambas GPUs si disponibles)\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n\n# Crear una instancia del modelo CheXNetRGB y moverlo al dispositivo\nmodel = CheXNetRGB().to(device)\n\n# Si tienes más de una GPU, utilizar nn.DataParallel para distribuir el trabajo\nif torch.cuda.device_count() > 1:\n    print(\"Usando\", torch.cuda.device_count(), \"GPUs\")\n    model = nn.DataParallel(model)\n\n# Definir la función de pérdida y el optimizador (usar Adam en lugar de SGD)\ncriterion = nn.BCELoss()\noptimizer = optim.Adam(model.parameters(), lr=1e-4)\n\n# Número de épocas de entrenamiento\nnum_epochs = 1\n\n# Definir el tamaño del lote (batch size)\nbatch_size = 32\n\n# Dataloader para datos de entrenamiento y validación (debes definir train_dataset y val_dataset)\ntrain_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\nval_loader = DataLoader(val_dataset, batch_size=batch_size)\n\nbest_val_loss = float(\"inf\")  # Inicializa la mejor pérdida en infinito positivo","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:11:42.667154Z","iopub.status.idle":"2023-09-24T17:11:42.667656Z","shell.execute_reply.started":"2023-09-24T17:11:42.667410Z","shell.execute_reply":"2023-09-24T17:11:42.667434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_model(model, train_loader, val_loader, criterion, optimizer, num_epochs=10, print_interval=10):\n    global best_val_loss\n    for epoch in range(num_epochs):\n        model.train()\n        train_loss = 0.0\n\n        for batch_idx, (images, labels) in enumerate(train_loader):\n            images, labels = images.to(device), labels.to(device)\n            optimizer.zero_grad()\n            outputs = model(images)\n            loss = criterion(outputs, labels.float().unsqueeze(1))\n            loss.backward()\n            optimizer.step()\n            train_loss += loss.item()\n\n            # Imprimir el progreso cada 'print_interval' lotes\n            if (batch_idx + 1) % print_interval == 0:\n                print(f'Epoch [{epoch + 1}/{num_epochs}] - '\n                      f'Batch [{batch_idx + 1}/{len(train_loader)}] - '\n                      f'Training Loss: {train_loss / (batch_idx + 1):.4f}')\n\n        train_loss /= len(train_loader)\n\n        # Validación\n        model.eval()\n        val_loss = 0.0\n        correct = 0\n        total = 0\n\n        with torch.no_grad():\n            for batch_idx, (images, labels) in enumerate(val_loader):\n                images, labels = images.to(device), labels.to(device)\n                outputs = model(images)\n                loss = criterion(outputs, labels.float().unsqueeze(1))\n                val_loss += loss.item()\n\n        val_loss /= len(val_loader)\n        print(f'Epoch [{epoch + 1}/{num_epochs}] - '\n              f'Training Loss: {train_loss:.4f}, '\n              f'Validation Loss: {val_loss:.4f}')\n\n        # Comprobar si la pérdida de validación es menor que la mejor pérdida registrada\n        if val_loss < best_val_loss:\n            print(\"Guardando el modelo...\")\n            best_val_loss = val_loss\n            torch.save(model.state_dict(), 'mejor_modelo.pth')\n        else:\n            # Cargar el modelo anterior si la pérdida aumenta en una época posterior\n            print(\"Revertir al mejor modelo...\")\n            model.load_state_dict(torch.load('mejor_modelo.pth'))\n            model.train()\n\n# Definir el intervalo de impresión para rastrear el progreso\nprint_interval = 1\n\n# Entrenar el modelo\ntrain_model(model, train_loader, val_loader, criterion, optimizer, num_epochs, print_interval)","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:11:42.669347Z","iopub.status.idle":"2023-09-24T17:11:42.669951Z","shell.execute_reply.started":"2023-09-24T17:11:42.669652Z","shell.execute_reply":"2023-09-24T17:11:42.669679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Definir una función de evaluación\ndef evaluate_model(model, dataloader, device):\n    model.eval()\n    y_true = []\n    y_pred = []\n    \n    with torch.no_grad():\n        for images, labels in dataloader:\n            images, labels = images.to(device), labels.to(device)\n            outputs = model(images)\n            predicted = (outputs > 0.5).float()  # Aplicar un umbral de 0.5 para las predicciones\n            y_true.extend(labels.cpu().numpy())\n            y_pred.extend(predicted.cpu().numpy())\n\n    accuracy = accuracy_score(y_true, y_pred)\n    precision = precision_score(y_true, y_pred)\n    recall = recall_score(y_true, y_pred)\n    f1 = f1_score(y_true, y_pred)\n    mcc = matthews_corrcoef(y_true, y_pred)\n    conf_matrix = confusion_matrix(y_true, y_pred)\n    \n    # Calcular TP, TN, FP, FN\n    tp = conf_matrix[1, 1]\n    tn = conf_matrix[0, 0]\n    fp = conf_matrix[0, 1]\n    fn = conf_matrix[1, 0]\n\n    return {\n        'Accuracy': accuracy,\n        'Precision': precision,\n        'Recall': recall,\n        'F1-Score': f1,\n        'MCC': mcc,\n        'Confusion Matrix': conf_matrix,\n        'True Positives (TP)': tp,\n        'True Negatives (TN)': tn,\n        'False Positives (FP)': fp,\n        'False Negatives (FN)': fn\n    }\n\n# Evaluar el modelo y obtener métricas\nmetrics = evaluate_model(model, val_loader, device)\nprint(\"Métricas en el conjunto de validación:\")\nfor metric_name, metric_value in metrics.items():\n    print(f\"{metric_name}: {metric_value}\")","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:11:42.673049Z","iopub.status.idle":"2023-09-24T17:11:42.673891Z","shell.execute_reply.started":"2023-09-24T17:11:42.673606Z","shell.execute_reply":"2023-09-24T17:11:42.673631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\ntest_loss = 0.0\ncorrect = 0\ntotal = 0\n\nwith torch.no_grad():\n    for images, labels in test_loader:\n        images, labels = images.to(device), labels.to(device)\n        outputs = model(images)\n        loss = criterion(outputs, labels.float().unsqueeze(1))\n        test_loss += loss.item()\n\ntest_loss /= len(test_loader)\nprint(f'Test Loss: {test_loss:.4f}')","metadata":{"execution":{"iopub.status.busy":"2023-09-24T17:11:42.675198Z","iopub.status.idle":"2023-09-24T17:11:42.676051Z","shell.execute_reply.started":"2023-09-24T17:11:42.675806Z","shell.execute_reply":"2023-09-24T17:11:42.675829Z"},"trusted":true},"execution_count":null,"outputs":[]}]}