Hello,
There are two points in your snippet do not make sense to me.



 IapCaL:

activations = SaveFeatures(list(self.model.children())[0][layer])


I have got that you want to extract features from intermediate layers, I think the first index [0] already represent the layer index, so what does the [layer] do for?



 IapCaL:

optimizer = torch.optim.Adam([img_var], lr=lr, weight_decay=1e-6)


Here the optimizer will only update the input, it seems weird, is there a specific purpose that you only want to “update the input”?
And I have reproduced your issue with a dummy ConvNet, I think the problem raises in this line
    def hook_fn(self, module, input, output):
        self.features = output.clone().detach().requires_grad_(True)

You should remove the .detach() so that the input.grad and model.module.weight.grad are not None.