{"cells":[{"metadata":{},"cell_type":"markdown","source":"**Welcome to the third Landmark Recognition competition!**\n\nThis is a quite interesting and difficult competition. I have just read a few EDA notebooks in this competition. I realize that most people EDA based on landmark_id. That is not enough to have a good result. Are you wondering: in this data, how many monastic photos ? how many temples, mountains,  even rocks ...   \n\nYou should check how many **landmark types**, what types and the **frequency of each type**. In this notebook, I classified 81K landmarks into (<1000) classes with pretrain resnet50. You can use the result to rebalance the dataset.","execution_count":null},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport sys\nsys.path.insert(0, \"../input\")\nimport cv2\n\nimport torch\nimport pandas as pd\nfrom matplotlib import pyplot as plt\n\n\nimport torchvision\nimport torchvision.models as models\nfrom torchvision import datasets, transforms as T\nfrom PIL import Image\nfrom torchvision import transforms\nfrom random import randint, choice, choices\nimport json\nfrom torch.utils.data import DataLoader, Dataset\nfrom tqdm.notebook import tqdm\n\n\nwith open(\"../input/imagenet-class-index/imagenet_class_index.json\") as json_file:\n    class_idx = json.load(json_file)\nidx2label = [class_idx[str(k)][1] for k in range(len(class_idx))]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def load_img(img_id, img_dir=f\"../input/landmark-recognition-2020/train\", PIL=True):\n    f1, f2, f3 = img_id[:3]\n    filename = f\"{img_dir}/{f1}/{f2}/{f3}/{img_id}.jpg\"\n    if PIL:\n        img = Image.open(filename)\n    else:\n        img = cv2.imread(filename)\n    return img\n\n\ndef plot_img(img, size=(7, 7), title=\"\"):\n    if isinstance(img, str):\n        img = load_img(img)\n    plt.figure(figsize=size)\n    plt.imshow(img)\n    plt.suptitle(title)\n    plt.show()\n    \n    \ndef plot_imgs(imgs, cols=5, size=7, title=\"\", title_list=None):\n    rows = len(imgs)//cols + 1\n    fig = plt.figure(figsize=(cols*size, rows*size))\n    for i, img in enumerate(imgs):\n        if isinstance(img, str):\n            img = load_img(img)\n        fig.add_subplot(rows, cols, i+1)\n        plt.imshow(img)\n        if title_list is not None:\n            plt.title(title_list[i])\n    plt.suptitle(title)\n    plt.show()\n\ndef toTensor(array, axis=(2,0,1)):\n    if isinstance(array, torch.Tensor):\n        return array\n    return torch.tensor(array).permute(axis)\n\ndef toNumpy(tensor, axis=(1,2,0)):\n    if isinstance(tensor, np.ndarray):\n        return tensor\n    return tensor.detach().cpu().permute(axis).numpy()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class LandmarkDataset(Dataset):\n    def __init__(self, landmark_ids, img_dir, dataframe, transforms=None):\n        self.landmark_ids = landmark_ids\n        self.img_dir = img_dir\n        self.df = dataframe\n        self.transforms = transforms\n        \n    def __getitem__(self, idx):\n        landmark_id = self.landmark_ids[idx]\n        df = self.df\n        img_id = df[df[\"landmark_id\"]==landmark_id][\"id\"].values[0]\n        img = load_img(img_id, self.img_dir)\n        if self.transforms:\n            img = self.transforms(img)\n        return landmark_id, img_id, img\n        \n    def __len__(self):\n        return len(self.landmark_ids)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img_dir=f\"../input/landmark-recognition-2020/train\"\ndf = pd.read_csv(\"../input/landmark-recognition-2020/train.csv\")\ndf.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Each landmark_id, you only need to classify one or a few images","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"landmark_ids = df[\"landmark_id\"].unique()\nsample_ids = []\n\nfor lmark_id in tqdm(landmark_ids):\n    sample_id = df[df[\"landmark_id\"]==lmark_id][\"id\"].values[0]\n    sample_ids.append(sample_id)\n    \nlandmark_df = pd.DataFrame({\n    \"landmark_id\": landmark_ids,\n    \"id\" : sample_ids\n})","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"n = len(df)\nimg_ids = list(df[\"id\"])\ntransforms_ = transforms.Compose([\n    transforms.Resize(256),\n    transforms.CenterCrop(224),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n])\n\nlandmark_dataset = LandmarkDataset(landmark_ids=landmark_ids, img_dir=img_dir, dataframe=landmark_df, transforms=transforms_)\nlandmark_loader = DataLoader(landmark_dataset, batch_size=80, shuffle=False, drop_last=False)\n# lmark_ids, ids, img = next(iter(landmark_loader))\n\nmodel_path = \"../input/pretrained-pytorch-models/resnet50-19c8e357.pth\"\nmodel = models.resnet50()\nmodel.eval()\nmodel.load_state_dict(torch.load(model_path))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pickle\n\ndef save_label(id_labels, filename):\n    with open(filename, \"w+\") as f:\n        pickle.dump(id_labels, f)\n        f.close()\n\ndevice = torch.device(\"cuda\")\nmodel.to(device)\nmodel.eval()\nresult = []\ni = 0\n\n\nfor lmark_ids, ids, img_patch in tqdm(landmark_loader):\n    i += 1\n    img_patch = img_patch.to(device)\n    labels = model(img_patch)\n    labels = labels.detach().cpu().numpy().argmax(1)\n    \n    for lmark_id, label in zip(lmark_ids, labels):\n        result.append([lmark_id, label])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"lmark_ids = [int(e[0]) for e in result]\nlabel_ids = [e[1] for e in result]\nlabels = [idx2label[l_id] for l_id in label_ids]\n\nclassify_df = pd.DataFrame({\n    \"landmark_id\": lmark_ids,\n    \"label_id\": label_ids,\n    \"label\": labels\n})\n\nclassify_df.to_csv(\"classify_dataframe.csv\")\nclassify_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"imgs = []\nlabels = []\n\nfor i,(lmark_id, _, img) in enumerate(landmark_dataset):\n    labels.append(classify_df[classify_df[\"landmark_id\"] == lmark_id][\"label\"].values[0])\n    imgs.append(toNumpy(img))\n    if i == 10:\n        break\nplot_imgs(imgs, title_list=labels)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Simple EDA\nIn this notebook, I focus on preparing the data for you instead of EDA. So I will only do some basic analysis.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from bokeh.plotting import figure as bokeh_figure\nfrom bokeh.io import output_notebook, show, output_file\nfrom bokeh.models import ColumnDataSource, HoverTool, Panel\nfrom bokeh.models.widgets import Tabs\n\n\ndef hist_hover(dataframe, column, color=[\"#94c8d8\", \"#ea5e51\"], bins=30, title=\"\", value_range=None):\n    hist, edges = np.histogram(dataframe[column], bins=bins, range=value_range)\n    hist_frame = pd.DataFrame({\n        column: hist,\n        \"left\": edges[:-1],\n        \"right\": edges[1:]\n    })\n    hist_frame[\"interval\"] = [\"%d to %d\" %\n                              (left, right) for left, right in zip(edges[:-1], edges[1:])]\n    src = ColumnDataSource(hist_frame)\n    plot = bokeh_figure(\n        plot_height=600, plot_width=1000,\n        title=title, x_axis_label=column,\n        y_axis_label=\"Count\"\n    )\n    plot.quad(\n        bottom=0, top=column, left=\"left\", right=\"right\",\n        source=src, fill_color=color[0], line_color=\"#35838d\",\n        fill_alpha=0.7, hover_fill_alpha=0.7,\n        hover_fill_color=color[1]\n    )\n    hover = HoverTool(\n        tooltips=[(\"Interval\", \"@interval\"), (\"Count\", str(f\"@{column}\"))]\n    )\n    plot.add_tools(hover)\n    output_notebook()\n    show(plot)\n\n\nhist_hover(classify_df, column=\"label_id\", bins=1000, title=\"frequency of landmark type\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"lmark_labels = classify_df[\"label\"]\nlabels, counts = np.unique(lmark_labels,return_counts=True)\nlabel_counts = list(zip(labels, counts))\nlabel_counts.sort(key=lambda x: x[1])\n\nprint(\"top 20 COMMON\")\nprint(label_counts[-20:])\n\nprint(\"top 20 NOT COMMON\")\nprint(label_counts[:20])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Note: **Certainly, the results returned by this model are not exactly accurate (but useful)**\n","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"Download csv file: [landmark-2020-landmark-classification-for-eda](https://www.kaggle.com/trungthanhnguyen0502/landmark-2020-landmark-classification-for-eda/download)\n## Don't forget to upvote me :D ","execution_count":null},{"metadata":{},"cell_type":"markdown","source":"","execution_count":null}],"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}