{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"## We have removed the sensitive portions of this script, and included those\n## that show you how we:\n## 1. Load your model\n## 2. Create embeddings\n## 3. Compare and score those embeddings.\n##\n## Note that this means this code will NOT run as-is.\n\nimport os\nos.sys.path.append('../input/glr2020-utility-ds')\nimport numpy as np\nfrom pathlib import Path\nimport tensorflow as tf\nfrom PIL import Image\nimport time\nfrom scipy.spatial import distance\nfrom tqdm import tqdm\n\nimport solution\nimport metrics","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"K = 100\nREQUIRED_SIGNATURE = 'serving_default'\nREQUIRED_OUTPUT = 'global_descriptor'\n\nDATASET_DIR = '../input/landmark-retrieval-2020/' # path to internal dataset\n\nSAVED_MODELS_DIR = os.path.join('/', 'kaggle', 'working')\nQUERY_IMAGE_DIR = os.path.join(DATASET_DIR, 'test')\nINDEX_IMAGE_DIR = os.path.join(DATASET_DIR, 'index')\nSOLUTION_PATH = '../input/glr2020-utility-ds/retrieval_solution_v2.1.csv'\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"!unzip -o ../input/baseline-submission/submission.zip\n# !unzip -o ../input/glr2020-0725-submit-test/submission.zip","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def to_hex(image_id: int) -> str:\n    return '{0:0{1}x}'.format(image_id, 16)\n\n\ndef show_elapsed_time(start):\n    hours, rem = divmod(time.time() - start, 3600)\n    minutes, seconds = divmod(rem, 60)\n    parts = []\n\n    if hours > 0:\n        parts.append('{:>02}h'.format(hours))\n\n    if minutes > 0:\n        parts.append('{:>02}m'.format(minutes))\n\n    parts.append('{:>05.2f}s'.format(seconds))\n\n    print('Elapsed Time: {}'.format(' '.join(parts)))\n\n\ndef get_distance(scored_prediction):\n    return scored_prediction[1]\n\nembedding_fn = None\n\ndef get_embedding(image_path: Path) -> np.ndarray:\n    image_data = np.array(Image.open(str(image_path)).convert('RGB'))\n    image_tensor = tf.convert_to_tensor(image_data)\n    return embedding_fn(image_tensor)[REQUIRED_OUTPUT].numpy()\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Submission:\n    def __init__(self, name, model):\n        self.name = name\n        self.model = model\n        public_solution, private_solution, ignored_ids = solution.load(SOLUTION_PATH, \n                                                         solution.RETRIEVAL_TASK_ID)\n        predictions = self.get_predictions()\n        \n        self.private_score = self.get_metrics(predictions, private_solution)\n        self.public_score = self.get_metrics(predictions, public_solution)\n\n    def load(self, saved_model_proto_filename):\n        saved_model_path = Path(saved_model_proto_filename).parent\n        \n        print (saved_model_path, saved_model_proto_filename)\n        \n        name = saved_model_path.relative_to(SAVED_MODELS_DIR)\n        \n        model = tf.saved_model.load(str(saved_model_path))\n        \n        found_signatures = list(model.signatures.keys())\n        \n        if REQUIRED_SIGNATURE not in found_signatures:\n            return None\n        \n        outputs = model.signatures[REQUIRED_SIGNATURE].structured_outputs\n        if REQUIRED_OUTPUT not in outputs:\n            return None\n        \n        global embedding_fn\n        embedding_fn = model.signatures[REQUIRED_SIGNATURE]\n\n        return Submission(name, model)\n    \n\n    def get_id(self, image_path: Path):\n        return int(image_path.name.split('.')[0], 16)\n\n\n    def get_embeddings(self, image_root_dir: str):\n        image_paths = [p for p in Path(image_root_dir).rglob('*.jpg')]\n        print(len(image_paths))\n        \n        embeddings = [get_embedding(image_path) \n                      for i, image_path in tqdm(enumerate(image_paths))]\n        ids = [self.get_id(image_path) for image_path in image_paths]\n\n        return ids, embeddings\n    \n    def get_predictions(self):\n        print('Embedding queries...')\n        start = time.time()\n        query_ids, query_embeddings = self.get_embeddings(QUERY_IMAGE_DIR)\n        show_elapsed_time(start)\n\n        print('Embedding index...')\n        start = time.time()\n        index_ids, index_embeddings = self.get_embeddings(INDEX_IMAGE_DIR)\n        show_elapsed_time(start)\n\n        print('Computing distances...', end='\\t')\n        start = time.time()\n        distances = distance.cdist(np.array(query_embeddings), \n                                   np.array(index_embeddings), 'euclidean')\n        show_elapsed_time(start)\n\n        print('Finding NN indices...', end='\\t')\n        start = time.time()\n        predicted_positions = np.argpartition(distances, K, axis=1)[:, :K]\n        show_elapsed_time(start)\n\n        print('Converting to dict...', end='\\t')\n        predictions = {}\n        for i, query_id in enumerate(query_ids):\n            nearest = [(index_ids[j], distances[i, j]) \n                       for j in predicted_positions[i]]\n            nearest.sort(key=lambda x: x[1])\n            prediction = [to_hex(index_id) for index_id, d in nearest]\n            predictions[to_hex(query_id)] = prediction\n        show_elapsed_time(start)\n\n        return predictions\n    \n    def get_metrics(self, predictions, solution):\n        relevant_predictions = {}\n\n        for key in solution.keys():\n            if key in predictions:\n                relevant_predictions[key] = predictions[key]\n\n        # Mean average precision.\n        mean_average_precision = metrics.MeanAveragePrecision(\n            relevant_predictions, solution, max_predictions=K)\n        print('Mean Average Precision (mAP): {:.4f}'.format(mean_average_precision))\n\n        return mean_average_precision","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"s = Submission.load(None, \"/kaggle/working/saved_model.pb\")\n# s.get_predictions()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"s","execution_count":null,"outputs":[]},{"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}