{"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 # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport matplotlib.pyplot as plt\nfrom PIL import Image \nimport matplotlib.image as mpimg\nimport os\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.layers import Input, Conv2D,Dropout\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.callbacks import EarlyStopping\nfrom IPython.display import clear_output\nimport random, re, math\nimport keras.backend as K\nfrom sklearn.model_selection import train_test_split","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-08-28T12:01:29.985549Z","iopub.execute_input":"2021-08-28T12:01:29.986325Z","iopub.status.idle":"2021-08-28T12:01:37.460927Z","shell.execute_reply.started":"2021-08-28T12:01:29.986149Z","shell.execute_reply":"2021-08-28T12:01:37.459892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df=pd.read_csv('../input/landmark-recognition-2021/train.csv')\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:01:37.462726Z","iopub.execute_input":"2021-08-28T12:01:37.463096Z","iopub.status.idle":"2021-08-28T12:01:39.383221Z","shell.execute_reply.started":"2021-08-28T12:01:37.463061Z","shell.execute_reply":"2021-08-28T12:01:39.382199Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\ndf['path']=['../input/landmark-recognition-2021/train/'+id[0]+'/'+id[1]+'/'+id[2]+'/'+id+'.jpg' for id in df['id']]\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:01:39.389393Z","iopub.execute_input":"2021-08-28T12:01:39.389836Z","iopub.status.idle":"2021-08-28T12:01:41.123680Z","shell.execute_reply.started":"2021-08-28T12:01:39.389789Z","shell.execute_reply":"2021-08-28T12:01:41.122340Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['landmark_id'].nunique()\n","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:01:41.125625Z","iopub.execute_input":"2021-08-28T12:01:41.126091Z","iopub.status.idle":"2021-08-28T12:01:41.176422Z","shell.execute_reply.started":"2021-08-28T12:01:41.126044Z","shell.execute_reply":"2021-08-28T12:01:41.175233Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['landmark_id'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:01:41.178135Z","iopub.execute_input":"2021-08-28T12:01:41.178587Z","iopub.status.idle":"2021-08-28T12:01:41.221232Z","shell.execute_reply.started":"2021-08-28T12:01:41.178543Z","shell.execute_reply":"2021-08-28T12:01:41.220265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['landmark_id'].describe()","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:01:41.222877Z","iopub.execute_input":"2021-08-28T12:01:41.223282Z","iopub.status.idle":"2021-08-28T12:01:41.265236Z","shell.execute_reply.started":"2021-08-28T12:01:41.223240Z","shell.execute_reply":"2021-08-28T12:01:41.264077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df['id_counts'] = df.landmark_id.value_counts().loc[df.landmark_id.values].values\nid_map = df.sort_values(by='id_counts').landmark_id.drop_duplicates().reset_index(drop=True)\nid_dict = {id_map.loc[x]:81312-x for x in range(81313)}\ndf['encode_id'] = df.landmark_id.apply(lambda x: id_dict[x])\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:01:41.269261Z","iopub.execute_input":"2021-08-28T12:01:41.269605Z","iopub.status.idle":"2021-08-28T12:01:44.692728Z","shell.execute_reply.started":"2021-08-28T12:01:41.269574Z","shell.execute_reply":"2021-08-28T12:01:44.691498Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.subplots(3, 4, figsize=(160, 120))\nfor i in range(12):\n    sp = plt.subplot(3, 4, i + 1)\n    sp.axis('Off')\n    im = mpimg.imread(df.iloc[i][2])\n    plt.imshow(im)\n    plt.title(f'landmark_id:{df.iloc[i][1]} ', \n                                     fontweight =\"bold\",fontsize=100)\n    ","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:01:44.694280Z","iopub.execute_input":"2021-08-28T12:01:44.694632Z","iopub.status.idle":"2021-08-28T12:02:07.968575Z","shell.execute_reply.started":"2021-08-28T12:01:44.694602Z","shell.execute_reply":"2021-08-28T12:02:07.967325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"AUTO = tf.data.experimental.AUTOTUNE\n\n# Configuration\nIMAGE_SIZE = [256, 256]\nEPOCHS = 50\nSEED = 36\nBATCH_SIZE = 42 ","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:04:01.793151Z","iopub.execute_input":"2021-08-28T12:04:01.793644Z","iopub.status.idle":"2021-08-28T12:04:01.799905Z","shell.execute_reply.started":"2021-08-28T12:04:01.793604Z","shell.execute_reply":"2021-08-28T12:04:01.798383Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def flip(image,label):\n    image = tf.image.flip_left_right(image)\n    return image,label\n\ndef rotate(image,label):\n\n    rot = 15. * tf.random.normal([1],dtype='float32')\n    rotation = math.pi * rot / 180.\n    c1 = tf.math.cos(rotation)\n    s1 = tf.math.sin(rotation)\n    one = tf.constant([1],dtype='float32')\n    zero = tf.constant([0],dtype='float32')\n    m = tf.reshape( tf.concat([c1,s1,zero, -s1,c1,zero, zero,zero,one],axis=0),[3,3] )\n    DIM = IMAGE_SIZE[0]\n    XDIM = DIM%2 \n    x = tf.repeat( tf.range(DIM//2,-DIM//2,-1), DIM )\n    y = tf.tile( tf.range(-DIM//2,DIM//2),[DIM] )\n    z = tf.ones([DIM*DIM],dtype='int32')\n    idx = tf.stack( [x,y,z] )\n    idx2 = K.dot(m,tf.cast(idx,dtype='float32'))\n    idx2 = K.cast(idx2,dtype='int32')\n    idx2 = K.clip(idx2,-DIM//2+XDIM+1,DIM//2)\n    idx3 = tf.stack( [DIM//2-idx2[0,], DIM//2-1+idx2[1,]] )\n    d = tf.gather_nd(image,tf.transpose(idx3))\n    img=tf.reshape(d,[DIM,DIM,3])\n    return img,label\n#tf.cast(np.array(img), dtype=tf.float32)","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:04:03.956541Z","iopub.execute_input":"2021-08-28T12:04:03.956952Z","iopub.status.idle":"2021-08-28T12:04:03.970751Z","shell.execute_reply.started":"2021-08-28T12:04:03.956918Z","shell.execute_reply":"2021-08-28T12:04:03.969881Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def read_image_and_label(image_path, label=None,resize=IMAGE_SIZE):\n    \n    image=tf.io.read_file(image_path)\n    image=tf.image.decode_jpeg(image, channels=3)\n    image=tf.image.resize(image, IMAGE_SIZE)\n    image = tf.cast(image, dtype=tf.float32)/255.\n    if not label is None:\n        return image, label\n    return image","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:04:04.677520Z","iopub.execute_input":"2021-08-28T12:04:04.678121Z","iopub.status.idle":"2021-08-28T12:04:04.683999Z","shell.execute_reply.started":"2021-08-28T12:04:04.678067Z","shell.execute_reply":"2021-08-28T12:04:04.683154Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_training_dataset(df):\n    \n    training_dataset = tf.data.Dataset.from_tensor_slices((df[\"path\"].values, df[\"encode_id\"].values))\n    training_dataset = training_dataset.map(read_image_and_label,num_parallel_calls=AUTO)\n    training_dataset = training_dataset.map(flip,num_parallel_calls=AUTO)\n    training_dataset = training_dataset.map(rotate,num_parallel_calls=AUTO)\n    training_dataset = training_dataset.shuffle(1000, reshuffle_each_iteration=True)\n    training_dataset = training_dataset.batch(BATCH_SIZE)\n    training_dataset = training_dataset.prefetch(AUTO)\n\n    return training_dataset\n","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:04:05.767423Z","iopub.execute_input":"2021-08-28T12:04:05.768028Z","iopub.status.idle":"2021-08-28T12:04:05.774345Z","shell.execute_reply.started":"2021-08-28T12:04:05.767968Z","shell.execute_reply":"2021-08-28T12:04:05.773390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_validation_dataset(df,batch_size=16):\n  \n  validation_dataset = tf.data.Dataset.from_tensor_slices((df[\"path\"].values, df[\"encode_id\"].values))\n  validation_dataset = validation_dataset.map(read_image_and_label)\n  validation_dataset = validation_dataset.batch(BATCH_SIZE)\n  \n\n  return validation_dataset\n","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:04:07.019342Z","iopub.execute_input":"2021-08-28T12:04:07.020068Z","iopub.status.idle":"2021-08-28T12:04:07.025388Z","shell.execute_reply.started":"2021-08-28T12:04:07.020007Z","shell.execute_reply":"2021-08-28T12:04:07.024132Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_test_dataset(images,batch_size=16):\n  \n  test_dataset = tf.data.Dataset.from_tensor_slices((images))\n  test_dataset = test_dataset.map(read_image_and_label)\n  test_dataset = test_dataset.batch(batch_size, drop_remainder=True)\n\n  return test_dataset","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:04:08.628554Z","iopub.execute_input":"2021-08-28T12:04:08.628997Z","iopub.status.idle":"2021-08-28T12:04:08.634187Z","shell.execute_reply.started":"2021-08-28T12:04:08.628955Z","shell.execute_reply":"2021-08-28T12:04:08.633311Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tr_dataset = get_training_dataset(train_test_split(df, random_state=SEED, test_size=.25)[0])\nval_dataset = get_validation_dataset(train_test_split(df, random_state=SEED, test_size=.25)[1])","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:04:10.230465Z","iopub.execute_input":"2021-08-28T12:04:10.231087Z","iopub.status.idle":"2021-08-28T12:04:14.056658Z","shell.execute_reply.started":"2021-08-28T12:04:10.231036Z","shell.execute_reply":"2021-08-28T12:04:14.055279Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"row = 2; col = 4;\nall_elements = tr_dataset.unbatch()\none_element = tf.data.Dataset.from_tensors( next(iter(all_elements)) )\naugmented_element = one_element.repeat().map(rotate).batch(row*col)\n\nfor (img,label) in augmented_element:\n    plt.figure(figsize=(15,int(15*row/col)))\n    for j in range(row*col):\n        plt.subplot(row,col,j+1)\n        plt.axis('off')\n        plt.imshow(img[j,])\n        \n    plt.show()\n    break","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:04:14.058405Z","iopub.execute_input":"2021-08-28T12:04:14.058736Z","iopub.status.idle":"2021-08-28T12:04:19.940584Z","shell.execute_reply.started":"2021-08-28T12:04:14.058704Z","shell.execute_reply":"2021-08-28T12:04:19.938977Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow import keras\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.layers.experimental import preprocessing\n\n\ndef conv_block(filters, inputs):\n    x = layers.SeparableConv2D(filters, 3, activation=\"relu\", padding=\"same\")(inputs)\n    x = layers.SeparableConv2D(filters, 3, activation=\"relu\", padding=\"same\")(x)\n    x = layers.BatchNormalization()(x)\n    outputs = layers.MaxPool2D()(x)\n\n    return outputs\n\n\ndef dense_block(units, dropout_rate, inputs):\n    x = layers.Dense(units, activation=\"relu\")(inputs)\n    x = layers.BatchNormalization()(x)\n    outputs = layers.Dropout(dropout_rate)(x)\n\n    return outputs\n","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:04:19.943694Z","iopub.execute_input":"2021-08-28T12:04:19.944228Z","iopub.status.idle":"2021-08-28T12:04:19.958404Z","shell.execute_reply.started":"2021-08-28T12:04:19.944163Z","shell.execute_reply":"2021-08-28T12:04:19.956653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_model():\n    inputs = keras.Input(shape=(IMAGE_SIZE[0], IMAGE_SIZE[1], 3))\n    x = layers.Conv2D(16, 3, activation=\"relu\", padding=\"same\")(inputs)\n    x = layers.Conv2D(16, 3, activation=\"relu\", padding=\"same\")(x)\n    x = layers.MaxPool2D()(x)\n\n    x = conv_block(32, x)\n    x = conv_block(64, x)\n\n    x = conv_block(128, x)\n    x = layers.Dropout(0.2)(x)\n\n    x = conv_block(256, x)\n    x = layers.Dropout(0.2)(x)\n\n    x = layers.Flatten()(x)\n    x = dense_block(512, 0.7, x)\n    x = dense_block(128, 0.5, x)\n    x = dense_block(64, 0.3, x)\n\n    outputs = layers.Dense(81313, activation=\"softmax\")(x)\n\n    model = keras.Model(inputs=inputs, outputs=outputs)\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:05:19.189890Z","iopub.execute_input":"2021-08-28T12:05:19.190295Z","iopub.status.idle":"2021-08-28T12:05:19.201719Z","shell.execute_reply.started":"2021-08-28T12:05:19.190262Z","shell.execute_reply":"2021-08-28T12:05:19.200253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = build_model()\nmodel.summary()\nmodel.compile(\n    optimizer='adam',\n    loss='sparse_categorical_crossentropy',\n    metrics=['acc']\n)\n","metadata":{"execution":{"iopub.status.busy":"2021-08-28T12:05:27.721734Z","iopub.execute_input":"2021-08-28T12:05:27.722154Z","iopub.status.idle":"2021-08-28T12:05:28.091230Z","shell.execute_reply.started":"2021-08-28T12:05:27.722118Z","shell.execute_reply":"2021-08-28T12:05:28.089752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}