Unexpected behaviour from trying to control model saliency

SchulzKilian: <p>I have a model where the human user during training gets to select parts of the image that he doesnt seem important, but they still have been included in the saliency map. Then multiply the selected pixels with the gradient and backpropagate the result, hoping to make the model not take those parts of the image into account.</p>
<p>The code of that part looks like this:</p>
<aside class="quote no-group">
<blockquote>
<p>loss = (torch.sum((self.gradients)* self.marked_pixels))<br>
loss.backward()</p>
</blockquote>
</aside>
<p>Then I check the gradients created, and zero the weights which have two high of a gradient (took the marked pixels into account). I get that Im overfitting here but even for one image, the next saliency map often times doesnt take out the marked regions, it rather returns a weird reverse saliency map, where every image part that was salient now isnt and vice versa. Any explanations as to why and how I can achieve what I want?</p>
<p>Thanks a lot in advance</p>

SchulzKilian: <p>Don’t necessarily need people who know the answer, also any ideas are very much welcome</p>

SchulzKilian: <p>ok so i realized it doesnt properly backpropagate because it doesnt manage to backpropagate to the marked pixels, how can i make it so only the gradients of the marked pixel go into the loss</p>

soulitzer: <aside class="quote no-group" data-username="SchulzKilian" data-post="1" data-topic="205103">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/schulzkilian/48/70261_2.png" class="avatar"> SchulzKilian:</div>
<blockquote>
<p>loss = (torch.sum((self.gradients)* self.marked_pixels))<br>
loss.backward()</p>
</blockquote>
</aside>
<p>Do you have more code illustrating the problem? Look at only this snippet, it should backprop toward the marked_pixels if they require grad.</p>

SchulzKilian: <p>sure I have two possible reasons why it doesnt backpropagate.</p>
<ol>
<li>it actually doesnt backpropagate, and here is the code part where I try to do it:</li>
</ol>
<aside class="quote no-group">
<blockquote>
<p>marked_pixels_grad = torch.tensor(self.marked_pixels, requires_grad=True)<br>
loss1 = (torch.sum((self.gradients<em>marked_pixels_grad)))<br>
loss1.backward(retain_graph=True)<br>
self.zero_out_weights_with_non_zero_gradients()<br>
def zero_weights_with_non_zero_gradients(self, instance_type= None):<br>
for param in self.model.parameters():<br>
if torch.isnan(param.grad).any():<br>
print(“Gradient contains NaN values.”)<br>
continue  # Skip this parameter<br>
sum1 =torch.sum(param.data)<br>
percentile = 1-  (self.marked_pixels_count</em>3)/self.input.numel()<br>
# print(f"percentile is {percentile}“)<br>
if param.grad is not None:<br>
limit = torch.quantile(abs(param.grad), percentile).item()<br>
# print(f"limit is {limit}”)<br>
if param.grad is not None and instance_type is None:<br>
param.data[abs(param.grad) &gt; limit] = 0<br>
param.data[abs(param.grad) &lt;= limit] *= 1/(1-percentile)<br>
# print(f"Amount of zeros before is {param.data.numel()} amount removed is {param.data[abs(param.grad) &gt; limit].numel()}“)<br>
elif param.grad is not None and isinstance(param, instance_type):<br>
param.data[abs(param.grad) &gt; limit] = 0<br>
param.data[abs(param.grad) &lt;= limit] *= 1/(1-percentile)<br>
sum2 =torch.sum(param.data)<br>
# print(f"We went from {sum1} to {sum2}”)<br>
param.requires_grad_()</p>
</blockquote>
</aside>
<p>The other way is I make a mistake while checking if i actually backpropagate to self.marked_pixels, but the way i do it is I create two losses, one with and one without marked_pixels, and check if there are differences with the gradients which there arent.</p>
<p>Also only backpropagating to the current gradients would explain why the saliency map gets inverted, you punish the weights that encourage current gradients and encourage the other ones. Maybe it doesnt backpropagate because marked pixels arent a continuous function? If so, is there maybe a way to still only add parts of the input gradients to the loss?</p>
<p>Edit: Maybe I go back to calculating the hessian for only the marked pixels?</p>