hiyata commited on
Commit
b7c4f98
·
verified ·
1 Parent(s): af1df76

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -16
app.py CHANGED
@@ -85,24 +85,62 @@ def sequence_to_kmer_vector(sequence: str, k: int = 4) -> np.ndarray:
85
  # 3. SHAP-VALUE (ABLATION) CALCULATION
86
  ###############################################################################
87
 
88
-
89
- def calculate_shap_values(model, x_tensor):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  model.eval()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  with torch.no_grad():
92
- baseline_output = model(x_tensor)
93
- baseline_probs = torch.softmax(baseline_output, dim=1)
94
- baseline_prob = baseline_probs[0, 1].item() # Prob of 'human'
95
- shap_values = []
96
- x_zeroed = x_tensor.clone()
97
- for i in range(x_tensor.shape[1]):
98
- original_val = x_zeroed[0, i].item()
99
- x_zeroed[0, i] = 0.0
100
- output = model(x_zeroed)
101
- probs = torch.softmax(output, dim=1)
102
- prob = probs[0, 1].item()
103
- shap_values.append(baseline_prob - prob)
104
- x_zeroed[0, i] = original_val
105
- return np.array(shap_values), baseline_prob
106
 
107
 
108
  ###############################################################################
 
85
  # 3. SHAP-VALUE (ABLATION) CALCULATION
86
  ###############################################################################
87
 
88
+ def calculate_shap_values(model, x_tensor, baseline=None, steps=50):
89
+ """
90
+ Calculate feature attributions using Integrated Gradients.
91
+
92
+ Args:
93
+ model: A PyTorch model.
94
+ x_tensor: Input tensor of shape (1, num_features).
95
+ baseline: Tensor of the same shape as x_tensor to use as the reference.
96
+ If None, defaults to a tensor of zeros.
97
+ steps: Number of steps in the Riemann approximation of the integral.
98
+
99
+ Returns:
100
+ attributions: A numpy array of shape (num_features,) with feature attributions.
101
+ baseline_prob: The model's predicted probability for the target class (human)
102
+ when using the baseline input.
103
+ """
104
  model.eval()
105
+ if baseline is None:
106
+ baseline = torch.zeros_like(x_tensor)
107
+
108
+ # Generate interpolated inputs between the baseline and the actual input.
109
+ scaled_inputs = [
110
+ baseline + (float(i) / steps) * (x_tensor - baseline)
111
+ for i in range(steps + 1)
112
+ ]
113
+ scaled_inputs = torch.cat(scaled_inputs, dim=0) # shape: (steps+1, num_features)
114
+ scaled_inputs.requires_grad = True
115
+
116
+ # Forward pass: compute model outputs for all interpolated inputs.
117
+ outputs = model(scaled_inputs) # shape: (steps+1, num_classes)
118
+ probs = torch.softmax(outputs, dim=1)[:, 1] # probability for the 'human' class
119
+
120
+ # Backward pass: compute gradients of the probability with respect to the inputs.
121
+ grads = torch.autograd.grad(
122
+ outputs=probs,
123
+ inputs=scaled_inputs,
124
+ grad_outputs=torch.ones_like(probs),
125
+ create_graph=False,
126
+ retain_graph=False
127
+ )[0] # shape: (steps+1, num_features)
128
+
129
+ # Approximate the integral using the trapezoidal rule.
130
+ # Compute the average gradient between consecutive steps.
131
+ avg_grads = (grads[:-1] + grads[1:]) / 2.0
132
+ # Average the gradients over all steps.
133
+ integrated_grad = avg_grads.mean(dim=0, keepdim=True) # shape: (1, num_features)
134
+
135
+ # Scale the integrated gradients by the difference between the input and the baseline.
136
+ attributions = (x_tensor - baseline) * integrated_grad # shape: (1, num_features)
137
+
138
+ # Compute the baseline probability (for reference)
139
  with torch.no_grad():
140
+ baseline_output = model(baseline)
141
+ baseline_prob = torch.softmax(baseline_output, dim=1)[0, 1].item()
142
+
143
+ return attributions.squeeze().cpu().numpy(), baseline_prob
 
 
 
 
 
 
 
 
 
 
144
 
145
 
146
  ###############################################################################