Kalpokoch commited on
Commit
2dcec79
Β·
1 Parent(s): f0b4428

changes to gradcam

Browse files
Files changed (2) hide show
  1. app.py +0 -1
  2. inference.py +29 -12
app.py CHANGED
@@ -51,7 +51,6 @@ def root():
51
  </html>
52
  """
53
 
54
-
55
  @app.get("/health")
56
  def health():
57
  return {"status": "ok", "device": DEVICE, "model": "DenseNet121-CBAM"}
 
51
  </html>
52
  """
53
 
 
54
  @app.get("/health")
55
  def health():
56
  return {"status": "ok", "device": DEVICE, "model": "DenseNet121-CBAM"}
inference.py CHANGED
@@ -97,17 +97,17 @@ class GradCAMPlusPlus:
97
  for name, module in self.model.named_modules():
98
  if name == target_layer_name:
99
  self.hooks.append(module.register_forward_hook(forward_hook))
100
- self.hooks.append(module.register_backward_hook(backward_hook))
101
  return
102
  raise ValueError(f"Layer '{target_layer_name}' not found in model")
103
 
104
  def generate_cam(self, input_tensor, class_idx=None):
105
  self.model.eval()
106
- input_tensor = input_tensor.clone().detach().requires_grad_(True)
107
 
108
  for param in self.model.parameters():
109
  param.requires_grad = True
110
 
 
111
  output = self.model(input_tensor)
112
 
113
  if class_idx is None:
@@ -117,18 +117,34 @@ class GradCAMPlusPlus:
117
  self.model.zero_grad()
118
  target_score.backward(retain_graph=True)
119
 
120
- grads = self.gradients # [1, C, H, W]
121
- acts = self.activations # [1, C, H, W]
 
 
122
 
123
- alpha_num = grads.pow(2)
124
- alpha_denom = 2.0 * grads.pow(2) + \
125
- acts.mul(grads.pow(3)).view(1, grads.size(1), -1).sum(dim=-1, keepdim=True).unsqueeze(-1)
126
- alpha_denom = torch.where(alpha_denom != 0.0, alpha_denom, torch.ones_like(alpha_denom))
127
- alpha = alpha_num.div(alpha_denom + 1e-7)
128
- weights = alpha.mul(torch.relu(grads).view(1, grads.size(1), -1).sum(dim=-1))
129
 
130
- cam = (weights.unsqueeze(-1).unsqueeze(-1) * acts).sum(dim=1, keepdim=True)
131
- cam = torch.relu(cam).squeeze().cpu().detach().numpy()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  cam = (cam - cam.min()) / (cam.max() - cam.min() + 1e-8)
133
  return cam
134
 
@@ -137,6 +153,7 @@ class GradCAMPlusPlus:
137
  hook.remove()
138
 
139
 
 
140
  # ─── Preprocessing ─────────────────────────────────────────────────────────────
141
 
142
  def get_transform(image_size=512):
 
97
  for name, module in self.model.named_modules():
98
  if name == target_layer_name:
99
  self.hooks.append(module.register_forward_hook(forward_hook))
100
+ self.hooks.append(module.register_full_backward_hook(backward_hook))
101
  return
102
  raise ValueError(f"Layer '{target_layer_name}' not found in model")
103
 
104
  def generate_cam(self, input_tensor, class_idx=None):
105
  self.model.eval()
 
106
 
107
  for param in self.model.parameters():
108
  param.requires_grad = True
109
 
110
+ input_tensor = input_tensor.clone().detach().requires_grad_(True)
111
  output = self.model(input_tensor)
112
 
113
  if class_idx is None:
 
117
  self.model.zero_grad()
118
  target_score.backward(retain_graph=True)
119
 
120
+ grads = self.gradients # [1, C, H, W]
121
+ acts = self.activations # [1, C, H, W]
122
+
123
+ B, C, H, W = grads.shape
124
 
125
+ # ── GradCAM++ alpha computation (all ops stay in [B, C, H, W]) ──
126
+ grads_sq = grads.pow(2) # [1, C, H, W]
127
+ grads_cub = grads.pow(3) # [1, C, H, W]
 
 
 
128
 
129
+ # sum over spatial dims H,W β†’ [1, C, 1, 1] then broadcast back
130
+ spatial_sum = (acts * grads_cub).sum(dim=[2, 3], keepdim=True) # [1, C, 1, 1]
131
+
132
+ alpha_denom = 2.0 * grads_sq + spatial_sum # [1, C, H, W]
133
+ alpha_denom = torch.where(
134
+ alpha_denom != 0.0,
135
+ alpha_denom,
136
+ torch.ones_like(alpha_denom)
137
+ )
138
+ alpha = grads_sq / (alpha_denom + 1e-7) # [1, C, H, W]
139
+
140
+ # weights: alpha * ReLU(grads), summed over H,W β†’ [1, C, 1, 1]
141
+ weights = (alpha * torch.relu(grads)).sum(dim=[2, 3], keepdim=True) # [1, C, 1, 1]
142
+
143
+ # CAM: weighted sum of activations β†’ [1, 1, H, W]
144
+ cam = (weights * acts).sum(dim=1, keepdim=True) # [1, 1, H, W]
145
+ cam = torch.relu(cam)
146
+
147
+ cam = cam.squeeze().cpu().detach().numpy() # [H, W]
148
  cam = (cam - cam.min()) / (cam.max() - cam.min() + 1e-8)
149
  return cam
150
 
 
153
  hook.remove()
154
 
155
 
156
+
157
  # ─── Preprocessing ─────────────────────────────────────────────────────────────
158
 
159
  def get_transform(image_size=512):