{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":22307,"databundleVersionId":1502524,"sourceType":"competition"},{"sourceId":5499303,"sourceType":"datasetVersion","datasetId":3173056},{"sourceId":5799741,"sourceType":"datasetVersion","datasetId":3331043},{"sourceId":5919660,"sourceType":"datasetVersion","datasetId":3399617}],"dockerImageVersionId":30152,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# <font size=\"70\">Detección de embolismos pulmonares mediante técnicas de aprendizaje automático</font>\n\n### Trabajo de Fin de Grado\n\n### Curso académico 2022-2023\n\n### Autores:\n- Pablo Palacios López\n- José Antonio Gámez Martín\n- Juan Carlos Alfaro Jiménez","metadata":{}},{"cell_type":"markdown","source":"# 1. Importamos librerias","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nfrom os import *\nimport pydicom as dcm\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport imageio\nfrom IPython import display\nimport glob\n\nfrom sklearn.model_selection import train_test_split\n\nfrom skimage import measure \nfrom mpl_toolkits.mplot3d.art3d import Poly3DCollection\nfrom skimage.morphology import disk, opening, closing\nfrom tqdm import tqdm\n\nfrom IPython.display import HTML\nfrom PIL import Image\n\nimport pydicom\nimport pydicom as dcm\n\nimport skimage.io as io\n\nimport plotly.express as px\nimport matplotlib.pyplot as plt\nfrom matplotlib import animation, rc\nimport glob\n\nfrom plotly.subplots import make_subplots\nimport plotly.graph_objs as go","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-03-19T12:09:37.787107Z","iopub.execute_input":"2024-03-19T12:09:37.787514Z","iopub.status.idle":"2024-03-19T12:09:42.491766Z","shell.execute_reply.started":"2024-03-19T12:09:37.7874Z","shell.execute_reply":"2024-03-19T12:09:42.490347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Importamos la base de datos","metadata":{}},{"cell_type":"markdown","source":"Número de imagenes que tenemos en la base de datos","metadata":{}},{"cell_type":"code","source":"# images = glob.glob('/kaggle/input/rsna-str-pulmonary-embolism-detection/train/*/*/*.dcm')\n# print(\"El número de imágenes es: \", len(images))\n# images = pd.Series(images)\n\nprint(\"El número de imágenes es:  1790594\")","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:09:42.494095Z","iopub.execute_input":"2024-03-19T12:09:42.494437Z","iopub.status.idle":"2024-03-19T12:09:42.501678Z","shell.execute_reply.started":"2024-03-19T12:09:42.494393Z","shell.execute_reply":"2024-03-19T12:09:42.50093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Para mostrar nuestras imagenes debemos utilizar la libreria PyDicom. Un paquete de python que nos permite leer archivos DICOM (Digital Imaging and Communications in Medicine) como por ejemplo en este caso, ya que son imágenes médicas.","metadata":{}},{"cell_type":"code","source":"ds = pydicom.dcmread(\"/kaggle/input/rsna-str-pulmonary-embolism-detection/train/0003b3d648eb/d2b2960c2bbf/11401f58474b.dcm\")\ndcm_sample=ds.pixel_array.astype('float32')\nscaled_image = (np.maximum(dcm_sample, 0) / dcm_sample.max())\nplt.imshow(scaled_image)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:09:42.503321Z","iopub.execute_input":"2024-03-19T12:09:42.504097Z","iopub.status.idle":"2024-03-19T12:09:42.947563Z","shell.execute_reply.started":"2024-03-19T12:09:42.504053Z","shell.execute_reply":"2024-03-19T12:09:42.945854Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. DICOM a JPG","metadata":{}},{"cell_type":"markdown","source":"En este caso, no hemos tenido que realizar la conversión de las imagenes a mano, debido a que hemos encontrado una base de datos que ya nos las proporcionaba en el formato deseado. Este es el caso de la base de datos \"train-jpgs\". Donde tendremos todas las imágenes en un formato JPG 256x256","metadata":{}},{"cell_type":"code","source":"img = io.imread('/kaggle/input/data-binary/data/train/normal/1000.jpg')\nio.imshow(img)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:09:42.950368Z","iopub.execute_input":"2024-03-19T12:09:42.95069Z","iopub.status.idle":"2024-03-19T12:09:43.31323Z","shell.execute_reply.started":"2024-03-19T12:09:42.950655Z","shell.execute_reply":"2024-03-19T12:09:43.311929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4. Analisis exploratorio de datos ","metadata":{}},{"cell_type":"code","source":"PATH = \"../input/rsna-str-pulmonary-embolism-detection/\"\n\ntrain_df = pd.read_csv(PATH + \"train.csv\")\ntest_df = pd.read_csv(PATH + \"test.csv\")\nsub = pd.read_csv(PATH + \"sample_submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:09:43.3147Z","iopub.execute_input":"2024-03-19T12:09:43.314981Z","iopub.status.idle":"2024-03-19T12:09:49.088586Z","shell.execute_reply.started":"2024-03-19T12:09:43.314948Z","shell.execute_reply":"2024-03-19T12:09:49.087758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Vemos que tenemos 16 campos distintos, los campos StudyInstanceUID, SeriesInstanceUID y SOPInstanceUID son strings, mientras que el resto de campos son int64, donde la mayoría tienen valores booleanos 0 o 1, obersevemos una pequeña muestra de nuestros datos.  ","metadata":{}},{"cell_type":"code","source":"train_df.info()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:09:49.089644Z","iopub.execute_input":"2024-03-19T12:09:49.089916Z","iopub.status.idle":"2024-03-19T12:09:49.1242Z","shell.execute_reply.started":"2024-03-19T12:09:49.089882Z","shell.execute_reply":"2024-03-19T12:09:49.123036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head(10)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:09:49.125821Z","iopub.execute_input":"2024-03-19T12:09:49.127215Z","iopub.status.idle":"2024-03-19T12:09:49.161534Z","shell.execute_reply.started":"2024-03-19T12:09:49.127161Z","shell.execute_reply":"2024-03-19T12:09:49.16083Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"En este gráfico podemos observar la relación entre los parámetros para evaluar la detección de embolismos pulmonares.\n\nEn el primer caso tenemos que detectar si la imagen que estamos observando es o no negativo con el supuesto PE. En caso de que SI sea negativo (es decir, que no exista ningún tipo de PE) habremos terminado y con esa imagen no hay nada que hacer, en cambio, si el examen NO es negativo (es decir, hay PE aparente en la imagen) pasaremos a Indeterminado.\n\nEn segundo lugar, tenemos que ver si la imagen que estamos observando es o no Indeterminado. Será indeterminado cuando la imagen no se pueda apreciar bien, debido al contraste o el movimiento de la imagen, en cambio, si no es Indeterminado significa que presenta un PE el paciente, ahora tenemos que ver de que se trata el embolismo. \n\nUna vez tenemos ya que nos encontramos ante un PE, tenemos que evaluar los distintos parámetros que nos permitirán detectar la gravedad del embolismo (seleccionar solamente un parametro), la localización del mismo (tenemos que seleccionar al menos un parametro) y el radio del ventrículo derecho hasta el ventrículo izquierdo (seleccionar solamente un parametro).","metadata":{}},{"cell_type":"markdown","source":"![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F115173%2Fa2a5ee66b5799274141dd547cc3ea466%2FPE%20figure.jpg?generation=1599575183749576&alt=media)","metadata":{}},{"cell_type":"markdown","source":"Vamos a observar de que está compuesto nuestro train.csv\n\nhttps://plotly.com/python/subplots/#multiple-subplots","metadata":{}},{"cell_type":"code","source":"columns = [\n    'pe_present_on_image', 'negative_exam_for_pe', 'qa_motion', \n    'qa_contrast', 'flow_artifact', 'rv_lv_ratio_gte_1', \n    'rv_lv_ratio_lt_1', 'leftsided_pe', 'chronic_pe', \n    'true_filling_defect_not_pe', 'rightsided_pe', \n    'acute_and_chronic_pe', 'central_pe', 'indeterminate'\n]\n\nfig = make_subplots(rows=5, cols=3)\n\ntraces = []\nfor col in columns:\n        bar = go.Bar(\n            x=[0, 1], \n            y=[len(train_df[train_df[col]==0]),len(train_df[train_df[col]==1])], name=col,\n            text = [\n                            # obtenemos cada uno de los 0 que hay en la base de datos\n                            # con sus respectivas columnas\n                            # por ejemplo, esto nos dará con pe_present_on_image un 0.94\n                            # y redondeamos a 2 decimas\n                str(round(100 * len(train_df[train_df[col]==0]) / len(train_df), 1)) + '%',\n                str(round(100 * len(train_df[train_df[col]==1]) / len(train_df), 1)) + '%']\n        )\n        traces.append(bar)\n\n\n    \nfor i in range(len(traces)):\n    fig.append_trace(traces[i], (i // 3) + 1, (i % 3)  +1)\n                                #esto es para las row y cols, la posición de cada uno de los gráficos\n                                #para el de la primera posicion 0, será 0//3 = 0 + 1 = 1\n                                # 0%3 = 0 + 1 = 1, es decir, que se encontrará en la row=1 col=1\n\nfig.update_layout(\n    title_text='Train CSV columnas',\n    height=1040,\n    width=1000\n)\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:09:49.162798Z","iopub.execute_input":"2024-03-19T12:09:49.163569Z","iopub.status.idle":"2024-03-19T12:09:56.697014Z","shell.execute_reply.started":"2024-03-19T12:09:49.163531Z","shell.execute_reply":"2024-03-19T12:09:56.695656Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Aquí vemos una disposición de las columnas en nuestra base de datos, como vemos, abundan el número de ceros en las columnas indicando en muchos casos que la imagen no presenta ese tipo de parámetro, por ejemplo, en el atributo *pe_present_on_image*, vemos que tenemos un 94.6% de las imágenes que no presentan PE (1,694,054 imágenes que no presentan PE), mientras que el 5.4% restante si presenta embolismos pulmonares (96,540 imágenes que presentan PE).","metadata":{}},{"cell_type":"markdown","source":"**Visualización de las imágenes**","metadata":{}},{"cell_type":"code","source":"TRAIN_PATH = '../input/rsna-str-pulmonary-embolism-detection/train/'","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:09:56.698425Z","iopub.execute_input":"2024-03-19T12:09:56.698706Z","iopub.status.idle":"2024-03-19T12:09:56.703878Z","shell.execute_reply.started":"2024-03-19T12:09:56.69867Z","shell.execute_reply":"2024-03-19T12:09:56.702527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"selected_exam = 12\nEXAM_IDs = os.listdir(TRAIN_PATH)\n# print(np.asarray(EXAM_IDs).shape)\nSERIES = os.listdir(TRAIN_PATH + '/' + EXAM_IDs[selected_exam])\n# print(SERIES)\nfiles = os.listdir(TRAIN_PATH + '/' + EXAM_IDs[selected_exam] + '/' + SERIES[0])\n# print(files)\nsingle_experiment_files = [TRAIN_PATH + '/' + EXAM_IDs[selected_exam] + '/' + SERIES[0] + '/' + file for file in files]","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:09:56.708398Z","iopub.execute_input":"2024-03-19T12:09:56.709093Z","iopub.status.idle":"2024-03-19T12:09:57.009584Z","shell.execute_reply.started":"2024-03-19T12:09:56.709041Z","shell.execute_reply":"2024-03-19T12:09:57.008211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_slice(paths):\n    slices = [pydicom.read_file(path) for path in paths]\n#     labels = [train_df[train_df.SOPInstanceUID == path[-16:-4]].pe_present_on_image.values for path in patient_image_paths]\n#     labels = np.array(labels).squeeze()\n    slices.sort(key = lambda x: int(x.InstanceNumber), reverse = False)\n#     labels.sort(key = lambda x: int(x.InstanceNumber), reverse = False)\n    return slices\ndef transform_to_hu(slices):\n    images = np.stack([file.pixel_array for file in slices])\n    images = images.astype(np.int16)\n\n    # convert ouside pixel-values to air:\n    # I'm using <= -1000 to be sure that other defaults are captured as well\n    images[images <= -1000] = 0\n    \n    # convert to HU\n    for n in range(len(slices)):    \n        intercept = slices[n].RescaleIntercept\n        slope = slices[n].RescaleSlope\n        if slope != 1:\n            images[n] = slope * images[n].astype(np.float64)\n            images[n] = images[n].astype(np.int16)      \n        images[n] += np.int16(intercept)\n    return np.array(images, dtype=np.int16)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:09:57.013268Z","iopub.execute_input":"2024-03-19T12:09:57.01364Z","iopub.status.idle":"2024-03-19T12:09:57.026408Z","shell.execute_reply.started":"2024-03-19T12:09:57.013599Z","shell.execute_reply":"2024-03-19T12:09:57.024942Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"stacked_dicoms = load_slice(single_experiment_files)\nstacked_patient_pixels = transform_to_hu(stacked_dicoms)\n\ndef sample_stack(stack, rows=6, cols=6, start_with=10, show_every=3):\n    fig,ax = plt.subplots(rows,cols,figsize=[20,22])\n    for i in range(rows*cols):\n        ind = start_with + i*show_every\n        ax[int(i/rows),int(i % rows)].set_title(f'slice {ind}')\n        ax[int(i/rows),int(i % rows)].imshow(stack[ind],cmap='gray')\n        ax[int(i/rows),int(i % rows)].axis('off')\n    plt.show()\n\nprint(f'Total Number of Slices: {len(stacked_patient_pixels)}')\nsample_stack(stacked_patient_pixels, \n             show_every = int((len(stacked_patient_pixels)-10)/36))","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:09:57.028442Z","iopub.execute_input":"2024-03-19T12:09:57.028834Z","iopub.status.idle":"2024-03-19T12:10:04.331955Z","shell.execute_reply.started":"2024-03-19T12:09:57.028791Z","shell.execute_reply":"2024-03-19T12:10:04.330892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"imageio.mimsave(f'stacked_{EXAM_IDs[selected_exam]}.gif', stacked_patient_pixels, duration=0.1)\ndisplay.Image(f'stacked_{EXAM_IDs[selected_exam]}.gif', format='png')","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:04.333362Z","iopub.execute_input":"2024-03-19T12:10:04.334527Z","iopub.status.idle":"2024-03-19T12:10:15.252287Z","shell.execute_reply.started":"2024-03-19T12:10:04.334413Z","shell.execute_reply":"2024-03-19T12:10:15.250615Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"A continuación, mostramos el algoritmo que hemos utilizado para convertir las imágenes JPG con el Filtro de Sobel. Ha sido realizado localmente en mi ordenador debido a que los tiempos de compilación eran muy grandes, y recordemos que la plataforma Kaggle tiene un límite de RAM y de horas de GPU.","metadata":{}},{"cell_type":"code","source":"# from skimage import io, color, filters, exposure\n# import matplotlib.pyplot as plt\n# import os\n\n# # Ruta de la carpeta que contiene las imágenes JPEG\n# carpeta_imagenes = 'D:/Descargas/train-jpegs_partion/'\n# carpeta_imagenes_nuevas = 'D:/Descargas/train-jpegs-gray-scale-Sobel-Filter/'\n\n# # Recorrer todas las imágenes en la carpeta\n# for i in range(len(df)):\n#     print(i)\n# # Ruta de la imagen original\n#     ruta_imagen = os.path.join(carpeta_imagenes, df.loc[i, 'StudyInstanceUID'], df.loc[i, 'SeriesInstanceUID'], df.loc[i, 'SOPInstanceUID']+'.jpg')\n\n# # Leer la imagen en color\n#     imagen = io.imread(ruta_imagen)\n\n# # Aplicar el filtro de realce de bordes de Sobel\n#     imagen_filtrada = filters.sobel(imagen)\n\n# # Convertir la imagen filtrada a escala de grises\n#     imagen_gris = color.rgb2gray(imagen_filtrada)\n\n# # Ajustar el contraste de la imagen\n#     imagen_contraste = exposure.rescale_intensity(imagen_gris)\n\n# # Guardar la imagen en escala de grises con contraste ajustado\n#     nombre_nueva_imagen = df.loc[i, 'SOPInstanceUID'] + '.jpg'\n\n#     carpeta_nueva = os.path.join(carpeta_imagenes_nuevas,  df.loc[i, 'StudyInstanceUID'], df.loc[i, 'SeriesInstanceUID'])\n\n# # Crear la carpeta de destino si no existe\n#     if not os.path.exists(carpeta_nueva):\n#         os.makedirs(carpeta_nueva)\n\n#     ruta_nueva_imagen = os.path.join(carpeta_imagenes_nuevas, df.loc[i, 'StudyInstanceUID'], df.loc[i, 'SeriesInstanceUID'], nombre_nueva_imagen)\n#     io.imsave(ruta_nueva_imagen, imagen_contraste)\n#     del imagen, imagen_filtrada, imagen_gris, imagen_contraste\n#     gc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:15.254413Z","iopub.execute_input":"2024-03-19T12:10:15.254827Z","iopub.status.idle":"2024-03-19T12:10:15.262868Z","shell.execute_reply.started":"2024-03-19T12:10:15.254791Z","shell.execute_reply":"2024-03-19T12:10:15.261179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Aquí tenemos un ejemplo de las imágenes con el filtro de Sobel","metadata":{}},{"cell_type":"code","source":"img = io.imread('/kaggle/input/train-jpegs-gray-scale-sobelfilter/train-jpegs-gray-scale-Sobel-Filter/0003b3d648eb/d2b2960c2bbf/11401f58474b.jpg')\nio.imshow(img)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:15.265057Z","iopub.execute_input":"2024-03-19T12:10:15.265346Z","iopub.status.idle":"2024-03-19T12:10:15.651758Z","shell.execute_reply.started":"2024-03-19T12:10:15.26531Z","shell.execute_reply":"2024-03-19T12:10:15.650485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5. Clasificación binaria de imágenes y partición 60% + 20% + 20%","metadata":{}},{"cell_type":"code","source":"from sklearn.metrics import confusion_matrix\nfrom sklearn.metrics import classification_report\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.decomposition import PCA\nfrom sklearn.tree import DecisionTreeClassifier\n \nfrom pylab import rcParams\n\nfrom imblearn.under_sampling import NearMiss\nfrom imblearn.over_sampling import RandomOverSampler\nfrom imblearn.under_sampling import RandomUnderSampler\nfrom imblearn.combine import SMOTETomek\nfrom imblearn.ensemble import BalancedBaggingClassifier\n \nfrom collections import Counter","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:15.654561Z","iopub.execute_input":"2024-03-19T12:10:15.65503Z","iopub.status.idle":"2024-03-19T12:10:16.14025Z","shell.execute_reply.started":"2024-03-19T12:10:15.654973Z","shell.execute_reply":"2024-03-19T12:10:16.139332Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Como hemos comprobado en el apartado anterior, vemos que nuestros datos se encuentran muy desbalanceados en la Base de datos y por tanto no podemos clasificar correctamente nuestras imágenes.\n\nLa base de datos que tenemos llamada *rsna-str-detection-partition-train-test-val-in-jpg* no hemos realizado una división justa del Train, test y validation, ya que no hemos tenido en cuenta este desbalanceo, es por eso por lo que no podremos entrenar nuestro modelo con esta BBDD.\n\nTambién tenemos el problema del tiempo de computo, debido que a la hora de realizar el modelo, tarda mucho (3 horas por cada Epoch). \n\nTendremos que encontrar una solución para estos problemas planteados.\n\nEn primer lugar para solucionar nuestro problema con la divisón de nuestra BBDD, lo que haremos será crear distintos csv y directorios, como por ejemplo: Train Normal (No-Embolia) y Train Not Normal (Embolia), en ambos introduciremos aquellas imágenes que se encuentran en nuestro Train.CSV que coincidan con las especificaciones de ambas carpetas, es decir, para el directorio Train Normal, observaremos en nuestro Train.CSV cuales son aquellas imágenes que NO contienen embolia y las introduciremos.\n\nEste paso lo realizaremos exactamente igual para el Test y Validation.\n","metadata":{}},{"cell_type":"markdown","source":"##### El siguiente código está realizado en Visual Studio Code debido a los tiempos de compilación y el así poder introducir un nuevo dataset en la libreta.","metadata":{}},{"cell_type":"markdown","source":"##### Primero cogeremos nuestra base de datos Train.csv, almacenada en *rsna-str-pulmonary-embolism-detection*\n\nRealizaremos la partición correspondiente que hemos pedido 60% train, 20% test, 20% validation","metadata":{}},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/rsna-str-pulmonary-embolism-detection/train.csv\")","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:16.141675Z","iopub.execute_input":"2024-03-19T12:10:16.142198Z","iopub.status.idle":"2024-03-19T12:10:20.096268Z","shell.execute_reply.started":"2024-03-19T12:10:16.142138Z","shell.execute_reply":"2024-03-19T12:10:20.095301Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Realizamos la división","metadata":{}},{"cell_type":"code","source":"# train, test = train_test_split(df, test_size=0.2)\n\n# train, valid = train_test_split(train, test_size=0.2)\n\n# train.to_csv('train.csv')\n# valid.to_csv('valid.csv')\n# test.to_csv('test.csv')","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:20.09796Z","iopub.execute_input":"2024-03-19T12:10:20.098815Z","iopub.status.idle":"2024-03-19T12:10:20.103708Z","shell.execute_reply.started":"2024-03-19T12:10:20.098721Z","shell.execute_reply":"2024-03-19T12:10:20.102345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Y almacenamos las divisiones que hemos hecho, en nuestro caso, esas divisiones son las que se encuentran en el directorio *data-binary/data*, con sus respectivos porcentajes","metadata":{}},{"cell_type":"markdown","source":"# Train","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/data-binary/data/trainDesbalanceado.csv\")\ntrain = train.drop(['Unnamed: 0'], axis=1)\ntrain","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:20.105657Z","iopub.execute_input":"2024-03-19T12:10:20.106126Z","iopub.status.idle":"2024-03-19T12:10:24.19526Z","shell.execute_reply.started":"2024-03-19T12:10:20.106062Z","shell.execute_reply":"2024-03-19T12:10:24.194137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"A continuación dividimos nuestra base de datos entre Train1 == Train Not Normal (con embolia) y Train0 == Train Normal (sin embolia)","metadata":{}},{"cell_type":"code","source":"train1 = train.loc[(train[\"pe_present_on_image\"] == 1)].reset_index(drop=True)\nprint(\"Tenemos\", len(train1), \"imágenes\")\ntrain1.head(5)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:24.197278Z","iopub.execute_input":"2024-03-19T12:10:24.197641Z","iopub.status.idle":"2024-03-19T12:10:24.258832Z","shell.execute_reply.started":"2024-03-19T12:10:24.197594Z","shell.execute_reply":"2024-03-19T12:10:24.257852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Realizando el estudio, nos hemos percatado de que existen tuplas en las que pe_present_on_image==0 y negative_exam_for_pe == 0 e indetermiante == 0  por tanto resulta un poco contradictorio, con respecto al gráfico del análisis exploratorio, determinar si tiene o no embolia en esos casos, ya que te está diciendo que no es negativo, no es indeterminado, y tampoco tiene embolia, por tanto hemos optado por descartar esos casos para el Train, quedandonos solamente con aquellas imágenes que son negativas directamente y entonces sabemos con certeza que no contienen embolia.","metadata":{}},{"cell_type":"code","source":"train0 = train.loc[(train[\"pe_present_on_image\"] == 0) & (train[\"negative_exam_for_pe\"] == 1)].reset_index(drop=True)\nprint(\"Tenemos\", len(train0), \"imágenes\")\ntrain0.head(5)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:24.26011Z","iopub.execute_input":"2024-03-19T12:10:24.260452Z","iopub.status.idle":"2024-03-19T12:10:24.44661Z","shell.execute_reply.started":"2024-03-19T12:10:24.260351Z","shell.execute_reply":"2024-03-19T12:10:24.445378Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Unimos ambos datasets para hacer un estudio de los datos","metadata":{}},{"cell_type":"code","source":"trainNuevoDesbalanceado_sinPEeq0_sinNEeq0 = pd.read_csv(\"/kaggle/input/data-binary/data/trainNuevoDesbalanceado_sinPEeq0_sinNEeq0.csv\")\ntrainNuevoDesbalanceado_sinPEeq0_sinNEeq0 = trainNuevoDesbalanceado_sinPEeq0_sinNEeq0.drop(['Unnamed: 0'], axis=1)\ntrainNuevoDesbalanceado_sinPEeq0_sinNEeq0","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:24.448788Z","iopub.execute_input":"2024-03-19T12:10:24.449238Z","iopub.status.idle":"2024-03-19T12:10:27.119249Z","shell.execute_reply.started":"2024-03-19T12:10:24.44919Z","shell.execute_reply":"2024-03-19T12:10:27.118278Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y=trainNuevoDesbalanceado_sinPEeq0_sinNEeq0['pe_present_on_image']\ny.value_counts()\nplt.figure(facecolor='white')\ny.value_counts().plot.pie(autopct='%.2f')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:27.121409Z","iopub.execute_input":"2024-03-19T12:10:27.122097Z","iopub.status.idle":"2024-03-19T12:10:27.251849Z","shell.execute_reply.started":"2024-03-19T12:10:27.122042Z","shell.execute_reply":"2024-03-19T12:10:27.250693Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Vemos el gran desbalanceo de los datos que existen, por tanto, llevaremos a cabo un RandomUnderSampling para tratarlo","metadata":{}},{"cell_type":"code","source":"X=trainNuevoDesbalanceado_sinPEeq0_sinNEeq0.drop(\"pe_present_on_image\",axis=1)\nX","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:27.253211Z","iopub.execute_input":"2024-03-19T12:10:27.253812Z","iopub.status.idle":"2024-03-19T12:10:27.335867Z","shell.execute_reply.started":"2024-03-19T12:10:27.253762Z","shell.execute_reply":"2024-03-19T12:10:27.334497Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"El código que tenemos debajo ha sido realizado en visual studio. En él llevamos a cabo la función de balanceo de datos RandomUnderSampler, el cual nos proporciona un dataset totalmente balanceado, en este caso, eliminamos instancias de la base de datos que tengan pe_present_on_image==1, hasta igualar su número con aquellas instancias que tengan pe_present_on_image==0, dando lugar a nuestra base de datos balanceada 50%-50%","metadata":{}},{"cell_type":"code","source":"# from imblearn.under_sampling import RandomUnderSampler\n\n# rus = RandomUnderSampler(sampling_strategy=1) # Numerical value\n\n# X_res, y_res = rus.fit_resample(X, y)\n\n# ax = y_res.value_counts().plot.pie(autopct='%.2f')\n\n# _ = ax.set_title(\"Under-sampling\")","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:27.337381Z","iopub.execute_input":"2024-03-19T12:10:27.337751Z","iopub.status.idle":"2024-03-19T12:10:27.342774Z","shell.execute_reply.started":"2024-03-19T12:10:27.337689Z","shell.execute_reply":"2024-03-19T12:10:27.341797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Esta será nuestra base de datos totalmente balanceada","metadata":{}},{"cell_type":"code","source":"trainBalanceado = pd.read_csv(\"/kaggle/input/data-binary/data/trainBalanceado.csv\")\ntrainBalanceado = trainBalanceado.drop(['Unnamed: 0'], axis=1)\ntrainBalanceado","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:27.34422Z","iopub.execute_input":"2024-03-19T12:10:27.344566Z","iopub.status.idle":"2024-03-19T12:10:27.780178Z","shell.execute_reply.started":"2024-03-19T12:10:27.34452Z","shell.execute_reply":"2024-03-19T12:10:27.779141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y=trainBalanceado['pe_present_on_image']\ny.value_counts()\nplt.figure(facecolor='white')\ny.value_counts().plot.pie(autopct='%.2f')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:27.781437Z","iopub.execute_input":"2024-03-19T12:10:27.781679Z","iopub.status.idle":"2024-03-19T12:10:27.876707Z","shell.execute_reply.started":"2024-03-19T12:10:27.781649Z","shell.execute_reply":"2024-03-19T12:10:27.875672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Vamos a comprobar de que está compuesto nuestra BBDD totalmente balanceada","metadata":{}},{"cell_type":"code","source":"#NOT NORMAL\n\ntrain1 = trainBalanceado.loc[trainBalanceado[\"pe_present_on_image\"] == 1].reset_index(drop=True)\nprint(\"Tenemos\", len(train1), \"imágenes\")\ntrain1.head(5)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:27.881531Z","iopub.execute_input":"2024-03-19T12:10:27.881812Z","iopub.status.idle":"2024-03-19T12:10:27.915346Z","shell.execute_reply.started":"2024-03-19T12:10:27.88178Z","shell.execute_reply":"2024-03-19T12:10:27.914269Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#NORMAL\n\ntrain0 = trainBalanceado.loc[(trainBalanceado[\"negative_exam_for_pe\"] == 1)].reset_index(drop=True)\nprint(\"Tenemos\", len(train0), \"imágenes\")\ntrain0.head(5)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:27.917125Z","iopub.execute_input":"2024-03-19T12:10:27.917381Z","iopub.status.idle":"2024-03-19T12:10:27.950176Z","shell.execute_reply.started":"2024-03-19T12:10:27.917348Z","shell.execute_reply":"2024-03-19T12:10:27.949156Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Ahora el siguiente paso será introducir en nuestras respectivas carpetas las imágenes. Este paso lo hemos relizado en mi ordenador local, ya que los tiempos de compilación eran muy grandes.","metadata":{}},{"cell_type":"code","source":"# Train_not_normal\n\n# df = train1\n\n# for i in tqdm(range(len(train1))):\n#     imJPG = io.imread(\"D:/Descargas/train-jpegs_partion/\" + df.loc[i,'StudyInstanceUID']+'/'+ df.loc[i,'SeriesInstanceUID']+'/'+ df.loc[i,'SOPInstanceUID']+'.jpg')\n#     im = Image.fromarray(imJPG)\n#     im.save(\"D:/Descargas/data/train/not_normal/\"+str(i)+\".jpg\")\n#     del imJPG, im\n#     gc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:27.951665Z","iopub.execute_input":"2024-03-19T12:10:27.951987Z","iopub.status.idle":"2024-03-19T12:10:27.956306Z","shell.execute_reply.started":"2024-03-19T12:10:27.951952Z","shell.execute_reply":"2024-03-19T12:10:27.955325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train_not_normal 20000 imagenes\n\n# df = train1\n\n# for i in tqdm(range(20000)):\n#     imJPG = io.imread(\"D:/Descargas/train-jpegs_partion/\" + df.loc[i,'StudyInstanceUID']+'/'+ df.loc[i,'SeriesInstanceUID']+'/'+ df.loc[i,'SOPInstanceUID']+'.jpg')\n#     im = Image.fromarray(imJPG)\n#     im.save(\"D:/Descargas/data/train/20000_not_normal/\"+str(i)+\".jpg\")\n#     del imJPG, im\n#     gc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:27.957622Z","iopub.execute_input":"2024-03-19T12:10:27.957947Z","iopub.status.idle":"2024-03-19T12:10:27.968696Z","shell.execute_reply.started":"2024-03-19T12:10:27.957887Z","shell.execute_reply":"2024-03-19T12:10:27.967484Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train normal\n\n# df = train0\n\n# for i in tqdm(range(len(train0))):\n#     imJPG = io.imread(\"D:/Descargas/train-jpegs_partion/\" + df.loc[i,'StudyInstanceUID']+'/'+ df.loc[i,'SeriesInstanceUID']+'/'+ df.loc[i,'SOPInstanceUID']+'.jpg')\n#     im = Image.fromarray(imJPG)\n#     im.save(\"D:/Descargas/data/train/normal/\"+str(i)+\".jpg\")\n#     del imJPG, im\n#     gc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:27.970218Z","iopub.execute_input":"2024-03-19T12:10:27.970562Z","iopub.status.idle":"2024-03-19T12:10:27.982278Z","shell.execute_reply.started":"2024-03-19T12:10:27.970512Z","shell.execute_reply":"2024-03-19T12:10:27.981083Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Train_normal 20000 imagenes\n\n# df = train0\n\n# for i in tqdm(range(20000)):\n#     imJPG = io.imread(\"D:/Descargas/train-jpegs_partion/\" + df.loc[i,'StudyInstanceUID']+'/'+ df.loc[i,'SeriesInstanceUID']+'/'+ df.loc[i,'SOPInstanceUID']+'.jpg')\n#     im = Image.fromarray(imJPG)\n#     im.save(\"D:/Descargas/data/train/20000_normal/\"+str(i)+\".jpg\")\n#     del imJPG, im\n#     gc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:27.983845Z","iopub.execute_input":"2024-03-19T12:10:27.984236Z","iopub.status.idle":"2024-03-19T12:10:28.00083Z","shell.execute_reply.started":"2024-03-19T12:10:27.984189Z","shell.execute_reply":"2024-03-19T12:10:27.999614Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Este código ha sido realizado en Visual Studio Code, en mi ordenador local, debido a los tiempos de comptuación, pero estos directorios se pueden encontrar en ***data-binary/data/train/normal*** y ***data-binary/data/train/not_normal***, ahí están las imágenes y su balanceo. También hemos hecho 2 directorios más ***data-binary/data/train/20000_normal*** y ***data-binary/data/train/20000_not_normal***, cogemos una pequeña meustra para realizar pruebas sobre los modelos hechos, así no nos tardará tanto.","metadata":{}},{"cell_type":"markdown","source":"A continuación realizaremos el mismo proceso para el test y el validation, pero ahora no podemos realizar ningún tipo de balanceo, un error que cometimos anteriormente y estamos solucionando ahora mismo, por tanto el único paso que realizaremos será dividir las imágenes si pe_present_on_image==1 a la carpeta Not Normal y si pe_present_on_image==0 irán a la carpeta Normal","metadata":{}},{"cell_type":"markdown","source":"# Test","metadata":{}},{"cell_type":"markdown","source":"Este es nuestro dataset Test para el problema de clasificación binario","metadata":{}},{"cell_type":"code","source":"test = pd.read_csv(\"/kaggle/input/data-binary/data/test.csv\")\ntest = test.drop(['Unnamed: 0'], axis=1)\ntest","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:28.002531Z","iopub.execute_input":"2024-03-19T12:10:28.002907Z","iopub.status.idle":"2024-03-19T12:10:29.257208Z","shell.execute_reply.started":"2024-03-19T12:10:28.00285Z","shell.execute_reply":"2024-03-19T12:10:29.256447Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y=test['pe_present_on_image']\ny.value_counts()\nplt.figure(facecolor='white')\ny.value_counts().plot.pie(autopct='%.2f')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:29.258391Z","iopub.execute_input":"2024-03-19T12:10:29.259256Z","iopub.status.idle":"2024-03-19T12:10:29.378555Z","shell.execute_reply.started":"2024-03-19T12:10:29.259216Z","shell.execute_reply":"2024-03-19T12:10:29.377797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test1 = test.loc[test[\"pe_present_on_image\"] == 1].reset_index(drop=True)\nprint(\"Tenemos\", len(test1), \"imágenes\")\ntest1.head(5)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:29.379864Z","iopub.execute_input":"2024-03-19T12:10:29.380764Z","iopub.status.idle":"2024-03-19T12:10:29.416892Z","shell.execute_reply.started":"2024-03-19T12:10:29.380699Z","shell.execute_reply":"2024-03-19T12:10:29.415626Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test0 = test.loc[test[\"pe_present_on_image\"] == 0].reset_index(drop=True)\nprint(\"Tenemos\", len(test0), \"imágenes\")\ntest0.head(5)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:29.418459Z","iopub.execute_input":"2024-03-19T12:10:29.420038Z","iopub.status.idle":"2024-03-19T12:10:29.51537Z","shell.execute_reply.started":"2024-03-19T12:10:29.419985Z","shell.execute_reply":"2024-03-19T12:10:29.514474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Introducimos las imágenes en nuestros directorios correspondientes","metadata":{}},{"cell_type":"code","source":"#Not Normal\n\n# df = test1\n\n# for i in tqdm(range(len(test1))):\n#     imJPG = io.imread(\"D:/Descargas/train-jpegs_partion/\" + df.loc[i,'StudyInstanceUID']+'/'+df.loc[i,'SeriesInstanceUID']+'/'+df.loc[i,'SOPInstanceUID']+'.jpg')\n#     im = Image.fromarray(imJPG)\n#     im.save(\"D:/Descargas/data/test/not_normal/\"+str(i)+\".jpg\")\n#     del imJPG, im\n#     gc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:29.516643Z","iopub.execute_input":"2024-03-19T12:10:29.516955Z","iopub.status.idle":"2024-03-19T12:10:29.522507Z","shell.execute_reply.started":"2024-03-19T12:10:29.516913Z","shell.execute_reply":"2024-03-19T12:10:29.521457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Normal\n\n# df = test0\n\n# for i in tqdm(range(len(test0))):\n#     imJPG = io.imread(\"D:/Descargas/train-jpegs_partion/\" + df.loc[i,'StudyInstanceUID']+'/'+df.loc[i,'SeriesInstanceUID']+'/'+df.loc[i,'SOPInstanceUID']+'.jpg')\n#     im = Image.fromarray(imJPG)\n#     im.save(\"D:/Descargas/data/test/normal/\"+str(i)+\".jpg\")\n#     del imJPG, im\n#     gc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:29.52423Z","iopub.execute_input":"2024-03-19T12:10:29.52461Z","iopub.status.idle":"2024-03-19T12:10:29.534997Z","shell.execute_reply.started":"2024-03-19T12:10:29.524566Z","shell.execute_reply":"2024-03-19T12:10:29.533755Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Este código ha sido realizado en Visual Studio Code, en mi ordenador local, debido a los tiempos de comptuación, pero estos directorios se pueden encontrar en ***data-binary/data/test/normal*** y ***data-binary/data/test/not_normal***, ahí están las imágenes y su balanceo","metadata":{}},{"cell_type":"markdown","source":"# Valid","metadata":{}},{"cell_type":"code","source":"valid = pd.read_csv(\"/kaggle/input/data-binary/data/valid.csv\")\nvalid = valid.drop(['Unnamed: 0'], axis=1)\nvalid","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:29.536641Z","iopub.execute_input":"2024-03-19T12:10:29.537082Z","iopub.status.idle":"2024-03-19T12:10:30.576582Z","shell.execute_reply.started":"2024-03-19T12:10:29.537044Z","shell.execute_reply":"2024-03-19T12:10:30.575682Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y=valid['pe_present_on_image']\ny.value_counts()\nplt.figure(facecolor='white')\ny.value_counts().plot.pie(autopct='%.2f')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:30.578196Z","iopub.execute_input":"2024-03-19T12:10:30.579021Z","iopub.status.idle":"2024-03-19T12:10:30.948941Z","shell.execute_reply.started":"2024-03-19T12:10:30.578965Z","shell.execute_reply":"2024-03-19T12:10:30.947839Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid1 = valid.loc[valid[\"pe_present_on_image\"] == 1].reset_index(drop=True)\nprint(\"Tenemos\", len(valid1), \"imágenes\")\nvalid1.head(5)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:30.950502Z","iopub.execute_input":"2024-03-19T12:10:30.951759Z","iopub.status.idle":"2024-03-19T12:10:30.98436Z","shell.execute_reply.started":"2024-03-19T12:10:30.951691Z","shell.execute_reply":"2024-03-19T12:10:30.983405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid0 = valid.loc[valid[\"pe_present_on_image\"] == 0].reset_index(drop=True)\nprint(\"Tenemos\", len(valid0), \"imágenes\")\nvalid0.head(5)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:30.985845Z","iopub.execute_input":"2024-03-19T12:10:30.9862Z","iopub.status.idle":"2024-03-19T12:10:31.056181Z","shell.execute_reply.started":"2024-03-19T12:10:30.98615Z","shell.execute_reply":"2024-03-19T12:10:31.055141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Validation not_normal\n\n# df = valid1\n\n# for i in tqdm(range(len(valid1))):\n#     imJPG = io.imread(\"D:/Descargas/train-jpegs_partion/\" + df.loc[i,'StudyInstanceUID']+'/'+df.loc[i,'SeriesInstanceUID']+'/'+df.loc[i,'SOPInstanceUID']+'.jpg')\n#     im = Image.fromarray(imJPG)\n#     im.save(\"D:/Descargas/data/valid/not_normal/\"+str(i)+\".jpg\")\n#     del imJPG, im\n#     gc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:31.057517Z","iopub.execute_input":"2024-03-19T12:10:31.057794Z","iopub.status.idle":"2024-03-19T12:10:31.06289Z","shell.execute_reply.started":"2024-03-19T12:10:31.057754Z","shell.execute_reply":"2024-03-19T12:10:31.061827Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Validation normal\n\n# df = valid0\n\n# for i in tqdm(range(len(valid0))):\n#     imJPG = io.imread(\"D:/Descargas/train-jpegs_partion/\" + df.loc[i,'StudyInstanceUID']+'/'+ df.loc[i,'SeriesInstanceUID']+'/'+ df.loc[i,'SOPInstanceUID']+'.jpg')\n#     im = Image.fromarray(imJPG)\n#     im.save(\"D:/Descargas/data/valid/normal/\"+str(i)+\".jpg\")\n#     del imJPG, im\n#     gc.collect()","metadata":{"execution":{"iopub.status.busy":"2024-03-19T12:10:31.064678Z","iopub.execute_input":"2024-03-19T12:10:31.06506Z","iopub.status.idle":"2024-03-19T12:10:31.076688Z","shell.execute_reply.started":"2024-03-19T12:10:31.065022Z","shell.execute_reply":"2024-03-19T12:10:31.0756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Este código ha sido realizado en Visual Studio Code, en mi ordenador local, debido a los tiempos de comptuación, pero estos directorios se pueden encontrar en ***data-binary/data/valid/normal*** y ***data-binary/data/valid/not_normal***, ahí están las imágenes y su balanceo","metadata":{}}]}