rusticolus commited on
Commit
d304e58
·
verified ·
1 Parent(s): 6878318

Upload 2 files

Browse files
Files changed (2) hide show
  1. benchmark_efficiency.py +55 -0
  2. measure_recall.py +89 -0
benchmark_efficiency.py ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import time
3
+ from cnn1 import UNet # Importing your UNet from your files
4
+ from thop import profile
5
+ import numpy as np
6
+
7
+ def benchmark(device="cpu"):
8
+ print(f"--- Benchmarking on {device.upper()} ---")
9
+
10
+ # 1. Setup Model
11
+ model = UNet(text_dim=512).to(device)
12
+ model.eval()
13
+
14
+ # 2. Setup Dummy Inputs (Standard 512x512 image + CLIP embedding)
15
+ dummy_image = torch.randn(1, 3, 512, 512).to(device)
16
+ dummy_text = torch.randn(1, 512).to(device) # Normalized text embedding
17
+
18
+ # --- METRIC 1: FLOPs & Parameters ---
19
+ if device == "cpu": # Only need to calc this once
20
+ print("Calculating FLOPs and Params...")
21
+ macs, params = profile(model, inputs=(dummy_image, dummy_text), verbose=False)
22
+ print(f"Parameters: {params / 1e6:.2f} M")
23
+ print(f"GFLOPs: {macs / 1e9:.2f} G")
24
+
25
+ # --- METRIC 2: Inference Time ---
26
+ print("Measuring Inference Speed...")
27
+
28
+ # Warmup (get cache ready)
29
+ for _ in range(5):
30
+ with torch.no_grad():
31
+ _ = model(dummy_image, dummy_text)
32
+
33
+ # Measure
34
+ latencies = []
35
+ with torch.no_grad():
36
+ for _ in range(50): # Run 50 times
37
+ start = time.time()
38
+ _ = model(dummy_image, dummy_text)
39
+ if device == "cuda":
40
+ torch.cuda.synchronize() # Wait for GPU to finish
41
+ end = time.time()
42
+ latencies.append(end - start)
43
+
44
+ avg_time = np.mean(latencies)
45
+ print(f"Avg Inference Time: {avg_time:.4f} seconds")
46
+ print(f"FPS: {1/avg_time:.2f}")
47
+ print("-" * 30)
48
+
49
+ if __name__ == "__main__":
50
+ # Run on CPU (Crucial for your "Lightweight" claim)
51
+ benchmark("cpu")
52
+
53
+ # Run on GPU (If available, for comparison)
54
+ if torch.cuda.is_available():
55
+ benchmark("cuda")
measure_recall.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import clip
3
+ import deeplake
4
+ from tqdm import tqdm
5
+ from tabulate import tabulate
6
+
7
+ # --- SETTINGS ---
8
+ EMBEDDINGS_PATH = "flickr_embeddings.pt"
9
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
10
+ BATCH_SIZE = 32
11
+ # ----------------
12
+
13
+ def calculate_recall():
14
+ print(f"Loading CLIP on {DEVICE}...")
15
+ model, _ = clip.load("ViT-B/32", device=DEVICE)
16
+
17
+ print(f"Loading Image Index from {EMBEDDINGS_PATH}...")
18
+ try:
19
+ # Load embeddings and force them to the correct device
20
+ image_embeds = torch.load(EMBEDDINGS_PATH, map_location=DEVICE)
21
+ except FileNotFoundError:
22
+ print(f"ERROR: Could not find '{EMBEDDINGS_PATH}'. Run indexer.py first.")
23
+ return
24
+
25
+ num_images = len(image_embeds)
26
+ print(f"Loaded {num_images} image fingerprints.")
27
+
28
+ print("Connecting to Deep Lake to fetch captions...")
29
+ # Ensure this matches the dataset used in indexer.py
30
+ ds = deeplake.load('hub://activeloop/flickr30k', access_method="stream")
31
+
32
+ text_embeds = []
33
+
34
+ print("Encoding Captions (this acts as the 'Search Query')...")
35
+ with torch.no_grad():
36
+ for i in tqdm(range(0, num_images, BATCH_SIZE)):
37
+ batch_captions = []
38
+ end_idx = min(i + BATCH_SIZE, num_images)
39
+
40
+ # Fetch batch of captions
41
+ for idx in range(i, end_idx):
42
+ try:
43
+ # Robust text extraction
44
+ txt = ds[idx].caption_0.text().numpy().item()
45
+ except AttributeError:
46
+ txt = ds[idx].caption_0.numpy().item()
47
+ except Exception:
48
+ txt = "unknown"
49
+
50
+ batch_captions.append(str(txt))
51
+
52
+ # Tokenize and Encode
53
+ text_tokens = clip.tokenize(batch_captions, truncate=True).to(DEVICE)
54
+ batch_features = model.encode_text(text_tokens)
55
+
56
+ # Normalize
57
+ batch_features /= batch_features.norm(dim=-1, keepdim=True)
58
+ text_embeds.append(batch_features)
59
+
60
+ text_embeds = torch.cat(text_embeds)
61
+
62
+ print("\nCalculating Similarity Matrix...")
63
+
64
+ # --- FIX: Force both to float32 to avoid mismatched types (Half vs Float) ---
65
+ image_embeds = image_embeds.float()
66
+ text_embeds = text_embeds.float()
67
+
68
+ # Cosine similarity
69
+ similarity = text_embeds @ image_embeds.t()
70
+
71
+ print("Computing Recall Metrics...")
72
+ results = {}
73
+ k_values = [1, 5, 10]
74
+
75
+ _, top_indices = similarity.topk(max(k_values), dim=1)
76
+
77
+ for k in k_values:
78
+ correct_count = 0
79
+ for i in range(num_images):
80
+ # Check if the correct index 'i' is in the top 'k' predictions
81
+ if i in top_indices[i, :k]:
82
+ correct_count += 1
83
+ results[f"R@{k}"] = (correct_count / num_images) * 100
84
+
85
+ print("\n--- RETRIEVAL RESULTS (Zero-Shot) ---")
86
+ print(tabulate([[k, f"{v:.2f}%"] for k, v in results.items()], headers=["Metric", "Score"]))
87
+
88
+ if __name__ == "__main__":
89
+ calculate_recall()