{"cells":[{"metadata":{},"cell_type":"markdown","source":"# Google Landmark Retrieval 2020 - Exploratory Data Analysis\n\n<img src=\"https://cdn.getyourguide.com/img/tour_img-2420980-146.jpg\" alt=\"drawing\" style=\"width:780px;\"/></br>\n\n\n### Previous Related Competitions\n\n1. [Google Landmark Retrieval 2019](https://www.kaggle.com/c/landmark-retrieval-2019)\n1. [Google Landmark Retrieval Challenge](https://www.kaggle.com/c/landmark-retrieval-challenge)\n\nReferences:\n1. https://www.kaggle.com/seriousran/google-landmark-retrieval-2020-eda\n2. https://www.kaggle.com/codename007/google-landmark-retrieval-exploratory-analysis\n3. https://www.kaggle.com/huangxiaoquan/google-landmarks-v2-exploratory-data-analysis-eda","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"## Structure\n1. Exploratory Data Analysis\n    1. [Training data](#2)\n    2. [Specific basic information](#2)\n    3. [Upload all the data](#4)\n    4. [Test examples](#5)\n    5. [Index examples](#6)\n    6. [Images by_classes](#7)","execution_count":null},{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","trusted":true},"cell_type":"code","source":"import numpy as np \nimport pandas as pd \n\nimport os\nimport glob\nimport cv2\n\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom plotly import graph_objs as go\nimport plotly.express as px\nimport plotly.figure_factory as ff\n\nfrom scipy import stats\n\nimport warnings\nwarnings.filterwarnings(\"ignore\")\n\n%matplotlib inline\n%config InlineBackend.figure_format = 'png'","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1.1 Train data\n\nIn this competition, you are asked to develop models that can efficiently retrieve landmark images from a large database. \nThe training set is available in the train/ folder, with corresponding landmark labels in train.csv. ","execution_count":null},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"df_train = pd.read_csv('../input/landmark-retrieval-2020/train.csv')\nprint(f'Train df consumes {df_train.memory_usage().sum() / 1024**2:.4f} MB of RAM and has a shape {df_train.shape}')\ndf_train.sample(5)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Landmark_id distribuition","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"value_counts = df_train.landmark_id.value_counts().reset_index().rename(columns={'landmark_id': 'count', 'index': 'landmark_id'})\nvalue_counts_sorted = value_counts.sort_values('count')\nvalue_counts","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"As we see, the frequency of landmark id 138982 greatly exceeds all the others. Hence, landmark_id equal to 138982 may be either a special number (for instance, referring no non-labeled or mixed images) or just represent the most popular landmark.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(12, 6))\nplt.title('landmark_id distribution')\nsns.distplot(df_train['landmark_id']);","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Training set: number of images per class (dist plot and line plot)\n\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(12,6))\np1=sns.distplot(value_counts, color=\"b\").set_title('Number of images per class')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(12, 6))\nsns.set()\nplt.title('Training set: number of images per class (line plot logarithmically scaled)')\nax = value_counts['count'].plot(logy=True, grid=True)\nlocs, labels = plt.xticks()\nplt.setp(labels, rotation=30)\nax.set(xlabel=\"Landmarks\", ylabel=\"Number of images\");","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Visualize outliers, min/max or quantiles of the landmarks count","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.set()\nax = value_counts.boxplot(column='landmark_id')\nax.set_yscale('log')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.set()\nres = stats.probplot(df_train['landmark_id'], plot=plt)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Training set: number of images per class(scatter plot)","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(12, 6))\nsns.set()\nlandmarks_fold_sorted = value_counts_sorted\nax = landmarks_fold_sorted.plot.scatter(\n     x='landmark_id',y='count',\n     title='Training set: number of images per class(statter plot)')\nlocs, labels = plt.xticks()\nplt.setp(labels, rotation=30)\nax.set(xlabel=\"Landmarks\", ylabel=\"Number of images\");","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1.2 Specific basic information\n\nIn this section we will derive some interesting and useful facts about the data distribution.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"threshold = [2, 3, 5, 10, 20, 50, 100]\nfor num in threshold:    \n    print(\"Number of classes under {}: {}/{} \"\n          .format(num, (df_train['landmark_id'].value_counts() < num).sum(), \n                  len(df_train['landmark_id'].unique()))\n          )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Visualize top-25 most and least frequent landmark ids","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.set()\nplt.figure(figsize=(14, 9))\nplt.title('Most frequent landmarks')\nsns.set_color_codes(\"pastel\")\nsns.barplot(x=\"landmark_id\", y=\"count\", data=value_counts_sorted.tail(25),\n            label=\"Count\")\nlocs, labels = plt.xticks()\nplt.setp(labels, rotation=45)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.set()\nplt.figure(figsize=(14, 9))\nplt.title('Least frequent landmarks')\nsns.set_color_codes(\"pastel\")\nsns.barplot(x=\"landmark_id\", y=\"count\", data=value_counts_sorted.head(25),\n            label=\"Count\")\nlocs, labels = plt.xticks()\nplt.setp(labels, rotation=45)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1.3 Upload all the data\n\nThe query images are listed in the test/ folder, while the \"index\" images from which you are retrieving are listed in index/. \n\nEach image has a unique id. Since there are a large number of images, each image is placed within three subfolders according to the first three characters of the image id (i.e. image abcdef.jpg is placed in a/b/c/abcdef.jpg).\n\n0-f in 0-f in 0-f","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"train_list = glob.glob('../input/landmark-retrieval-2020/train/*/*/*/*')\ntest_list = glob.glob('../input/landmark-retrieval-2020/test/*/*/*/*')\nindex_list = glob.glob('../input/landmark-retrieval-2020/index/*/*/*/*')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print( 'Query', len(test_list), ' test images in ', len(index_list), 'index images')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1.4 Test examples","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_random_images(data_list, seed=2020_07_02, n_rows=3, n_cols=3):\n    \n    np.random.seed(seed)\n    random_ids = np.random.choice(range(len(data_list)), n_rows * n_cols, False)\n\n    plt.rcParams[\"axes.grid\"] = False\n    f, axarr = plt.subplots(n_rows, n_cols, figsize=(24, 22))\n\n    curr_row = 0\n    for i, random_id in enumerate(random_ids):\n        example = cv2.imread(data_list[random_id])\n        example = example[:,:,::-1]\n\n        col = i % n_cols\n        axarr[col, curr_row].imshow(example)\n        if col == n_cols - 1:\n            curr_row += 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_random_images(test_list)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1.5 Index examples","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_random_images(index_list)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1.6 Images by classes","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"all_ids = df_train.landmark_id.unique()\n\nnp.random.seed(2020)\nn_random, len_row = 5, 3\nrandom_ids = np.append(np.random.choice(all_ids, n_random, False), [138982])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.rcParams[\"axes.grid\"] = False\nf, axarr = plt.subplots(n_random+1, len_row, figsize=(len_row*7, 6*(n_random+1)))\n\ncurr_row = 0\nfor random_id in random_ids:\n    images = df_train.query(f'landmark_id == {random_id}').sample(len_row)['id']\n    for i, img in enumerate(images):\n        arg_img = int(np.argwhere(list(map(lambda x: img in x, train_list))).ravel())\n        example = cv2.imread(train_list[arg_img])\n        example = example[:,:,::-1]\n\n        col = i % len_row\n        axarr[curr_row, col].imshow(example)\n        if col == len_row - 1:\n            curr_row += 1","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### A few more examples\n(I found the images, depicted using another random seed, representative for other points).","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"np.random.seed(0)\nn_random, len_row = 3, 3\nrandom_ids = np.random.choice(all_ids, n_random, False)\n\nplt.rcParams[\"axes.grid\"] = False\nf, axarr = plt.subplots(n_random, len_row, figsize=(len_row*7, 6*n_random))\n\ncurr_row = 0\nfor random_id in random_ids:\n    images = df_train.query(f'landmark_id == {random_id}').sample(len_row)['id']\n    for i, img in enumerate(images):\n        arg_img = int(np.argwhere(list(map(lambda x: img in x, train_list))).ravel())\n        example = cv2.imread(train_list[arg_img])\n        example = example[:,:,::-1]\n\n        col = i % len_row\n        axarr[curr_row, col].imshow(example)\n        if col == len_row - 1:\n            curr_row += 1","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## 1.7 Inference","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"### We can derive several important aspects of the data:\n    1. Some photos are either augmented versions of others (2nd and 3rd images in the last row of the second cell).\n    2. There are a lot of classes containing images of the same places (1st and 5th rows in the first cell, last two rows in the second cell).\n    3. Some classes may contain non-trivial or, what is more probable, noisy data (the last image in row 4 in the first cell).\n    4. The most popular landmark_id refers to photographs with annotation. An interesting fact is the annotation always has the same structure with first number turned upside down. It may probably stand for the photo's id. \n    5. Index data contains images with people zoomed, while test / train data do not or store less of them.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"","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}