| 130 | self.range = range |
| 131 | |
| 132 | def __call__(self, x: torch.Tensor, index: torch.Tensor | int | None = None, **kwargs: Any) -> torch.Tensor: |
| 133 | stdev = (self.stdev_spread * (x.max() - x.min())).item() |
| 134 | total_gradients = torch.zeros_like(x) |
| 135 | for _ in self.range(self.n_samples): |
| 136 | # create noisy image |
| 137 | noise = torch.normal(0, stdev, size=x.shape, dtype=torch.float32, device=x.device) |
| 138 | x_plus_noise = x + noise |
| 139 | x_plus_noise = x_plus_noise.detach() |
| 140 | |
| 141 | # get gradient and accumulate |
| 142 | grad = self.get_grad(x_plus_noise, index, **kwargs) |
| 143 | total_gradients += (grad * grad) if self.magnitude else grad |
| 144 | |
| 145 | # average |
| 146 | if self.magnitude: |
| 147 | total_gradients = total_gradients**0.5 |
| 148 | |
| 149 | return total_gradients / self.n_samples |
| 150 | |
| 151 | |
| 152 | class GuidedBackpropGrad(VanillaGrad): |