{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"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 tensorflow as tf\nimport tensorflow.keras as K\nimport cv2\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nimport seaborn as sns\n#!pip install efficientnet\nimport efficientnet.tfkeras as efn","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"train = pd.read_csv(\"../input/landmark-recognition-2020/train.csv\")\ntrain","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"num_classes = len(train[\"landmark_id\"].unique()) #81313 unique landmarks\nnum_classes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train[\"path\"] = train[\"id\"].map(lambda x: \"../input/landmark-recognition-2020/train/\" + \n                                x[0] + \"/\" + x[1] + \"/\" + x[2] + \"/\" + x + \".jpg\")\ntrain","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"There are 81313 unique landmarks in our training dataset, with a mean of ~19 images per landmark and a median of 9. The dataset is strongly imbalanced: in the 75th percentile, images appear 20 times. Some images, however, appear thousands of times and they dominate the dataset. We should consider balancing the dataset (oversampling/undersampling).","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"train[\"landmark_id\"].value_counts().describe()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.style.use(\"ggplot\")\nsns.distplot(train[\"landmark_id\"].value_counts())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.set_style('whitegrid', {'axes.grid' : False})\nplt.figure(figsize=(20,10))\n\nsample = train.sample(n=16).reset_index()\n\nfor i in range(16):\n    plt.subplot(4, 4, i+1)\n    img = cv2.imread(sample[\"path\"][i])\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    plt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\nX_train, X_test, y_train, y_test = train_test_split(train[\"path\"], train[\"landmark_id\"], test_size=0.3)\n\n# tf.dataset setting\nAUTOTUNE = tf.data.experimental.AUTOTUNE\n\n# training configuration\nEPOCHS = 5\nBATCH_SIZE = 32\n\n# for model\nIMAGE_SIZE = 128\n\ndef decode_image(filename, image_size=(IMAGE_SIZE, IMAGE_SIZE)):\n    image = tf.io.read_file(filename)\n    image = tf.image.decode_jpeg(image, channels=3)\n    image = tf.cast(image, tf.float32) / 255.0\n    image = tf.image.resize(image, image_size)\n    return image\n    \ndef to_onehot(label):\n    label = tf.one_hot(tf.cast(label, tf.int32), num_classes)\n    label = tf.cast(label, tf.int32)\n    return label","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image_ds_train = tf.data.Dataset.from_tensor_slices(X_train).map(decode_image)\nlabel_ds_train = tf.data.Dataset.from_tensor_slices(y_train).map(to_onehot)\nimage_ds_test = tf.data.Dataset.from_tensor_slices(X_test).map(decode_image)\nlabel_ds_test = tf.data.Dataset.from_tensor_slices(y_test).map(to_onehot)\n\ntrain_dataset = tf.data.Dataset.zip((image_ds_train, label_ds_train)).shuffle(1024).repeat().batch(BATCH_SIZE).prefetch(buffer_size=AUTOTUNE)\nvalid_dataset = tf.data.Dataset.zip((image_ds_test, label_ds_test)).batch(BATCH_SIZE)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = tf.keras.Sequential([\n        efn.EfficientNetB3(\n            input_shape=(IMAGE_SIZE, IMAGE_SIZE, 3),\n            weights='imagenet',\n            include_top=False\n        ),\n        K.layers.GlobalAveragePooling2D(),\n        K.layers.Dense(num_classes, activation='sigmoid')\n    ])\n\nmodel.compile(\n        optimizer='adam',\n        loss = 'categorical_crossentropy',\n        metrics=['accuracy']\n    )\n\nmodel.summary()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"STEPS_PER_EPOCH = y_train.shape[0] // BATCH_SIZE\n\nhistory = model.fit(\n    train_dataset, \n    batch_size=BATCH_SIZE,\n    epochs=EPOCHS, \n    validation_data=valid_dataset,\n    steps_per_epoch=STEPS_PER_EPOCH\n#     callbacks=[],\n)","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}