{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.12.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"colab":{"provenance":[]}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# https://www.kaggle.com/c/landmark-recognition-2021/data?select=train.csv","metadata":{"id":"hK0NBHQ2rTS4","trusted":true,"execution":{"iopub.status.busy":"2026-08-03T11:32:00.610767Z","iopub.execute_input":"2026-08-03T11:32:00.611174Z","iopub.status.idle":"2026-08-03T11:32:00.614664Z","shell.execute_reply.started":"2026-08-03T11:32:00.611145Z","shell.execute_reply":"2026-08-03T11:32:00.613935Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nprint(os.listdir('/kaggle/input/competitions/landmark-recognition-2021'))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-08-03T11:32:00.617237Z","iopub.execute_input":"2026-08-03T11:32:00.617574Z","iopub.status.idle":"2026-08-03T11:32:00.63105Z","shell.execute_reply.started":"2026-08-03T11:32:00.61754Z","shell.execute_reply":"2026-08-03T11:32:00.630454Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\n\nimport pandas as pd\n\nimport os\n\nimport tensorflow as tf\nimport tensorflow.keras as keras\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.callbacks import EarlyStopping\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau\nfrom tensorflow.keras.callbacks import ModelCheckpoint\nfrom tensorflow.keras import regularizers\n\nimport matplotlib.pyplot as plt\n\nimport cv2\n\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix\n\nimport sys\nimport gc\nimport time\nimport seaborn as sns\n\nSEED = 42\n","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.status.busy":"2026-08-03T11:32:00.632176Z","iopub.execute_input":"2026-08-03T11:32:00.632462Z","iopub.status.idle":"2026-08-03T11:32:00.642382Z","shell.execute_reply.started":"2026-08-03T11:32:00.632441Z","shell.execute_reply":"2026-08-03T11:32:00.641826Z"},"id":"APpKpm0ybVc3","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load training data\ndef load_traindf():\n\n    # Read the CSV file\n    traindf = pd.read_csv(\n        \"/kaggle/input/competitions/landmark-recognition-2021/train.csv\"\n    )\n\n    # Base folder where all training images are stored\n    train_dir = \"/kaggle/input/competitions/landmark-recognition-2021/train\"\n\n    # Build the image path for every image\n    traindf[\"img_path\"] = traindf[\"id\"].apply(\n        lambda img_id: os.path.join(\n            train_dir,\n            img_id[0],\n            img_id[1],\n            img_id[2],\n            img_id + \".jpg\"\n        )\n    )\n\n    # Convert landmark_id to int32\n    traindf[\"landmark_id\"] = traindf[\"landmark_id\"].astype(np.int32)\n\n    return traindf\n\n\n# Read and resize image\ndef img_read_resize(img_path):\n    img = plt.imread(img_path)\n    img_redim = cv2.resize(img, (IMG_SIZE, IMG_SIZE))\n    return img_redim\n\n\n# Calculate object size recursively\ndef get_size(obj, seen=None):\n    \"\"\"\n    Recursively finds the memory size of an object.\n    \"\"\"\n\n    size = sys.getsizeof(obj)\n\n    if seen is None:\n        seen = set()\n\n    obj_id = id(obj)\n\n    if obj_id in seen:\n        return 0\n\n    seen.add(obj_id)\n\n    if isinstance(obj, dict):\n        size += sum(get_size(v, seen) for v in obj.values())\n        size += sum(get_size(k, seen) for k in obj.keys())\n\n    elif hasattr(obj, \"__dict__\"):\n        size += get_size(obj.__dict__, seen)\n\n    elif hasattr(obj, \"__iter__\") and not isinstance(obj, (str, bytes, bytearray)):\n        size += sum(get_size(i, seen) for i in obj)\n\n    return size","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:00.643163Z","iopub.execute_input":"2026-08-03T11:32:00.643449Z","iopub.status.idle":"2026-08-03T11:32:00.656858Z","shell.execute_reply.started":"2026-08-03T11:32:00.643428Z","shell.execute_reply":"2026-08-03T11:32:00.656307Z"},"id":"5D5mmbdJbVc6","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"traindf = load_traindf()\nlandmark_unique = len(traindf['landmark_id'].unique())\ntraindf\n","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:00.657751Z","iopub.execute_input":"2026-08-03T11:32:00.658062Z","iopub.status.idle":"2026-08-03T11:32:04.460866Z","shell.execute_reply.started":"2026-08-03T11:32:00.658033Z","shell.execute_reply":"2026-08-03T11:32:04.460237Z"},"id":"_ea-p8MRbVc6","outputId":"8b64963c-20ac-47b9-c0b1-18debe739f76","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"get_size(traindf)","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:04.46251Z","iopub.execute_input":"2026-08-03T11:32:04.462752Z","iopub.status.idle":"2026-08-03T11:32:06.241882Z","shell.execute_reply.started":"2026-08-03T11:32:04.462731Z","shell.execute_reply":"2026-08-03T11:32:06.241207Z"},"id":"CQJN8dd6bVc7","outputId":"53fdf95f-6eff-49cc-be94-b971a4a193c7","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"traindf.info(memory_usage='deep')","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:06.242699Z","iopub.execute_input":"2026-08-03T11:32:06.243051Z","iopub.status.idle":"2026-08-03T11:32:06.974894Z","shell.execute_reply.started":"2026-08-03T11:32:06.243026Z","shell.execute_reply":"2026-08-03T11:32:06.974047Z"},"id":"CBIdzQCJbVc7","outputId":"2cd05690-08bc-447d-bae0-5edd3fad1036","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('Data from the original training dataset \\n')\nprint('Number of images in the dataset: ', traindf.shape[0])\nprint('Number of different classes: ', landmark_unique)\nprint('Min class: ', min(traindf['landmark_id']))\nprint('Max class: ', max(traindf['landmark_id']))\nprint('\\nRepetitions of elements by class:')\nprint(traindf['landmark_id'].value_counts())","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:06.975958Z","iopub.execute_input":"2026-08-03T11:32:06.976286Z","iopub.status.idle":"2026-08-03T11:32:07.26753Z","shell.execute_reply.started":"2026-08-03T11:32:06.976261Z","shell.execute_reply":"2026-08-03T11:32:07.266666Z"},"id":"MiKVkJX8bVc8","outputId":"89792ffd-841d-48d6-c435-e72febe38f44","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(25,10))\n\nfor i in range(20):\n    j = np.random.randint(0, traindf.shape[0])\n    img = plt.imread((traindf['img_path'][j]))\n    plt.subplot(4 , 5, i+1)\n    plt.xticks([])\n    plt.yticks([])\n    plt.xlabel(str(img.shape[0])+'x'+str(img.shape[1]), fontweight = \"bold\", fontsize=16)\n    plt.imshow(img)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:07.268551Z","iopub.execute_input":"2026-08-03T11:32:07.268922Z","iopub.status.idle":"2026-08-03T11:32:08.821217Z","shell.execute_reply.started":"2026-08-03T11:32:07.268897Z","shell.execute_reply":"2026-08-03T11:32:08.818626Z"},"id":"3qQ5RPlwbVc8","outputId":"0bdef4ee-8435-422a-baeb-4e5df1b3e67c","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"IMG_SIZE = 128\n\nMIN_CLASS = 0\nMAX_CLASS = 500\n\ntraindf_s = traindf[(MIN_CLASS < traindf['landmark_id']) & (traindf['landmark_id'] <= MAX_CLASS)]\n\n\nUNDERSAMPLING_THRESHOLD = 80\n\nimport pandas as pd\ntraindf_s = pd.concat(\n    [group.sample(n=min(len(group), UNDERSAMPLING_THRESHOLD), random_state=SEED)\n     for _, group in traindf_s.groupby('landmark_id')],\n    ignore_index=True,\n)\ntraindf_s['landmark_id'].value_counts()\n\nN_DATA = len(traindf_s['landmark_id'])\nclases = traindf_s['landmark_id'].unique()\nN_CLASS = len(clases)\n\nprint('Sample data number, N_DATA: '+str(N_DATA))\nprint('\\nNumber of classes in the sample, N_CLASS: '+str(N_CLASS))\nprint('\\nMIN class of the sample: '+str(min(traindf_s['landmark_id'])))\nprint('\\nMAX class of the sample: '+str(max(traindf_s['landmark_id'])))\nprint('\\nRepetitions of elements by class in the sample after Undersampling:')\nprint(traindf_s['landmark_id'].value_counts())","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:08.82228Z","iopub.execute_input":"2026-08-03T11:32:08.822652Z","iopub.status.idle":"2026-08-03T11:32:08.917201Z","shell.execute_reply.started":"2026-08-03T11:32:08.822628Z","shell.execute_reply":"2026-08-03T11:32:08.916621Z"},"id":"2sWS5jKNbVc8","outputId":"3e623a6d-0841-451e-dc77-33bca0645077","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"traindf_s['landmark_id'].value_counts().describe()","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:08.91824Z","iopub.execute_input":"2026-08-03T11:32:08.918559Z","iopub.status.idle":"2026-08-03T11:32:08.926244Z","shell.execute_reply.started":"2026-08-03T11:32:08.918536Z","shell.execute_reply":"2026-08-03T11:32:08.925664Z"},"id":"n8VoZgrGbVc9","outputId":"12d5c817-7d58-4d9f-b249-f2b10361be81","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(25,10))\n\nfor i in range(20):\n    j = np.random.randint(0, N_DATA)\n    img = img_read_resize(traindf_s['img_path'][j])\n    plt.subplot(4 , 5, i+1)\n    plt.xticks([])\n    plt.yticks([])\n    plt.xlabel('landmark_id: '+ str(traindf_s['landmark_id'][j]), fontweight =\"bold\", fontsize=16)\n    plt.imshow(img)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:08.92721Z","iopub.execute_input":"2026-08-03T11:32:08.927582Z","iopub.status.idle":"2026-08-03T11:32:09.704322Z","shell.execute_reply.started":"2026-08-03T11:32:08.927558Z","shell.execute_reply":"2026-08-03T11:32:09.703326Z"},"id":"6QwH_CMXbVc9","outputId":"3ec0ab79-ec68-49bc-d31b-161c9bc83736","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = []   #Images\ny = []   #Classes\n\nfor i in range(traindf_s.shape[0]):\n    X.append(img_read_resize(traindf_s['img_path'][i]))\n    y.append(np.array(traindf_s['landmark_id'][i]))\n\nprint('Variable types: \\n')\nprint('X: ', type(X))\nprint('X elements: ', type(X[0]))\nprint('\\ny: ', type(y))\nprint('y elements: ', type(y[0]))","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:09.705528Z","iopub.execute_input":"2026-08-03T11:32:09.705998Z","iopub.status.idle":"2026-08-03T11:32:22.278277Z","shell.execute_reply.started":"2026-08-03T11:32:09.705972Z","shell.execute_reply":"2026-08-03T11:32:22.2773Z"},"id":"vqGI8AdQbVc9","outputId":"ac078656-1668-4eaf-a0cc-30cf1f636f9c","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Label Encoding\n\nLE = LabelEncoder()\nLE.fit(clases)\ny_LE = LE.transform(y)","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:22.279396Z","iopub.execute_input":"2026-08-03T11:32:22.279784Z","iopub.status.idle":"2026-08-03T11:32:22.285393Z","shell.execute_reply.started":"2026-08-03T11:32:22.27975Z","shell.execute_reply":"2026-08-03T11:32:22.284399Z"},"id":"2ZVV0BPUbVc-","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = [n/255 for n in X]\n\nX = np.array(X)\ny_LE = np.array(y_LE)\ny = np.array(y)","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:22.288403Z","iopub.execute_input":"2026-08-03T11:32:22.288742Z","iopub.status.idle":"2026-08-03T11:32:23.72028Z","shell.execute_reply.started":"2026-08-03T11:32:22.288718Z","shell.execute_reply":"2026-08-03T11:32:23.719306Z"},"id":"Hu-A8zpcbVc-","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Separating data for training, testing and validating\nX_train, X_val, y_train, y_val = train_test_split(X, y_LE, test_size = 0.10, random_state=SEED, shuffle=True)\n\nX_train, X_test, y_train, y_test = train_test_split(X_train, y_train, test_size = 0.05, random_state=SEED, shuffle=True)\n\ntraining_data = len(X_train)\n\nprint('X-Images: ',len(X), 'and y labels: ', len(y_LE))\nprint('Training. Images in X_train: ',len(X_train), 'and labels in y_train: ',len(y_train))\nprint('Validation. Images in X_val: ',len(X_val), 'and labels in y_val: ',len(y_val))\nprint('Testing. Images in X_test: ',len(X_test), 'and labels in y_test: ',len(y_test))","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:23.721392Z","iopub.execute_input":"2026-08-03T11:32:23.721701Z","iopub.status.idle":"2026-08-03T11:32:24.412999Z","shell.execute_reply.started":"2026-08-03T11:32:23.721679Z","shell.execute_reply":"2026-08-03T11:32:24.412071Z"},"id":"pVdSw-1kbVc-","outputId":"bda3042e-e333-4252-a7ab-ec469f201807","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_augmentation = tf.keras.Sequential([\n    #layers.RandomFlip('horizontal'),\n    layers.RandomZoom(height_factor=(-0.2, 0.2)),\n    layers.RandomContrast(0.4),\n    layers.RandomTranslation(height_factor= (-0.2, 0.2), width_factor=(-0.2, 0.2)),\n    layers.RandomRotation(factor= (-0.1, 0.1)),\n    #layers.RandomCrop(120, 120, seed=SEED)\n])\n\nplt.figure(figsize=(25,7))\nj = 1 #np.random.randint(0, N_DATA)\nimg_orig = X[j]\nplt.subplot(2 , 6, 1)\nplt.xticks([])\nplt.yticks([])\nplt.xlabel('ORIGINAL. landmark_id: '+ str(y[j]), fontweight =\"bold\", fontsize=12)\nplt.imshow(img_orig)\n\nfor i in range(11):\n    img_mod = data_augmentation(img_orig)\n    plt.subplot(2 , 6, i+2)\n    plt.xticks([])\n    plt.yticks([])\n    plt.xlabel('Modification '+str(i+1), fontweight =\"bold\", fontsize=12)\n    plt.imshow(img_mod)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:24.413912Z","iopub.execute_input":"2026-08-03T11:32:24.414154Z","iopub.status.idle":"2026-08-03T11:32:25.38479Z","shell.execute_reply.started":"2026-08-03T11:32:24.414132Z","shell.execute_reply":"2026-08-03T11:32:25.384101Z"},"id":"vNXkRQEcbVc-","outputId":"1b1e6f98-a23c-4698-e15a-2b25f4da1b2b","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"start_time = time.time()\n\nOVERSAMPLING_THRESHOLD = 0.2 * UNDERSAMPLING_THRESHOLD\n\nfor i in range(N_CLASS):\n    cont = int(np.sum(y_train == i))\n    if cont < OVERSAMPLING_THRESHOLD:\n        img_class_i = X_train[y_train == i]\n        n_needed = int(OVERSAMPLING_THRESHOLD - cont)\n        idx = np.random.randint(len(img_class_i), size=n_needed)\n        X_train = np.concatenate((X_train, img_class_i[idx]), axis=0)\n        y_train = np.append(y_train, np.full(n_needed, i))\n\nprint('\\nOversampling duration: %s seconds' % (time.time() - start_time))\nn_data_train_def = len(X_train)\nprint('\\nTraining data after oversampling: '+str(n_data_train_def)+' data')\nprint('\\nThe training data has gone from: '+str(training_data)+' to:'+ str(n_data_train_def))\n","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:32:25.387582Z","iopub.execute_input":"2026-08-03T11:32:25.38796Z","iopub.status.idle":"2026-08-03T11:33:25.364589Z","shell.execute_reply.started":"2026-08-03T11:32:25.387902Z","shell.execute_reply":"2026-08-03T11:33:25.363838Z"},"id":"NHCeuRNMbVeG","outputId":"c72bb1b4-e99f-46d3-e36b-5262dcf34bbb","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# CNN Hyperparameters\nkernelSize = (3,3)         #Convolution template size\npaddingType = 'same'\nactivationF = 'relu'      # Activation Function\npoolSize = (2,2)          # Maximum pooling template size\nstridesSize = (2,2)       # Template offset during maximum pooling\ndropoutRate = 0.5         # Percentage of neurons that are deactivated with the Dropout layer\nbatchSize = 256           # Amount of data with which it is trained in each epoch\nepochsSize= 30          # Number of epochs to train\nlr = 0.01                # Learning Rate\nweightDecay = regularizers.L2(0.01) # Regularization of weights","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:33:25.365683Z","iopub.execute_input":"2026-08-03T11:33:25.365991Z","iopub.status.idle":"2026-08-03T11:33:25.370457Z","shell.execute_reply.started":"2026-08-03T11:33:25.365955Z","shell.execute_reply":"2026-08-03T11:33:25.369756Z"},"id":"8XCyzviMbVeG","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def create_model():\n\n    model = keras.Sequential([\n\n        #DATA AUGMENTATION\n        layers.RandomZoom(height_factor=(-0.2, 0.2)),\n        layers.RandomContrast(0.4),\n        layers.RandomTranslation(height_factor= (-0.2, 0.2), width_factor=(-0.2, 0.2)),\n        layers.RandomRotation(factor= (-0.1, 0.1)),\n\n        # MODEL BASIS ---- Feature Extraction\n        # convolutional block 1\n        layers.Conv2D(filters=32, kernel_size=kernelSize, strides=1, padding=paddingType, activation=activationF, input_shape=[IMG_SIZE, IMG_SIZE, 3]),\n        layers.BatchNormalization(),\n        layers.MaxPool2D(pool_size=poolSize, strides=stridesSize, padding=paddingType),\n        # convolutional block 2\n        layers.Conv2D(filters=64, kernel_size=kernelSize, strides=1, padding=paddingType, activation=activationF),\n        layers.BatchNormalization(),\n        layers.MaxPool2D(pool_size=poolSize, strides=stridesSize, padding=paddingType),\n        # convolutional block 3\n        layers.Conv2D(filters=128, kernel_size=kernelSize, strides=1, padding=paddingType, activation=activationF),\n        layers.BatchNormalization(),\n        layers.MaxPool2D(pool_size=poolSize, strides=stridesSize, padding=paddingType),\n        # convolutional block 4\n        layers.Conv2D(filters=256, kernel_size=kernelSize, strides=1, padding=paddingType, activation=activationF),\n        layers.BatchNormalization(),\n        layers.MaxPool2D(pool_size=poolSize, strides=stridesSize, padding=paddingType),\n        # convolutional block 5\n        layers.Conv2D(filters=512, kernel_size=kernelSize, strides=1, padding=paddingType, activation=activationF),\n        layers.BatchNormalization(),\n        layers.MaxPool2D(pool_size=poolSize, strides=stridesSize, padding=paddingType),\n\n        # MODEL HEAD ---- Classification\n        layers.Flatten(),\n        layers.Dense(units = 512, activation=activationF, kernel_regularizer=weightDecay),\n        layers.Dropout(rate=dropoutRate,seed=SEED),\n        layers.BatchNormalization(),\n        #Output Layer\n        layers.Dense(units = N_CLASS, activation='softmax'),\n    ])\n\n    # OPTIMIZERS\n    # The lower lr, the less sudden changes there are in metrics such as accuracy\n    opt1 = tf.keras.optimizers.RMSprop(learning_rate=lr, rho=0.9, momentum=0.5, epsilon=1e-07)\n    opt2 = tf.keras.optimizers.Adam(learning_rate=lr, beta_1=0.9, beta_2=0.999, epsilon=1e-07)\n    opt3 = tf.keras.optimizers.SGD(learning_rate=lr, momentum=0.9, nesterov=False)                 #momentum--> acelera gradiente y amortigua oscilaciones\n\n    # Model compilation\n    model.compile(\n        optimizer = opt3,\n        loss = 'sparse_categorical_crossentropy',\n        metrics = ['sparse_categorical_accuracy']\n    )\n\n    # Callback 1\n    early_stopping = EarlyStopping(\n        monitor = \"val_loss\",\n        mode = \"auto\",\n        min_delta = 0.0001,                                              # minimium amount of change to count as an improvement\n        patience = 150,                                                  # how many epochs to wait before stopping\n        restore_best_weights = True)\n\n    # Callback 2\n    reduce_lr = ReduceLROnPlateau(\n        monitor='val_loss', factor=0.7,\n        patience=40, cooldown=1, min_lr=0.0005,\n        min_delta=0.001, verbose=1)\n\n    # Callback 3\n    checkpoint = ModelCheckpoint(\n        'best-weights.weights.h5', monitor='val_loss',\n        save_best_only=True, save_weights_only=True)\n\n\n    # Model Training\n    history = model.fit(\n        X_train, y_train,\n        validation_data = (X_val, y_val),       # THE LABELS ARE WITH LABEL ENCODING\n        class_weight = train_classWeights,\n        shuffle = True,                         # Only affects training data (1 time at first)\n        batch_size = batchSize,\n        steps_per_epoch = len(X_train)//batchSize,\n        epochs = epochsSize,\n        callbacks = [early_stopping, reduce_lr, checkpoint],\n        verbose=1,\n        # use_multiprocessing = True,\n        # max_queue_size = 15,        # Default = 10\n        # workers = 32,\n    )\n\n    return model, history","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:33:25.371475Z","iopub.execute_input":"2026-08-03T11:33:25.371816Z","iopub.status.idle":"2026-08-03T11:33:25.389212Z","shell.execute_reply.started":"2026-08-03T11:33:25.371795Z","shell.execute_reply":"2026-08-03T11:33:25.388534Z"},"id":"bUpszwa2bVeG","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.utils import class_weight\nclassWeights = class_weight.compute_class_weight(class_weight ='balanced',classes = np.unique(y_train), y = y_train)\ntrain_classWeights = dict(enumerate(classWeights))\n\n# Calculation of weights of each class of data for sample training\n_, freq = np.unique(y_train, return_counts=True)\nmax_freq = np.max(freq)\nprint ('Highest frequency: '+str(np.max(freq)))","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:33:25.390267Z","iopub.execute_input":"2026-08-03T11:33:25.390607Z","iopub.status.idle":"2026-08-03T11:33:25.408711Z","shell.execute_reply.started":"2026-08-03T11:33:25.390569Z","shell.execute_reply":"2026-08-03T11:33:25.407891Z"},"id":"7TiKJ6f3bVeH","outputId":"463b7f17-e023-4286-eb27-f583dbaff7a8","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"start_time = time.time()\n\nmodel, history = create_model()\n\nhistory_df = pd.DataFrame(history.history)\n\nprint('\\nbatchSize = '+str(batchSize))\n\nplt.figure(figsize=(15,5))        #Width and Height of the graphs, respectively\n\nplt.subplot(1,2,1)\n#history_df.loc[0:, ['loss', 'val_loss']].plot()\nplt.plot(history.history['loss'], label='Entrenamiento')\nplt.plot(history.history['val_loss'], label='Validación')\nplt.legend()\nplt.title('Loss and Validation Loss')\nplt.xlabel('batchSize = '+str(batchSize))\nprint((\"Minimum Validation Loss: {:0.4f} in epoch {:0.0f} \").format(history_df['val_loss'].min(), history_df['val_loss'].idxmin()))\n\nplt.subplot(1,2,2)\n#history_df.loc[0:, ['accuracy', 'val_accuracy']].plot()\nplt.plot(history.history['sparse_categorical_accuracy'], label='Training')\nplt.plot(history.history['val_sparse_categorical_accuracy'], label='Validation')\nplt.legend()\nplt.title('Accuracy and Validation Accuracy')\nplt.xlabel('batchSize = '+str(batchSize))\nprint((\"Maximum Validation Accuracy: {:0.4f} in epoch {:0.0f} \").format(history_df['val_sparse_categorical_accuracy'].max(), history_df['val_sparse_categorical_accuracy'].idxmax()))\n\nprint(\"\\nEvaluation of the model with training data\")\nscore = model.evaluate(X_train, y_train)\nprint(\"Test loss, Test accuracy:\", score[0], score[1])\n\nprint(\"\\nModel evaluation with validation data\")\nscore = model.evaluate(X_val, y_val)\nprint(\"Test loss, Test accuracy:\", score[0], score[1])\n\nplt.show()\n\nprint('\\ntraining duration: %s minutes' % ((time.time() - start_time)/60))","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:33:25.409825Z","iopub.execute_input":"2026-08-03T11:33:25.410188Z","iopub.status.idle":"2026-08-03T11:35:19.108313Z","shell.execute_reply.started":"2026-08-03T11:33:25.410149Z","shell.execute_reply":"2026-08-03T11:35:19.107566Z"},"id":"FQ-AIWN2bVeI","outputId":"49101033-41e5-4ff4-f968-41eb73db5219","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:35:19.109487Z","iopub.execute_input":"2026-08-03T11:35:19.109837Z","iopub.status.idle":"2026-08-03T11:35:19.139626Z","shell.execute_reply.started":"2026-08-03T11:35:19.109812Z","shell.execute_reply":"2026-08-03T11:35:19.138824Z"},"id":"dQNJQhqpbVeI","outputId":"4077533a-d309-4bc5-d423-d0edc5c346d7","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(25,7))\n\nfor i in range(12):\n    img = X_test[i]  #Ya se hizo el shuffle con el split\n    plt.subplot(2 , 6, i+1)\n    plt.xticks([])\n    plt.yticks([])\n    plt.xlabel('Class: determined')\n    plt.imshow(img)","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:35:19.140558Z","iopub.execute_input":"2026-08-03T11:35:19.14084Z","iopub.status.idle":"2026-08-03T11:35:19.829174Z","shell.execute_reply.started":"2026-08-03T11:35:19.140811Z","shell.execute_reply":"2026-08-03T11:35:19.828369Z"},"id":"TUD5AJWvbVeI","outputId":"1e1982d4-25a8-40ec-aeea-74e624a38a5b","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predict = model.predict(X_test, verbose=1)","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:35:19.830236Z","iopub.execute_input":"2026-08-03T11:35:19.83051Z","iopub.status.idle":"2026-08-03T11:35:20.601628Z","shell.execute_reply.started":"2026-08-03T11:35:19.830486Z","shell.execute_reply":"2026-08-03T11:35:20.600959Z"},"id":"sGuxq3L4bVeI","outputId":"7e04ce98-17a8-4ad9-ee36-39901ed43f7a","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_pred = []\nconfidence = []\n\nfor i in range(len(predict)):\n    y_pred.append(np.argmax(predict[i]))\n    confidence.append(predict[i][y_pred[i]].round(2))\n\ny_pred = LE.inverse_transform(y_pred)","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:35:20.60265Z","iopub.execute_input":"2026-08-03T11:35:20.603038Z","iopub.status.idle":"2026-08-03T11:35:20.612649Z","shell.execute_reply.started":"2026-08-03T11:35:20.603013Z","shell.execute_reply":"2026-08-03T11:35:20.611813Z"},"id":"w1OqU7XwbVeJ","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"\\nEvaluation of the model on test data\")\nscore = model.evaluate(X_test, y_test)\nprint(\"Test loss, Test accuracy:\", score[0], score[1])","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:35:20.613659Z","iopub.execute_input":"2026-08-03T11:35:20.613947Z","iopub.status.idle":"2026-08-03T11:35:20.811739Z","shell.execute_reply.started":"2026-08-03T11:35:20.613924Z","shell.execute_reply":"2026-08-03T11:35:20.811143Z"},"id":"GT8MpqeebVeJ","outputId":"ba204e50-1402-4de2-c1c9-ac7b612901fc","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_test = LE.inverse_transform(y_test)","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:35:20.812686Z","iopub.execute_input":"2026-08-03T11:35:20.812982Z","iopub.status.idle":"2026-08-03T11:35:20.817313Z","shell.execute_reply.started":"2026-08-03T11:35:20.812951Z","shell.execute_reply":"2026-08-03T11:35:20.816564Z"},"id":"BW9wwOtPbVeK","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"traindf = load_traindf()","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:35:20.818218Z","iopub.execute_input":"2026-08-03T11:35:20.818587Z","iopub.status.idle":"2026-08-03T11:35:24.583563Z","shell.execute_reply.started":"2026-08-03T11:35:20.818552Z","shell.execute_reply":"2026-08-03T11:35:24.582904Z"},"id":"5t38R8C8bVeK","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"col = 5\nn_pred_rep = 30\n\nk = 0\nfor k in range(n_pred_rep):\n    plt.figure(figsize=(16,7))\n    img_pred = X_test[k]\n    plt.subplot(1, col, 1)\n    plt.xticks([])\n    plt.yticks([])\n    plt.title('Image to predict #'+ str(k))\n    str1 = 'Predicted class: ' + str(y_pred[k])\n    str2 = 'Confidence: ' + str(confidence[k])\n    str3 = 'Actual class: ' + str(y_test[k])\n    plt.xlabel(str1 + '\\n' + str2 + '\\n' + str3, fontsize = 12, weight = 'bold')\n    plt.imshow(img_pred)\n\n    i=0\n    img_class_df = traindf[traindf['landmark_id']==y_pred[k]]\n\n\n    for i in range(len(img_class_df)):\n        if i < (col-1):\n            img_class_path = img_class_df.iloc[i,2]\n            img_class = img_read_resize(img_class_path)\n            plt.subplot(1, col, i+2)\n            plt.xticks([])\n            plt.yticks([])\n            plt.title('Image of class '+ str(y_pred[k]))\n            plt.xlabel(str())\n            plt.imshow(img_class)\n        else:\n            break;","metadata":{"execution":{"iopub.status.busy":"2026-08-03T11:35:24.58445Z","iopub.execute_input":"2026-08-03T11:35:24.584765Z","iopub.status.idle":"2026-08-03T11:35:33.146898Z","shell.execute_reply.started":"2026-08-03T11:35:24.584742Z","shell.execute_reply":"2026-08-03T11:35:33.146242Z"},"id":"yeXm_cv2bVeK","outputId":"a412ef96-2f7a-40fe-c4f7-361a10176317","trusted":true},"outputs":[],"execution_count":null}]}