{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":11848,"databundleVersionId":862157,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# HCD con TensorFlow y Hugging Face","metadata":{}},{"cell_type":"code","source":"# Todo lo que requiera importar\nimport os\nimport pandas as pd\nimport tensorflow as tf\nimport matplotlib.pyplot as plt\n\nfrom PIL import Image\nfrom tqdm import tqdm\nfrom tensorflow.keras.utils import image_dataset_from_directory\nfrom tensorflow.keras import layers, models","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-04T00:09:25.877650Z","iopub.execute_input":"2024-12-04T00:09:25.878243Z","iopub.status.idle":"2024-12-04T00:09:25.883361Z","shell.execute_reply.started":"2024-12-04T00:09:25.878209Z","shell.execute_reply":"2024-12-04T00:09:25.882419Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Función para graficar la historia del entrenamiento\ndef plot_history(history):\n  train = history.history['roc_auc']\n  val = history.history['val_roc_auc']\n  epocas = range(len(train))\n  plt.plot(epocas, train, 'bo', label='Train')\n  plt.plot(epocas, val, 'b', label='Val')\n  plt.title('ROC_AUC vs. epochs')\n  plt.legend(loc=0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-04T00:09:28.761339Z","iopub.execute_input":"2024-12-04T00:09:28.761694Z","iopub.status.idle":"2024-12-04T00:09:28.766745Z","shell.execute_reply.started":"2024-12-04T00:09:28.761666Z","shell.execute_reply":"2024-12-04T00:09:28.765860Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Lectura de datos","metadata":{}},{"cell_type":"code","source":"# Las constantes que necesito\nBATCH_SIZE = 32\nIMAGE_SIZE = 96\n# Directorios con los datos\nINPUT_DIR = '/kaggle/input'\ndf_labels = pd.read_csv(os.path.join(INPUT_DIR, 'train_labels.csv'))\n\n# Ordeno por 'id', para que me funcione image_dataset_from_directory\ndf_labels = df_labels.sort_values(by='id')\ny = df_labels['label'].values.tolist()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-04T00:09:32.661770Z","iopub.execute_input":"2024-12-04T00:09:32.662098Z","iopub.status.idle":"2024-12-04T00:09:33.292736Z","shell.execute_reply.started":"2024-12-04T00:09:32.662070Z","shell.execute_reply":"2024-12-04T00:09:33.291758Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# image_dataset_from_directory no acepta .TIF\ndef tif2jpg(tif_folder, jpg_folder):\n    tif_files = [f for f in os.listdir(tif_folder) if f.endswith('.tif')]\n    n_files = len(tif_files)\n    \n    for filename in tqdm(tif_files, total=n_files, desc='Converting images'):\n        tif_path = os.path.join(tif_folder, filename)\n        jpg_path = os.path.join(jpg_folder, filename[:-4] + '.jpg')\n        try:\n            img = Image.open(tif_path)\n            img.save(jpg_path)\n        except Exception as e:\n            print(f'Error converting {tif_path}:{e}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-04T00:19:50.837448Z","iopub.execute_input":"2024-12-04T00:19:50.837792Z","iopub.status.idle":"2024-12-04T00:19:50.843505Z","shell.execute_reply.started":"2024-12-04T00:19:50.837766Z","shell.execute_reply":"2024-12-04T00:19:50.842593Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TRAIN_DIR = '/kaggle/working/train_jpg'\nos.mkdir(TRAIN_DIR)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-04T00:19:53.953176Z","iopub.execute_input":"2024-12-04T00:19:53.954101Z","iopub.status.idle":"2024-12-04T00:19:53.958411Z","shell.execute_reply.started":"2024-12-04T00:19:53.954041Z","shell.execute_reply":"2024-12-04T00:19:53.957600Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Convierto las imágenes de train a JPG\ntif2jpg(INPUT_DIR + '/train', TRAIN_DIR)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-04T00:19:58.007366Z","iopub.execute_input":"2024-12-04T00:19:58.008101Z","iopub.status.idle":"2024-12-04T00:47:23.171702Z","shell.execute_reply.started":"2024-12-04T00:19:58.008068Z","shell.execute_reply":"2024-12-04T00:47:23.170851Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Ahora sí podemos usar image_dataset_from_directory\ntrain_ds, val_ds = image_dataset_from_directory(\n    TRAIN_DIR,\n    labels=y,\n    label_mode='int',\n    batch_size=BATCH_SIZE,\n    image_size=(IMAGE_SIZE, IMAGE_SIZE),\n    shuffle=True,\n    seed=42,\n    validation_split=0.1,\n    subset='both'\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-04T00:47:23.173113Z","iopub.execute_input":"2024-12-04T00:47:23.173377Z","iopub.status.idle":"2024-12-04T00:47:31.826495Z","shell.execute_reply.started":"2024-12-04T00:47:23.173352Z","shell.execute_reply":"2024-12-04T00:47:31.825826Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Modelo 1: CNN propia","metadata":{}},{"cell_type":"code","source":"# Arquitectura CNN propia\ncnn1 = models.Sequential([\n    layers.Input(shape=(IMAGE_SIZE, IMAGE_SIZE, 3)),\n    layers.Rescaling(1./255),\n    \n    layers.Conv2D(32, (3,3), activation='relu'),\n    layers.MaxPooling2D((2, 2)),\n    \n    layers.Conv2D(64, (3, 3), activation='relu'),\n    layers.MaxPooling2D((2, 2)),\n    \n    layers.Conv2D(128, (3, 3), activation='relu'),\n    layers.MaxPooling2D((2, 2)),\n\n    layers.Conv2D(128, (3, 3), activation='relu'),\n    layers.MaxPooling2D((2, 2)),\n    \n    layers.Flatten(),\n    layers.Dropout(0.5),\n    layers.Dense(512, activation='relu'),\n    layers.Dense(1, activation='sigmoid')  # Binary classification output\n])\n\ncnn1.compile(\n    optimizer='adam',\n    loss='binary_crossentropy',\n    metrics=[tf.keras.metrics.AUC(name='roc_auc')]\n)\n\ncnn1.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-04T00:59:37.660359Z","iopub.execute_input":"2024-12-04T00:59:37.660738Z","iopub.status.idle":"2024-12-04T00:59:37.789981Z","shell.execute_reply.started":"2024-12-04T00:59:37.660704Z","shell.execute_reply":"2024-12-04T00:59:37.789334Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = cnn1.fit(\n    train_ds,\n    validation_data=val_ds,\n    epochs=15\n)\n\ncnn1.save('cnn1.keras')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-04T01:36:49.785596Z","iopub.execute_input":"2024-12-04T01:36:49.786419Z","iopub.status.idle":"2024-12-04T01:47:16.719255Z","shell.execute_reply.started":"2024-12-04T01:36:49.786373Z","shell.execute_reply":"2024-12-04T01:47:16.718256Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_history(history)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-04T01:47:16.720857Z","iopub.execute_input":"2024-12-04T01:47:16.721138Z","iopub.status.idle":"2024-12-04T01:47:16.923611Z","shell.execute_reply.started":"2024-12-04T01:47:16.721111Z","shell.execute_reply":"2024-12-04T01:47:16.922805Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Modelo 2: CNN pre-entrenada TensorFlow\nhttps://keras.io/guides/transfer_learning/","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.applications import ResNet50V2\n\nresnet = ResNet50V2(include_top=False, weights='imagenet',\n                    input_shape=(IMAGE_SIZE, IMAGE_SIZE, 3))\nresnet.trainable = False\n\ncnn2 = models.Sequential([\n    layers.Input(shape=(IMAGE_SIZE, IMAGE_SIZE, 3)),\n    layers.Rescaling(1./255),\n\n    resnet,\n\n    layers.GlobalAveragePooling2D(),\n    layers.Dropout(0.5),\n    layers.Dense(512, activation='relu'),\n    layers.Dense(1, activation='sigmoid')  # Binary classification output\n])\n\ncnn2.compile(\n    optimizer='adam',\n    loss='binary_crossentropy',\n    metrics=[tf.keras.metrics.AUC(name='roc_auc')]\n)\n\ncnn2.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T09:00:47.327450Z","iopub.execute_input":"2024-12-03T09:00:47.328217Z","iopub.status.idle":"2024-12-03T09:00:48.337576Z","shell.execute_reply.started":"2024-12-03T09:00:47.328170Z","shell.execute_reply":"2024-12-03T09:00:48.336599Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = cnn2.fit(\n    train_ds,\n    validation_data=val_ds,\n    epochs=15\n)\n\ncnn2.save('cnn2.keras')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T08:02:23.131690Z","iopub.execute_input":"2024-12-03T08:02:23.132069Z","iopub.status.idle":"2024-12-03T08:28:06.059648Z","shell.execute_reply.started":"2024-12-03T08:02:23.132036Z","shell.execute_reply":"2024-12-03T08:28:06.058671Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_history(history)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T08:28:06.061463Z","iopub.execute_input":"2024-12-03T08:28:06.061761Z","iopub.status.idle":"2024-12-03T08:28:06.345305Z","shell.execute_reply.started":"2024-12-03T08:28:06.061733Z","shell.execute_reply":"2024-12-03T08:28:06.344388Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Ahora que ya se entrenó con las nuevas salidas, se puede hacer el fine-tuning. Hay que tener cuidado con las capas de BatchNormalization.","metadata":{}},{"cell_type":"code","source":"# Opcional: importar el modelo ya entrenado\ncnn2 = models.load_model('cnn2.keras')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T09:00:56.924663Z","iopub.execute_input":"2024-12-03T09:00:56.925608Z","iopub.status.idle":"2024-12-03T09:01:04.107625Z","shell.execute_reply.started":"2024-12-03T09:00:56.925573Z","shell.execute_reply":"2024-12-03T09:01:04.106597Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Ahora que ya se entrenó una pasada, se puede entrenar de nuevo incluyendo el modelo pre-entrenado.\nresnet.trainable = True\n# Se vuelve a ejecutar compile para permitir el cambio de entrenamiento\ncnn2.compile(\n    optimizer='adam',\n    loss='binary_crossentropy',\n    metrics=[tf.keras.metrics.AUC(name='roc_auc')]\n)\n# Revisemos cómo quedó\ncnn2.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T09:01:06.406385Z","iopub.execute_input":"2024-12-03T09:01:06.406849Z","iopub.status.idle":"2024-12-03T09:01:06.441141Z","shell.execute_reply.started":"2024-12-03T09:01:06.406817Z","shell.execute_reply":"2024-12-03T09:01:06.440260Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = cnn2.fit(\n    train_ds,\n    validation_data=val_ds,\n    epochs=15\n)\n\ncnn2.save('cnn2_ft.keras')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T09:01:18.074883Z","iopub.execute_input":"2024-12-03T09:01:18.075242Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plot_history(history)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T08:54:18.982903Z","iopub.status.idle":"2024-12-03T08:54:18.983234Z","shell.execute_reply.started":"2024-12-03T08:54:18.983087Z","shell.execute_reply":"2024-12-03T08:54:18.983103Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Modelo 3: CNN HuggingFace","metadata":{}},{"cell_type":"code","source":"!pip install --quiet transformers","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T03:11:30.078521Z","iopub.execute_input":"2024-12-03T03:11:30.079153Z","iopub.status.idle":"2024-12-03T03:11:38.482497Z","shell.execute_reply.started":"2024-12-03T03:11:30.079118Z","shell.execute_reply":"2024-12-03T03:11:38.481297Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load model directly\nfrom transformers import TFAutoModelForImageClassification, AutoConfig, AutoImageProcessor\n\ncheckpoint = 'microsoft/resnet-50'\nconfig = AutoConfig.from_pretrained(checkpoint, num_labels=2, finetuning_task='image-classification')\nprocessor = AutoImageProcessor.from_pretrained(checkpoint)\nmodel = TFAutoModelForImageClassification.from_pretrained(checkpoint, config=config)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-03T03:12:12.706493Z","iopub.execute_input":"2024-12-03T03:12:12.707441Z","iopub.status.idle":"2024-12-03T03:12:21.225680Z","shell.execute_reply.started":"2024-12-03T03:12:12.707399Z","shell.execute_reply":"2024-12-03T03:12:21.224981Z"}},"outputs":[],"execution_count":null}]}