wyctorfogos commited on
Commit
d4ef6cc
·
1 Parent(s): f60bdbe

update: Add de logs

Browse files
Files changed (2) hide show
  1. app.py +9 -0
  2. src/models/inference.py +97 -16
app.py CHANGED
@@ -1,14 +1,23 @@
1
  import sys
2
  import os
 
 
 
3
 
4
  ROOT = os.path.dirname(__file__)
5
  SRC = os.path.join(ROOT, "src")
 
 
 
6
  if SRC not in sys.path:
7
  sys.path.insert(0, SRC)
8
 
 
9
  from main import demo
 
10
 
11
  if __name__ == "__main__":
 
12
  demo.launch(
13
  server_name="0.0.0.0",
14
  server_port=int(os.environ.get("PORT", 7860)),
 
1
  import sys
2
  import os
3
+ import logging
4
+
5
+ logging.info("[app.py] starting...")
6
 
7
  ROOT = os.path.dirname(__file__)
8
  SRC = os.path.join(ROOT, "src")
9
+ logging.info(f"[app.py] ROOT={ROOT}")
10
+ logging.info(f"[app.py] SRC={SRC}")
11
+
12
  if SRC not in sys.path:
13
  sys.path.insert(0, SRC)
14
 
15
+ logging.info("[app.py] importing main...")
16
  from main import demo
17
+ logging.info("[app.py] imported main successfully")
18
 
19
  if __name__ == "__main__":
20
+ logging.info("[app.py] launching gradio...")
21
  demo.launch(
22
  server_name="0.0.0.0",
23
  server_port=int(os.environ.get("PORT", 7860)),
src/models/inference.py CHANGED
@@ -1,16 +1,21 @@
1
- import torch
2
- import numpy as np
3
- import matplotlib.pyplot as plt
4
  import os
 
5
  from glob import glob
 
 
 
 
 
6
  from models.preprocessing import process_image_pil, process_metadata_pad20
7
  from models.model_loader import load_model, find_last_conv
8
  from models.cam import GradCAMPlusPlus
9
 
 
 
10
  DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
11
  PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
12
 
13
- CLASS_LIST = ["NEV","BCC","ACK","SEK","SCC","MEL"]
14
 
15
  ENCODER_DIR = os.path.join(PROJECT_ROOT, "data", "preprocess_data")
16
  MODEL_ROOT_PATTERNS = [
@@ -35,6 +40,7 @@ MODEL_ROOT_PATTERNS = [
35
  "model_*_with_one-hot-encoder_512_with_best_architecture",
36
  ),
37
  ]
 
38
  PREFERRED_FOLD = 3
39
  IMPLEMENTED_ATTENTION_MECHANISMS = {
40
  "no-metadata",
@@ -56,9 +62,31 @@ MODEL_CONFIGS = {}
56
  MODEL_LABELS = {}
57
  MODEL_CACHE = {}
58
  DEFAULT_MODEL_KEY = None
 
 
 
 
 
 
 
 
59
 
 
 
 
60
 
61
- def _parse_cnn_model_name(model_dir_name):
 
 
 
 
 
 
 
 
 
 
 
62
  prefix = "model_"
63
  suffix = "_with_one-hot-encoder_512_with_best_architecture"
64
  if not model_dir_name.startswith(prefix) or not model_dir_name.endswith(suffix):
@@ -66,7 +94,7 @@ def _parse_cnn_model_name(model_dir_name):
66
  return model_dir_name[len(prefix):-len(suffix)]
67
 
68
 
69
- def _find_fold_dir(model_root, cnn_model_name):
70
  fold_dirs = sorted(glob(os.path.join(model_root, f"{cnn_model_name}_fold_*")))
71
  if not fold_dirs:
72
  return None
@@ -82,12 +110,12 @@ def _find_fold_dir(model_root, cnn_model_name):
82
  return None
83
 
84
 
85
- def _extract_fold_number(fold_dir):
86
  name = os.path.basename(fold_dir)
87
  return name.split("_fold_")[-1] if "_fold_" in name else "?"
88
 
89
 
90
- def _extract_path_metadata(model_root):
91
  parts = os.path.normpath(model_root).split(os.sep)
92
  mechanism = os.path.basename(os.path.dirname(model_root))
93
  unfreeze_weights = "unfrozen_weights"
@@ -105,25 +133,45 @@ def _extract_path_metadata(model_root):
105
  return mechanism, unfreeze_weights, num_heads
106
 
107
 
108
- def _discover_models():
109
  global DEFAULT_MODEL_KEY
 
 
 
 
 
 
110
  model_roots = sorted({
111
  path
112
  for pattern in MODEL_ROOT_PATTERNS
113
  for path in glob(pattern)
114
  })
 
 
 
 
 
 
 
115
  for model_root in model_roots:
116
  mechanism, unfreeze_weights, num_heads = _extract_path_metadata(model_root)
117
  model_dir_name = os.path.basename(model_root)
118
  cnn_model_name = _parse_cnn_model_name(model_dir_name)
 
119
  if cnn_model_name is None:
 
120
  continue
121
 
122
  fold_dir = _find_fold_dir(model_root, cnn_model_name)
123
  if fold_dir is None:
 
124
  continue
125
 
126
  model_path = os.path.join(fold_dir, "model.pth")
 
 
 
 
127
  fold_number = _extract_fold_number(fold_dir)
128
  model_key = f"{mechanism}|{cnn_model_name}|{unfreeze_weights}|{num_heads}|{fold_number}"
129
  supported = mechanism in IMPLEMENTED_ATTENTION_MECHANISMS
@@ -140,6 +188,7 @@ def _discover_models():
140
  "label": label,
141
  }
142
  MODEL_LABELS[model_key] = label
 
143
 
144
  preferred_defaults = [
145
  key for key, cfg in MODEL_CONFIGS.items()
@@ -154,27 +203,49 @@ def _discover_models():
154
  elif MODEL_CONFIGS:
155
  DEFAULT_MODEL_KEY = sorted(MODEL_CONFIGS.keys())[0]
156
 
 
 
 
 
 
 
 
 
157
 
158
- _discover_models()
 
 
159
 
160
 
161
  def get_available_model_choices():
 
162
  return [(MODEL_LABELS[key], key) for key in sorted(MODEL_LABELS.keys())]
163
 
164
 
165
  def get_default_model_key():
 
166
  return DEFAULT_MODEL_KEY
167
 
168
 
169
  def get_model_label(model_key):
 
170
  return MODEL_LABELS.get(model_key, "Unknown model")
171
 
172
 
173
  def _get_model_and_cam(model_key):
 
 
174
  if not MODEL_CONFIGS:
175
  raise RuntimeError(
176
- f"No compatible model checkpoints were found in {os.path.join(PROJECT_ROOT, 'data', 'weights')}. "
177
- "Please check that model assets are available."
 
 
 
 
 
 
 
178
  )
179
 
180
  if model_key is None:
@@ -195,7 +266,8 @@ def _get_model_and_cam(model_key):
195
 
196
  if model_key not in MODEL_CACHE:
197
  model_path = cfg["model_path"]
198
- print(f"Loading model from {model_path}...")
 
199
  model = load_model(
200
  device=DEVICE,
201
  model_path=model_path,
@@ -204,9 +276,13 @@ def _get_model_and_cam(model_key):
204
  num_heads=cfg["num_heads"],
205
  unfreeze_weights=cfg["unfreeze_weights"],
206
  )
 
 
207
  target_layer = find_last_conv(model.image_encoder)
 
 
208
  MODEL_CACHE[model_key] = (model, GradCAMPlusPlus(model, target_layer))
209
- print("Model ready.")
210
 
211
  return MODEL_CACHE[model_key]
212
 
@@ -214,14 +290,17 @@ def _get_model_and_cam(model_key):
214
  def run_inference(image_pil, metadata_text, model_key=None):
215
  model, cam = _get_model_and_cam(model_key)
216
 
 
217
  image_tensor = process_image_pil(image_pil, DEVICE)
218
 
 
219
  metadata_tensor = process_metadata_pad20(
220
  metadata_text,
221
  ENCODER_DIR,
222
  DEVICE
223
  )
224
 
 
225
  with torch.no_grad():
226
  logits = model(image_tensor, metadata_tensor)
227
  probs = torch.softmax(logits, dim=1)
@@ -229,13 +308,14 @@ def run_inference(image_pil, metadata_text, model_key=None):
229
  pred_class = torch.argmax(probs, dim=1).item()
230
  confidence = probs[0, pred_class].item()
231
 
 
232
  heatmap = cam.generate(
233
  image_tensor,
234
  metadata_tensor,
235
  pred_class
236
  )
237
 
238
- fig, ax = plt.subplots(figsize=(6,6))
239
  ax.imshow(image_pil)
240
  ax.imshow(heatmap, cmap="jet", alpha=0.4)
241
  ax.axis("off")
@@ -247,4 +327,5 @@ def run_inference(image_pil, metadata_text, model_key=None):
247
  result = np.array(fig.canvas.renderer.buffer_rgba())
248
  plt.close(fig)
249
 
250
- return result, title
 
 
 
 
 
1
  import os
2
+ import logging
3
  from glob import glob
4
+
5
+ import matplotlib.pyplot as plt
6
+ import numpy as np
7
+ import torch
8
+
9
  from models.preprocessing import process_image_pil, process_metadata_pad20
10
  from models.model_loader import load_model, find_last_conv
11
  from models.cam import GradCAMPlusPlus
12
 
13
+ logging.basicConfig(level=logging.INFO)
14
+
15
  DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
16
  PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
17
 
18
+ CLASS_LIST = ["NEV", "BCC", "ACK", "SEK", "SCC", "MEL"]
19
 
20
  ENCODER_DIR = os.path.join(PROJECT_ROOT, "data", "preprocess_data")
21
  MODEL_ROOT_PATTERNS = [
 
40
  "model_*_with_one-hot-encoder_512_with_best_architecture",
41
  ),
42
  ]
43
+
44
  PREFERRED_FOLD = 3
45
  IMPLEMENTED_ATTENTION_MECHANISMS = {
46
  "no-metadata",
 
62
  MODEL_LABELS = {}
63
  MODEL_CACHE = {}
64
  DEFAULT_MODEL_KEY = None
65
+ _DISCOVERED = False
66
+
67
+
68
+ def _debug_paths() -> None:
69
+ print(f"[inference] DEVICE={DEVICE}")
70
+ print(f"[inference] PROJECT_ROOT={PROJECT_ROOT}")
71
+ print(f"[inference] ENCODER_DIR={ENCODER_DIR}")
72
+ print(f"[inference] ENCODER_DIR exists? {os.path.exists(ENCODER_DIR)}")
73
 
74
+ data_root = os.path.join(PROJECT_ROOT, "data")
75
+ weights_root = os.path.join(data_root, "weights")
76
+ to_be_used_root = os.path.join(weights_root, "TO_BE_USED")
77
 
78
+ print(f"[inference] data root={data_root}")
79
+ print(f"[inference] data root exists? {os.path.exists(data_root)}")
80
+ print(f"[inference] weights root={weights_root}")
81
+ print(f"[inference] weights root exists? {os.path.exists(weights_root)}")
82
+ print(f"[inference] TO_BE_USED root={to_be_used_root}")
83
+ print(f"[inference] TO_BE_USED root exists? {os.path.exists(to_be_used_root)}")
84
+
85
+ for pattern in MODEL_ROOT_PATTERNS:
86
+ print(f"[inference] MODEL_ROOT_PATTERN={pattern}")
87
+
88
+
89
+ def _parse_cnn_model_name(model_dir_name: str):
90
  prefix = "model_"
91
  suffix = "_with_one-hot-encoder_512_with_best_architecture"
92
  if not model_dir_name.startswith(prefix) or not model_dir_name.endswith(suffix):
 
94
  return model_dir_name[len(prefix):-len(suffix)]
95
 
96
 
97
+ def _find_fold_dir(model_root: str, cnn_model_name: str):
98
  fold_dirs = sorted(glob(os.path.join(model_root, f"{cnn_model_name}_fold_*")))
99
  if not fold_dirs:
100
  return None
 
110
  return None
111
 
112
 
113
+ def _extract_fold_number(fold_dir: str) -> str:
114
  name = os.path.basename(fold_dir)
115
  return name.split("_fold_")[-1] if "_fold_" in name else "?"
116
 
117
 
118
+ def _extract_path_metadata(model_root: str):
119
  parts = os.path.normpath(model_root).split(os.sep)
120
  mechanism = os.path.basename(os.path.dirname(model_root))
121
  unfreeze_weights = "unfrozen_weights"
 
133
  return mechanism, unfreeze_weights, num_heads
134
 
135
 
136
+ def _discover_models() -> None:
137
  global DEFAULT_MODEL_KEY
138
+
139
+ print("[inference] starting model discovery...")
140
+ MODEL_CONFIGS.clear()
141
+ MODEL_LABELS.clear()
142
+ DEFAULT_MODEL_KEY = None
143
+
144
  model_roots = sorted({
145
  path
146
  for pattern in MODEL_ROOT_PATTERNS
147
  for path in glob(pattern)
148
  })
149
+
150
+ print(f"[inference] candidate model roots found: {len(model_roots)}")
151
+ for idx, path in enumerate(model_roots[:20], start=1):
152
+ print(f"[inference] candidate[{idx}] = {path}")
153
+ if len(model_roots) > 20:
154
+ print("[inference] ... additional candidates omitted from log ...")
155
+
156
  for model_root in model_roots:
157
  mechanism, unfreeze_weights, num_heads = _extract_path_metadata(model_root)
158
  model_dir_name = os.path.basename(model_root)
159
  cnn_model_name = _parse_cnn_model_name(model_dir_name)
160
+
161
  if cnn_model_name is None:
162
+ print(f"[inference] skipping invalid model dir name: {model_dir_name}")
163
  continue
164
 
165
  fold_dir = _find_fold_dir(model_root, cnn_model_name)
166
  if fold_dir is None:
167
+ print(f"[inference] no valid fold dir found for: {model_root}")
168
  continue
169
 
170
  model_path = os.path.join(fold_dir, "model.pth")
171
+ if not os.path.exists(model_path):
172
+ print(f"[inference] missing model.pth: {model_path}")
173
+ continue
174
+
175
  fold_number = _extract_fold_number(fold_dir)
176
  model_key = f"{mechanism}|{cnn_model_name}|{unfreeze_weights}|{num_heads}|{fold_number}"
177
  supported = mechanism in IMPLEMENTED_ATTENTION_MECHANISMS
 
188
  "label": label,
189
  }
190
  MODEL_LABELS[model_key] = label
191
+ print(f"[inference] registered model: {label}")
192
 
193
  preferred_defaults = [
194
  key for key, cfg in MODEL_CONFIGS.items()
 
203
  elif MODEL_CONFIGS:
204
  DEFAULT_MODEL_KEY = sorted(MODEL_CONFIGS.keys())[0]
205
 
206
+ print(f"[inference] discovery done. models={len(MODEL_CONFIGS)}")
207
+ print(f"[inference] DEFAULT_MODEL_KEY={DEFAULT_MODEL_KEY}")
208
+
209
+
210
+ def ensure_models_discovered() -> None:
211
+ global _DISCOVERED
212
+ if _DISCOVERED:
213
+ return
214
 
215
+ _debug_paths()
216
+ _discover_models()
217
+ _DISCOVERED = True
218
 
219
 
220
  def get_available_model_choices():
221
+ ensure_models_discovered()
222
  return [(MODEL_LABELS[key], key) for key in sorted(MODEL_LABELS.keys())]
223
 
224
 
225
  def get_default_model_key():
226
+ ensure_models_discovered()
227
  return DEFAULT_MODEL_KEY
228
 
229
 
230
  def get_model_label(model_key):
231
+ ensure_models_discovered()
232
  return MODEL_LABELS.get(model_key, "Unknown model")
233
 
234
 
235
  def _get_model_and_cam(model_key):
236
+ ensure_models_discovered()
237
+
238
  if not MODEL_CONFIGS:
239
  raise RuntimeError(
240
+ f"No compatible model checkpoints were found in "
241
+ f"{os.path.join(PROJECT_ROOT, 'data', 'weights')}. "
242
+ f"Please verify that the model assets were uploaded to the Space."
243
+ )
244
+
245
+ if not os.path.exists(ENCODER_DIR):
246
+ raise RuntimeError(
247
+ f"Metadata encoder directory not found: {ENCODER_DIR}. "
248
+ "Please verify that preprocess artifacts were uploaded to the Space."
249
  )
250
 
251
  if model_key is None:
 
266
 
267
  if model_key not in MODEL_CACHE:
268
  model_path = cfg["model_path"]
269
+ print(f"[inference] loading model from: {model_path}")
270
+
271
  model = load_model(
272
  device=DEVICE,
273
  model_path=model_path,
 
276
  num_heads=cfg["num_heads"],
277
  unfreeze_weights=cfg["unfreeze_weights"],
278
  )
279
+
280
+ print("[inference] locating final conv layer...")
281
  target_layer = find_last_conv(model.image_encoder)
282
+
283
+ print("[inference] creating GradCAM++ object...")
284
  MODEL_CACHE[model_key] = (model, GradCAMPlusPlus(model, target_layer))
285
+ print("[inference] model ready.")
286
 
287
  return MODEL_CACHE[model_key]
288
 
 
290
  def run_inference(image_pil, metadata_text, model_key=None):
291
  model, cam = _get_model_and_cam(model_key)
292
 
293
+ print("[inference] processing image...")
294
  image_tensor = process_image_pil(image_pil, DEVICE)
295
 
296
+ print("[inference] processing metadata...")
297
  metadata_tensor = process_metadata_pad20(
298
  metadata_text,
299
  ENCODER_DIR,
300
  DEVICE
301
  )
302
 
303
+ print("[inference] running forward pass...")
304
  with torch.no_grad():
305
  logits = model(image_tensor, metadata_tensor)
306
  probs = torch.softmax(logits, dim=1)
 
308
  pred_class = torch.argmax(probs, dim=1).item()
309
  confidence = probs[0, pred_class].item()
310
 
311
+ print("[inference] generating heatmap...")
312
  heatmap = cam.generate(
313
  image_tensor,
314
  metadata_tensor,
315
  pred_class
316
  )
317
 
318
+ fig, ax = plt.subplots(figsize=(6, 6))
319
  ax.imshow(image_pil)
320
  ax.imshow(heatmap, cmap="jet", alpha=0.4)
321
  ax.axis("off")
 
327
  result = np.array(fig.canvas.renderer.buffer_rgba())
328
  plt.close(fig)
329
 
330
+ print(f"[inference] inference complete: {title}")
331
+ return result, title