{"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":"markdown","source":"このノートブックは4章のkaggleコンテストによる投稿例を紹介します。\n\n実行には GPU を使います。Accelerator に GPU P100 を設定してください。\n\n次のデータセットを追加してください： \n\n* https://www.kaggle.com/datasets/confirm/gldv2micropretrained (小規模部分セットの GLDv2 micro で学習したモデルの重み)\n* https://www.kaggle.com/datasets/astarikov/faissgpu17 (faiss-gpu パッケージ)\n\n[Google Landmark Dataset v2](https://github.com/cvdfoundation/google-landmark) によって学習したモデルの重みファイルは以下に用意しています：\n\n* https://www.kaggle.com/datasets/confirm/gldv2cleanpretrained","metadata":{}},{"cell_type":"code","source":"# 必要なパッケージをインストール\n!pip install -q /kaggle/input/faissgpu17/faiss_gpu-1.7.0-cp37-cp37m-manylinux2014_x86_64.whl","metadata":{"execution":{"iopub.status.busy":"2023-01-26T19:18:24.382705Z","iopub.execute_input":"2023-01-26T19:18:24.383097Z","iopub.status.idle":"2023-01-26T19:18:37.290121Z","shell.execute_reply.started":"2023-01-26T19:18:24.383063Z","shell.execute_reply":"2023-01-26T19:18:37.288969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 作成する投稿ファイルのフォーマットを確認\n!head /kaggle/input/landmark-retrieval-2021/sample_submission.csv","metadata":{"execution":{"iopub.status.busy":"2023-01-26T18:45:26.950581Z","iopub.execute_input":"2023-01-26T18:45:26.950981Z","iopub.status.idle":"2023-01-26T18:45:27.907903Z","shell.execute_reply.started":"2023-01-26T18:45:26.950942Z","shell.execute_reply":"2023-01-26T18:45:27.906738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pathlib import Path\nimport sys\nsys.path.append(\"/kaggle/input/gldv2micropretrained/\")\n\nimport tqdm\nimport faiss\nimport torch\nimport numpy as np\nimport albumentations as A\nfrom torch.utils.data import DataLoader, Dataset\nfrom torch.utils.data.sampler import SequentialSampler\nfrom PIL import Image\n\nfrom model import AngularModel","metadata":{"execution":{"iopub.status.busy":"2023-01-26T18:45:27.909524Z","iopub.execute_input":"2023-01-26T18:45:27.909859Z","iopub.status.idle":"2023-01-26T18:45:31.033284Z","shell.execute_reply.started":"2023-01-26T18:45:27.909828Z","shell.execute_reply":"2023-01-26T18:45:31.032164Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_model():\n    state_dict = torch.load(\"/kaggle/input/gldv2micropretrained/resnext101_64x4d_size384_aug_scalerotate_colorjit_cutoff_last.pth\")\n    model = AngularModel(model_name=\"resnext101_64x4d\", n_classes=3103, pretrained=False)\n    model.load_state_dict(state_dict[\"state_dict\"])\n    return model.cuda()\n\n\nclass GL21InferenceDataset(Dataset):\n    def __init__(self, filelist, transform) -> None:\n        self.filelist = filelist\n        self.transform = transform\n\n    def __len__(self) -> int:\n        return len(self.filelist)\n\n    def __getitem__(self, index):\n        filepath = Path(self.filelist[index])\n        assert filepath.exists()\n\n        im = np.array(Image.open(str(filepath)))\n        im = self.transform(image=im)[\"image\"]\n        im = torch.from_numpy(im.transpose((2, 0, 1))).float()\n        id_name = filepath.stem\n\n        return im, id_name\n\n\ndef get_dataloaders(batch_size=8, input_size=384):\n    test_transform = A.Compose([\n        A.Resize(width=input_size, height=input_size),\n        A.Normalize(),\n    ])\n\n    index_filelist = list(Path(\"/kaggle/input/landmark-retrieval-2021/index\").glob(\"./**/*.jpg\"))\n    index_dataset = GL21InferenceDataset(index_filelist, test_transform)\n    index_dataloader = DataLoader(\n        dataset=index_dataset,\n        sampler=SequentialSampler(index_dataset),\n        batch_size=batch_size,\n        pin_memory=True,\n        num_workers=2,\n        drop_last=False,\n    )\n\n    query_filelist = list(Path(\"/kaggle/input/landmark-retrieval-2021/test\").glob(\"./**/*.jpg\"))\n    query_dataset = GL21InferenceDataset(query_filelist, test_transform)\n    query_dataloader = DataLoader(\n        dataset=query_dataset,\n        sampler=SequentialSampler(query_dataset),\n        batch_size=batch_size,\n        pin_memory=True,\n        num_workers=2,\n        drop_last=False,\n    )\n    \n    return query_dataloader, index_dataloader\n\n\ndef l2norm_numpy(x):\n    return x / np.linalg.norm(x, ord=2, axis=1, keepdims=True)","metadata":{"execution":{"iopub.status.busy":"2023-01-26T18:45:31.036277Z","iopub.execute_input":"2023-01-26T18:45:31.036868Z","iopub.status.idle":"2023-01-26T19:12:06.590629Z","shell.execute_reply.started":"2023-01-26T18:45:31.036826Z","shell.execute_reply":"2023-01-26T19:12:06.589378Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = get_model()\nquery_dataloader, index_dataloader = get_dataloaders(batch_size=32, input_size=384)\n\n\n# Query\nquery_features = []\nquery_ids = []\nfor i, (batch, id_names) in tqdm.tqdm(enumerate(query_dataloader), total=len(query_dataloader)):\n    with torch.no_grad():\n        batch = batch.cuda()\n        out = model.extract_features(batch)\n        query_features.append(out.data.cpu().numpy())\n        query_ids += list(id_names)\n\nquery_features = l2norm_numpy(np.vstack(query_features))\n\n# Index\ngpu_resource = faiss.StandardGpuResources()\ncpu_index = faiss.IndexFlatIP(512)\nindex = faiss.index_cpu_to_gpu(gpu_resource, 0, cpu_index)\nindex_ids = []\nfor i, (batch, id_names) in tqdm.tqdm(enumerate(index_dataloader), total=len(index_dataloader)):\n    with torch.no_grad():\n        batch = batch.cuda()\n        out = model.extract_features(batch)\n        index_ids += list(id_names)\n        index.add(l2norm_numpy(out.data.cpu().numpy()))\n\nsims, topk_idx = index.search(x=query_features, k=100)\nprint(sims.shape, topk_idx.shape)\n\nwith open(\"/kaggle/working/submission.csv\", \"w\") as f:\n    f.write(\"id,images\\n\")\n    for query_idx, query_id in enumerate(query_ids):\n        index_images = \" \".join(np.array(index_ids)[topk_idx[query_idx]].tolist())\n        f.write(f\"{query_id},{index_images}\\n\")","metadata":{},"execution_count":null,"outputs":[]}]}