def generate_gradients(self, input_image, target_class):
        import pdb; pdb.set_trace()
        input_image = input_image.cuda()
        input_image.requires_grad = True
        model_output = self.model(input_image)
        # Zero gradients
        self.model.zero_grad()
        # Target for backprop
        one_hot_output = torch.FloatTensor(1, model_output.size()[-1]).zero_()
        one_hot_output[0][target_class] = 1
        one_hot_output = one_hot_output.cuda()
        # Backward pass
        model_output.backward(gradient=one_hot_output, retain_graph = True)
        # Convert Pytorch variable to numpy array
        # [0] to get rid of the first channel (1,3,224,224)
        gradients_as_arr = self.gradients.data.detach().cpu().numpy()[0]
        return gradients_as_arr

Yes, I am using hooks to create it. When I try to set requires_grad = True, I get RuntimeError: you can only change requires_grad flags of leaf variables. The code is a bit large to put here so I am not able to put a completely reproducible example. My intention is to do guided back-propagation, i believe for this the gradient needs to flow all the back to the inputs so I can get the gradient in the shape of the input (correct me if I am wrong), do I need to set required_grad = True at the time of training then?