{"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":"# Detección de melanomas malignos utilizando CNN y TPUs","metadata":{}},{"cell_type":"markdown","source":"## Librerías a utilizar","metadata":{}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd\nimport tensorflow as tf\nfrom kaggle_datasets import KaggleDatasets\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import roc_curve\nfrom sklearn.metrics import auc\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom numpy.random import seed\nseed(1)\ntf.random.set_seed(1)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-07-06T01:55:16.214175Z","iopub.execute_input":"2021-07-06T01:55:16.214542Z","iopub.status.idle":"2021-07-06T01:55:16.220859Z","shell.execute_reply.started":"2021-07-06T01:55:16.214513Z","shell.execute_reply":"2021-07-06T01:55:16.220153Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Configuración de TPU para el entrenamiento </br>\n","metadata":{}},{"cell_type":"markdown","source":"<img src=\"https://storage.googleapis.com/kaggle-media/tpu/tpu_cores_and_chips.png\">","metadata":{}},{"cell_type":"code","source":"try:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect() # busca conectarse a una TPU disponible por grpc\n    print('Conexion:', tpu.master()) # muestra el TPU (hostname)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu) # instancia una estrategia de distribución\n    print('Número de núcleos:', strategy.num_replicas_in_sync) # 4 chips, 2 núcleos c/u\nexcept:\n    strategy = tf.distribute.get_strategy() # trabajar con CPU  o GPU\n    print('Número de núcleos: ', strategy.num_replicas_in_sync)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:06:37.866362Z","iopub.execute_input":"2021-07-06T02:06:37.866663Z","iopub.status.idle":"2021-07-06T02:06:43.703097Z","shell.execute_reply.started":"2021-07-06T02:06:37.866638Z","shell.execute_reply":"2021-07-06T02:06:43.702178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Funcionamiento de un CPU </br>\n<img src=\"https://cloud.google.com/tpu/docs/images/image6.gif\"> </br>\n### Funcionamiento de un GPU </br>\n<img src=\"https://cloud.google.com/tpu/docs/images/image2.gif\"> </br>\n### Funcionamiento del TPU </br>\n<img src=\"https://cloud.google.com/tpu/docs/images/image1_2pdcvle.gif\"> </br>\nFuente: https://cloud.google.com/tpu/docs/beginners-guide","metadata":{}},{"cell_type":"markdown","source":"## Definir ruta en  Google Cloud Storage (necesario para TPU), Batch Size, tamaños de imagen\n\n","metadata":{}},{"cell_type":"markdown","source":"<img src=\"https://www.fatalerrors.org/images/blog/d28ad66f32d6730cfcc732d8dcd74c64.jpg\">","metadata":{}},{"cell_type":"code","source":"!lscpu","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:12:30.699026Z","iopub.execute_input":"2021-07-06T02:12:30.699433Z","iopub.status.idle":"2021-07-06T02:12:31.440745Z","shell.execute_reply.started":"2021-07-06T02:12:30.699399Z","shell.execute_reply":"2021-07-06T02:12:31.439750Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!lsb_release -a","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:13:25.770804Z","iopub.execute_input":"2021-07-06T02:13:25.771328Z","iopub.status.idle":"2021-07-06T02:13:26.716725Z","shell.execute_reply.started":"2021-07-06T02:13:25.771288Z","shell.execute_reply":"2021-07-06T02:13:26.715778Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"AUTOTUNE = tf.data.experimental.AUTOTUNE # es un comodín que calcula el número óptimo para cierto parámetro en tiempo de ejcución\nGCS_PATH = KaggleDatasets().get_gcs_path() # obtener la ruta de la data en GCS\nBATCH_SIZE = 128 * strategy.num_replicas_in_sync # batch_size = 128\nIMAGE_SIZE = [1024, 1024] # tamaño de las imágenes en tfrec\nIMAGE_RESIZE = [256, 256] # tamaño al entrar a la CNN","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:34:28.968980Z","iopub.execute_input":"2021-07-06T02:34:28.969586Z","iopub.status.idle":"2021-07-06T02:34:33.356392Z","shell.execute_reply.started":"2021-07-06T02:34:28.969535Z","shell.execute_reply":"2021-07-06T02:34:33.355373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"GCS_PATH","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:34:35.818715Z","iopub.execute_input":"2021-07-06T02:34:35.819310Z","iopub.status.idle":"2021-07-06T02:34:35.827453Z","shell.execute_reply.started":"2021-07-06T02:34:35.819257Z","shell.execute_reply":"2021-07-06T02:34:35.826585Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Tamaño de la data en .jpeg","metadata":{}},{"cell_type":"code","source":"!du -sh ../input/siim-isic-melanoma-classification/jpeg/train","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:26:41.641854Z","iopub.execute_input":"2021-07-06T02:26:41.642303Z","iopub.status.idle":"2021-07-06T02:27:43.525501Z","shell.execute_reply.started":"2021-07-06T02:26:41.642266Z","shell.execute_reply":"2021-07-06T02:27:43.524279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Tamaño en tfrec","metadata":{}},{"cell_type":"code","source":"!du -ach ../input/siim-isic-melanoma-classification/tfrecords/train*","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:29:53.717709Z","iopub.execute_input":"2021-07-06T02:29:53.718072Z","iopub.status.idle":"2021-07-06T02:29:54.486756Z","shell.execute_reply.started":"2021-07-06T02:29:53.718040Z","shell.execute_reply":"2021-07-06T02:29:54.485627Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## ¿Por qué TFRecords?\n\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F4003597%2F9564cf28fc1ec979cbbfa286e115aac2%2FScreen%20Shot%202020-12-01%20at%2017.50.06.png?generation=1606874056869465&alt=media\">\n\n","metadata":{}},{"cell_type":"markdown","source":"## Dividir en data de entrenamiento y validación (a nivel de tfrecs)","metadata":{}},{"cell_type":"code","source":"FILENAMES = tf.io.gfile.glob(GCS_PATH + '/tfrecords/train*')\nFILENAMES","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:35:14.265599Z","iopub.execute_input":"2021-07-06T02:35:14.265959Z","iopub.status.idle":"2021-07-06T02:35:18.368709Z","shell.execute_reply.started":"2021-07-06T02:35:14.265928Z","shell.execute_reply":"2021-07-06T02:35:18.367731Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(FILENAMES)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:35:18.370140Z","iopub.execute_input":"2021-07-06T02:35:18.370444Z","iopub.status.idle":"2021-07-06T02:35:18.376224Z","shell.execute_reply.started":"2021-07-06T02:35:18.370416Z","shell.execute_reply":"2021-07-06T02:35:18.375187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAINING_FILENAMES, VALID_TEST_FILENAMES = train_test_split( # dividir en train y test\n    FILENAMES, # busca por patrón\n    test_size=0.2, random_state=1 # tamaño del test y un seed\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:46:02.820965Z","iopub.execute_input":"2021-07-06T02:46:02.821344Z","iopub.status.idle":"2021-07-06T02:46:02.829785Z","shell.execute_reply.started":"2021-07-06T02:46:02.821315Z","shell.execute_reply":"2021-07-06T02:46:02.828963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAINING_FILENAMES, VALID_TEST_FILENAMES","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:46:04.588746Z","iopub.execute_input":"2021-07-06T02:46:04.589276Z","iopub.status.idle":"2021-07-06T02:46:04.595854Z","shell.execute_reply.started":"2021-07-06T02:46:04.589237Z","shell.execute_reply":"2021-07-06T02:46:04.595067Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"VALID_FILENAMES, TEST_FILENAMES = train_test_split( # dividir en train y test\n    VALID_TEST_FILENAMES, # busca por patrón\n    test_size=0.5, random_state=1 # tamaño del test y un seed\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:46:19.968301Z","iopub.execute_input":"2021-07-06T02:46:19.968795Z","iopub.status.idle":"2021-07-06T02:46:19.973641Z","shell.execute_reply.started":"2021-07-06T02:46:19.968764Z","shell.execute_reply":"2021-07-06T02:46:19.972740Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAINING_FILENAMES, VALID_FILENAMES, TEST_FILENAMES","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:46:23.962454Z","iopub.execute_input":"2021-07-06T02:46:23.962872Z","iopub.status.idle":"2021-07-06T02:46:23.970921Z","shell.execute_reply.started":"2021-07-06T02:46:23.962841Z","shell.execute_reply":"2021-07-06T02:46:23.969582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(TRAINING_FILENAMES), len(VALID_FILENAMES), len(TEST_FILENAMES)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:47:59.557781Z","iopub.execute_input":"2021-07-06T02:47:59.558177Z","iopub.status.idle":"2021-07-06T02:47:59.564404Z","shell.execute_reply.started":"2021-07-06T02:47:59.558136Z","shell.execute_reply":"2021-07-06T02:47:59.563333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Contar data para el batching, balance de clases","metadata":{}},{"cell_type":"code","source":"train_csv = pd.read_csv('../input/siim-isic-melanoma-classification/train.csv')","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:48:16.557858Z","iopub.execute_input":"2021-07-06T02:48:16.558377Z","iopub.status.idle":"2021-07-06T02:48:16.663357Z","shell.execute_reply.started":"2021-07-06T02:48:16.558332Z","shell.execute_reply":"2021-07-06T02:48:16.662245Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls /kaggle/input/siim-isic-melanoma-classification/jpeg/train | wc -l","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:48:59.099601Z","iopub.execute_input":"2021-07-06T02:48:59.099959Z","iopub.status.idle":"2021-07-06T02:49:00.569674Z","shell.execute_reply.started":"2021-07-06T02:48:59.099922Z","shell.execute_reply":"2021-07-06T02:49:00.568525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"total = train_csv['target'].size\n\nmaligno = np.count_nonzero(train_csv['target'])\nbenigno = total - maligno\n\nprint('Total: {}'.format(total))\nprint('Maligno: {}, Benigno: {}'.format(maligno, benigno))","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:49:49.492106Z","iopub.execute_input":"2021-07-06T02:49:49.492495Z","iopub.status.idle":"2021-07-06T02:49:49.506010Z","shell.execute_reply.started":"2021-07-06T02:49:49.492461Z","shell.execute_reply":"2021-07-06T02:49:49.505042Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Conteo de número de imágenes de training y validación (necesario para el batching)","metadata":{}},{"cell_type":"code","source":"NUM_IMG_TRAIN = 11*2071 + 2061\nNUM_IMG_VAL = 2071\nNUM_IMG_TEST = 2071","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:51:56.004429Z","iopub.execute_input":"2021-07-06T02:51:56.004797Z","iopub.status.idle":"2021-07-06T02:51:56.008557Z","shell.execute_reply.started":"2021-07-06T02:51:56.004769Z","shell.execute_reply":"2021-07-06T02:51:56.007910Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Ver la estructura de la data en formato tfrec","metadata":{}},{"cell_type":"code","source":"primer_tfrec = tf.data.TFRecordDataset(TRAINING_FILENAMES[0]) #primer tfrec\n\nfor raw_record in primer_tfrec.take(1): # coge un elemento del tfrec. Take genera un dataset a partir del tfrec\n    example = tf.train.Example() #instancia un objeto para leer en formato tfrec (como un JSON)\n    example.ParseFromString(raw_record.numpy()) # lee los datos serializados\n    print(example) #debemos ver las keys y el tipo de dato","metadata":{"execution":{"iopub.status.busy":"2021-07-06T02:55:16.080976Z","iopub.execute_input":"2021-07-06T02:55:16.081355Z","iopub.status.idle":"2021-07-06T02:55:22.090892Z","shell.execute_reply.started":"2021-07-06T02:55:16.081324Z","shell.execute_reply":"2021-07-06T02:55:22.090102Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Crear el pipeline de entrada de datos","metadata":{}},{"cell_type":"markdown","source":"<img src=\"https://storage.googleapis.com/jalammar-ml/tf.data/images/tf.data-pipeline-4.png\">","metadata":{}},{"cell_type":"markdown","source":"### Convertir imagen .jpeg a tensor y normalizar","metadata":{}},{"cell_type":"code","source":"def decode_image(image):\n    image = tf.image.decode_jpeg(image, channels=3) # convierte jpeg en un tensor uint8\n    image = tf.cast(image, tf.float32) / 255.0 # normalizar la imagen\n    image = tf.reshape(image, [*IMAGE_SIZE, 3]) # dar forma (1024, 1024, 3) (aunque ya está así)\n    return image","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:16:40.643812Z","iopub.execute_input":"2021-07-06T03:16:40.644175Z","iopub.status.idle":"2021-07-06T03:16:40.649621Z","shell.execute_reply.started":"2021-07-06T03:16:40.644145Z","shell.execute_reply":"2021-07-06T03:16:40.648424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Leer un ejemplo de entrenamiento en .tfrec","metadata":{}},{"cell_type":"code","source":"def read_tfrecord(example):\n    tfrec_format = { # obtener del código anterior\n        \"image\": tf.io.FixedLenFeature(shape = (), dtype = tf.string),\n        \"image_name\": tf.io.FixedLenFeature(shape = (), dtype = tf.string), \n        \"target\": tf.io.FixedLenFeature(shape = (), dtype = tf.int64)\n    }\n    example = tf.io.parse_single_example(example, tfrec_format) # pasar de serializado a formato\n    image = decode_image(example['image']) # decodificar imagen .jpeg a tensor\n    label = tf.cast(example['target'], tf.int32)\n    return image, label","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:13:19.930993Z","iopub.execute_input":"2021-07-06T03:13:19.931395Z","iopub.status.idle":"2021-07-06T03:13:19.938324Z","shell.execute_reply.started":"2021-07-06T03:13:19.931363Z","shell.execute_reply":"2021-07-06T03:13:19.937261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Cargar un dataset de .tfrec para luego pasarlo a tensores (con `dataset.map`)","metadata":{}},{"cell_type":"code","source":"def load_dataset(filenames):\n    opciones = tf.data.Options() # configuración del dataset\n    opciones.experimental_deterministic = False # no se tiene un orden específico\n    dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTOTUNE) # crea un dataset a paratir de tfrec\n    dataset = dataset.with_options(opciones) # usa la data en cualquier orden\n    dataset = dataset.map(read_tfrecord, num_parallel_calls=AUTOTUNE) # realizar en paralelo\n    return dataset","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:16:28.713575Z","iopub.execute_input":"2021-07-06T03:16:28.714127Z","iopub.status.idle":"2021-07-06T03:16:28.719040Z","shell.execute_reply.started":"2021-07-06T03:16:28.714071Z","shell.execute_reply":"2021-07-06T03:16:28.718271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds_dummy = load_dataset(TRAINING_FILENAMES)\nprint(ds_dummy)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:16:43.687782Z","iopub.execute_input":"2021-07-06T03:16:43.688147Z","iopub.status.idle":"2021-07-06T03:16:43.979372Z","shell.execute_reply.started":"2021-07-06T03:16:43.688093Z","shell.execute_reply":"2021-07-06T03:16:43.978359Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for (image, label) in ds_dummy.take(1):\n    print(image, label)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:17:06.515584Z","iopub.execute_input":"2021-07-06T03:17:06.516273Z","iopub.status.idle":"2021-07-06T03:17:21.687103Z","shell.execute_reply.started":"2021-07-06T03:17:06.516215Z","shell.execute_reply":"2021-07-06T03:17:21.686074Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Obtener el dataset procesado","metadata":{}},{"cell_type":"markdown","source":"### Data augmentation (flip)","metadata":{}},{"cell_type":"code","source":"def augmentation_pipeline(image, label):\n    image = tf.image.random_flip_left_right(image)\n    image = tf.image.random_flip_up_down(image)\n    image = tf.image.resize(image, IMAGE_RESIZE)\n    return image, label","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:22:14.881487Z","iopub.execute_input":"2021-07-06T03:22:14.881950Z","iopub.status.idle":"2021-07-06T03:22:14.887210Z","shell.execute_reply.started":"2021-07-06T03:22:14.881897Z","shell.execute_reply":"2021-07-06T03:22:14.886213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def valid_test_map(image, label):\n    image = tf.image.resize(image, IMAGE_RESIZE)\n    return image, label","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:22:20.240926Z","iopub.execute_input":"2021-07-06T03:22:20.241432Z","iopub.status.idle":"2021-07-06T03:22:20.245853Z","shell.execute_reply.started":"2021-07-06T03:22:20.241401Z","shell.execute_reply":"2021-07-06T03:22:20.244895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Dataset de entrenamiento, con augmentation, repeat, shuffle, batch","metadata":{}},{"cell_type":"markdown","source":"<a href=\"https://ibb.co/DzJSN7C\"><img src=\"https://i.ibb.co/sbfMhFw/repeat-shuffle-batch.png\" alt=\"repeat-shuffle-batch\" border=\"0\"></a><br /><a target='_blank' href='https://es.imgbb.com/'>","metadata":{}},{"cell_type":"code","source":"def get_training_dataset():\n    dataset = load_dataset(TRAINING_FILENAMES)\n    dataset = dataset.map(augmentation_pipeline, num_parallel_calls=AUTOTUNE) # se realiza el aumento de datos\n    dataset = dataset.shuffle(buffer_size=NUM_IMG_TRAIN, seed=42) # genera un buffer de tamaño 2048 para consumir la data\n    dataset = dataset.repeat() # repite los elementos del dataset para que no se acabe la memoria\n    dataset = dataset.batch(BATCH_SIZE) # separa el dataset en batches de tamaño BATCH_SIZE, hacerlo después garantiza\n    # que los batches sean diferentes en cada epoch\n    dataset = dataset.prefetch(AUTOTUNE) # prepara los elementos siguientes mientras se procesan los actuales\n    return dataset","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:30:39.644572Z","iopub.execute_input":"2021-07-06T03:30:39.644928Z","iopub.status.idle":"2021-07-06T03:30:39.650299Z","shell.execute_reply.started":"2021-07-06T03:30:39.644899Z","shell.execute_reply":"2021-07-06T03:30:39.649412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Dataset de validación","metadata":{}},{"cell_type":"code","source":"def get_validation_test_dataset(VAL_OR_TEST_FILENAMES):\n    dataset = load_dataset(VAL_OR_TEST_FILENAMES)\n    dataset = dataset.map(valid_test_map, num_parallel_calls=AUTOTUNE)\n    dataset = dataset.batch(BATCH_SIZE)\n    dataset = dataset.cache()  # almacena data en memoria para reducir algunas operaciones\n    dataset = dataset.prefetch(AUTOTUNE) # asegura que haya un batch de data listo antes\n    return dataset","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:31:22.732048Z","iopub.execute_input":"2021-07-06T03:31:22.732436Z","iopub.status.idle":"2021-07-06T03:31:22.737910Z","shell.execute_reply.started":"2021-07-06T03:31:22.732405Z","shell.execute_reply":"2021-07-06T03:31:22.736783Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = get_training_dataset()\nvalid_dataset = get_validation_test_dataset(VALID_FILENAMES)\ntest_dataset = get_validation_test_dataset(TEST_FILENAMES)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:32:16.131103Z","iopub.execute_input":"2021-07-06T03:32:16.131542Z","iopub.status.idle":"2021-07-06T03:32:16.350312Z","shell.execute_reply.started":"2021-07-06T03:32:16.131511Z","shell.execute_reply":"2021-07-06T03:32:16.349338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Construcción del modelo\n\n<img src=\"https://www.researchgate.net/publication/336874848/figure/fig1/AS:819325225144320@1572353764073/Illustrations-of-transfer-learning-a-neural-network-is-pretrained-on-ImageNet-and.png\">\n\n<img src=\"https://1.bp.blogspot.com/-M8UvZJWNW4E/WsKk-tbzp8I/AAAAAAAAChw/OqxBVPbDygMIQWGug4ZnHNDvuyK5FBMcQCLcBGAs/s640/image5.png\">","metadata":{}},{"cell_type":"markdown","source":"<a href=\"https://ibb.co/tzdCkyJ\"><img src=\"https://i.ibb.co/Nr4YQwy/depthwise.jpg\" alt=\"depthwise\" border=\"0\"></a>","metadata":{}},{"cell_type":"markdown","source":"### Definir un bias inicial","metadata":{}},{"cell_type":"markdown","source":"$ p_{maligno} = \\frac{1}{1+\\exp{(-(w\\cdot x+b))}} $\n\nConsiderando una primera suposición, sin entradas $x$: </br>\n\n$ p_{maligno} = \\frac{maligno}{total} = \\frac{1}{1+\\exp{(-(b))}} $ </br>\n\nDespejando se obtiene:","metadata":{}},{"cell_type":"code","source":"initial_bias = np.log([maligno/benigno])\ninitial_bias","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:46:28.034854Z","iopub.execute_input":"2021-07-06T03:46:28.035241Z","iopub.status.idle":"2021-07-06T03:46:28.042761Z","shell.execute_reply.started":"2021-07-06T03:46:28.035206Z","shell.execute_reply":"2021-07-06T03:46:28.041734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_model(output_bias, metrics = None):    \n    output_bias = tf.keras.initializers.Constant(output_bias)\n        \n    base_model = tf.keras.applications.MobileNetV2(input_shape=(*IMAGE_RESIZE, 3),\n                                                include_top=False,\n                                                weights='imagenet')\n    \n    base_model.trainable = False # fija los parámetros de la red\n    \n    model = tf.keras.Sequential([\n        base_model,\n        tf.keras.layers.GlobalAveragePooling2D(),\n        tf.keras.layers.Dense(8, activation='relu'),\n        tf.keras.layers.Dense(1, activation='sigmoid',\n                              bias_initializer=output_bias)\n    ])\n    \n    model.compile(optimizer='adam',\n                  loss='binary_crossentropy',\n                  metrics=metrics)\n    \n    return model","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:57:01.717004Z","iopub.execute_input":"2021-07-06T03:57:01.717387Z","iopub.status.idle":"2021-07-06T03:57:01.725052Z","shell.execute_reply.started":"2021-07-06T03:57:01.717356Z","shell.execute_reply":"2021-07-06T03:57:01.723750Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"STEPS_PER_EPOCH = NUM_IMG_TRAIN // BATCH_SIZE\nVALID_STEPS = NUM_IMG_VAL // BATCH_SIZE","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:57:12.228873Z","iopub.execute_input":"2021-07-06T03:57:12.229244Z","iopub.status.idle":"2021-07-06T03:57:12.233325Z","shell.execute_reply.started":"2021-07-06T03:57:12.229202Z","shell.execute_reply":"2021-07-06T03:57:12.232379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Asignar mayor peso a los ejemplos menos abundantes","metadata":{}},{"cell_type":"code","source":"peso_0 = total / benigno # ~1\npeso_1 = total / maligno # ~56..\n\nclass_weight = {0: peso_0, 1: peso_1}\n\nprint('Pesos para clase 0: {:.2f}'.format(peso_0))\nprint('Pesos para clase 1: {:.2f}'.format(peso_1))","metadata":{"execution":{"iopub.status.busy":"2021-07-06T03:58:52.359413Z","iopub.execute_input":"2021-07-06T03:58:52.359762Z","iopub.status.idle":"2021-07-06T03:58:52.365724Z","shell.execute_reply.started":"2021-07-06T03:58:52.359733Z","shell.execute_reply":"2021-07-06T03:58:52.364594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Matriz de confusión\n\n<img src=\"https://in2techs.com/wp-content/uploads/2020/09/exampel-2.png\"> </br>\nTasa de verdaderos positivos: $tpr = \\frac{TP}{TP+FN}$\nTasa de falsos positivos: $fpr = \\frac{FP}{FP+TN} $","metadata":{}},{"cell_type":"markdown","source":"## ¿Por qué AUC?\n\n<img src=\"https://glassboxmedicine.files.wordpress.com/2019/02/roc-curve-v2.png\"> </br>\n","metadata":{}},{"cell_type":"code","source":"with strategy.scope(): # llamar al tpu\n    model = make_model(output_bias = initial_bias, metrics=tf.keras.metrics.AUC(name='auc'))","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:07:32.026724Z","iopub.execute_input":"2021-07-06T04:07:32.027175Z","iopub.status.idle":"2021-07-06T04:07:41.605423Z","shell.execute_reply.started":"2021-07-06T04:07:32.027138Z","shell.execute_reply":"2021-07-06T04:07:41.604424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Callbacks para guardar el modelo (mejor métrica)","metadata":{}},{"cell_type":"code","source":"checkpoint_cb = tf.keras.callbacks.ModelCheckpoint(\"melanoma_mobilenetv2.h5\",\n                                                   monitor = 'val_auc',\n                                                   mode = 'max',\n                                                    save_best_only=True)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:07:55.676352Z","iopub.execute_input":"2021-07-06T04:07:55.676730Z","iopub.status.idle":"2021-07-06T04:07:55.681735Z","shell.execute_reply.started":"2021-07-06T04:07:55.676698Z","shell.execute_reply":"2021-07-06T04:07:55.680539Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:08:52.252228Z","iopub.execute_input":"2021-07-06T04:08:52.252646Z","iopub.status.idle":"2021-07-06T04:08:52.275165Z","shell.execute_reply.started":"2021-07-06T04:08:52.252611Z","shell.execute_reply":"2021-07-06T04:08:52.273999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = model.fit(\n    train_dataset, epochs=20,\n    steps_per_epoch=STEPS_PER_EPOCH,\n    validation_data=valid_dataset,\n    validation_steps=VALID_STEPS,\n    callbacks=[checkpoint_cb],\n    class_weight=class_weight,\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:09:10.526975Z","iopub.execute_input":"2021-07-06T04:09:10.527393Z","iopub.status.idle":"2021-07-06T04:20:54.371492Z","shell.execute_reply.started":"2021-07-06T04:09:10.527357Z","shell.execute_reply":"2021-07-06T04:20:54.370479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.evaluate(test_dataset)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:21:17.643711Z","iopub.execute_input":"2021-07-06T04:21:17.644072Z","iopub.status.idle":"2021-07-06T04:21:40.275352Z","shell.execute_reply.started":"2021-07-06T04:21:17.644041Z","shell.execute_reply":"2021-07-06T04:21:40.274390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.evaluate(valid_dataset)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:21:49.364516Z","iopub.execute_input":"2021-07-06T04:21:49.365008Z","iopub.status.idle":"2021-07-06T04:21:50.508550Z","shell.execute_reply.started":"2021-07-06T04:21:49.364976Z","shell.execute_reply":"2021-07-06T04:21:50.507580Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.evaluate(train_dataset, steps = STEPS_PER_EPOCH)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:22:16.113746Z","iopub.execute_input":"2021-07-06T04:22:16.114083Z","iopub.status.idle":"2021-07-06T04:23:08.625717Z","shell.execute_reply.started":"2021-07-06T04:22:16.114055Z","shell.execute_reply":"2021-07-06T04:23:08.624724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y = tf.concat([y for x, y in test_dataset], axis=0)\np_class = model.predict(test_dataset)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:25:11.972790Z","iopub.execute_input":"2021-07-06T04:25:11.973164Z","iopub.status.idle":"2021-07-06T04:25:13.107466Z","shell.execute_reply.started":"2021-07-06T04:25:11.973133Z","shell.execute_reply":"2021-07-06T04:25:13.106515Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = np.where(p_class > 0.5, 1, 0).reshape(-1)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:25:14.944260Z","iopub.execute_input":"2021-07-06T04:25:14.944783Z","iopub.status.idle":"2021-07-06T04:25:14.952027Z","shell.execute_reply.started":"2021-07-06T04:25:14.944738Z","shell.execute_reply":"2021-07-06T04:25:14.951291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y, y_pred","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:25:27.674640Z","iopub.execute_input":"2021-07-06T04:25:27.675235Z","iopub.status.idle":"2021-07-06T04:25:27.683783Z","shell.execute_reply.started":"2021-07-06T04:25:27.675181Z","shell.execute_reply":"2021-07-06T04:25:27.682545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"conf_mat = tf.math.confusion_matrix(y, y_pred, num_classes=2)\nconf_mat","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:25:37.963027Z","iopub.execute_input":"2021-07-06T04:25:37.963437Z","iopub.status.idle":"2021-07-06T04:25:37.984259Z","shell.execute_reply.started":"2021-07-06T04:25:37.963402Z","shell.execute_reply":"2021-07-06T04:25:37.982996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_confusion_matrix(conf_mat, labels):\n  plt.figure(figsize=(10, 8))\n  sns.heatmap(conf_mat, xticklabels=labels, yticklabels=labels, annot =True, fmt= 'd')\n  plt.xlabel('Prediccion')\n  plt.ylabel('Real')\n  plt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:25:41.053680Z","iopub.execute_input":"2021-07-06T04:25:41.054053Z","iopub.status.idle":"2021-07-06T04:25:41.058954Z","shell.execute_reply.started":"2021-07-06T04:25:41.054018Z","shell.execute_reply":"2021-07-06T04:25:41.058289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_confusion_matrix(conf_mat, ('Benigno', 'Maligno'))","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:25:42.702764Z","iopub.execute_input":"2021-07-06T04:25:42.703365Z","iopub.status.idle":"2021-07-06T04:25:42.926985Z","shell.execute_reply.started":"2021-07-06T04:25:42.703312Z","shell.execute_reply":"2021-07-06T04:25:42.925906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"falsos_positivos = 800/(3268+800)\nfalsos_positivos","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:26:38.947837Z","iopub.execute_input":"2021-07-06T04:26:38.948201Z","iopub.status.idle":"2021-07-06T04:26:38.953453Z","shell.execute_reply.started":"2021-07-06T04:26:38.948170Z","shell.execute_reply":"2021-07-06T04:26:38.952631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"verdaderos_pos = 46/(46+28)\nverdaderos_pos","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:27:12.514871Z","iopub.execute_input":"2021-07-06T04:27:12.515253Z","iopub.status.idle":"2021-07-06T04:27:12.521023Z","shell.execute_reply.started":"2021-07-06T04:27:12.515219Z","shell.execute_reply":"2021-07-06T04:27:12.520168Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_auc = history.history['auc']\nval_auc = history.history['val_auc']\nloss = history.history['loss']\nval_loss = history.history['val_loss']\n\nepochs = range(len(train_auc))\n\n#Plotear el auc  de training y validation\nplt.figure()\nplt.plot(epochs, train_auc)\nplt.plot(epochs, val_auc)\nplt.title('AUC de entrenamiento y validation')\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:27:44.043572Z","iopub.execute_input":"2021-07-06T04:27:44.043948Z","iopub.status.idle":"2021-07-06T04:27:44.199570Z","shell.execute_reply.started":"2021-07-06T04:27:44.043913Z","shell.execute_reply":"2021-07-06T04:27:44.198348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fpr, tpr, thresholds = roc_curve(y, p_class)\nauc_test = auc(fpr, tpr)","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:27:54.138500Z","iopub.execute_input":"2021-07-06T04:27:54.138864Z","iopub.status.idle":"2021-07-06T04:27:54.152256Z","shell.execute_reply.started":"2021-07-06T04:27:54.138832Z","shell.execute_reply":"2021-07-06T04:27:54.151333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot([0, 1], [0, 1], 'k--')\nplt.plot(fpr, tpr, label='area = {:.3f}'.format(auc_test))\nplt.xlabel('Tasa de verdaderos positivos')\nplt.ylabel('Tasa de falsos positivos')\nplt.title('ROC curve')\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:27:55.953243Z","iopub.execute_input":"2021-07-06T04:27:55.953886Z","iopub.status.idle":"2021-07-06T04:27:56.115032Z","shell.execute_reply.started":"2021-07-06T04:27:55.953850Z","shell.execute_reply":"2021-07-06T04:27:56.113996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls /kaggle/working","metadata":{"execution":{"iopub.status.busy":"2021-07-06T04:28:08.033804Z","iopub.execute_input":"2021-07-06T04:28:08.034175Z","iopub.status.idle":"2021-07-06T04:28:08.756520Z","shell.execute_reply.started":"2021-07-06T04:28:08.034146Z","shell.execute_reply":"2021-07-06T04:28:08.755324Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}