(Newbie) Getting the gradient with respect to the input

diravan: <p>Hi all,</p>
<p>I have read all the other threads on the subject but I do not get what I am doing wrong. I have just started using pytorch so I am probably doing something stupid. I have a trained VGG19 on CIFAR10 (without the softmax) let us call it  <code>net</code>. Then I have my input <code>normalized_input</code> which is simply the first image of the test dataset plus the batch size of one. Now I would like to compute the gradient of the output w.r.t. the input. Right now I am doing this</p>
<pre><code class="lang-auto">net.zero_grad()
output = softmax(net(normalized_input), dim=1)
for i in range(10):
    output[0, i].backward(retain_graph=True)
print("GRADIENT")
print(normalized_input.grad)
</code></pre>
<p>But I am getting <code>None</code> as an output and it is not clear to me why.</p>

ptrblck: <p>You have to make sure <code>normalized_input</code> is wrapped in a <code>Variable</code> with <code>required_grad=True</code>.<br>
Try <code>normalized_input = Variable(normalized_input, requires_grad=True)</code> and check it again.<br>
Usually this flag is set to false, since you don’t need the gradient w.r.t. the input.</p>

diravan: <p>I was kindly told that my understanding of how pytorch gradient worked was completely off the mark. Now with some help I solved my problem by using this code</p>
<pre><code class="lang-auto">net.zero_grad()
output = net(input)

g = torch.zeros(batch_size, 10, 3, 32, 32)

for i in range(10):
    g[:, i] = torch.autograd.grad(output[:, i].sum(), input, retain_graph=True)[0].data

print("GRADIENT: {}")
print(g[0])
</code></pre>
<p>It is probably not super helpful but maybe it will help someone in the future. I am not sure that <code>net.zero_grad()</code> is required now since I use grad.</p>
<p>Btw, is there a place where I can read how autograd works in detail, without having to read the source code?</p>

ptrblck: <p>You can find some documents:</p>
<ul>
<li><a href="http://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html" rel="nofollow noopener">Tutorial on autograd</a></li>
<li><a href="http://pytorch.org/docs/master/notes/autograd.html" rel="nofollow noopener">Autograd mechanics</a></li>
<li><a href="https://openreview.net/pdf?id=BJJsrmfCZ" rel="nofollow noopener">Paper on Automatic differentiation in PyTorch (Paszke et al.)</a></li>
</ul>

diravan: <p>Thanks, I did not know the NIPS paper.</p>

moonlightlane: <p>Hi <a class="mention" href="/u/diravan">@diravan</a>, thanks for this nice solution! I was trying it just now but encounter one small problem, so I wanted to drop it here and see if you might be able to help out <img src="https://discuss.pytorch.org/images/emoji/apple/wink.png?v=5" title=":wink:" class="emoji" alt=":wink:"></p>
<p>In my code I encountered the error that says <code>RuntimeError: element 0 of variables tuple is volatile</code> when I tried to execute the line in your code <code>torch.autograd.grad</code>. I didn’t know how to deal with it, but I checked that my <code>output</code> and <code>input</code> Variables do not require gradients, e.g., <code>output.requires_grad = False</code> and <code>input.requires_grad = False</code>. But even after I set those two Variables to require grad, I still get the above error.</p>
<p>Thanks in advance!</p>

akhilpan: <p>I am trying this out now. It works for batch_size= 1 but for batch_size &gt; 1 I get the following error:</p>
<pre><code class="lang-auto">RuntimeError: grad can be implicitly created only for scalar outputs
</code></pre>
<p>Is there any efficient way to use the autograd for batch_size more than 1?</p>

gebbissimo: <p>Since this thread is still the first google hit when searching for “pytorch calculate gradient for input”, a small update:</p>
<p>Variables have been deprecated for a while now: <a href="https://pytorch.org/docs/stable/autograd.html#variable-deprecated" rel="nofollow noopener">https://pytorch.org/docs/stable/autograd.html#variable-deprecated</a></p>
<p>In order to calculate the gradient of the loss with respect to the input data (tensor), that is calculate dloss/ddata, simply do… (based on <a href="https://github.com/pytorch/examples/blob/master/mnist/main.py" rel="nofollow noopener">https://github.com/pytorch/examples/blob/master/mnist/main.py</a>)</p>
<pre><code class="lang-auto">    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)
        data.requires_grad = True  ### CRUCIAL LINE !!!
        optimizer.zero_grad()
        output = model(data)
        loss = F.nll_loss(output, target)
        loss.backward() # Calculates x.grad = dloss/dx for every x with x.requires_grad=True
</code></pre>
<p>–&gt; Afterwards, you can easily access dloss/ddata via data.grad=dloss/ddata</p>

MaheepChaudhary: <p>can we do it simultaneously using jacobian instead of using a loop?</p>