{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"#  imports the NumPy library and assigns it the alias \"np\" for convenience.\nimport numpy as np \n\n# This line imports the pandas library, which is a popular library for data manipulation and analysis in Python.\nimport pandas as pd\n\n# This line imports the os library, which provides a way to interact with the operating system\nimport os\n\n# This line imports the TensorFlow library, which is a popular library for machine learning and deep learning.\nimport tensorflow as tf\n# This line imports the Keras library, which is a high-level neural networks API, written in Python and capable of running on top of TensorFlow.\nimport tensorflow.keras as keras\n# This line imports the layers module from the Keras library, which provides a set of reusable neural network layers.\nfrom tensorflow.keras import layers\n# This line imports the preprocessing module from the experimental module of the layers module in the Keras library\nfrom tensorflow.keras.layers.experimental import preprocessing\n# This line imports three callback functions from the callbacks module of the Keras library, which are used to stop the training process early if the model is not improving\nfrom tensorflow.keras.callbacks import EarlyStopping\nfrom tensorflow.keras.callbacks import ReduceLROnPlateau\nfrom tensorflow.keras.callbacks import ModelCheckpoint\n\n#This line imports the regularizers module from the Keras library, which provides a way to apply different regularization techniques on the model's weights.\nfrom tensorflow.keras import regularizers\n\n# This line imports the pyplot module of the matplotlib library\nimport matplotlib.pyplot as plt\n\n# This line imports the OpenCV library, which is a library for computer vision tasks, such as image processing and video analysis.\nimport cv2\n\n# This line imports the LabelEncoder class from the preprocessing module of the scikit-learn library\nfrom sklearn.preprocessing import LabelEncoder\n# This line imports the train_test_split function from the model_selection module of the scikit-learn library\nfrom sklearn.model_selection import train_test_split\n# This line imports the confusion_matrix function from the metrics module of the scikit-learn library\nfrom sklearn.metrics import confusion_matrix\n\n# This line imports the sys module, which provides access to some variables used or maintained by the interpreter\nimport sys\n# This line imports the gc module, which provides access to the garbage collector for reference cycles\nimport gc\n# This line imports the time module, which provides various time-related functions\nimport time\n# This line imports the seaborn library, which is a data visualization library built on top of matplotlib\nimport seaborn as sns\n#This line sets a constant value for the variable SEED to 42. This value can be used as a seed for random number generators to ensure reproducibility of results.\nSEED = 42","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-10-28T18:04:43.35952Z","iopub.execute_input":"2022-10-28T18:04:43.359875Z","iopub.status.idle":"2022-10-28T18:04:43.36687Z","shell.execute_reply.started":"2022-10-28T18:04:43.359846Z","shell.execute_reply":"2022-10-28T18:04:43.365718Z"}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# loads the data and preprocesses it\ndef load_traindf():\n    traindf = pd.read_csv('../input/landmark-recognition-2021/train.csv')\n    traindf['img_path'] = (traindf['id'].apply(lambda r: os.path.join\n                            ('../input/landmark-recognition-2021/train', r[0], r[1], r[2], r + '.jpg')))\n    \n    traindf['landmark_id'] = traindf['landmark_id'].apply(lambda x: np.int32(x))\n    \n    return traindf\n\n# reads the image file and resize it to a specified size\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# This block of code defines a function called get_size() that calculates the size of an object and its sub-objects in bytes recursively, which can be used to monitor memory usage and optimize the memory usage of a program.\ndef get_size(obj, seen=None):\n    \"\"\"Recursively finds size of objects\"\"\"\n    size = sys.getsizeof(obj)\n    if seen is None:\n        seen = set()\n    obj_id = id(obj)\n    if obj_id in seen:\n        return 0\n    seen.add(obj_id)\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    elif hasattr(obj, '__dict__'):\n        size += get_size(obj.__dict__, seen)\n    elif hasattr(obj, '__iter__') and not isinstance(obj, (str, bytes, bytearray)):\n        size += sum([get_size(i, seen) for i in obj])\n    return size","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:04:43.42154Z","iopub.execute_input":"2022-10-28T18:04:43.421804Z","iopub.status.idle":"2022-10-28T18:04:43.43115Z","shell.execute_reply.started":"2022-10-28T18:04:43.42178Z","shell.execute_reply":"2022-10-28T18:04:43.430232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# loads the training data from a CSV file\ntraindf = load_traindf()\n# creates a variable called landmark_unique which is the number of unique landmarks in the training dataset by using the unique() function on the 'landmark_id' column of the dataframe and finding the length of the returned unique values.\nlandmark_unique = len(traindf['landmark_id'].unique())\n# simply returning the dataframe, which can be used for further analysis or training a model.\ntraindf\n","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:04:43.499315Z","iopub.execute_input":"2022-10-28T18:04:43.501142Z","iopub.status.idle":"2022-10-28T18:04:50.445263Z","shell.execute_reply.started":"2022-10-28T18:04:43.501115Z","shell.execute_reply":"2022-10-28T18:04:50.444101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# function call to the previously defined get_size() function\nget_size(traindf)","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:04:50.447678Z","iopub.execute_input":"2022-10-28T18:04:50.448115Z","iopub.status.idle":"2022-10-28T18:04:52.638627Z","shell.execute_reply.started":"2022-10-28T18:04:50.448063Z","shell.execute_reply":"2022-10-28T18:04:52.637501Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# used to display a summary of the DataFrame's memory usage, including memory usage of the sub-objects.\ntraindf.info(memory_usage='deep')","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:04:52.640383Z","iopub.execute_input":"2022-10-28T18:04:52.640769Z","iopub.status.idle":"2022-10-28T18:04:53.049877Z","shell.execute_reply.started":"2022-10-28T18:04:52.640731Z","shell.execute_reply":"2022-10-28T18:04:53.048775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# used to analyze the training dataset, by providing information about the number of images in the dataset, the number of different classes, the minimum and maximum class value and the number of repetitions of elements for each class in the dataset.\nprint('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":"2022-10-28T18:04:53.052458Z","iopub.execute_input":"2022-10-28T18:04:53.053044Z","iopub.status.idle":"2022-10-28T18:04:53.336714Z","shell.execute_reply.started":"2022-10-28T18:04:53.053007Z","shell.execute_reply":"2022-10-28T18:04:53.335728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# creates a figure with a specified size, \nplt.figure(figsize=(25,10))\n\n# then generates a random sample of 20 images from the training dataset and plots them on the figure in a 4x5 grid, with the x and y axis ticks removed and the image size labeled for each image\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    \n# and finally it shows the plot.    \nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:04:53.338037Z","iopub.execute_input":"2022-10-28T18:04:53.338635Z","iopub.status.idle":"2022-10-28T18:04:55.389938Z","shell.execute_reply.started":"2022-10-28T18:04:53.338598Z","shell.execute_reply":"2022-10-28T18:04:55.388738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"IMG_SIZE = 128  \n\nMIN_CLASS = 0\nMAX_CLASS = 500\n\n# contains only the rows in the traindf dataframe where the landmark_id column is greater than MIN_CLASS and less than or equal to MAX_CLASS.\ntraindf_s = traindf[(MIN_CLASS < traindf['landmark_id']) & (traindf['landmark_id'] <= MAX_CLASS)]\n\n#defines a variable UNDERSAMPLING_THRESHOLD with a value of 80, it will be used later in the code.\nUNDERSAMPLING_THRESHOLD = 80   \n\n# groups the dataframe traindf_s by the 'landmark_id' column\ntraindf_s = (traindf_s.groupby('landmark_id', group_keys=False).\n           apply(lambda x: x.sample(n = min(len(x), UNDERSAMPLING_THRESHOLD), random_state= SEED)))\n# resets the index of the traindf_s dataframe and drop the old index.\ntraindf_s.reset_index(inplace=True, drop=True)\n# shows the count of unique values in the 'landmark_id' column of the traindf_s dataframe.\ntraindf_s['landmark_id'].value_counts()\n\n# creates a variable N_DATA that contains the length of the 'landmark_id' column of the traindf_s dataframe.\nN_DATA = len(traindf_s['landmark_id'])\n# contains the unique values of the 'landmark_id' column of the traindf_s dataframe.\nclases = traindf_s['landmark_id'].unique()\n# creates a variable N_CLASS that contains the length of the clases variable, which represents the number of classes in the dataframe.\nN_CLASS = len(clases)\n\n# print some statistics about the preprocessed data, including the number of data points, number of classes, \n# minimum and maximum class value and the number of repetitions of elements for each class in the dataset after the undersampling operation.\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":"2022-10-28T18:04:55.391008Z","iopub.execute_input":"2022-10-28T18:04:55.391376Z","iopub.status.idle":"2022-10-28T18:04:55.716861Z","shell.execute_reply.started":"2022-10-28T18:04:55.391341Z","shell.execute_reply":"2022-10-28T18:04:55.715711Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# gives summary statistics of the distribution of unique values count in the 'landmark_id' column of the 'traindf_s' DataFrame after the under-sampling step.\ntraindf_s['landmark_id'].value_counts().describe()","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:04:55.718508Z","iopub.execute_input":"2022-10-28T18:04:55.71889Z","iopub.status.idle":"2022-10-28T18:04:55.73169Z","shell.execute_reply.started":"2022-10-28T18:04:55.718853Z","shell.execute_reply":"2022-10-28T18:04:55.730537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# creates a figure with a specified size\nplt.figure(figsize=(25,10))\n\n# generates a random sample of 20 images from the preprocessed dataset and plots them on the figure in a 4x5 grid\nfor i in range(20):\n    j = np.random.randint(0, N_DATA)\n    # images are also resized to a specified size by calling the function img_read_resize().\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\n# shows the plot\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:04:55.733519Z","iopub.execute_input":"2022-10-28T18:04:55.733795Z","iopub.status.idle":"2022-10-28T18:04:57.025948Z","shell.execute_reply.started":"2022-10-28T18:04:55.733771Z","shell.execute_reply":"2022-10-28T18:04:57.025169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":"2022-10-28T18:04:57.027314Z","iopub.execute_input":"2022-10-28T18:04:57.027948Z","iopub.status.idle":"2022-10-28T18:05:32.830654Z","shell.execute_reply.started":"2022-10-28T18:04:57.02791Z","shell.execute_reply":"2022-10-28T18:05:32.82963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Label Encoding\n\nLE = LabelEncoder()\nLE.fit(clases)\ny_LE = LE.transform(y)","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:05:32.834368Z","iopub.execute_input":"2022-10-28T18:05:32.83501Z","iopub.status.idle":"2022-10-28T18:05:32.842901Z","shell.execute_reply.started":"2022-10-28T18:05:32.834976Z","shell.execute_reply":"2022-10-28T18:05:32.841743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":"2022-10-28T18:05:32.8445Z","iopub.execute_input":"2022-10-28T18:05:32.845035Z","iopub.status.idle":"2022-10-28T18:05:34.199775Z","shell.execute_reply.started":"2022-10-28T18:05:32.845Z","shell.execute_reply":"2022-10-28T18:05:34.198605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Separates the 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":"2022-10-28T18:05:34.201331Z","iopub.execute_input":"2022-10-28T18:05:34.201887Z","iopub.status.idle":"2022-10-28T18:05:34.881484Z","shell.execute_reply.started":"2022-10-28T18:05:34.20185Z","shell.execute_reply":"2022-10-28T18:05:34.880367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# applies data augmentation to an image \n# and shows the original and modified images in a figure.\n\ndata_augmentation = tf.keras.Sequential([\n    preprocessing.RandomZoom(height_factor=(-0.2, 0.2)),\n    preprocessing.RandomContrast(0.4),\n    preprocessing.RandomTranslation(height_factor= (-0.2, 0.2), width_factor=(-0.2, 0.2)), \n    preprocessing.RandomRotation(factor= (-0.1, 0.1)),  \n])\n\nplt.figure(figsize=(25,7))\nj = 1 \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":"2022-10-28T18:05:34.88308Z","iopub.execute_input":"2022-10-28T18:05:34.883474Z","iopub.status.idle":"2022-10-28T18:05:38.974809Z","shell.execute_reply.started":"2022-10-28T18:05:34.883437Z","shell.execute_reply":"2022-10-28T18:05:38.974012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#  performs oversampling \n# and prints time taken and data count after oversampling.\nstart_time = time.time()\n\nOVERSAMPLING_THRESHOLD = 0.2 * UNDERSAMPLING_THRESHOLD    \ni=0; n=0; k=0\n\nfor i in range(N_CLASS):\n    cont=0\n    for n in range(len(y_train)):\n        if y_train[n] == i:\n            cont = cont+1\n                  \n    if cont < OVERSAMPLING_THRESHOLD:\n        img_class_i = X_train[y_train==i]\n        for k in range(int(OVERSAMPLING_THRESHOLD-cont)):\n            X_train = np.concatenate((X_train,np.array([(img_class_i[np.random.randint(len(img_class_i))])])),axis = 0)\n            y_train = np.append(y_train, 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))","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:05:38.976016Z","iopub.execute_input":"2022-10-28T18:05:38.976505Z","iopub.status.idle":"2022-10-28T18:16:01.162823Z","shell.execute_reply.started":"2022-10-28T18:05:38.976473Z","shell.execute_reply":"2022-10-28T18:16:01.161652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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= 1000          # Number of epochs to train\nlr = 0.01                # Learning Rate\nweightDecay = regularizers.L2(0.01) # Regularization of weights","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:16:01.164317Z","iopub.execute_input":"2022-10-28T18:16:01.164956Z","iopub.status.idle":"2022-10-28T18:16:01.171485Z","shell.execute_reply.started":"2022-10-28T18:16:01.164918Z","shell.execute_reply":"2022-10-28T18:16:01.170357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_model():\n    \n    model = keras.Sequential([\n        \n        #DATA AUGMENTATION\n        preprocessing.RandomZoom(height_factor=(-0.2, 0.2)),\n        preprocessing.RandomContrast(0.4),\n        preprocessing.RandomTranslation(height_factor= (-0.2, 0.2), width_factor=(-0.2, 0.2)),  \n        preprocessing.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.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":"2022-10-28T18:16:01.173208Z","iopub.execute_input":"2022-10-28T18:16:01.173638Z","iopub.status.idle":"2022-10-28T18:16:01.192767Z","shell.execute_reply.started":"2022-10-28T18:16:01.173591Z","shell.execute_reply":"2022-10-28T18:16:01.191707Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":"2022-10-28T18:16:01.195352Z","iopub.execute_input":"2022-10-28T18:16:01.196038Z","iopub.status.idle":"2022-10-28T18:16:01.210072Z","shell.execute_reply.started":"2022-10-28T18:16:01.196002Z","shell.execute_reply":"2022-10-28T18:16:01.209043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":"2022-10-28T18:16:01.211522Z","iopub.execute_input":"2022-10-28T18:16:01.211932Z","iopub.status.idle":"2022-10-28T18:35:30.321714Z","shell.execute_reply.started":"2022-10-28T18:16:01.211899Z","shell.execute_reply":"2022-10-28T18:35:30.3207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# displays a summary of a model's architecture, including layers, \n# output shapes, and number of parameters.\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:39:01.921043Z","iopub.execute_input":"2022-10-28T18:39:01.921531Z","iopub.status.idle":"2022-10-28T18:39:01.936671Z","shell.execute_reply.started":"2022-10-28T18:39:01.921489Z","shell.execute_reply":"2022-10-28T18:39:01.935499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# This code is creating a figure with 12 subplots of images and adding labels to the subplots.\nplt.figure(figsize=(25,7))\n\nfor i in range(12):  \n    img = X_test[i]\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":"2022-10-28T18:42:36.711999Z","iopub.execute_input":"2022-10-28T18:42:36.712418Z","iopub.status.idle":"2022-10-28T18:42:38.038332Z","shell.execute_reply.started":"2022-10-28T18:42:36.712383Z","shell.execute_reply":"2022-10-28T18:42:38.037347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# predict input data and saves the predictions in a variable\npredict = model.predict(X_test, verbose=1) ","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:42:43.424112Z","iopub.execute_input":"2022-10-28T18:42:43.424483Z","iopub.status.idle":"2022-10-28T18:42:43.733426Z","shell.execute_reply.started":"2022-10-28T18:42:43.424451Z","shell.execute_reply":"2022-10-28T18:42:43.732526Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#  creates two lists from model predictions, \n# and applies inverse_transform to the first list.\ny_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":"2022-10-28T18:44:16.872631Z","iopub.execute_input":"2022-10-28T18:44:16.873001Z","iopub.status.idle":"2022-10-28T18:44:16.883671Z","shell.execute_reply.started":"2022-10-28T18:44:16.872971Z","shell.execute_reply":"2022-10-28T18:44:16.882461Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# evaluates the model's performance on test data \n# and prints the test loss and test accuracy.\nprint(\"\\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":"2022-10-28T18:44:55.462696Z","iopub.execute_input":"2022-10-28T18:44:55.463047Z","iopub.status.idle":"2022-10-28T18:44:55.584655Z","shell.execute_reply.started":"2022-10-28T18:44:55.463019Z","shell.execute_reply":"2022-10-28T18:44:55.58364Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# reverses the encoded labels of y_test back to their original values.\ny_test = LE.inverse_transform(y_test)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# loads a dataframe into a variable\ntraindf = load_traindf()","metadata":{"execution":{"iopub.status.busy":"2022-10-28T18:45:35.419718Z","iopub.execute_input":"2022-10-28T18:45:35.420066Z","iopub.status.idle":"2022-10-28T18:45:41.810772Z","shell.execute_reply.started":"2022-10-28T18:45:35.420036Z","shell.execute_reply":"2022-10-28T18:45:41.809582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# displays test images with their predictions, \n# actual classes and similar images from a dataframe.\ncol = 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":"2022-10-28T18:48:18.076849Z","iopub.execute_input":"2022-10-28T18:48:18.077203Z","iopub.status.idle":"2022-10-28T18:48:30.44097Z","shell.execute_reply.started":"2022-10-28T18:48:18.077173Z","shell.execute_reply":"2022-10-28T18:48:30.440163Z"},"trusted":true},"execution_count":null,"outputs":[]}]}