{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from utils import *\n", "warnings.filterwarnings('ignore')\n", "%matplotlib inline\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "fd_collection = getCollection(\"team_5_mwdb_phase_2\", \"fd_collection\")\n" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "class ImageGraph:\n", " \"\"\"\n", " Construct image-similarity graph and apply personalized pagerank algorithm to get PPR scores and find relevant images\n", " \"\"\"\n", "\n", " def __init__(self, fd_collection, verbose=False):\n", " self.fd_collection = fd_collection\n", " self.similarity_graph = None\n", " self.verbose = verbose\n", "\n", " def create_similarity_graph(\n", " self, n, feature_model, semantic_data=None, dim_reduction_method=None\n", " ):\n", " if semantic_data is None:\n", " # Similarity graph from feature models\n", " image_sim_matrix = find_image_image_similarity(fd_collection, feature_model)\n", " if self.verbose:\n", " print(\"Image-image similarity matrix constructed from\", feature_model)\n", " else:\n", " # Similarity graph from image-semantic latent space\n", " # LS3, LS4\n", " if \"sim-matrix\" in semantic_data:\n", " # for now, don't work with LS3\n", " # TODO: do similar to task 7 and 10\n", " image_sim_matrix = np.array(semantic_data[\"sim-matrix\"])\n", " if image_sim_matrix.shape[0] != NUM_IMAGES:\n", " raise TypeError(\n", " \"Functionality to construct similarity graph from LS3 not yet done\"\n", " )\n", " if self.verbose:\n", " print(\"Using image-image similarity matrix from semantic data\")\n", " # LS1, LS2\n", " else:\n", " image_semantic = semantic_data[\"image-semantic\"]\n", " # SVD, CP\n", " if \"semantics-core\" in semantic_data:\n", " semantics_core = np.array(semantic_data[\"semantics-core\"])\n", " if len(semantics_core.shape) == 1:\n", " semantics_core = np.diag(semantics_core)\n", " image_semantic = np.matmul(image_semantic, semantics_core)\n", "\n", " image_sim_matrix = np.zeros((NUM_IMAGES, NUM_IMAGES))\n", " # Calculate half and fill the other\n", " for i in range(NUM_IMAGES):\n", " for j in range(i + 1, NUM_IMAGES):\n", " # Note: lower the value, lower the distance => higher the similarity\n", " distance_measure = (\n", " kl_divergence_measure\n", " if dim_reduction_method == \"lda\"\n", " else euclidean_distance_measure\n", " )\n", " image_sim_matrix[j][i] = distance_measure(\n", " np.array(image_semantic[i]),\n", " np.array(image_semantic[j]),\n", " )\n", " image_sim_matrix[i][j] = image_sim_matrix[j][i]\n", " if self.verbose:\n", " print(\n", " \"Image-image similarity matrix constructed from given image-semantic\"\n", " )\n", "\n", " # Create an unweighted directed similarity graph, with no self-loops\n", " self.similarity_graph = []\n", " for i in range(len(image_sim_matrix)):\n", " # distances should be small, so sort in ascending order\n", " similar_image_ids = np.argsort(image_sim_matrix[i])[\n", " 1 : n + 1\n", " ] # exclude self\n", " self.similarity_graph.extend(\n", " [(i * 2, j * 2) for j in similar_image_ids]\n", " ) # i*2 cuz even IDs\n", " if self.verbose:\n", " print(\"Similarity graph created\")\n", "\n", " def personalized_pagerank(\n", " self, label, m, damping_factor=0.85, max_iter=1000, tol=1e-6\n", " ):\n", " import time\n", "\n", " if self.similarity_graph is None:\n", " raise ValueError(\n", " \"Similarity graph not created. Call create_similarity_graph() first.\"\n", " )\n", "\n", " label_indices = [\n", " img[\"image_id\"] for img in self.fd_collection.find({\"true_label\": label})\n", " ] # IDs of images with the given label\n", " num_label_nodes = len(label_indices)\n", "\n", " pr_scores = np.ones(NUM_IMAGES) / NUM_IMAGES # Initialize PageRank scores\n", " if self.verbose:\n", " print(\"Initialized pagerank scores\")\n", "\n", " for _iter in range(max_iter):\n", " prev_scores = np.copy(pr_scores)\n", "\n", " # for every edge\n", " for (i, j) in self.similarity_graph:\n", " # add neighbor's score\n", " pr_scores[int(i / 2)] += pr_scores[int(j / 2)]\n", " # damping\n", " pr_scores *= damping_factor\n", "\n", " # extra teleport prob for label nodes only\n", " for label_node in label_indices:\n", " pr_scores[label_node] += 1 - damping_factor\n", " pr_scores[label_node] /= num_label_nodes\n", "\n", " # normalize\n", " pr_scores /= sum(pr_scores)\n", "\n", " # check for convergence\n", " conv_tol = np.sum(np.abs(prev_scores - pr_scores))\n", " if self.verbose:\n", " print(f\"Iter {_iter}, conv_tol={conv_tol}\")\n", " if conv_tol < tol:\n", " if self.verbose:\n", " print(f\"Converged\")\n", " break\n", "\n", " # Select top m images based on PageRank scores\n", " top_m_indices = np.argsort(pr_scores)[::-1][\n", " :m\n", " ] # sort indices, reverse and take top m\n", " return top_m_indices * 2 # again, even IDs\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "image_sim-cm_fd-svd-10-semantics.json loaded\n" ] } ], "source": [ "n = int(input(\"Enter value of n (no. of edges for each image in similarity graph): \"))\n", "if n < 1:\n", " raise ValueError(\"n should be a positive integer\")\n", "\n", "l = int(input(\"Enter target label l:\"))\n", "if l < 0 or l > 100:\n", " raise ValueError(\"l should be in range[0,100]\")\n", "\n", "m = int(input(\"Enter value of m (no. of significant images relative to given label): \"))\n", "if m < 1:\n", " raise ValueError(\"m should be a positive integer\")\n", "\n", "given_ls = int(\n", " (input(\"Enter 0 to select a feature model, 1 to select a latent space: \"))\n", ")\n", "\n", "selected_feature_model = valid_feature_models[\n", " str(input(\"Enter feature model - one of \" + str(list(valid_feature_models.keys()))))\n", "]\n", "\n", "if given_ls:\n", " selected_latent_space = valid_latent_spaces[\n", " str(\n", " input(\n", " \"Enter latent space - one of \" + str(list(valid_latent_spaces.keys()))\n", " )\n", " )\n", " ]\n", "\n", " k = int(input(\"Enter value of k (no. of latent semantics): \"))\n", " if k < 1:\n", " raise ValueError(\"k should be a positive integer\")\n", "\n", " if selected_latent_space != \"cp\":\n", " selected_dim_reduction_method = str(\n", " input(\n", " \"Enter dimensionality reduction method - one of \"\n", " + str(list(valid_dim_reduction_methods.keys()))\n", " )\n", " )\n", "\n", " # Loading latent semantics\n", " match selected_latent_space:\n", " # LS1\n", " case \"\":\n", " file_prefix = (\n", " f\"{selected_feature_model}-{selected_dim_reduction_method}-{k}\"\n", " )\n", " file_name = file_prefix + \"-semantics.json\"\n", " model_name = file_prefix + \"-model.joblib\"\n", " if os.path.exists(file_name):\n", " data = json.load(open(file_name))\n", " print(file_name + \" loaded\")\n", " else:\n", " raise Exception(file_name + \" does not exist\")\n", " # LDA model\n", " if selected_dim_reduction_method == \"lda\":\n", " if os.path.exists(model_name):\n", " data_model = load(model_name)\n", " print(model_name + \" loaded\")\n", " else:\n", " raise Exception(model_name + \" does not exist\")\n", " # LS2\n", " case \"cp\":\n", " file_name = f\"{selected_feature_model}-cp-{k}-semantics.json\"\n", " if os.path.exists(file_name):\n", " data = json.load(open(file_name))\n", " print(file_name + \" loaded\")\n", " else:\n", " raise Exception(file_name + \" does not exist\")\n", " # LS3, LS4\n", " case _:\n", " file_name = f\"{selected_latent_space}-{selected_feature_model}-{selected_dim_reduction_method}-{k}-semantics.json\"\n", " if os.path.exists(file_name):\n", " data = json.load(open(file_name))\n", " print(file_name + \" loaded\")\n", " else:\n", " raise Exception(file_name + \" does not exist\")\n" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Using image-image similarity matrix from semantic data\n", "Similarity graph created\n", "Initialized pagerank scores\n", "Iter 0, conv_tol=1.719665978050747\n", "Iter 1, conv_tol=1.2881607697596094\n", "Iter 2, conv_tol=0.2665287566432058\n", "Iter 3, conv_tol=0.059527897230663145\n", "Iter 4, conv_tol=0.0347000929210205\n", "Iter 5, conv_tol=0.02202852715618498\n", "Iter 6, conv_tol=0.013882145533702685\n", "Iter 7, conv_tol=0.008684261384663692\n", "Iter 8, conv_tol=0.005407038899165463\n", "Iter 9, conv_tol=0.0033566552382892495\n", "Iter 10, conv_tol=0.002079980308951357\n", "Iter 11, conv_tol=0.0012874164560444917\n", "Iter 12, conv_tol=0.0007962948214944976\n", "Iter 13, conv_tol=0.0004923115832688122\n", "Iter 14, conv_tol=0.00030429131691503663\n", "Iter 15, conv_tol=0.0001880472373585323\n", "Iter 16, conv_tol=0.00011619830480688171\n", "Iter 17, conv_tol=7.179680034073339e-05\n", "Iter 18, conv_tol=4.4360187507886776e-05\n", "Iter 19, conv_tol=2.740760859338375e-05\n", "Iter 20, conv_tol=1.6933331813984318e-05\n", "Iter 21, conv_tol=1.0461878708516084e-05\n", "Iter 22, conv_tol=6.463599865544653e-06\n", "Iter 23, conv_tol=3.993353111534267e-06\n", "Iter 24, conv_tol=2.4671753579536407e-06\n", "Iter 25, conv_tol=1.524269424726632e-06\n", "Iter 26, conv_tol=9.417228262050036e-07\n", "Converged\n" ] } ], "source": [ "if not given_ls:\n", " img_graph = ImageGraph(fd_collection, True)\n", " img_graph.create_similarity_graph(n, selected_feature_model)\n", " imgs = img_graph.personalized_pagerank(l, m)\n", "else:\n", " img_graph = ImageGraph(fd_collection, True)\n", " img_graph.create_similarity_graph(\n", " n,\n", " selected_feature_model,\n", " data,\n", " selected_dim_reduction_method\n", " )\n", " imgs = img_graph.personalized_pagerank(l, m)\n" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([8464, 8432, 8354, 7988, 8312, 8674, 8628, 8586, 8208, 7990],\n", " dtype=int64)" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "imgs" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.5" } }, "nbformat": 4, "nbformat_minor": 2 }