{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":84209,"databundleVersionId":9414711,"sourceType":"competition"}],"dockerImageVersionId":30822,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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","trusted":true,"execution":{"iopub.status.busy":"2025-01-04T20:21:03.828815Z","iopub.execute_input":"2025-01-04T20:21:03.829102Z","iopub.status.idle":"2025-01-04T20:21:11.597145Z","shell.execute_reply.started":"2025-01-04T20:21:03.829080Z","shell.execute_reply":"2025-01-04T20:21:11.596367Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Path del directorio donde se encuentran las imágenes y csv\npath_base_img=\"/kaggle/input/computer-vision-xm/images/kaggle/working/Reorganized_Data/images\"\npath_csv=\"/kaggle/input/computer-vision-xm\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:22.604267Z","iopub.execute_input":"2025-01-05T18:44:22.604606Z","iopub.status.idle":"2025-01-05T18:44:22.608437Z","shell.execute_reply.started":"2025-01-05T18:44:22.604548Z","shell.execute_reply":"2025-01-05T18:44:22.607490Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#CSV de la data de train y test para cargar los datos\nimport os\ntrain_path=os.path.join(path_csv,\"train.csv\")\ntest_path=os.path.join(path_csv,\"test.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:24.372292Z","iopub.execute_input":"2025-01-05T18:44:24.372626Z","iopub.status.idle":"2025-01-05T18:44:24.376491Z","shell.execute_reply.started":"2025-01-05T18:44:24.372599Z","shell.execute_reply":"2025-01-05T18:44:24.375619Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Obtengo los dataframes\nimport pandas as pd\ntrain_df=pd.read_csv(train_path,index_col=0) #index_col los ID's de las imgs\ntest_df=pd.read_csv(test_path,index_col=0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:26.139659Z","iopub.execute_input":"2025-01-05T18:44:26.139940Z","iopub.status.idle":"2025-01-05T18:44:26.152021Z","shell.execute_reply.started":"2025-01-05T18:44:26.139921Z","shell.execute_reply":"2025-01-05T18:44:26.151293Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.head(5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:27.809200Z","iopub.execute_input":"2025-01-05T18:44:27.809494Z","iopub.status.idle":"2025-01-05T18:44:27.816976Z","shell.execute_reply.started":"2025-01-05T18:44:27.809470Z","shell.execute_reply":"2025-01-05T18:44:27.816260Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df[\"Labels\"].value_counts() #Dataset sin desbalance de clases","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:29.287549Z","iopub.execute_input":"2025-01-05T18:44:29.287872Z","iopub.status.idle":"2025-01-05T18:44:29.294176Z","shell.execute_reply.started":"2025-01-05T18:44:29.287849Z","shell.execute_reply":"2025-01-05T18:44:29.293443Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Separo la data de train para luego separar la data de val\nfrom sklearn.model_selection import train_test_split\n\ndf_train,df_val=train_test_split(train_df,test_size=0.2,stratify=train_df[\"Labels\"],random_state=42,shuffle=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:30.725156Z","iopub.execute_input":"2025-01-05T18:44:30.725691Z","iopub.status.idle":"2025-01-05T18:44:30.734082Z","shell.execute_reply.started":"2025-01-05T18:44:30.725657Z","shell.execute_reply":"2025-01-05T18:44:30.733253Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_train.shape,df_val.shape,test_df.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:32.807027Z","iopub.execute_input":"2025-01-05T18:44:32.807310Z","iopub.status.idle":"2025-01-05T18:44:32.812773Z","shell.execute_reply.started":"2025-01-05T18:44:32.807287Z","shell.execute_reply":"2025-01-05T18:44:32.811908Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Clases balanceadas en ambos conjuntos\ndf_train[\"Labels\"].value_counts(),df_val[\"Labels\"].value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:34.543340Z","iopub.execute_input":"2025-01-05T18:44:34.543657Z","iopub.status.idle":"2025-01-05T18:44:34.550533Z","shell.execute_reply.started":"2025-01-05T18:44:34.543633Z","shell.execute_reply":"2025-01-05T18:44:34.549767Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Cambio el tipo de datos de la columna Labels a STR, pues estoy usando class_mode=\"binary\"\ndf_train[\"Labels\"]=df_train[\"Labels\"].astype(\"str\")\ndf_val[\"Labels\"]=df_val[\"Labels\"].astype(\"str\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:35.979211Z","iopub.execute_input":"2025-01-05T18:44:35.979527Z","iopub.status.idle":"2025-01-05T18:44:35.985176Z","shell.execute_reply.started":"2025-01-05T18:44:35.979498Z","shell.execute_reply":"2025-01-05T18:44:35.984307Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_train[\"Labels\"].dtype,df_val[\"Labels\"].dtype","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:37.889327Z","iopub.execute_input":"2025-01-05T18:44:37.889675Z","iopub.status.idle":"2025-01-05T18:44:37.894871Z","shell.execute_reply.started":"2025-01-05T18:44:37.889646Z","shell.execute_reply":"2025-01-05T18:44:37.894149Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Ahora, creo los objetos generadores para cargar los datos y aplicar transformaciones a la data de train (data augmentation)\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\ntrain_gen=ImageDataGenerator(\n    rescale=1/255,\n    rotation_range=30,\n    fill_mode=\"nearest\",\n    zoom_range=0.2,\n    brightness_range=[0.5,1.5],\n    width_shift_range=0.3\n)\n    \nval_gen=ImageDataGenerator(\n    rescale=1/255\n)\n\ntest_gen=ImageDataGenerator(\n    rescale=1/255\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:40.788087Z","iopub.execute_input":"2025-01-05T18:44:40.788369Z","iopub.status.idle":"2025-01-05T18:44:40.792940Z","shell.execute_reply.started":"2025-01-05T18:44:40.788347Z","shell.execute_reply":"2025-01-05T18:44:40.792041Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Obtengo los datos\ntrain_data=train_gen.flow_from_dataframe(\n    dataframe=df_train,\n    directory=path_base_img, #Directorio donde se encuentran las imágenes\n    x_col=\"Images\",\n    y_col=\"Labels\",\n    target_size=(128,128),\n    color_mode=\"rgb\",\n    class_mode=\"binary\",\n    batch_size=20,\n    shuffle=False #Pues ya se realizó el shuffle al realizar el train_test_split\n    \n)\nval_data=val_gen.flow_from_dataframe(\n    dataframe=df_val,\n    directory=path_base_img,\n    x_col=\"Images\",\n    y_col=\"Labels\",\n    target_size=(128,128),\n    color_mode=\"rgb\",\n    class_mode=\"binary\",\n    batch_size=20,\n    shuffle=False\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:45.644470Z","iopub.execute_input":"2025-01-05T18:44:45.644775Z","iopub.status.idle":"2025-01-05T18:44:49.815327Z","shell.execute_reply.started":"2025-01-05T18:44:45.644753Z","shell.execute_reply":"2025-01-05T18:44:49.814651Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Defino las clases, según el dataset\nclases=[\"healthy\",\"diseased\"]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:54.380637Z","iopub.execute_input":"2025-01-05T18:44:54.380939Z","iopub.status.idle":"2025-01-05T18:44:54.384739Z","shell.execute_reply.started":"2025-01-05T18:44:54.380918Z","shell.execute_reply":"2025-01-05T18:44:54.383944Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Realizo el plotteo para algunas imágenes de la validación\nimport matplotlib.pyplot as plt\n\nfor batch,batch_labels in val_data:\n    for i in range(9):\n        plt.subplot(3,3,i+1)\n        plt.xticks([]),plt.yticks([])\n        plt.title(clases[int(batch_labels[i])])\n        plt.imshow(batch[i])\n    break","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:44:56.280455Z","iopub.execute_input":"2025-01-05T18:44:56.280759Z","iopub.status.idle":"2025-01-05T18:44:59.756121Z","shell.execute_reply.started":"2025-01-05T18:44:56.280739Z","shell.execute_reply":"2025-01-05T18:44:59.754808Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Modelo from scratch","metadata":{}},{"cell_type":"code","source":"from tensorflow import keras\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.regularizers import L2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:06:31.718513Z","iopub.execute_input":"2025-01-05T22:06:31.718853Z","iopub.status.idle":"2025-01-05T22:06:31.722643Z","shell.execute_reply.started":"2025-01-05T22:06:31.718825Z","shell.execute_reply":"2025-01-05T22:06:31.721649Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"m_s=keras.Input((128,128,3))\nx0=layers.Conv2D(filters=32,kernel_size=3,activation=\"relu\")(m_s)\nx0=layers.MaxPooling2D(pool_size=(2,2))(x0)\n\n\nx0=layers.Conv2D(filters=64,kernel_size=3,activation=\"relu\")(x0)\nx0=layers.MaxPooling2D(pool_size=(2,2))(x0)\n\n\nx0=layers.Conv2D(filters=128,kernel_size=3,activation=\"relu\")(x0)\nx0=layers.MaxPooling2D(pool_size=(2,2))(x0)\n\n\nx0=layers.Conv2D(filters=256,kernel_size=3,activation=\"relu\")(x0)\nx0=layers.MaxPooling2D(pool_size=(2,2))(x0)\n\n\nx0=layers.GlobalAveragePooling2D()(x0) #GlobalAveragePooling --> 256, 1d vector\nx0=layers.Dense(50,activation=\"relu\")(x0)\nx0=layers.Dropout(0.3)(x0)\nm_o=layers.Dense(1,activation=\"sigmoid\")(x0)\n\nmodelo_scratch=keras.Model(m_s,m_o)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:06:33.102279Z","iopub.execute_input":"2025-01-05T22:06:33.102667Z","iopub.status.idle":"2025-01-05T22:06:33.162676Z","shell.execute_reply.started":"2025-01-05T22:06:33.102541Z","shell.execute_reply":"2025-01-05T22:06:33.162031Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"modelo_scratch.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:06:41.924965Z","iopub.execute_input":"2025-01-05T22:06:41.925272Z","iopub.status.idle":"2025-01-05T22:06:41.945989Z","shell.execute_reply.started":"2025-01-05T22:06:41.925248Z","shell.execute_reply":"2025-01-05T22:06:41.945308Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.callbacks import EarlyStopping\nES_scratch=EarlyStopping(\n    monitor=\"val_loss\",\n    patience=3,\n    restore_best_weights=True #Para que se 'restablezcan' los mejores pesos luego de que el callback para el training\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:08:16.189446Z","iopub.execute_input":"2025-01-05T22:08:16.189775Z","iopub.status.idle":"2025-01-05T22:08:16.193682Z","shell.execute_reply.started":"2025-01-05T22:08:16.189748Z","shell.execute_reply":"2025-01-05T22:08:16.192833Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Compile step\nfrom tensorflow.keras.optimizers import Adam\n\nmodelo_scratch.compile(\n    optimizer=Adam(learning_rate=0.001), #Depende de cómo van los valores en el training, iré cambiando los valores\n    loss=\"binary_crossentropy\", #Pues es clasificación binaria\n    metrics=[\"accuracy\"]\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:08:17.837014Z","iopub.execute_input":"2025-01-05T22:08:17.837266Z","iopub.status.idle":"2025-01-05T22:08:17.844972Z","shell.execute_reply.started":"2025-01-05T22:08:17.837245Z","shell.execute_reply":"2025-01-05T22:08:17.844278Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Training step\nhistory_scratch=modelo_scratch.fit(\n    train_data,\n    validation_data=val_data,\n    epochs=10,\n    callbacks=[ES_scratch]\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:08:21.430433Z","iopub.execute_input":"2025-01-05T22:08:21.430729Z","iopub.status.idle":"2025-01-05T23:09:09.528372Z","shell.execute_reply.started":"2025-01-05T22:08:21.430706Z","shell.execute_reply":"2025-01-05T23:09:09.527651Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\naccuracy_sc=history_scratch.history[\"accuracy\"]\nval_accuracy_sc=history_scratch.history[\"val_accuracy\"]\nepochs=range(1,len(accuracy_sc)+1)\n\nplt.plot(epochs,accuracy_sc,\"red\",label=\"accuracy\")\nplt.plot(epochs,val_accuracy_sc,\"green\",label=\"val_accuracy\")\nplt.xlabel(\"epochs\")\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:19:53.808112Z","iopub.execute_input":"2025-01-05T23:19:53.808444Z","iopub.status.idle":"2025-01-05T23:19:54.036938Z","shell.execute_reply.started":"2025-01-05T23:19:53.808416Z","shell.execute_reply":"2025-01-05T23:19:54.036100Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"loss_sc=history_scratch.history[\"loss\"]\nval_loss_sc=history_scratch.history[\"val_loss\"]\nepochs=range(1,len(loss_sc)+1)\n\nplt.plot(epochs,loss_sc,\"red\",label=\"loss\")\nplt.plot(epochs,val_loss_sc,\"blue\",label=\"val_loss\")\nplt.xlabel(\"epochs\")\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:20:37.752129Z","iopub.execute_input":"2025-01-05T23:20:37.752429Z","iopub.status.idle":"2025-01-05T23:20:37.912838Z","shell.execute_reply.started":"2025-01-05T23:20:37.752404Z","shell.execute_reply":"2025-01-05T23:20:37.912073Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Predicciones\nval_pred_sc=modelo_scratch.predict(val_data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:12:55.130110Z","iopub.execute_input":"2025-01-05T23:12:55.130422Z","iopub.status.idle":"2025-01-05T23:14:09.518951Z","shell.execute_reply.started":"2025-01-05T23:12:55.130398Z","shell.execute_reply":"2025-01-05T23:14:09.518262Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_pred_sc=(val_pred_sc>0.5).astype(\"int32\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:14:16.343485Z","iopub.execute_input":"2025-01-05T23:14:16.343850Z","iopub.status.idle":"2025-01-05T23:14:16.347877Z","shell.execute_reply.started":"2025-01-05T23:14:16.343821Z","shell.execute_reply":"2025-01-05T23:14:16.346927Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_pred_n_sc=val_pred_sc.reshape(val_pred_sc.shape[0],)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:14:35.833389Z","iopub.execute_input":"2025-01-05T23:14:35.833726Z","iopub.status.idle":"2025-01-05T23:14:35.837490Z","shell.execute_reply.started":"2025-01-05T23:14:35.833697Z","shell.execute_reply":"2025-01-05T23:14:35.836474Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_labels_sc=val_data.classes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:14:38.558596Z","iopub.execute_input":"2025-01-05T23:14:38.558876Z","iopub.status.idle":"2025-01-05T23:14:38.562660Z","shell.execute_reply.started":"2025-01-05T23:14:38.558855Z","shell.execute_reply":"2025-01-05T23:14:38.561887Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Matriz de confusión\nfrom sklearn.metrics import confusion_matrix,ConfusionMatrixDisplay,accuracy_score,precision_score\nc_m_s=confusion_matrix(val_labels_sc,val_pred_n_sc)\nc_m_d_s=ConfusionMatrixDisplay(c_m_s)\nc_m_d_s.plot()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:16:18.264309Z","iopub.execute_input":"2025-01-05T23:16:18.264778Z","iopub.status.idle":"2025-01-05T23:16:18.502218Z","shell.execute_reply.started":"2025-01-05T23:16:18.264734Z","shell.execute_reply":"2025-01-05T23:16:18.501490Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Accuracy\nacc_sc=accuracy_score(val_labels_sc,val_pred_n_sc)\nprint(f\"Accuracy: {acc_sc}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:16:47.270175Z","iopub.execute_input":"2025-01-05T23:16:47.270464Z","iopub.status.idle":"2025-01-05T23:16:47.276246Z","shell.execute_reply.started":"2025-01-05T23:16:47.270441Z","shell.execute_reply":"2025-01-05T23:16:47.275499Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Precision score: la clase positiva es el label \"diseased\"\nprecision_sc=precision_score(val_labels_sc,val_pred_n_sc)\nprint(f\"Precision: {precision_sc}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:17:18.558088Z","iopub.execute_input":"2025-01-05T23:17:18.558382Z","iopub.status.idle":"2025-01-05T23:17:18.565292Z","shell.execute_reply.started":"2025-01-05T23:17:18.558349Z","shell.execute_reply":"2025-01-05T23:17:18.564642Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"-------------------","metadata":{}},{"cell_type":"markdown","source":"# Modelo 2: NO Fine-Tuning","metadata":{}},{"cell_type":"code","source":"#Ya que la data fue cargada correctamente, import el modelo preentrenado VGG16\nfrom tensorflow.keras.applications import vgg16\nVGG16=vgg16.VGG16(\n    input_shape=(128,128,3),\n    include_top=False,\n    weights=\"imagenet\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:45:04.340825Z","iopub.execute_input":"2025-01-05T18:45:04.341113Z","iopub.status.idle":"2025-01-05T18:45:04.590956Z","shell.execute_reply.started":"2025-01-05T18:45:04.341091Z","shell.execute_reply":"2025-01-05T18:45:04.590237Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Establezco que los pesos del modelo de la base convolucional no sean entrenables\nVGG16.trainable=False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:45:07.724228Z","iopub.execute_input":"2025-01-05T18:45:07.724523Z","iopub.status.idle":"2025-01-05T18:45:07.728201Z","shell.execute_reply.started":"2025-01-05T18:45:07.724499Z","shell.execute_reply":"2025-01-05T18:45:07.727408Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"VGG16.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:45:12.744896Z","iopub.execute_input":"2025-01-05T18:45:12.745180Z","iopub.status.idle":"2025-01-05T18:45:12.769601Z","shell.execute_reply.started":"2025-01-05T18:45:12.745159Z","shell.execute_reply":"2025-01-05T18:45:12.768909Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Añado las capas densamente conectadas\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.regularizers import L2\n\nx1=VGG16.output\nx1=layers.Flatten()(x1) #Capa flatten para que sea un vector 1-d\n\nx1=layers.Dense(1000,activation=\"relu\")(x1) \nx1=layers.BatchNormalization()(x1)\nx1=layers.Dropout(0.3)(x1) #30% de dropout\n\nx1=layers.Dense(100,activation=\"relu\")(x1)\nx1=layers.BatchNormalization()(x1)\nx1=layers.Dropout(0.3)(x1) #30% de dropout\n\noutput=layers.Dense(1,activation=\"sigmoid\")(x1) #1 neurona en la capa de salida: pues es binary classification\nmodelo=keras.Model(VGG16.inputs,output) #Creación del modelo","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:50:56.570492Z","iopub.execute_input":"2025-01-05T18:50:56.570802Z","iopub.status.idle":"2025-01-05T18:50:56.616966Z","shell.execute_reply.started":"2025-01-05T18:50:56.570780Z","shell.execute_reply":"2025-01-05T18:50:56.616311Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"modelo.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:50:59.253404Z","iopub.execute_input":"2025-01-05T18:50:59.253728Z","iopub.status.idle":"2025-01-05T18:50:59.284289Z","shell.execute_reply.started":"2025-01-05T18:50:59.253704Z","shell.execute_reply":"2025-01-05T18:50:59.283616Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Defino el callback EarlyStopping para frenar el training cuando el modelo empieza a sobreajustarse\nfrom tensorflow.keras.callbacks import EarlyStopping\nES=EarlyStopping(\n    monitor=\"val_loss\",\n    patience=3,\n    restore_best_weights=True #Para que se 'restablezcan' los mejores pesos luego de que el callback para el training\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:51:02.945610Z","iopub.execute_input":"2025-01-05T18:51:02.945905Z","iopub.status.idle":"2025-01-05T18:51:02.949912Z","shell.execute_reply.started":"2025-01-05T18:51:02.945884Z","shell.execute_reply":"2025-01-05T18:51:02.949040Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Compile step\nfrom tensorflow.keras.optimizers import Adam\n\nmodelo.compile(\n    optimizer=Adam(learning_rate=0.001), #Depende de cómo van los valores en el training, iré cambiando los valores\n    loss=\"binary_crossentropy\", #Pues es clasificación binaria\n    metrics=[\"accuracy\"]\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:51:04.919949Z","iopub.execute_input":"2025-01-05T18:51:04.920236Z","iopub.status.idle":"2025-01-05T18:51:04.928423Z","shell.execute_reply.started":"2025-01-05T18:51:04.920213Z","shell.execute_reply":"2025-01-05T18:51:04.927697Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Training step\nhistory=modelo.fit(\n    train_data,\n    validation_data=val_data,\n    epochs=10,\n    callbacks=[ES]\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T18:51:10.679973Z","iopub.execute_input":"2025-01-05T18:51:10.680248Z","iopub.status.idle":"2025-01-05T19:48:44.827725Z","shell.execute_reply.started":"2025-01-05T18:51:10.680227Z","shell.execute_reply":"2025-01-05T19:48:44.826998Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\naccuracy=history.history[\"accuracy\"]\nval_accuracy=history.history[\"val_accuracy\"]\nepochs=range(1,len(accuracy)+1)\n\nplt.plot(epochs,accuracy,\"red\",label=\"accuracy\")\nplt.plot(epochs,val_accuracy,\"green\",label=\"val_accuracy\")\nplt.xlabel(\"epochs\")\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T19:50:09.240997Z","iopub.execute_input":"2025-01-05T19:50:09.241300Z","iopub.status.idle":"2025-01-05T19:50:09.475657Z","shell.execute_reply.started":"2025-01-05T19:50:09.241277Z","shell.execute_reply":"2025-01-05T19:50:09.474785Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"loss=history.history[\"loss\"]\nval_loss=history.history[\"val_loss\"]\nepochs=range(1,len(accuracy)+1)\n\nplt.plot(epochs,loss,\"red\",label=\"loss\")\nplt.plot(epochs,val_loss,\"blue\",label=\"val_loss\")\nplt.xlabel(\"epochs\")\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T19:50:15.328803Z","iopub.execute_input":"2025-01-05T19:50:15.329089Z","iopub.status.idle":"2025-01-05T19:50:15.549512Z","shell.execute_reply.started":"2025-01-05T19:50:15.329066Z","shell.execute_reply":"2025-01-05T19:50:15.548829Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Predicciones\nval_pred=modelo.predict(val_data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:02:36.617856Z","iopub.execute_input":"2025-01-05T22:02:36.618142Z","iopub.status.idle":"2025-01-05T22:03:56.388589Z","shell.execute_reply.started":"2025-01-05T22:02:36.618118Z","shell.execute_reply":"2025-01-05T22:03:56.387907Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_pred_n=(val_pred>0.5).astype(\"int32\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:04:33.667672Z","iopub.execute_input":"2025-01-05T22:04:33.667988Z","iopub.status.idle":"2025-01-05T22:04:33.671966Z","shell.execute_reply.started":"2025-01-05T22:04:33.667962Z","shell.execute_reply":"2025-01-05T22:04:33.671245Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_pred_n=val_pred_n.reshape(val_pred_n.shape[0],)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:04:36.107082Z","iopub.execute_input":"2025-01-05T22:04:36.107370Z","iopub.status.idle":"2025-01-05T22:04:36.111285Z","shell.execute_reply.started":"2025-01-05T22:04:36.107346Z","shell.execute_reply":"2025-01-05T22:04:36.110392Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_labels_=val_data.classes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:04:37.602413Z","iopub.execute_input":"2025-01-05T22:04:37.602739Z","iopub.status.idle":"2025-01-05T22:04:37.606318Z","shell.execute_reply.started":"2025-01-05T22:04:37.602710Z","shell.execute_reply":"2025-01-05T22:04:37.605448Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Matriz de confusión\nfrom sklearn.metrics import confusion_matrix,ConfusionMatrixDisplay,accuracy_score,precision_score\nc_m_1=confusion_matrix(val_labels_,val_pred_n)\nc_m_d_1=ConfusionMatrixDisplay(c_m_1)\nc_m_d_1.plot()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:04:41.850894Z","iopub.execute_input":"2025-01-05T22:04:41.851190Z","iopub.status.idle":"2025-01-05T22:04:42.097875Z","shell.execute_reply.started":"2025-01-05T22:04:41.851168Z","shell.execute_reply":"2025-01-05T22:04:42.097181Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Accuracy\nacc1=accuracy_score(val_labels_,val_pred_n)\nprint(f\"Accuracy: {acc1}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:05:13.626862Z","iopub.execute_input":"2025-01-05T22:05:13.627156Z","iopub.status.idle":"2025-01-05T22:05:13.633159Z","shell.execute_reply.started":"2025-01-05T22:05:13.627133Z","shell.execute_reply":"2025-01-05T22:05:13.632268Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Precision score: la clase positiva es el label \"diseased\"\nprecision1=precision_score(val_labels_,val_pred_n)\nprint(f\"Precision: {precision1}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:05:44.868862Z","iopub.execute_input":"2025-01-05T22:05:44.869130Z","iopub.status.idle":"2025-01-05T22:05:44.876207Z","shell.execute_reply.started":"2025-01-05T22:05:44.869111Z","shell.execute_reply":"2025-01-05T22:05:44.875318Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"----------","metadata":{}},{"cell_type":"markdown","source":"# Modelo 3: Modelo SÍ Fine-Tuning","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.applications import vgg16\nVGG16_2=vgg16.VGG16(\n    input_shape=(128,128,3),\n    include_top=False,\n    weights=\"imagenet\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T20:22:53.271034Z","iopub.execute_input":"2025-01-05T20:22:53.271398Z","iopub.status.idle":"2025-01-05T20:22:53.515748Z","shell.execute_reply.started":"2025-01-05T20:22:53.271358Z","shell.execute_reply":"2025-01-05T20:22:53.515039Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"VGG16_2.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T20:22:56.256676Z","iopub.execute_input":"2025-01-05T20:22:56.256989Z","iopub.status.idle":"2025-01-05T20:22:56.282606Z","shell.execute_reply.started":"2025-01-05T20:22:56.256963Z","shell.execute_reply":"2025-01-05T20:22:56.281943Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"VGG16_2.trainable=True","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T20:22:58.821365Z","iopub.execute_input":"2025-01-05T20:22:58.821709Z","iopub.status.idle":"2025-01-05T20:22:58.825307Z","shell.execute_reply.started":"2025-01-05T20:22:58.821680Z","shell.execute_reply":"2025-01-05T20:22:58.824522Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for layer in VGG16_2.layers[:-2]: #Última capa, ya que la de max pooling no se entrena\n    layer.trainable=False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T20:23:00.381797Z","iopub.execute_input":"2025-01-05T20:23:00.382074Z","iopub.status.idle":"2025-01-05T20:23:00.385935Z","shell.execute_reply.started":"2025-01-05T20:23:00.382049Z","shell.execute_reply":"2025-01-05T20:23:00.385095Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"VGG16_2.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T20:23:02.367313Z","iopub.execute_input":"2025-01-05T20:23:02.367600Z","iopub.status.idle":"2025-01-05T20:23:02.392361Z","shell.execute_reply.started":"2025-01-05T20:23:02.367576Z","shell.execute_reply":"2025-01-05T20:23:02.391722Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"x2=VGG16_2.output\nx2=layers.Flatten()(x2) #Capa flatten para que sea un vector 1-d\n\nx2=layers.Dense(1000,activation=\"relu\")(x2) \nx2=layers.BatchNormalization()(x2)\nx2=layers.Dropout(0.3)(x2) #30% de dropout\n\nx2=layers.Dense(100,activation=\"relu\")(x2)\nx2=layers.BatchNormalization()(x2)\nx2=layers.Dropout(0.3)(x2) #30% de dropout\n\noutput2=layers.Dense(1,activation=\"sigmoid\")(x2) #1 neurona en la capa de salida: pues es binary classification\nmodelo2=keras.Model(VGG16_2.inputs,output2) #Creación del modelo","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T20:23:04.766273Z","iopub.execute_input":"2025-01-05T20:23:04.766548Z","iopub.status.idle":"2025-01-05T20:23:04.811997Z","shell.execute_reply.started":"2025-01-05T20:23:04.766527Z","shell.execute_reply":"2025-01-05T20:23:04.811377Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Defino el callback EarlyStopping para frenar el training cuando el modelo empieza a sobreajustarse\nfrom tensorflow.keras.callbacks import EarlyStopping\nES2=EarlyStopping(\n    monitor=\"val_loss\",\n    patience=3,\n    restore_best_weights=True #Para que se 'restablezcan' los mejores pesos luego de que el callback para el training\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T20:47:13.995010Z","iopub.execute_input":"2025-01-05T20:47:13.995337Z","iopub.status.idle":"2025-01-05T20:47:13.999021Z","shell.execute_reply.started":"2025-01-05T20:47:13.995308Z","shell.execute_reply":"2025-01-05T20:47:13.998191Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Compile step\nfrom tensorflow.keras.optimizers import Adam\n\nmodelo2.compile(\n    optimizer=Adam(learning_rate=0.001), \n    loss=\"binary_crossentropy\", #Pues es clasificación binaria\n    metrics=[\"accuracy\"]\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T20:47:12.118641Z","iopub.execute_input":"2025-01-05T20:47:12.118986Z","iopub.status.idle":"2025-01-05T20:47:12.127742Z","shell.execute_reply.started":"2025-01-05T20:47:12.118959Z","shell.execute_reply":"2025-01-05T20:47:12.126883Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Training step\nhistory2=modelo2.fit(\n    train_data,\n    validation_data=val_data,\n    epochs=10,\n    callbacks=[ES2]\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T20:47:45.808400Z","iopub.execute_input":"2025-01-05T20:47:45.808751Z","iopub.status.idle":"2025-01-05T21:49:09.194993Z","shell.execute_reply.started":"2025-01-05T20:47:45.808719Z","shell.execute_reply":"2025-01-05T21:49:09.194202Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"accuracy2=history2.history[\"accuracy\"]\nval_accuracy2=history2.history[\"val_accuracy\"]\nepochs=range(1,len(accuracy2)+1)\n\nplt.plot(epochs,accuracy2,\"red\",label=\"accuracy\")\nplt.plot(epochs,val_accuracy2,\"green\",label=\"val_accuracy\")\nplt.xlabel(\"epochs\")\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:52:20.002198Z","iopub.execute_input":"2025-01-05T21:52:20.002493Z","iopub.status.idle":"2025-01-05T21:52:20.218703Z","shell.execute_reply.started":"2025-01-05T21:52:20.002469Z","shell.execute_reply":"2025-01-05T21:52:20.217928Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"loss2=history2.history[\"loss\"]\nval_loss2=history2.history[\"val_loss\"]\nepochs=range(1,len(loss2)+1)\n\nplt.plot(epochs,loss2,\"red\",label=\"loss\")\nplt.plot(epochs,val_loss2,\"blue\",label=\"val_loss\")\nplt.xlabel(\"epochs\")\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:51:38.474226Z","iopub.execute_input":"2025-01-05T21:51:38.474532Z","iopub.status.idle":"2025-01-05T21:51:38.689324Z","shell.execute_reply.started":"2025-01-05T21:51:38.474508Z","shell.execute_reply":"2025-01-05T21:51:38.688638Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Predicciones\nval_pred2=modelo2.predict(val_data)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:53:03.346817Z","iopub.execute_input":"2025-01-05T21:53:03.347112Z","iopub.status.idle":"2025-01-05T21:54:18.960302Z","shell.execute_reply.started":"2025-01-05T21:53:03.347090Z","shell.execute_reply":"2025-01-05T21:54:18.959623Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_pred2_n=(val_pred2>0.5).astype(\"int32\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:55:10.351307Z","iopub.execute_input":"2025-01-05T21:55:10.351630Z","iopub.status.idle":"2025-01-05T21:55:10.355269Z","shell.execute_reply.started":"2025-01-05T21:55:10.351602Z","shell.execute_reply":"2025-01-05T21:55:10.354507Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_pred2_n=val_pred2_n.reshape(val_pred2_n.shape[0],)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:56:17.854428Z","iopub.execute_input":"2025-01-05T21:56:17.854761Z","iopub.status.idle":"2025-01-05T21:56:17.858388Z","shell.execute_reply.started":"2025-01-05T21:56:17.854733Z","shell.execute_reply":"2025-01-05T21:56:17.857429Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_labels=val_data.classes","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T21:56:43.941354Z","iopub.execute_input":"2025-01-05T21:56:43.941718Z","iopub.status.idle":"2025-01-05T21:56:43.945470Z","shell.execute_reply.started":"2025-01-05T21:56:43.941687Z","shell.execute_reply":"2025-01-05T21:56:43.944618Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Matriz de confusión\nfrom sklearn.metrics import confusion_matrix,ConfusionMatrixDisplay,accuracy_score,precision_score\nc_m=confusion_matrix(val_labels,val_pred2_n)\nc_m_d=ConfusionMatrixDisplay(c_m)\nc_m_d.plot()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:00:48.594905Z","iopub.execute_input":"2025-01-05T22:00:48.595209Z","iopub.status.idle":"2025-01-05T22:00:48.832786Z","shell.execute_reply.started":"2025-01-05T22:00:48.595185Z","shell.execute_reply":"2025-01-05T22:00:48.831604Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Accuracy\nacc=accuracy_score(val_labels,val_pred2_n)\nprint(f\"Accuracy: {acc}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:02:06.529754Z","iopub.execute_input":"2025-01-05T22:02:06.530028Z","iopub.status.idle":"2025-01-05T22:02:06.536016Z","shell.execute_reply.started":"2025-01-05T22:02:06.530007Z","shell.execute_reply":"2025-01-05T22:02:06.535278Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Precision score: la clase positiva es el label \"diseased\"\nprecision=precision_score(val_labels,val_pred2_n)\nprint(f\"Precision: {precision}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T22:01:29.376685Z","iopub.execute_input":"2025-01-05T22:01:29.376987Z","iopub.status.idle":"2025-01-05T22:01:29.385797Z","shell.execute_reply.started":"2025-01-05T22:01:29.376966Z","shell.execute_reply":"2025-01-05T22:01:29.384902Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"---------","metadata":{}},{"cell_type":"code","source":"#Obtengo la data de test\nimport cv2\nimg_size= 128\n\n#Cargar y resize a las imágenes\ndef CargarTest(image_path):\n    imagen = cv2.imread(image_path)\n    imagen = cv2.resize(imagen, (img_size,img_size))\n    imagen = imagen / 255.0  #Normalizando la data\n    return imagen","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:51:56.684993Z","iopub.execute_input":"2025-01-05T23:51:56.685323Z","iopub.status.idle":"2025-01-05T23:51:56.689433Z","shell.execute_reply.started":"2025-01-05T23:51:56.685293Z","shell.execute_reply":"2025-01-05T23:51:56.688644Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Preprocesamiento para todas las imágenes\nimagenes = []\n\nfor i,fila in test_df.iterrows():\n    nombre_img=fila[\"Images\"]\n    imgs=os.path.join(path_base_img,nombre_img)\n    imagenes.append(CargarTest(imgs))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:52:02.685616Z","iopub.execute_input":"2025-01-05T23:52:02.685896Z","iopub.status.idle":"2025-01-05T23:54:16.305391Z","shell.execute_reply.started":"2025-01-05T23:52:02.685876Z","shell.execute_reply":"2025-01-05T23:54:16.304711Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Convierto a un array\nimport numpy as np\nx_test=np.array(imagenes)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:54:23.396177Z","iopub.execute_input":"2025-01-05T23:54:23.396467Z","iopub.status.idle":"2025-01-05T23:54:23.495330Z","shell.execute_reply.started":"2025-01-05T23:54:23.396446Z","shell.execute_reply":"2025-01-05T23:54:23.494644Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Predicción\npred_final=modelo2.predict(x_test)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:54:43.845705Z","iopub.execute_input":"2025-01-05T23:54:43.846026Z","iopub.status.idle":"2025-01-05T23:54:45.699813Z","shell.execute_reply.started":"2025-01-05T23:54:43.845999Z","shell.execute_reply":"2025-01-05T23:54:45.699110Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred_final_labels=(pred_final>0.5).astype(\"int32\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:55:19.974343Z","iopub.execute_input":"2025-01-05T23:55:19.974703Z","iopub.status.idle":"2025-01-05T23:55:19.979112Z","shell.execute_reply.started":"2025-01-05T23:55:19.974676Z","shell.execute_reply":"2025-01-05T23:55:19.978304Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred_final_labels=pred_final_labels.reshape(pred_final_labels.shape[0],)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:55:57.448086Z","iopub.execute_input":"2025-01-05T23:55:57.448378Z","iopub.status.idle":"2025-01-05T23:55:57.452259Z","shell.execute_reply.started":"2025-01-05T23:55:57.448357Z","shell.execute_reply":"2025-01-05T23:55:57.451511Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Creo el dataframe\nsubmission_df = pd.DataFrame({\n    'Images': test_df['Images'],\n    'Labels': pred_final_labels\n})","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-05T23:56:26.588712Z","iopub.execute_input":"2025-01-05T23:56:26.589007Z","iopub.status.idle":"2025-01-05T23:56:26.593231Z","shell.execute_reply.started":"2025-01-05T23:56:26.588986Z","shell.execute_reply":"2025-01-05T23:56:26.592451Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission_df.to_csv('submission.csv', index=False)\nprint('Submission file was created.')","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}