{"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":"import numpy as np\nimport pandas as pd\nimport tensorflow as tf\nimport os","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:12:56.04687Z","iopub.execute_input":"2021-09-25T07:12:56.04714Z","iopub.status.idle":"2021-09-25T07:12:56.05306Z","shell.execute_reply.started":"2021-09-25T07:12:56.047097Z","shell.execute_reply":"2021-09-25T07:12:56.050828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.listdir('../input/hotel-id-2021-fgvc8')","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:12:58.661182Z","iopub.execute_input":"2021-09-25T07:12:58.661735Z","iopub.status.idle":"2021-09-25T07:12:58.668717Z","shell.execute_reply.started":"2021-09-25T07:12:58.661702Z","shell.execute_reply":"2021-09-25T07:12:58.667903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv('../input/hotel-id-2021-fgvc8/train.csv')\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:01.055596Z","iopub.execute_input":"2021-09-25T07:13:01.056142Z","iopub.status.idle":"2021-09-25T07:13:01.156077Z","shell.execute_reply.started":"2021-09-25T07:13:01.056088Z","shell.execute_reply":"2021-09-25T07:13:01.155216Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images ='../input/hotel-id-2021-fgvc8/train_images/'","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:02.641761Z","iopub.execute_input":"2021-09-25T07:13:02.642528Z","iopub.status.idle":"2021-09-25T07:13:02.646506Z","shell.execute_reply.started":"2021-09-25T07:13:02.642481Z","shell.execute_reply":"2021-09-25T07:13:02.645546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['train_images']= train_images + df.chain.astype(str) +'/'+ df.image\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:03.366233Z","iopub.execute_input":"2021-09-25T07:13:03.366768Z","iopub.status.idle":"2021-09-25T07:13:03.536357Z","shell.execute_reply.started":"2021-09-25T07:13:03.366734Z","shell.execute_reply":"2021-09-25T07:13:03.535523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_dash = df[:100]\ndf_dash.head()","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:04.275574Z","iopub.execute_input":"2021-09-25T07:13:04.276354Z","iopub.status.idle":"2021-09-25T07:13:04.289598Z","shell.execute_reply.started":"2021-09-25T07:13:04.276306Z","shell.execute_reply":"2021-09-25T07:13:04.288563Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_dash.shape","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:05.107598Z","iopub.execute_input":"2021-09-25T07:13:05.108275Z","iopub.status.idle":"2021-09-25T07:13:05.113577Z","shell.execute_reply.started":"2021-09-25T07:13:05.108234Z","shell.execute_reply":"2021-09-25T07:13:05.112732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"print random images to see that my train images is showing or not","metadata":{}},{"cell_type":"code","source":"# import required libraries\nimport random\nfrom IPython.core.display import Image\nfrom IPython.display import display","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:09.432456Z","iopub.execute_input":"2021-09-25T07:13:09.43271Z","iopub.status.idle":"2021-09-25T07:13:09.439509Z","shell.execute_reply.started":"2021-09-25T07:13:09.432683Z","shell.execute_reply":"2021-09-25T07:13:09.438752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for n in range(3):\n    tr_image = random.choice(list(df['train_images']))\n    print(tr_image)\n    display(Image(tr_image,width=400,height=400))\n    print('\\n')","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:10.47666Z","iopub.execute_input":"2021-09-25T07:13:10.476927Z","iopub.status.idle":"2021-09-25T07:13:10.551022Z","shell.execute_reply.started":"2021-09-25T07:13:10.4769Z","shell.execute_reply":"2021-09-25T07:13:10.550223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train_images_reading(path,labels):\n    \n    images = tf.io.read_file(path)\n    \n    images = tf.image.decode_jpeg(images, channels=3)\n    \n    images = tf.image.resize(images, [64,64])\n    \n    images = tf.cast(images, tf.float32)\n    \n    images /= 255.0\n    \n    return(images,labels)","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:11.70307Z","iopub.execute_input":"2021-09-25T07:13:11.703633Z","iopub.status.idle":"2021-09-25T07:13:11.708954Z","shell.execute_reply.started":"2021-09-25T07:13:11.703596Z","shell.execute_reply":"2021-09-25T07:13:11.708196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# data augmentation techniques on image used from this colab file \n#https://colab.research.google.com/github/tensorflow/docs/blob/master/site/en/tutorials/images/data_augmentation.ipynb\ndef train_images_preprocessing(images, labels):\n    \n    images = tf.image.stateless_random_flip_left_right(images,seed=(2,0))\n    \n    images = tf.image.stateless_random_flip_up_down(images,seed=(2,0))\n    \n    images = tf.image.rot90(images)\n    \n    images = tf.image.stateless_random_brightness(images, max_delta=32.0 / 255.0,seed=(2,0))\n    \n    images = tf.image.stateless_random_saturation(images, lower=0.5, upper=1.5,seed=(2,0))\n    \n    images = tf.image.stateless_random_hue(images, 0.2,seed=(2,0))\n\n    #Make sure the image is still in [0, 1]\n    images = tf.clip_by_value(images, 0.0, 1.0)\n\n    return (images, labels) , labels","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:39.12911Z","iopub.execute_input":"2021-09-25T07:13:39.129466Z","iopub.status.idle":"2021-09-25T07:13:39.139412Z","shell.execute_reply.started":"2021-09-25T07:13:39.129429Z","shell.execute_reply":"2021-09-25T07:13:39.13782Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import library for performing Label Encoding on hotel ids\nfrom sklearn.preprocessing import LabelEncoder","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:40.354221Z","iopub.execute_input":"2021-09-25T07:13:40.354888Z","iopub.status.idle":"2021-09-25T07:13:40.358903Z","shell.execute_reply.started":"2021-09-25T07:13:40.354848Z","shell.execute_reply":"2021-09-25T07:13:40.357927Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labelencoder = LabelEncoder()\ndf['hotel_id'] = labelencoder.fit_transform(df['hotel_id'])","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:40.997694Z","iopub.execute_input":"2021-09-25T07:13:40.998369Z","iopub.status.idle":"2021-09-25T07:13:41.013058Z","shell.execute_reply.started":"2021-09-25T07:13:40.998333Z","shell.execute_reply":"2021-09-25T07:13:41.012342Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labelencoder.classes_","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:41.887279Z","iopub.execute_input":"2021-09-25T07:13:41.887942Z","iopub.status.idle":"2021-09-25T07:13:41.894111Z","shell.execute_reply.started":"2021-09-25T07:13:41.887894Z","shell.execute_reply":"2021-09-25T07:13:41.893288Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pickle","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:42.800692Z","iopub.execute_input":"2021-09-25T07:13:42.800964Z","iopub.status.idle":"2021-09-25T07:13:42.805095Z","shell.execute_reply.started":"2021-09-25T07:13:42.800936Z","shell.execute_reply":"2021-09-25T07:13:42.804348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save label encoder to use in prediction\nle_path = 'labelencoder.pkl'\nwith open(le_path, 'wb') as fw:\n    pickle.dump(labelencoder, fw)","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:43.268084Z","iopub.execute_input":"2021-09-25T07:13:43.268658Z","iopub.status.idle":"2021-09-25T07:13:43.273283Z","shell.execute_reply.started":"2021-09-25T07:13:43.268626Z","shell.execute_reply":"2021-09-25T07:13:43.272587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# save the train images and hotel ids as a tensor\nlabel_ids = tf.convert_to_tensor(np.array(df['hotel_id']), dtype=tf.int32)\nimage_files  = tf.convert_to_tensor(df['train_images'].tolist(), dtype=tf.string)","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:44.287834Z","iopub.execute_input":"2021-09-25T07:13:44.288367Z","iopub.status.idle":"2021-09-25T07:13:44.335708Z","shell.execute_reply.started":"2021-09-25T07:13:44.28833Z","shell.execute_reply":"2021-09-25T07:13:44.334957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(label_ids)","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:47.751317Z","iopub.execute_input":"2021-09-25T07:13:47.751925Z","iopub.status.idle":"2021-09-25T07:13:47.757532Z","shell.execute_reply.started":"2021-09-25T07:13:47.751887Z","shell.execute_reply":"2021-09-25T07:13:47.756638Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_files[:2]","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:48.368007Z","iopub.execute_input":"2021-09-25T07:13:48.36865Z","iopub.status.idle":"2021-09-25T07:13:48.374763Z","shell.execute_reply.started":"2021-09-25T07:13:48.368613Z","shell.execute_reply":"2021-09-25T07:13:48.373861Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_ids[0:5]","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:50.186851Z","iopub.execute_input":"2021-09-25T07:13:50.187114Z","iopub.status.idle":"2021-09-25T07:13:50.19717Z","shell.execute_reply.started":"2021-09-25T07:13:50.187086Z","shell.execute_reply":"2021-09-25T07:13:50.196255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a train dataset\n#https://udibhaskar.github.io/practical-ml/debugging%20nn/neural%20network/overfit/underfit/2020/02/03/Effective_Training_and_Debugging_of_a_Neural_Networks.html\n#read all the train file names along with labels to create a Dataset type object\ntrain_dataset = tf.data.Dataset.from_tensor_slices((image_files, label_ids))\n\n# shuffle the dataset\ntrain_dataset = train_dataset.shuffle(len(image_files))\n\n#this map fucntion is also taken from \n#https://colab.research.google.com/github/tensorflow/docs/blob/master/site/en/tutorials/images/data_augmentation.ipynb\n# Map the read_train_image function on the dataset in order to read dataset\ntrain_dataset = train_dataset.map(train_images_reading,num_parallel_calls=tf.data.AUTOTUNE)\n\n# Map the read_train_image function on the dataset in order to get preprocessed dataset\ntrain_dataset = train_dataset.map(train_images_preprocessing,num_parallel_calls=tf.data.AUTOTUNE)\n\n#bacth and prefetch the dataset\ntrain_dataset = train_dataset.batch(64)\ntrain_dataset = train_dataset.prefetch(2)","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:51.959713Z","iopub.execute_input":"2021-09-25T07:13:51.959969Z","iopub.status.idle":"2021-09-25T07:13:52.064943Z","shell.execute_reply.started":"2021-09-25T07:13:51.959941Z","shell.execute_reply":"2021-09-25T07:13:52.064182Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:53.712173Z","iopub.execute_input":"2021-09-25T07:13:53.712778Z","iopub.status.idle":"2021-09-25T07:13:53.719351Z","shell.execute_reply.started":"2021-09-25T07:13:53.712742Z","shell.execute_reply":"2021-09-25T07:13:53.718336Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for input_text, output_label in train_dataset:\n    print(input_text[0:3], output_label[0:3])\n    break","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:13:54.856365Z","iopub.execute_input":"2021-09-25T07:13:54.857067Z","iopub.status.idle":"2021-09-25T07:13:56.136211Z","shell.execute_reply.started":"2021-09-25T07:13:54.857034Z","shell.execute_reply":"2021-09-25T07:13:56.135442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_dataset)","metadata":{"execution":{"iopub.status.busy":"2021-09-25T06:46:17.915882Z","iopub.execute_input":"2021-09-25T06:46:17.916303Z","iopub.status.idle":"2021-09-25T06:46:17.923518Z","shell.execute_reply.started":"2021-09-25T06:46:17.916263Z","shell.execute_reply":"2021-09-25T06:46:17.92263Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import required model libraries\nimport tensorflow as tf\nfrom tensorflow.keras import Model\nfrom tensorflow.keras.layers import Dense,Dropout,Flatten,Input\nfrom tensorflow.keras.applications import ResNet50","metadata":{"execution":{"iopub.status.busy":"2021-09-25T06:46:19.090162Z","iopub.execute_input":"2021-09-25T06:46:19.09228Z","iopub.status.idle":"2021-09-25T06:46:19.09926Z","shell.execute_reply.started":"2021-09-25T06:46:19.092239Z","shell.execute_reply":"2021-09-25T06:46:19.098651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#https://www.kaggle.com/chankhavu/keras-layers-arcface-cosface-adacos\n#Image representations were trained by Arcface as it is very good for face recognition and also used by 1'st place winner and bucnch of people in this competiton \nclass ArcMarginLoss(tf.keras.layers.Layer):\n    \n    def __init__(self, num_classes, margin=0.5, logist_scale=64, **kwargs):\n        super(ArcMarginLoss, self).__init__(**kwargs)\n        self.num_classes = num_classes\n        self.margin = margin\n        self.logist_scale = logist_scale\n\n    def build(self, input_shape):\n        self.w = self.add_variable(\n            \"weights\", shape=[int(input_shape[-1]), self.num_classes])\n        self.cos_m = tf.identity(math.cos(self.margin), name='cos_m')\n        self.sin_m = tf.identity(math.sin(self.margin), name='sin_m')\n        self.th = tf.identity(math.cos(math.pi - self.margin), name='th')\n        self.mm = tf.multiply(self.sin_m, self.margin, name='mm')\n\n    def call(self, embds, labels):\n        normed_embds = tf.nn.l2_normalize(embds, axis=1, name='normed_embd')\n        normed_w = tf.nn.l2_normalize(self.w, axis=0, name='normed_weights')\n\n        cos_t = tf.matmul(normed_embds, normed_w, name='cos_t')\n        sin_t = tf.sqrt(1. - cos_t ** 2, name='sin_t')\n\n        cos_mt = tf.subtract(\n            cos_t * self.cos_m, sin_t * self.sin_m, name='cos_mt')\n\n        cos_mt = tf.where(cos_t > self.th, cos_mt, cos_t - self.mm)\n\n        mask = tf.one_hot(tf.cast(labels, tf.int32), depth=self.num_classes,\n                          name='one_hot_mask')\n\n        logists = tf.where(mask == 1., cos_mt, cos_t)\n        logists = tf.multiply(logists, self.logist_scale, 'arcface_logist')\n\n        return logists","metadata":{"execution":{"iopub.status.busy":"2021-09-25T06:46:33.051646Z","iopub.execute_input":"2021-09-25T06:46:33.051939Z","iopub.status.idle":"2021-09-25T06:46:33.068114Z","shell.execute_reply.started":"2021-09-25T06:46:33.05191Z","shell.execute_reply":"2021-09-25T06:46:33.067199Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_classes=len(set(df['hotel_id'].values))","metadata":{"execution":{"iopub.status.busy":"2021-09-25T06:55:02.423885Z","iopub.execute_input":"2021-09-25T06:55:02.424215Z","iopub.status.idle":"2021-09-25T06:55:02.457243Z","shell.execute_reply.started":"2021-09-25T06:55:02.424182Z","shell.execute_reply":"2021-09-25T06:55:02.456263Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#import keras\nfrom tensorflow.keras.layers import SpatialDropout1D, LSTM, BatchNormalization,concatenate,Flatten,Embedding,Dense,Dropout,MaxPooling2D,Reshape","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:02:55.749552Z","iopub.execute_input":"2021-09-25T07:02:55.749805Z","iopub.status.idle":"2021-09-25T07:02:55.753719Z","shell.execute_reply.started":"2021-09-25T07:02:55.749778Z","shell.execute_reply":"2021-09-25T07:02:55.753021Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#def ArcFaceModel():\n    \n# The input layer\nx = inputs = Input(shape=(64,64,3,), name='input_image')\n\n# The ResNet50 model using imagenet weights\nx = ResNet50(include_top=False,weights='imagenet')(x)\n\nx = tf.keras.layers.BatchNormalization()(x)\n\n#Dropout layer\nx = Dropout(rate=0.5)(x)\n\n#Flatten layer\nx = Flatten()(x)\n\n#A dense layer of size 64 with l2 regularization\nx = Dense(64, kernel_regularizer=tf.keras.regularizers.l2(5e-4))(x)\n\noutput = Dense(num_classes, activation=\"softmax\")(x)\n\nmodel = Model(inputs=inputs, outputs=output)\n\n    #Creates embeddings of size (batchsize,64)\n    #embeds =tf.keras.layers.BatchNormalization()(x)\n    \n    #Input layer for labels\n    #labels = Input([], name='label')\n    \n            \n    #compue logits using the ArcMarginPenaltyLogists call giving embeddings and labels as inputs\n    #logist = ArcMarginLoss(num_classes=len(set(df['hotel_id'].values)), margin=0.5,\n                             #logist_scale=64)(embeds, labels)\n    \n    #return the model which takes (input,label) as input and gives logits as output \n    #return Model((inputs, labels), output)\n    \n","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:09:34.08962Z","iopub.execute_input":"2021-09-25T07:09:34.089888Z","iopub.status.idle":"2021-09-25T07:09:35.814789Z","shell.execute_reply.started":"2021-09-25T07:09:34.089859Z","shell.execute_reply":"2021-09-25T07:09:35.814025Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.summary()","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:09:37.557705Z","iopub.execute_input":"2021-09-25T07:09:37.557966Z","iopub.status.idle":"2021-09-25T07:09:37.581991Z","shell.execute_reply.started":"2021-09-25T07:09:37.55794Z","shell.execute_reply":"2021-09-25T07:09:37.581301Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# clear session\ntf.keras.backend.clear_session()","metadata":{"execution":{"iopub.status.busy":"2021-09-25T06:56:45.88346Z","iopub.execute_input":"2021-09-25T06:56:45.884038Z","iopub.status.idle":"2021-09-25T06:56:45.893671Z","shell.execute_reply.started":"2021-09-25T06:56:45.884Z","shell.execute_reply":"2021-09-25T06:56:45.892821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import math","metadata":{"execution":{"iopub.status.busy":"2021-09-25T06:56:48.27484Z","iopub.execute_input":"2021-09-25T06:56:48.275093Z","iopub.status.idle":"2021-09-25T06:56:48.278784Z","shell.execute_reply.started":"2021-09-25T06:56:48.275067Z","shell.execute_reply":"2021-09-25T06:56:48.277962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# create the model\nmodel = ArcFaceModel()","metadata":{"execution":{"iopub.status.busy":"2021-09-25T06:56:58.928099Z","iopub.execute_input":"2021-09-25T06:56:58.928464Z","iopub.status.idle":"2021-09-25T06:57:00.715931Z","shell.execute_reply.started":"2021-09-25T06:56:58.928421Z","shell.execute_reply":"2021-09-25T06:57:00.713876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check the architecture of the model\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-09-25T06:47:25.238043Z","iopub.execute_input":"2021-09-25T06:47:25.238554Z","iopub.status.idle":"2021-09-25T06:47:25.259009Z","shell.execute_reply.started":"2021-09-25T06:47:25.238517Z","shell.execute_reply":"2021-09-25T06:47:25.258321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef SoftmaxLoss():\n    \"\"\"Function calls softmax loss \n    to output the cross entropy loss between true labels and the predicted logits\"\"\"\n    def softmax_loss(y_true, y_pred):\n        # y_true: sparse target\n        # y_pred: logist\n        \n        y_true = tf.cast(tf.reshape(y_true, [-1]), tf.int32)\n        ce = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y_true,\n                                                            logits=y_pred)\n        \n        return tf.reduce_mean(ce)\n    return softmax_loss","metadata":{"execution":{"iopub.status.busy":"2021-09-25T06:47:36.101433Z","iopub.execute_input":"2021-09-25T06:47:36.101707Z","iopub.status.idle":"2021-09-25T06:47:36.10734Z","shell.execute_reply.started":"2021-09-25T06:47:36.101676Z","shell.execute_reply":"2021-09-25T06:47:36.106441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# the hyper parameters - learning rate, optimizer SGD and custom loss function SoftmaxLoss\nlearning_rate = tf.constant(0.01)\noptimizer = tf.keras.optimizers.SGD(learning_rate=learning_rate, momentum=0.9, nesterov=True, clipvalue=0.5)\n#loss_fn = SoftmaxLoss()","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:10:08.973978Z","iopub.execute_input":"2021-09-25T07:10:08.974706Z","iopub.status.idle":"2021-09-25T07:10:08.97963Z","shell.execute_reply.started":"2021-09-25T07:10:08.974668Z","shell.execute_reply":"2021-09-25T07:10:08.978602Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# compile the model with above hyperparameters\nmodel.compile(optimizer=optimizer, loss=tf.keras.losses.SparseCategoricalCrossentropy())","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:10:10.512258Z","iopub.execute_input":"2021-09-25T07:10:10.512531Z","iopub.status.idle":"2021-09-25T07:10:10.527403Z","shell.execute_reply.started":"2021-09-25T07:10:10.512505Z","shell.execute_reply":"2021-09-25T07:10:10.526655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import datetime","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:10:11.343865Z","iopub.execute_input":"2021-09-25T07:10:11.344147Z","iopub.status.idle":"2021-09-25T07:10:11.348159Z","shell.execute_reply.started":"2021-09-25T07:10:11.344101Z","shell.execute_reply":"2021-09-25T07:10:11.347314Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nfrom time import time\nfrom tensorflow.python.keras.callbacks import TensorBoard\n#create a directory to save logs during model training\nlog_dir=\"model_logs_\" + datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\")\n\n\n#create a tensorboard callback with the log directory path\ntensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir,histogram_freq=1,\n                                                      write_graph=True,write_grads=True)\nfilepath=\"./weights_model_1.best.h5\" \ncheck = tf.keras.callbacks.ModelCheckpoint(filepath=filepath, save_best_only = True, verbose = True,monitor='val_loss', mode=\"min\")\n\ncallback_list = [tensorboard_callback, check]","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:10:12.239926Z","iopub.execute_input":"2021-09-25T07:10:12.240211Z","iopub.status.idle":"2021-09-25T07:10:12.542876Z","shell.execute_reply.started":"2021-09-25T07:10:12.240181Z","shell.execute_reply":"2021-09-25T07:10:12.541766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train the model for 15 epochs\nmodel.fit(train_dataset,epochs=1,verbose=1,callbacks=[callback_list])","metadata":{"execution":{"iopub.status.busy":"2021-09-25T07:10:13.583933Z","iopub.execute_input":"2021-09-25T07:10:13.584584Z","iopub.status.idle":"2021-09-25T07:10:13.812955Z","shell.execute_reply.started":"2021-09-25T07:10:13.584548Z","shell.execute_reply":"2021-09-25T07:10:13.810837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save_weights(\"./weights_1_model.h5\")","metadata":{"execution":{"iopub.status.busy":"2021-09-17T09:54:32.84229Z","iopub.execute_input":"2021-09-17T09:54:32.842538Z","iopub.status.idle":"2021-09-17T09:54:33.280716Z","shell.execute_reply.started":"2021-09-17T09:54:32.842512Z","shell.execute_reply":"2021-09-17T09:54:33.279798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#load the saved weights\nmodel.load_weights(\"../input/weights/weights_1_model.h5\")","metadata":{"execution":{"iopub.status.busy":"2021-09-17T10:01:59.80266Z","iopub.execute_input":"2021-09-17T10:01:59.803643Z","iopub.status.idle":"2021-09-17T10:02:02.304381Z","shell.execute_reply.started":"2021-09-17T10:01:59.803603Z","shell.execute_reply":"2021-09-17T10:02:02.303402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train the model for 15 epochs\nmodel.fit(train_dataset,epochs=15,verbose=1,callbacks=[callback_list])","metadata":{"execution":{"iopub.status.busy":"2021-09-17T10:02:07.89372Z","iopub.execute_input":"2021-09-17T10:02:07.894502Z","iopub.status.idle":"2021-09-17T16:04:52.23005Z","shell.execute_reply.started":"2021-09-17T10:02:07.894445Z","shell.execute_reply":"2021-09-17T16:04:52.229277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save_weights(\"./weights_2_model.h5\")","metadata":{"execution":{"iopub.status.busy":"2021-09-17T16:08:23.869666Z","iopub.execute_input":"2021-09-17T16:08:23.870373Z","iopub.status.idle":"2021-09-17T16:08:24.18082Z","shell.execute_reply.started":"2021-09-17T16:08:23.870329Z","shell.execute_reply":"2021-09-17T16:08:24.180097Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#load the saved weights\nmodel.load_weights(\"../input/weights2/weights_2_model.h5\")","metadata":{"execution":{"iopub.status.busy":"2021-09-19T11:56:17.21066Z","iopub.execute_input":"2021-09-19T11:56:17.21092Z","iopub.status.idle":"2021-09-19T11:56:19.753527Z","shell.execute_reply.started":"2021-09-19T11:56:17.210891Z","shell.execute_reply":"2021-09-19T11:56:19.752779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train the model for 15 epochs\nmodel.fit(train_dataset,epochs=15,verbose=1,callbacks=[callback_list])","metadata":{"execution":{"iopub.status.busy":"2021-09-19T11:56:25.809243Z","iopub.execute_input":"2021-09-19T11:56:25.809908Z","iopub.status.idle":"2021-09-19T18:43:17.766133Z","shell.execute_reply.started":"2021-09-19T11:56:25.809872Z","shell.execute_reply":"2021-09-19T18:43:17.765104Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save_weights(\"./weights_3_model.h5\")","metadata":{"execution":{"iopub.status.busy":"2021-09-19T18:46:44.384719Z","iopub.execute_input":"2021-09-19T18:46:44.385008Z","iopub.status.idle":"2021-09-19T18:46:44.697401Z","shell.execute_reply.started":"2021-09-19T18:46:44.384977Z","shell.execute_reply":"2021-09-19T18:46:44.696653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#load the saved weights\nmodel.load_weights(\"../input/weight3/weights_3_model.h5\")","metadata":{"execution":{"iopub.status.busy":"2021-09-20T04:14:34.941224Z","iopub.execute_input":"2021-09-20T04:14:34.941485Z","iopub.status.idle":"2021-09-20T04:14:37.598046Z","shell.execute_reply.started":"2021-09-20T04:14:34.941456Z","shell.execute_reply":"2021-09-20T04:14:37.597107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train the model for 15 epochs\nmodel.fit(train_dataset,epochs=20,verbose=1,callbacks=[callback_list])","metadata":{"execution":{"iopub.status.busy":"2021-09-20T04:14:53.503235Z","iopub.execute_input":"2021-09-20T04:14:53.504097Z","iopub.status.idle":"2021-09-20T12:29:04.145585Z","shell.execute_reply.started":"2021-09-20T04:14:53.50405Z","shell.execute_reply":"2021-09-20T12:29:04.144844Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save_weights(\"./weights_4_model.h5\")","metadata":{"execution":{"iopub.status.busy":"2021-09-20T12:29:08.127599Z","iopub.execute_input":"2021-09-20T12:29:08.186342Z","iopub.status.idle":"2021-09-20T12:29:08.505109Z","shell.execute_reply.started":"2021-09-20T12:29:08.186288Z","shell.execute_reply":"2021-09-20T12:29:08.504355Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#load the saved weights\nmodel.load_weights(\"../input/weight4/weights_4_model.h5\")","metadata":{"execution":{"iopub.status.busy":"2021-09-20T13:16:44.463582Z","iopub.execute_input":"2021-09-20T13:16:44.463885Z","iopub.status.idle":"2021-09-20T13:16:47.378872Z","shell.execute_reply.started":"2021-09-20T13:16:44.463857Z","shell.execute_reply":"2021-09-20T13:16:47.377367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train the model for 15 epochs\nmodel.fit(train_dataset,epochs=10,verbose=1,callbacks=[callback_list])","metadata":{"execution":{"iopub.status.busy":"2021-09-20T13:16:48.66903Z","iopub.execute_input":"2021-09-20T13:16:48.669856Z","iopub.status.idle":"2021-09-20T18:08:05.498691Z","shell.execute_reply.started":"2021-09-20T13:16:48.669821Z","shell.execute_reply":"2021-09-20T18:08:05.497654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save_weights(\"./weights_5_model.h5\")","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:30:19.535154Z","iopub.execute_input":"2021-09-24T07:30:19.535456Z","iopub.status.idle":"2021-09-24T07:30:19.805826Z","shell.execute_reply.started":"2021-09-24T07:30:19.535423Z","shell.execute_reply":"2021-09-24T07:30:19.804974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#load the saved weights\nmodel.load_weights(\"../input/weight5/weights_5_model.h5\")","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:30:20.750186Z","iopub.execute_input":"2021-09-24T07:30:20.750493Z","iopub.status.idle":"2021-09-24T07:30:23.851615Z","shell.execute_reply.started":"2021-09-24T07:30:20.750462Z","shell.execute_reply":"2021-09-24T07:30:23.850914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save('./model_saved')","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:30:48.849516Z","iopub.execute_input":"2021-09-24T07:30:48.852238Z","iopub.status.idle":"2021-09-24T07:31:21.534996Z","shell.execute_reply.started":"2021-09-24T07:30:48.852187Z","shell.execute_reply":"2021-09-24T07:31:21.534133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import required libraries\nimport numpy as np\nimport pandas as pd\nimport os\nimport tensorflow as tf\nfrom tensorflow.keras import Model","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:31:51.089468Z","iopub.execute_input":"2021-09-24T07:31:51.089806Z","iopub.status.idle":"2021-09-24T07:31:51.096499Z","shell.execute_reply.started":"2021-09-24T07:31:51.089774Z","shell.execute_reply":"2021-09-24T07:31:51.095695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_1 = tf.keras.models.load_model('./model_saved', compile=False)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:31:55.158164Z","iopub.execute_input":"2021-09-24T07:31:55.159151Z","iopub.status.idle":"2021-09-24T07:32:06.815182Z","shell.execute_reply.started":"2021-09-24T07:31:55.159111Z","shell.execute_reply":"2021-09-24T07:32:06.814559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check its architecture\nmodel_1.summary()","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:32:30.164598Z","iopub.execute_input":"2021-09-24T07:32:30.164979Z","iopub.status.idle":"2021-09-24T07:32:30.203866Z","shell.execute_reply.started":"2021-09-24T07:32:30.164943Z","shell.execute_reply":"2021-09-24T07:32:30.202832Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a model which takes a 64x64x3 image as input and returns the 64 dim embeddings as output\ntest_model = Model(model_1.input[0],model_1.layers[6].output)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:52:02.214606Z","iopub.execute_input":"2021-09-24T07:52:02.214932Z","iopub.status.idle":"2021-09-24T07:52:02.22491Z","shell.execute_reply.started":"2021-09-24T07:52:02.214901Z","shell.execute_reply":"2021-09-24T07:52:02.224252Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_model","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:52:40.975412Z","iopub.execute_input":"2021-09-24T07:52:40.976223Z","iopub.status.idle":"2021-09-24T07:52:40.983053Z","shell.execute_reply.started":"2021-09-24T07:52:40.976172Z","shell.execute_reply":"2021-09-24T07:52:40.982152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# save the model for testing purpose\ntest_model.save('./test_model')","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:32:51.745451Z","iopub.execute_input":"2021-09-24T07:32:51.746409Z","iopub.status.idle":"2021-09-24T07:33:23.860331Z","shell.execute_reply.started":"2021-09-24T07:32:51.746366Z","shell.execute_reply":"2021-09-24T07:33:23.85952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load the final saved test model\ntest_model = tf.keras.models.load_model('test_model', compile=False)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:33:27.06611Z","iopub.execute_input":"2021-09-24T07:33:27.066439Z","iopub.status.idle":"2021-09-24T07:33:39.067109Z","shell.execute_reply.started":"2021-09-24T07:33:27.066408Z","shell.execute_reply":"2021-09-24T07:33:39.066129Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def read_image(path):\n    '''\n    The function reads an image path\n    Read the image from image path, decode the channels in the image\n    Resize it to 64x64\n    Cast it to a float32 array and normalize each pixel\n    Returns the preprocessed image\n    '''\n    \n    #read image file at the path\n    image = tf.io.read_file(path)\n    \n    image = tf.image.decode_jpeg(image, channels=3)\n    \n    #resize image\n    image = tf.image.resize(image, [64,64])\n    \n    #convert to float32\n    image = tf.cast(image, tf.float32)\n    \n    # normalize image to [0,1] range\n    image /= 255.0\n    \n    \n    return image","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:52:54.038521Z","iopub.execute_input":"2021-09-24T07:52:54.038841Z","iopub.status.idle":"2021-09-24T07:52:54.046753Z","shell.execute_reply.started":"2021-09-24T07:52:54.038809Z","shell.execute_reply":"2021-09-24T07:52:54.045914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# read a test image\ntest_image = np.expand_dims(read_image('../input/hotel-id-2021-fgvc8/test_images/99e91ad5f2870678.jpg'),0)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:52:57.268081Z","iopub.execute_input":"2021-09-24T07:52:57.268367Z","iopub.status.idle":"2021-09-24T07:52:57.295478Z","shell.execute_reply.started":"2021-09-24T07:52:57.268338Z","shell.execute_reply":"2021-09-24T07:52:57.294803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_image","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:40:15.119394Z","iopub.execute_input":"2021-09-24T07:40:15.120659Z","iopub.status.idle":"2021-09-24T07:40:15.132106Z","shell.execute_reply.started":"2021-09-24T07:40:15.120593Z","shell.execute_reply":"2021-09-24T07:40:15.131063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert the model to tflite\nconverter = tf.lite.TFLiteConverter.from_saved_model('test_model') # path to the SavedModel directory\nconverter.optimizations = [tf.lite.Optimize.DEFAULT]\nconverter.target_spec.supported_types = [tf.float16]\ntflite_model = converter.convert()\n\n# Save the converted model\nwith open('./test_model_tflite', 'wb') as f:\n    f.write(tflite_model)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:53:39.446717Z","iopub.execute_input":"2021-09-24T07:53:39.447013Z","iopub.status.idle":"2021-09-24T07:53:54.120297Z","shell.execute_reply.started":"2021-09-24T07:53:39.446983Z","shell.execute_reply":"2021-09-24T07:53:54.119367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#read the optimized tflite test model\ntflite_test_model = tf.lite.Interpreter('./test_model_tflite')","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:54:12.59003Z","iopub.execute_input":"2021-09-24T07:54:12.590675Z","iopub.status.idle":"2021-09-24T07:54:12.596488Z","shell.execute_reply.started":"2021-09-24T07:54:12.590639Z","shell.execute_reply":"2021-09-24T07:54:12.595351Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#allocate the tensors\ntflite_test_model.allocate_tensors()","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:55:21.582Z","iopub.execute_input":"2021-09-24T07:55:21.582811Z","iopub.status.idle":"2021-09-24T07:55:21.587859Z","shell.execute_reply.started":"2021-09-24T07:55:21.58276Z","shell.execute_reply":"2021-09-24T07:55:21.586934Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get input and output tensors.\ninput_details = tflite_test_model.get_input_details()\noutput_details = tflite_test_model.get_output_details()","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:55:22.837878Z","iopub.execute_input":"2021-09-24T07:55:22.838244Z","iopub.status.idle":"2021-09-24T07:55:22.843973Z","shell.execute_reply.started":"2021-09-24T07:55:22.838208Z","shell.execute_reply":"2021-09-24T07:55:22.843117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#set the input details tensor in the test model\ntflite_test_model.set_tensor(input_details[0]['index'], test_image)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:55:32.74548Z","iopub.execute_input":"2021-09-24T07:55:32.746164Z","iopub.status.idle":"2021-09-24T07:55:32.75099Z","shell.execute_reply.started":"2021-09-24T07:55:32.746122Z","shell.execute_reply":"2021-09-24T07:55:32.750169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#invoke the test model\ntflite_test_model.invoke()","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:55:44.7654Z","iopub.execute_input":"2021-09-24T07:55:44.765729Z","iopub.status.idle":"2021-09-24T07:55:45.365689Z","shell.execute_reply.started":"2021-09-24T07:55:44.765698Z","shell.execute_reply":"2021-09-24T07:55:45.364662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# The function `get_tensor()` returns a copy of the tensor data\ntest_embeds = tflite_test_model.get_tensor(output_details[0]['index'])\nprint(test_embeds)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:55:50.05722Z","iopub.execute_input":"2021-09-24T07:55:50.058177Z","iopub.status.idle":"2021-09-24T07:55:50.064967Z","shell.execute_reply.started":"2021-09-24T07:55:50.058115Z","shell.execute_reply":"2021-09-24T07:55:50.063824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# normalize the embeddings\nnorm = np.linalg.norm(test_embeds, axis=1, keepdims=True)\ntest_embeds = test_embeds / norm\ntest_embeds","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:55:56.212621Z","iopub.execute_input":"2021-09-24T07:55:56.212931Z","iopub.status.idle":"2021-09-24T07:55:56.223109Z","shell.execute_reply.started":"2021-09-24T07:55:56.212902Z","shell.execute_reply":"2021-09-24T07:55:56.222103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Read train data\ntrain_df = pd.read_csv('../input/hotel-id-2021-fgvc8/train.csv')","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:56:05.809961Z","iopub.execute_input":"2021-09-24T07:56:05.81026Z","iopub.status.idle":"2021-09-24T07:56:05.943316Z","shell.execute_reply.started":"2021-09-24T07:56:05.810231Z","shell.execute_reply":"2021-09-24T07:56:05.942051Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# store the image path as the absolute path because each image is contained in a folder of some hotel chain\ntrain_df['image_path'] = \"../input/hotel-id-2021-fgvc8/train_images/\" + train_df['chain'].astype(str) +'/'+ train_df['image']","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:56:08.782751Z","iopub.execute_input":"2021-09-24T07:56:08.783094Z","iopub.status.idle":"2021-09-24T07:56:08.984111Z","shell.execute_reply.started":"2021-09-24T07:56:08.783062Z","shell.execute_reply":"2021-09-24T07:56:08.983247Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:56:11.322876Z","iopub.execute_input":"2021-09-24T07:56:11.323297Z","iopub.status.idle":"2021-09-24T07:56:11.335035Z","shell.execute_reply.started":"2021-09-24T07:56:11.323267Z","shell.execute_reply":"2021-09-24T07:56:11.334196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# save the image paths as a tensor\ntrain_filenames  = tf.convert_to_tensor(train_df['image_path'].tolist(), dtype=tf.string)\n\n# Create a train dataset\n\n# read all the train file names to create a Dataset type object\ntrain_dataset = tf.data.Dataset.from_tensor_slices(train_filenames)\n\n# shuffle the dataset\ntrain_dataset = train_dataset.shuffle(len(train_filenames))\n\n# Map the read_train_image function on the dataset in order to read dataset\ntrain_dataset = train_dataset.map(read_image,num_parallel_calls=4)\n\n#batch and prefetch the dataset\ntrain_dataset = train_dataset.batch(64)\ntrain_dataset = train_dataset.prefetch(1)\n\n# check shape of train dataset\ntrain_dataset","metadata":{"execution":{"iopub.status.busy":"2021-09-25T06:35:54.4059Z","iopub.execute_input":"2021-09-25T06:35:54.406189Z","iopub.status.idle":"2021-09-25T06:35:54.433425Z","shell.execute_reply.started":"2021-09-25T06:35:54.406151Z","shell.execute_reply":"2021-09-25T06:35:54.432418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#get embeddings for the train images using the saved test model\ntrain_embeds = test_model.predict(train_dataset)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T07:56:13.626668Z","iopub.execute_input":"2021-09-24T07:56:13.626953Z","iopub.status.idle":"2021-09-24T08:20:13.533893Z","shell.execute_reply.started":"2021-09-24T07:56:13.626923Z","shell.execute_reply":"2021-09-24T08:20:13.53298Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check the shape of the embeddings\ntrain_embeds.shape","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:23:46.777375Z","iopub.execute_input":"2021-09-24T08:23:46.77772Z","iopub.status.idle":"2021-09-24T08:23:46.783989Z","shell.execute_reply.started":"2021-09-24T08:23:46.777685Z","shell.execute_reply":"2021-09-24T08:23:46.783139Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# normalize the embeddings\nnorm = np.linalg.norm(train_embeds, axis=1, keepdims=True)\ntrain_embeds = train_embeds / norm\ntrain_embeds","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:23:58.385187Z","iopub.execute_input":"2021-09-24T08:23:58.385613Z","iopub.status.idle":"2021-09-24T08:23:58.412149Z","shell.execute_reply.started":"2021-09-24T08:23:58.385583Z","shell.execute_reply":"2021-09-24T08:23:58.411251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# save the train embeddings\nnp.save('./train_embeddings.npy',train_embeds)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:24:23.742046Z","iopub.execute_input":"2021-09-24T08:24:23.742338Z","iopub.status.idle":"2021-09-24T08:24:23.769242Z","shell.execute_reply.started":"2021-09-24T08:24:23.74231Z","shell.execute_reply":"2021-09-24T08:24:23.768258Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pip install faiss-cpu","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:25:55.548191Z","iopub.execute_input":"2021-09-24T08:25:55.548516Z","iopub.status.idle":"2021-09-24T08:26:03.562803Z","shell.execute_reply.started":"2021-09-24T08:25:55.548482Z","shell.execute_reply":"2021-09-24T08:26:03.561912Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#import the faiss library\nimport faiss","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:26:06.807548Z","iopub.execute_input":"2021-09-24T08:26:06.807889Z","iopub.status.idle":"2021-09-24T08:26:06.857512Z","shell.execute_reply.started":"2021-09-24T08:26:06.807853Z","shell.execute_reply":"2021-09-24T08:26:06.856494Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load the train embeddings\ntrain_embeds = np.load('./train_embeddings.npy')","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:26:21.915047Z","iopub.execute_input":"2021-09-24T08:26:21.915374Z","iopub.status.idle":"2021-09-24T08:26:21.933466Z","shell.execute_reply.started":"2021-09-24T08:26:21.915333Z","shell.execute_reply":"2021-09-24T08:26:21.932685Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define the hyperparameters - no. of dimensions, no. of clusters(centroids), no. of iterations\n#https://github.com/facebookresearch/faiss/wiki/Faiss-building-blocks:-clustering,-PCA,-quantization\n#https://towardsdatascience.com/understanding-faiss-619bb6db2d1a\ndim = train_embeds.shape[1]\nn_centroids = 7770\nn_iter = 20\nverbose = True","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:26:27.063925Z","iopub.execute_input":"2021-09-24T08:26:27.064262Z","iopub.status.idle":"2021-09-24T08:26:27.069702Z","shell.execute_reply.started":"2021-09-24T08:26:27.064228Z","shell.execute_reply":"2021-09-24T08:26:27.068645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define a kmeans model with the hyper parameters and train the model with train embeddings\nkmeans = faiss.Kmeans(dim, n_centroids, niter=n_iter, verbose=verbose)\nkmeans.train(train_embeds)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:26:32.812296Z","iopub.execute_input":"2021-09-24T08:26:32.812584Z","iopub.status.idle":"2021-09-24T08:27:32.414408Z","shell.execute_reply.started":"2021-09-24T08:26:32.812556Z","shell.execute_reply":"2021-09-24T08:27:32.413639Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# the error after training for n iterations\nkmeans.obj[-1]","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:30:54.466784Z","iopub.execute_input":"2021-09-24T08:30:54.467158Z","iopub.status.idle":"2021-09-24T08:30:54.473255Z","shell.execute_reply.started":"2021-09-24T08:30:54.467115Z","shell.execute_reply":"2021-09-24T08:30:54.472399Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pickle","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:31:19.078983Z","iopub.execute_input":"2021-09-24T08:31:19.079317Z","iopub.status.idle":"2021-09-24T08:31:19.084422Z","shell.execute_reply.started":"2021-09-24T08:31:19.079284Z","shell.execute_reply":"2021-09-24T08:31:19.083117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# save the error for future reference\nwith open(\"./kmeans_error.pkl\", \"wb\") as f:\n    pickle.dump(kmeans.obj[-1], f)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:31:32.545749Z","iopub.execute_input":"2021-09-24T08:31:32.546145Z","iopub.status.idle":"2021-09-24T08:31:32.552797Z","shell.execute_reply.started":"2021-09-24T08:31:32.546105Z","shell.execute_reply":"2021-09-24T08:31:32.551914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# return the nearest centroid and its distance for each line vector in train_embeds\ntrain_to_centroid_dist, train_to_centroid_ind = kmeans.index.search(train_embeds, 1)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:32:12.650601Z","iopub.execute_input":"2021-09-24T08:32:12.651415Z","iopub.status.idle":"2021-09-24T08:32:15.6193Z","shell.execute_reply.started":"2021-09-24T08:32:12.651366Z","shell.execute_reply":"2021-09-24T08:32:15.618405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check the shape of results\ntrain_to_centroid_dist.shape","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:32:25.276031Z","iopub.execute_input":"2021-09-24T08:32:25.276347Z","iopub.status.idle":"2021-09-24T08:32:25.282171Z","shell.execute_reply.started":"2021-09-24T08:32:25.276317Z","shell.execute_reply":"2021-09-24T08:32:25.281581Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check the number and dimensions of centroids found\nkmeans.centroids.shape","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:32:34.773943Z","iopub.execute_input":"2021-09-24T08:32:34.774527Z","iopub.status.idle":"2021-09-24T08:32:34.78005Z","shell.execute_reply.started":"2021-09-24T08:32:34.774489Z","shell.execute_reply":"2021-09-24T08:32:34.779458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train an index with the centroids found from trained kmeans model\nkmeans_index = faiss.IndexFlatL2(dim)\nkmeans_index.add(kmeans.centroids)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:32:50.614481Z","iopub.execute_input":"2021-09-24T08:32:50.615096Z","iopub.status.idle":"2021-09-24T08:32:50.620302Z","shell.execute_reply.started":"2021-09-24T08:32:50.615059Z","shell.execute_reply":"2021-09-24T08:32:50.619472Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# save the trained index\nfaiss.write_index(kmeans_index, \"./kmeans_trained.index\")","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:33:20.348681Z","iopub.execute_input":"2021-09-24T08:33:20.349222Z","iopub.status.idle":"2021-09-24T08:33:20.355185Z","shell.execute_reply.started":"2021-09-24T08:33:20.349187Z","shell.execute_reply":"2021-09-24T08:33:20.354415Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load the saved index\nkmeans_index = faiss.read_index(\"./kmeans_trained.index\")","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:33:52.341133Z","iopub.execute_input":"2021-09-24T08:33:52.34165Z","iopub.status.idle":"2021-09-24T08:33:52.347347Z","shell.execute_reply.started":"2021-09-24T08:33:52.341614Z","shell.execute_reply":"2021-09-24T08:33:52.346626Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#find the 5 nearest distance in test_embeds to the computed centroids\ntest_to_centroid_dist, test_to_centroid_ind = kmeans_index.search(test_embeds, 5)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:34:43.038225Z","iopub.execute_input":"2021-09-24T08:34:43.038823Z","iopub.status.idle":"2021-09-24T08:34:43.049094Z","shell.execute_reply.started":"2021-09-24T08:34:43.038785Z","shell.execute_reply":"2021-09-24T08:34:43.048189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check the number of distances returned\ntest_to_centroid_dist.shape","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:34:52.412695Z","iopub.execute_input":"2021-09-24T08:34:52.413044Z","iopub.status.idle":"2021-09-24T08:34:52.418403Z","shell.execute_reply.started":"2021-09-24T08:34:52.413011Z","shell.execute_reply":"2021-09-24T08:34:52.417824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check distances\ntest_to_centroid_dist","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:35:01.175124Z","iopub.execute_input":"2021-09-24T08:35:01.175828Z","iopub.status.idle":"2021-09-24T08:35:01.185678Z","shell.execute_reply.started":"2021-09-24T08:35:01.175785Z","shell.execute_reply":"2021-09-24T08:35:01.184426Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check the nearest centroid indices\ntest_to_centroid_ind","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:35:07.457976Z","iopub.execute_input":"2021-09-24T08:35:07.458293Z","iopub.status.idle":"2021-09-24T08:35:07.465349Z","shell.execute_reply.started":"2021-09-24T08:35:07.458264Z","shell.execute_reply":"2021-09-24T08:35:07.46431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load the saved label encoder\nwith open('./labelencoder.pkl', \"rb\") as input_file:\n    le = pickle.load(input_file)","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:35:38.966425Z","iopub.execute_input":"2021-09-24T08:35:38.967326Z","iopub.status.idle":"2021-09-24T08:35:38.990656Z","shell.execute_reply.started":"2021-09-24T08:35:38.96727Z","shell.execute_reply":"2021-09-24T08:35:38.989735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get the actual labels for these predicted labels (which were transformed earlier using label encoder)\nactual_output_labels = le.inverse_transform(test_to_centroid_ind[0])\nactual_output_labels","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:35:46.787242Z","iopub.execute_input":"2021-09-24T08:35:46.787575Z","iopub.status.idle":"2021-09-24T08:35:46.797504Z","shell.execute_reply.started":"2021-09-24T08:35:46.787541Z","shell.execute_reply":"2021-09-24T08:35:46.796468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import required libraries for visualization of clusters and nearest centroids to test data\nimport matplotlib.pyplot as plt\nfrom sklearn.decomposition import PCA\nimport seaborn as sns\nsns.set()","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:36:02.610041Z","iopub.execute_input":"2021-09-24T08:36:02.610424Z","iopub.status.idle":"2021-09-24T08:36:02.993204Z","shell.execute_reply.started":"2021-09-24T08:36:02.610386Z","shell.execute_reply":"2021-09-24T08:36:02.992237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load the train embeddings\ntrain_embeds = np.load('./train_embeddings.npy')","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:36:21.870277Z","iopub.execute_input":"2021-09-24T08:36:21.870849Z","iopub.status.idle":"2021-09-24T08:36:21.890053Z","shell.execute_reply.started":"2021-09-24T08:36:21.870814Z","shell.execute_reply":"2021-09-24T08:36:21.889107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# reduce the high dimensional data to 2D for visualization\npca1 = PCA(2)\npca2 = PCA(2)\n \n#Transform the data\ncentroids = pca1.fit_transform(kmeans.centroids)\ntrain_data = pca2.fit_transform(train_embeds)\n","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:36:27.447913Z","iopub.execute_input":"2021-09-24T08:36:27.448203Z","iopub.status.idle":"2021-09-24T08:36:27.824654Z","shell.execute_reply.started":"2021-09-24T08:36:27.448175Z","shell.execute_reply":"2021-09-24T08:36:27.823671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#save the dimensionality reduced centroids\npickle.dump(centroids, open('./kmeans_centroids_pca.pkl', 'wb'))","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:37:09.16864Z","iopub.execute_input":"2021-09-24T08:37:09.169191Z","iopub.status.idle":"2021-09-24T08:37:09.176217Z","shell.execute_reply.started":"2021-09-24T08:37:09.16914Z","shell.execute_reply":"2021-09-24T08:37:09.175015Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#read the train data csv\ntrain_df = pd.read_csv('../input/hotel-id-2021-fgvc8/train.csv')","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:37:50.200617Z","iopub.execute_input":"2021-09-24T08:37:50.201155Z","iopub.status.idle":"2021-09-24T08:37:50.419317Z","shell.execute_reply.started":"2021-09-24T08:37:50.20112Z","shell.execute_reply":"2021-09-24T08:37:50.418593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"''' Saving the plot which has the train embeddings along with the cluster centers (classes)'''\n#create the figure size\nfig,ax = plt.subplots(1,1)\nfig.set_size_inches(20, 15)\n\n#get the unique original hotel id's from the train csv\nu_labels = np.unique(train_df['hotel_id'])\n \n\n#plotting the results:\n\n#iterate over the unique hotel id's\nfor i in u_labels:\n    \n    #plot the images of each unique hotel id in a separate colour\n    ax.scatter(train_data[train_df['hotel_id']==i,0] , train_data[train_df['hotel_id']==i,1], cmap='viridis', s=50)\n    \n#plot the centroids of each of the above cluster\nax.scatter(centroids[:,0] , centroids[:,1], s = 5, color = 'black',alpha=0.8,label='Hotel ID centroid')\n\n#for faster access, saving this master plot which serves as a common plot for each inference\npickle.dump((fig,ax), open('./train_fig.pkl', 'wb'))","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:38:45.1725Z","iopub.execute_input":"2021-09-24T08:38:45.173524Z","iopub.status.idle":"2021-09-24T08:44:37.75499Z","shell.execute_reply.started":"2021-09-24T08:38:45.173477Z","shell.execute_reply":"2021-09-24T08:44:37.754257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"''' Loading the saved master plot which has the train embeddings along with the cluster centers (classes)\n    and plotting the inference predictions on top of it\n'''\n\n#load the saved plot and unpack to its figure and axes\nfig2,ax2 = pickle.load(open('./train_fig.pkl', 'rb'))\nfig2.set_size_inches(20, 15)\n\n##load the dimensionality reduced centroids\ncentroids = pickle.load(open('./kmeans_centroids_pca.pkl', 'rb'))\n\n# define colours for marking the 5 nearest neighbours\npredicted_colours = ['tomato','gold','springgreen','cornflowerblue','hotpink']\ncount=0\n\n#get the max dimensions of the x and y axis\nleft_x, right_x = plt.xlim()\nmin_y, max_y = plt.ylim()\n\n#iterate over the 5 nearest predicted centroid indices for the test embeddings\nfor j in list(test_to_centroid_ind[0]):\n    \n    #plot the nearest centroid i.e. predicted hotel ID for the test input image\n    ax2.scatter(centroids[j,0] , centroids[j,1], s=1500, c=predicted_colours[count], alpha=0.9,label='Predicted Hotel ID '+str(count+1),marker='*',edgecolors='white',linewidth=2)\n    \n    # also show the predicted hotel ID on the marked point\n    ax2.text(0.05+left_x+(0.05*count), min_y+(0.01),str(actual_output_labels[count]),fontsize=15,bbox=dict(edgecolor='black',facecolor=predicted_colours[count], alpha=0.9))\n    \n    count+=1\n    \n#add legend to mark labels\nplt.legend(fontsize='large')\n","metadata":{"execution":{"iopub.status.busy":"2021-09-24T08:50:11.960477Z","iopub.execute_input":"2021-09-24T08:50:11.960786Z","iopub.status.idle":"2021-09-24T08:51:56.155368Z","shell.execute_reply.started":"2021-09-24T08:50:11.960742Z","shell.execute_reply":"2021-09-24T08:51:56.154573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}