{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","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":"none","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"},{"sourceId":9375582,"sourceType":"datasetVersion","datasetId":5686930}],"dockerImageVersionId":30761,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-09-12T13:48:42.922704Z","iopub.execute_input":"2024-09-12T13:48:42.923137Z","iopub.status.idle":"2024-09-12T13:48:43.333165Z","shell.execute_reply.started":"2024-09-12T13:48:42.923093Z","shell.execute_reply":"2024-09-12T13:48:43.332079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os              # Permite interactuar con el sistema de archivos.\nimport numpy as np      # Trabaja con arrays y operaciones matemáticas eficientes.\nimport pandas as pd     # Maneja y analiza grandes conjuntos de datos estructurados.\nimport random as rnd    # Genera números aleatorios para simulaciones o muestreo.\nimport matplotlib.pyplot as plt  # Crea gráficos y visualizaciones de datos.\n%matplotlib inline      \n# Muestra gráficos dentro de notebooks.\n\nfrom sklearn.model_selection import train_test_split  # Divide datos en conjuntos de entrenamiento y prueba.\n\nimport keras                          # Biblioteca para construir redes neuronales.\nfrom keras.models import Sequential   # Construye modelos de redes neuronales secuenciales.\nfrom keras.utils import to_categorical  # Convierte etiquetas a formato categórico.\nfrom keras.preprocessing.image import load_img  # Carga imágenes para su procesamiento.\nfrom keras.layers import Flatten, Dense, Dropout  # Define capas de redes neuronales.\nfrom keras.layers import Conv2D, MaxPool2D, BatchNormalization, Activation  # Capas para redes neuronales convolucionales.\n\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator  # Aumenta y prepara imágenes para el entrenamiento.\n\nprint(os.listdir(\"/kaggle/input/dogs-vs-cats\"))  # Muestra los archivos en la carpeta especificada.","metadata":{"execution":{"iopub.status.busy":"2024-09-12T13:53:35.187825Z","iopub.execute_input":"2024-09-12T13:53:35.188415Z","iopub.status.idle":"2024-09-12T13:53:50.223216Z","shell.execute_reply.started":"2024-09-12T13:53:35.188373Z","shell.execute_reply":"2024-09-12T13:53:50.221763Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"FAST_RUN = False  # Opción para entrenar más rápido o más completo (se usa mas tarde).\nIMAGE_WIDTH = 128  # El ancho de cada imagen que vamos a usar.\nIMAGE_HEIGHT = 128  # La altura de cada imagen que vamos a usar.\nIMAGE_CHANNELS = 3  # Indica que las imágenes son a color (3 colores: rojo, verde, azul).\nIMAGE_SIZE = (IMAGE_WIDTH, IMAGE_HEIGHT)  # Establece el tamaño final de las imágenes que usaremos.","metadata":{"execution":{"iopub.status.busy":"2024-09-12T13:54:05.956712Z","iopub.execute_input":"2024-09-12T13:54:05.957174Z","iopub.status.idle":"2024-09-12T13:54:05.963364Z","shell.execute_reply.started":"2024-09-12T13:54:05.957132Z","shell.execute_reply":"2024-09-12T13:54:05.961986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import zipfile  # Sirve para abrir y descomprimir archivos comprimidos (.zip)\n\npath = \"/kaggle/input/dogs-vs-cats\"  # Ubicación de los archivos comprimidos.(es un dataset disponible en kaggle)\nfor zip_file in os.listdir(path)[:2]:  # Recorre los primeros 2 archivos en esa ubicación.\n    zipfile.ZipFile(f\"{path}/{zip_file}\", 'r').extractall(\".\")  # Abre y descomprime los archivos.\n#     print(f\"{path}/{zip_file}\")  # (opcional) Muestra la ruta completa de cada archivo.\n    print(f\"{zip_file} unzipped\")  # Muestra que el archivo ha sido descomprimido.","metadata":{"execution":{"iopub.status.busy":"2024-09-12T13:54:42.364002Z","iopub.execute_input":"2024-09-12T13:54:42.364446Z","iopub.status.idle":"2024-09-12T13:55:01.820464Z","shell.execute_reply.started":"2024-09-12T13:54:42.364409Z","shell.execute_reply":"2024-09-12T13:55:01.819303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images = os.listdir(\"/kaggle/working/train\")  # Lista los nombres de las imágenes en la carpeta \"train\".\nCATEGORIES = []  # Aquí guardaremos las categorías (0 o 1) de cada imagen.\n\nfor image_name in train_images:  # Recorre cada imagen en la carpeta \"train\".\n    class_name = image_name.split('.')[0]  # Toma el nombre antes del punto, por ejemplo: \"cat\" de \"cat.588.jpg\".\n    CATEGORIES.append(0 if class_name == 'cat' else 1)  # Si es \"cat\", asigna 0; si no, asigna 1.\n\ndf = pd.DataFrame({\"train_images\": train_images, \"CATEGORIES\": CATEGORIES})  # Crea una tabla con las imágenes y sus categorías.","metadata":{"execution":{"iopub.status.busy":"2024-09-12T13:55:51.057486Z","iopub.execute_input":"2024-09-12T13:55:51.057961Z","iopub.status.idle":"2024-09-12T13:55:51.097824Z","shell.execute_reply.started":"2024-09-12T13:55:51.057919Z","shell.execute_reply":"2024-09-12T13:55:51.096210Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head() #nos muestra las primeras filas del dataframe categorizado","metadata":{"execution":{"iopub.status.busy":"2024-09-12T13:56:29.075717Z","iopub.execute_input":"2024-09-12T13:56:29.076143Z","iopub.status.idle":"2024-09-12T13:56:29.096139Z","shell.execute_reply.started":"2024-09-12T13:56:29.076105Z","shell.execute_reply":"2024-09-12T13:56:29.094959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.tail()#nos muestra las últimas filas del dataframe","metadata":{"execution":{"iopub.status.busy":"2024-09-12T13:56:54.263859Z","iopub.execute_input":"2024-09-12T13:56:54.264281Z","iopub.status.idle":"2024-09-12T13:56:54.274746Z","shell.execute_reply.started":"2024-09-12T13:56:54.264241Z","shell.execute_reply":"2024-09-12T13:56:54.273406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.describe()","metadata":{"execution":{"iopub.status.busy":"2024-09-12T13:58:08.397088Z","iopub.execute_input":"2024-09-12T13:58:08.397570Z","iopub.status.idle":"2024-09-12T13:58:08.422790Z","shell.execute_reply.started":"2024-09-12T13:58:08.397511Z","shell.execute_reply":"2024-09-12T13:58:08.421631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df[\"CATEGORIES\"].value_counts()","metadata":{"execution":{"iopub.status.busy":"2024-09-12T13:58:17.702689Z","iopub.execute_input":"2024-09-12T13:58:17.703577Z","iopub.status.idle":"2024-09-12T13:58:17.718015Z","shell.execute_reply.started":"2024-09-12T13:58:17.703509Z","shell.execute_reply":"2024-09-12T13:58:17.716833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df[\"CATEGORIES\"].value_counts().plot.bar() #muestra el gráfico\n# Cambiamos las etiquetas del eje x, así sale cats/dogs en lugar de solo 0 y 1\nplt.xticks([0, 1], ['cats (0)', 'dogs (1)'])\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-09-12T13:58:25.983056Z","iopub.execute_input":"2024-09-12T13:58:25.983986Z","iopub.status.idle":"2024-09-12T13:58:26.228946Z","shell.execute_reply.started":"2024-09-12T13:58:25.983933Z","shell.execute_reply":"2024-09-12T13:58:26.227863Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"shapes = []  # Lista para almacenar las dimensiones de cada imagen.\n\nfor image in df[\"train_images\"]:  # Recorre cada imagen en el DataFrame.\n    path = os.path.join(\"/kaggle/working/train\", image)  # Crea la ruta completa para cada imagen.\n    image_array = plt.imread(path)  # Lee la imagen y la convierte a un formato que el programa pueda entender.\n    shapes.append(image_array.shape)  # Guarda las dimensiones (alto, ancho, canales) de la imagen.\n\n# Muestra cuántas imágenes tienen las mismas dimensiones.\nprint(pd.Series(shapes).value_counts())  \n\n# Encuentra el índice de la imagen con la dimensión más pequeña.\nindex = np.argmin(shapes)  \nprint(f\"\\nThe Minimum Dimension is ==> {shapes[index]}\\n\")  # Muestra las dimensiones más pequeñas encontradas.\nprint(\"*El número 3 al final representa los canales (R,G,B)\")","metadata":{"execution":{"iopub.status.busy":"2024-09-12T13:59:24.868536Z","iopub.execute_input":"2024-09-12T13:59:24.869831Z","iopub.status.idle":"2024-09-12T14:00:00.488285Z","shell.execute_reply.started":"2024-09-12T13:59:24.869776Z","shell.execute_reply":"2024-09-12T14:00:00.486830Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample = rnd.choice(train_images)  # Selecciona una imagen al azar de la lista \"train_images\".\nimage = load_img(os.path.join(\"/kaggle/working/train\", sample))  # Carga la imagen seleccionada desde su ubicación.\nprint(type(image))  # Muestra el tipo de objeto de la imagen (normalmente, será una imagen en formato PIL).\n\nplt.imshow(image)  # Muestra la imagen seleccionada en pantalla.\nplt.axis(\"off\")  # Oculta los ejes de la imagen (no queremos ver números alrededor).\nplt.show()  # Muestra la imagen final sin ejes.","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:00:22.623831Z","iopub.execute_input":"2024-09-12T14:00:22.624259Z","iopub.status.idle":"2024-09-12T14:00:22.853534Z","shell.execute_reply.started":"2024-09-12T14:00:22.624221Z","shell.execute_reply":"2024-09-12T14:00:22.852313Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df[\"CATEGORIES\"] = df[\"CATEGORIES\"].replace({0: 'cat', 1: 'dog'}) ","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:01:20.432787Z","iopub.execute_input":"2024-09-12T14:01:20.433230Z","iopub.status.idle":"2024-09-12T14:01:20.444389Z","shell.execute_reply.started":"2024-09-12T14:01:20.433191Z","shell.execute_reply":"2024-09-12T14:01:20.442972Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df, valid_df = train_test_split(df, test_size=0.20, random_state=42) \ntrain_df = train_df.reset_index(drop=True)\nvalid_df = valid_df.reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:06:05.917145Z","iopub.execute_input":"2024-09-12T14:06:05.917564Z","iopub.status.idle":"2024-09-12T14:06:05.931997Z","shell.execute_reply.started":"2024-09-12T14:06:05.917512Z","shell.execute_reply":"2024-09-12T14:06:05.930652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['CATEGORIES'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:06:35.554844Z","iopub.execute_input":"2024-09-12T14:06:35.555249Z","iopub.status.idle":"2024-09-12T14:06:35.565853Z","shell.execute_reply.started":"2024-09-12T14:06:35.555214Z","shell.execute_reply":"2024-09-12T14:06:35.564494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['CATEGORIES'].value_counts().plot.bar()","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:06:53.403126Z","iopub.execute_input":"2024-09-12T14:06:53.403561Z","iopub.status.idle":"2024-09-12T14:06:53.615525Z","shell.execute_reply.started":"2024-09-12T14:06:53.403505Z","shell.execute_reply":"2024-09-12T14:06:53.614340Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_df['CATEGORIES'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:07:04.919752Z","iopub.execute_input":"2024-09-12T14:07:04.920179Z","iopub.status.idle":"2024-09-12T14:07:04.930027Z","shell.execute_reply.started":"2024-09-12T14:07:04.920137Z","shell.execute_reply":"2024-09-12T14:07:04.928701Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_df['CATEGORIES'].value_counts().plot.bar()","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:07:14.378630Z","iopub.execute_input":"2024-09-12T14:07:14.379093Z","iopub.status.idle":"2024-09-12T14:07:14.563148Z","shell.execute_reply.started":"2024-09-12T14:07:14.379052Z","shell.execute_reply":"2024-09-12T14:07:14.562025Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"total_train = train_df.shape[0]  # Cuenta el número total de imágenes en el conjunto de entrenamiento.\ntotal_validate = valid_df.shape[0]  # Cuenta el número total de imágenes en el conjunto de validación.\nbatch_size = 15  # Define el número de imágenes que procesamos a la vez durante el entrenamiento.\n\nprint(f'TOTAL TRAIN: {total_train}')\nprint(f'TOTAL VALIDATE: {total_validate}')","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:07:40.663930Z","iopub.execute_input":"2024-09-12T14:07:40.664427Z","iopub.status.idle":"2024-09-12T14:07:40.670908Z","shell.execute_reply.started":"2024-09-12T14:07:40.664386Z","shell.execute_reply":"2024-09-12T14:07:40.669774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:09:24.897314Z","iopub.execute_input":"2024-09-12T14:09:24.897789Z","iopub.status.idle":"2024-09-12T14:09:24.910160Z","shell.execute_reply.started":"2024-09-12T14:09:24.897746Z","shell.execute_reply":"2024-09-12T14:09:24.908846Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(  # Crea un generador que transforma las imágenes de varias maneras.\n    rotation_range=15,  # Gira las imágenes hasta 15 grados al azar.\n    rescale=1./255,  # Normaliza los valores de los píxeles para que estén entre 0 y 1.\n    shear_range=0.1,  # Aplica un efecto de corte o \"cisallamiento\" en las imágenes.\n    zoom_range=0.2,  # Realiza un zoom al azar en las imágenes hasta un 20%.\n    horizontal_flip=True,  # Gira las imágenes horizontalmente (de izquierda a derecha).\n    width_shift_range=0.1,  # Desplaza las imágenes horizontalmente hasta un 10%.\n    height_shift_range=0.1  # Desplaza las imágenes verticalmente hasta un 10%.\n)\n\ntrain_generator = train_datagen.flow_from_dataframe(  # Genera imágenes modificadas a partir del DataFrame.\n    train_df,  # Usa el conjunto de entrenamiento.\n    \"/kaggle/working/train\",  # Ruta donde están almacenadas las imágenes.\n    x_col='train_images',  # Columna que contiene los nombres de las imágenes.\n    y_col='CATEGORIES',  # Columna que contiene las categorías (gato o perro).\n    target_size=IMAGE_SIZE,  # Tamaño al que se redimensionarán las imágenes.\n    class_mode='categorical',  # Las etiquetas de las imágenes estarán en formato categórico (una para gato, otra para perro).\n    batch_size=batch_size  # Número de imágenes procesadas juntas en cada lote.\n)","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:09:36.945724Z","iopub.execute_input":"2024-09-12T14:09:36.946145Z","iopub.status.idle":"2024-09-12T14:09:37.165581Z","shell.execute_reply.started":"2024-09-12T14:09:36.946110Z","shell.execute_reply":"2024-09-12T14:09:37.164331Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"valid_datagen = ImageDataGenerator(rescale=1./255)  \n# Normaliza los valores de los píxeles de las imágenes de validación, convirtiéndolos en un rango de 0 a 1.\n\nvalid_generator = valid_datagen.flow_from_dataframe(  \n    valid_df,  # Utiliza el conjunto de datos de validación.\n    \"/kaggle/working/train\",  # Ruta donde están almacenadas las imágenes.\n    x_col='train_images',  # Columna que contiene los nombres de las imágenes.\n    y_col='CATEGORIES',  # Columna que contiene las categorías (gato o perro).\n    target_size=IMAGE_SIZE,  # Redimensiona las imágenes al tamaño especificado.\n    class_mode='categorical',  # Las etiquetas están en formato categórico (gato/perro).\n    batch_size=batch_size  # Procesa las imágenes en lotes pequeños, de tamaño batch_size.\n)","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:09:48.661023Z","iopub.execute_input":"2024-09-12T14:09:48.661462Z","iopub.status.idle":"2024-09-12T14:09:48.726764Z","shell.execute_reply.started":"2024-09-12T14:09:48.661416Z","shell.execute_reply":"2024-09-12T14:09:48.725482Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"example_df = train_df.sample(n=1)  # Toma una muestra aleatoria de 1 imagen del conjunto de entrenamiento.\nprint(example_df, \"\\n\")  # Muestra la información de esa imagen seleccionada.\n\nexample_df = example_df.reset_index(drop=True)  # Reinicia los índices de la muestra seleccionada para que empiece desde 0.\nprint(example_df, \"\\n\")  # Muestra la información con el nuevo índice.\n\nexample_generator = train_datagen.flow_from_dataframe(\n    example_df,  # Utiliza la muestra de 1 imagen que seleccionamos.\n    \"/kaggle/working/train\",  # Ruta donde están las imágenes.\n    x_col='train_images',  # Columna con los nombres de las imágenes.\n    y_col='CATEGORIES',  # Columna con las categorías (gato o perro).\n    target_size=IMAGE_SIZE,  # Redimensiona la imagen al tamaño deseado.\n    class_mode='categorical'  # Define que las categorías son en formato categórico (gato o perro).\n)","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:10:06.505246Z","iopub.execute_input":"2024-09-12T14:10:06.506610Z","iopub.status.idle":"2024-09-12T14:10:06.523707Z","shell.execute_reply.started":"2024-09-12T14:10:06.506539Z","shell.execute_reply":"2024-09-12T14:10:06.522458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(12, 12))  # Crea una figura de tamaño 12x12 para mostrar varias imágenes.\nfor i in range(0, 15):  # Repite el proceso 15 veces para mostrar 15 imágenes.\n    plt.subplot(5, 3, i+1)  # Divide el área de la figura en una cuadrícula de 5 filas y 3 columnas.\n    for X_batch, Y_batch in example_generator:  # Obtiene un lote de imágenes y sus categorías del generador.\n        image = X_batch[0]  # Toma la primera imagen del lote.\n        plt.imshow(image)  # Muestra la imagen.\n        plt.axis('off')  # Oculta los ejes alrededor de la imagen.\n        break  # Sale del bucle después de mostrar la imagen para evitar mostrar el mismo lote varias veces.\nplt.tight_layout()  # Ajusta el diseño para que las imágenes no se superpongan.\nplt.show()  # Muestra la figura con todas las imágenes.","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:11:05.970760Z","iopub.execute_input":"2024-09-12T14:11:05.971213Z","iopub.status.idle":"2024-09-12T14:11:07.186068Z","shell.execute_reply.started":"2024-09-12T14:11:05.971174Z","shell.execute_reply":"2024-09-12T14:11:07.184401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Sequential([  # Creamos un modelo secuencial, donde las capas se apilan una tras otra.\n    Conv2D(32, (3, 3), activation='relu', input_shape=(IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS)),  \n    # Capa convolucional que aplica 32 filtros de tamaño 3x3 a las imágenes. Ayuda a detectar patrones como bordes.\n    \n    MaxPool2D(pool_size=(4,4)),  # Reduce el tamaño de la imagen, manteniendo solo la información importante.\n    Dropout(rate=0.25),  # Apaga aleatoriamente el 25% de las neuronas para evitar sobreajuste.\n\n    Conv2D(64, (3, 3), activation='relu'),  # Segunda capa convolucional con 64 filtros.\n    BatchNormalization(),  # Normaliza los valores de salida para mejorar la estabilidad y acelerar el entrenamiento.\n    MaxPool2D(pool_size=(4,4)),  # Segunda reducción del tamaño de la imagen.\n    Dropout(rate=0.25),  # Apaga el 25% de las neuronas.\n\n    Conv2D(128, (3, 3), activation='relu'),  # Tercera capa convolucional con 128 filtros.\n    BatchNormalization(),  # Normaliza las salidas.\n    MaxPool2D(pool_size=(4,4)),  # Tercera reducción de tamaño de la imagen.\n    Dropout(rate=0.25),  # Apaga el 25% de las neuronas.\n\n    Flatten(),  # Aplana la imagen en un vector para que pueda ser usada en las capas densas.\n\n    Dense(512, activation='relu'),  # Capa densa totalmente conectada con 512 neuronas.\n    Dropout(rate=0.5),  # Apaga el 50% de las neuronas para evitar sobreajuste.\n\n    Dense(2, activation='softmax')  # Capa de salida con 2 neuronas (gato o perro) usando softmax para clasificación.\n])\n\n# Compilación del modelo\nmodel.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])  \n# Configura el modelo con la función de pérdida, el optimizador y la métrica que mediremos (exactitud).\n\n# Resumen del Modelo\nmodel.summary()  # Muestra un resumen de las capas y parámetros del modelo.","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:11:35.561923Z","iopub.execute_input":"2024-09-12T14:11:35.562334Z","iopub.status.idle":"2024-09-12T14:11:35.747410Z","shell.execute_reply.started":"2024-09-12T14:11:35.562297Z","shell.execute_reply":"2024-09-12T14:11:35.746401Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.callbacks import EarlyStopping\nfrom keras.callbacks import ReduceLROnPlateau","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:16:23.124535Z","iopub.execute_input":"2024-09-12T14:16:23.125032Z","iopub.status.idle":"2024-09-12T14:16:23.132229Z","shell.execute_reply.started":"2024-09-12T14:16:23.124989Z","shell.execute_reply":"2024-09-12T14:16:23.130586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"earlystop = EarlyStopping(patience=5)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"earlystop = EarlyStopping(patience=5)\nlearning_rate_reduction = ReduceLROnPlateau(monitor='val_acc',  # Monitorea la exactitud en los datos de validación.\n                                            patience=2,  # Si no mejora en 2 épocas, reduce la tasa de aprendizaje.\n                                            verbose=1,  # Muestra mensajes sobre el cambio de la tasa de aprendizaje.\n                                            factor=0.5,  # Reduce la tasa de aprendizaje a la mitad.\n                                            min_lr=0.00001)  # Define la tasa de aprendizaje mínima.\n\ncallbacks = [earlystop, learning_rate_reduction]  # Lista de funciones especiales que ejecutamos durante el entrenamiento.","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:18:25.745410Z","iopub.execute_input":"2024-09-12T14:18:25.746593Z","iopub.status.idle":"2024-09-12T14:18:25.752891Z","shell.execute_reply.started":"2024-09-12T14:18:25.746515Z","shell.execute_reply":"2024-09-12T14:18:25.751406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"epochs = 3 if FAST_RUN else 10  # Si FAST_RUN es True, entrenamos por 3 épocas; de lo contrario, 10 épocas.\n\nhistory = model.fit(train_generator,  # Utiliza el conjunto de imágenes de entrenamiento.\n                    epochs=epochs,  # Entrena por 3 o 10 repeticiones, según FAST_RUN.\n                    validation_data=valid_generator,  # Usa el conjunto de validación para evaluar el rendimiento.\n#                     validation_steps=total_validate//batch_size, # Opcional: número de pasos en validación.\n#                     steps_per_epoch=total_train//batch_size,     # Opcional: número de pasos por época.\n                    callbacks=callbacks)  # Usa las funciones especiales (como reducción de tasa de aprendizaje y early stopping).","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:18:39.163496Z","iopub.execute_input":"2024-09-12T14:18:39.164532Z","iopub.status.idle":"2024-09-12T14:49:36.419304Z","shell.execute_reply.started":"2024-09-12T14:18:39.164484Z","shell.execute_reply":"2024-09-12T14:49:36.418179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"accuracy = history.history[\"accuracy\"]  # Guarda los valores de precisión del entrenamiento.\nval_accuracy = history.history[\"val_accuracy\"]  # Guarda los valores de precisión en los datos de validación.\n\nloss = history.history[\"loss\"]  # Guarda los valores de pérdida del entrenamiento.\nval_loss = history.history[\"val_loss\"]  # Guarda los valores de pérdida en los datos de validación.\n\nepochs = range(len(accuracy))  # Crea una lista de números de épocas (ciclos de entrenamiento).\n\nplt.figure(figsize=(12,6))  # Crea un gráfico de tamaño 12x6 pulgadas.\n\nplt.subplot(1,2,1)  # Crea el primer gráfico en una cuadrícula de 1 fila y 2 columnas.\nplt.plot(epochs, accuracy, 'bo', label=\"Train_Acc\")  # Grafica la precisión de entrenamiento.\nplt.plot(epochs, val_accuracy, 'r', label=\"val_Acc\")  # Grafica la precisión de validación.\nplt.legend(loc='best', shadow=True)  # Muestra una leyenda explicando qué es cada línea.\n\nplt.subplot(1,2,2)  # Crea el segundo gráfico.\nplt.plot(epochs, loss, 'bo', label=\"Train_Loss\")  # Grafica la pérdida de entrenamiento.\nplt.plot(epochs, val_loss, 'r', label=\"val_Loss\")  # Grafica la pérdida de validación.\nplt.legend(loc='best', shadow=True)  # Muestra una leyenda explicando qué es cada línea.\n\nplt.show()  # Muestra los dos gráficos.","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:57:25.463033Z","iopub.execute_input":"2024-09-12T14:57:25.463916Z","iopub.status.idle":"2024-09-12T14:57:25.840073Z","shell.execute_reply.started":"2024-09-12T14:57:25.463871Z","shell.execute_reply":"2024-09-12T14:57:25.839005Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_file_names = os.listdir(\"/kaggle/working/test1\")  # Lista los nombres de los archivos de prueba en la carpeta \"test1\".\ntest_df = pd.DataFrame({'file_name': test_file_names})  # Crea un DataFrame con los nombres de los archivos de prueba.\n\ntotal_testing = test_df.shape[0]  # Cuenta el número total de archivos de prueba.","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:57:37.891066Z","iopub.execute_input":"2024-09-12T14:57:37.891475Z","iopub.status.idle":"2024-09-12T14:57:37.905970Z","shell.execute_reply.started":"2024-09-12T14:57:37.891439Z","shell.execute_reply":"2024-09-12T14:57:37.904493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_gen = ImageDataGenerator(rescale=1./255)  # Normaliza los valores de los píxeles de las imágenes de prueba.\n\ntest_generator = test_gen.flow_from_dataframe(\n    test_df,  # Utiliza el DataFrame que contiene los nombres de los archivos de prueba.\n    \"/kaggle/working/test1\",  # Ruta donde están las imágenes de prueba.\n    x_col='file_name',  # Columna que contiene los nombres de las imágenes.\n    y_col=None,  # No tenemos etiquetas (categorías) porque son imágenes para probar.\n    class_mode=None,  # No se necesitan etiquetas ya que solo queremos hacer predicciones.\n    target_size=IMAGE_SIZE,  # Redimensiona las imágenes al tamaño deseado.\n    batch_size=batch_size,  # Procesa las imágenes en lotes pequeños.\n    shuffle=False  # No mezclamos las imágenes para que las predicciones sigan el mismo orden que los nombres.\n)","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:57:46.900696Z","iopub.execute_input":"2024-09-12T14:57:46.901119Z","iopub.status.idle":"2024-09-12T14:57:47.017433Z","shell.execute_reply.started":"2024-09-12T14:57:46.901082Z","shell.execute_reply":"2024-09-12T14:57:47.016412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = model.predict(test_generator)  # Utiliza el modelo entrenado para hacer predicciones en las imágenes de prueba.","metadata":{"execution":{"iopub.status.busy":"2024-09-12T14:58:00.541724Z","iopub.execute_input":"2024-09-12T14:58:00.542164Z","iopub.status.idle":"2024-09-12T14:58:29.377667Z","shell.execute_reply.started":"2024-09-12T14:58:00.542129Z","shell.execute_reply":"2024-09-12T14:58:29.376387Z"},"trusted":true},"execution_count":null,"outputs":[]}]}