Implement Evaluation Metrics

#13
by thesparshsaxena - opened
repository/DBClient.py CHANGED
@@ -14,3 +14,10 @@ def get_db_client():
14
  }
15
  )
16
  return db
 
 
 
 
 
 
 
 
14
  }
15
  )
16
  return db
17
+
18
+ def get_db_client_for_relevance():
19
+ client = chromadb.PersistentClient(path=f"/data/dbs/{get_user_storage_id()}")
20
+ db = client.get_or_create_collection(
21
+ name = "relevance",
22
+ )
23
+ return db
repository/Search_Image.py CHANGED
@@ -6,7 +6,7 @@ import numpy as np
6
  from io import BytesIO
7
  import time
8
  import bm25s
9
- from repository.DBClient import get_db_client
10
  from repository.Embedding_model import load_embedding_model
11
  import torch
12
  import torch.nn.functional as F
@@ -22,6 +22,7 @@ with st.sidebar:
22
  # show all images from chromadb in batch of 50
23
  try:
24
  db = get_db_client()
 
25
  except Exception as e:
26
  st.warning("No images found. Please upload some images first.")
27
  st.stop()
@@ -62,8 +63,10 @@ if not search_query:
62
  st.image(image, width="stretch")
63
  if st.button("Delete", key=metadata["id"]):
64
  db.delete(ids=[metadata["id"]])
 
65
  if os.path.exists(metadata["filepath"]):
66
  os.remove(metadata["filepath"])
 
67
 
68
  else:
69
  start_time = time.time()
@@ -146,7 +149,8 @@ else:
146
  }
147
 
148
  best_metadata = dict(sorted(best_metadata.items(), key=lambda item: item[1]["combined_score"], reverse=True)[:k])
149
-
 
150
  for filename, data in best_metadata.items():
151
  metadata = data["metadata"]
152
 
@@ -167,9 +171,37 @@ else:
167
  f"Combined: {data['combined_score']:.2f}"
168
  )
169
  )
170
- if st.button("Delete", key=f"delete_{metadata['id']}"):
171
- db.delete(ids=[metadata["id"]])
172
- if os.path.exists(metadata["filepath"]):
173
- os.remove(metadata["filepath"])
174
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  st.write(f"Search took {time.time() - start_time:.2f} seconds")
 
 
 
 
 
 
 
 
 
 
 
 
6
  from io import BytesIO
7
  import time
8
  import bm25s
9
+ from repository.DBClient import get_db_client, get_db_client_for_relevance
10
  from repository.Embedding_model import load_embedding_model
11
  import torch
12
  import torch.nn.functional as F
 
22
  # show all images from chromadb in batch of 50
23
  try:
24
  db = get_db_client()
25
+ relevance_db = get_db_client_for_relevance()
26
  except Exception as e:
27
  st.warning("No images found. Please upload some images first.")
28
  st.stop()
 
63
  st.image(image, width="stretch")
64
  if st.button("Delete", key=metadata["id"]):
65
  db.delete(ids=[metadata["id"]])
66
+ relevance_db.delete(ids=[metadata["id"]])
67
  if os.path.exists(metadata["filepath"]):
68
  os.remove(metadata["filepath"])
69
+
70
 
71
  else:
72
  start_time = time.time()
 
149
  }
150
 
151
  best_metadata = dict(sorted(best_metadata.items(), key=lambda item: item[1]["combined_score"], reverse=True)[:k])
152
+ if "relevance_score" not in st.session_state:
153
+ st.session_state["relevance_score"] = [0] * k
154
  for filename, data in best_metadata.items():
155
  metadata = data["metadata"]
156
 
 
171
  f"Combined: {data['combined_score']:.2f}"
172
  )
173
  )
174
+ columns = st.columns(3)
175
+ i = 1
176
+ with columns[0]:
177
+ if st.button("Delete", key=f"delete_{metadata['id']}"):
178
+ db.delete(ids=[metadata["id"]])
179
+ if os.path.exists(metadata["filepath"]):
180
+ os.remove(metadata["filepath"])
181
+ with columns[1]:
182
+ if st.checkbox("Relevant ๐Ÿ‘", key=f"relevant_{metadata['id']}"):
183
+ relevance_db.add(
184
+ ids=[metadata["id"]],
185
+ metadatas=[{**metadata, "relevance": 1, "query": search_query}]
186
+ )
187
+ st.session_state["relevance_score"][i - 1] = 1
188
+ with columns[2]:
189
+ if st.checkbox("Irrelevant ๐Ÿ‘Ž", key=f"irrelevant_{metadata['id']}"):
190
+ relevance_db.add(
191
+ ids=[metadata["id"]],
192
+ metadatas=[{**metadata, "relevance": 0, "query": search_query}]
193
+ )
194
+ st.session_state["relevance_score"][i - 1] = 0
195
+ i += 1
196
  st.write(f"Search took {time.time() - start_time:.2f} seconds")
197
+ st.info(f"You can provide relevance feedback by marking images as relevant or irrelevant. Ensure you have atleast {k} relevant images to evaluate the NDCG@{k} score.")
198
+ with st.button(f"Evaluate NDCG@{k}"):
199
+ ndcg_score = 0.0
200
+ if "relevance_score" in st.session_state:
201
+ relevance_scores = st.session_state["relevance_score"]
202
+ ideal_relevance_scores = sorted(relevance_scores, reverse=True)
203
+ dcg = sum((2 ** rel - 1) / math.log2(idx + 2) for idx, rel in enumerate(relevance_scores))
204
+ idcg = sum((2 ** rel - 1) / math.log2(idx + 2) for idx, rel in enumerate(ideal_relevance_scores))
205
+ ndcg_score = dcg / idcg if idcg > 0 else 0.0
206
+ st.title(f"NDCG@{k}: {ndcg_score:.4f}")
207
+ st.warning("Please note that the NDCG score is based on the relevance feedback you have provided. If you haven't marked any images as relevant or irrelevant, the score will be inaccurate.")