Sure here it is. I added a couple notes and changes I would do in there 
class VanillaBackprop():
    """
        Produces gradients generated with vanilla back propagation from the image
    """
    def __init__(self, model):
        self.model = model
        self.gradients = None
        # Put model in evaluation mode
        self.model.eval()

    def generate_gradients(self, input_image, target_class):
        # Register input hook
        self.hook_input(input_image)
        # Forward
        model_output = self.model(input_image)
        # Zero grads NOTE: not needed anymore
        # self.model.zero_grad()
        # Target for backprop NOTE: Equivalently you can just select the output you want
        # and this work will be done by the backward of the indexing ops
        # device = input_image.device
        # one_hot_output = torch.FloatTensor(1, model_output.size()[-1]).zero_()
        # one_hot_output[0][target_class] = 1
        # one_hot_output = one_hot_output.to(device)
        # # Backward pass
        # device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
        # NOTE: as doing:
        out = model_output[0][target_class]
        grad, = autograd.grad(out, input_image, one_hot_output.to(device))
        # Convert Pytorch variable to numpy array
        # [0] to get rid of the first channel (1,3,224,224)
        # NOTE: Never use .data!
        gradients_as_arr = grad.detach().cpu().numpy()[0]
        return gradients_as_arr