Trouble with torch.autograd.grad

bala: <p>I find torch.autograd.grad working inconsistently. I will explain through two examples.</p>
<p><strong>First Example</strong><br>
In this example I compute until third order derivatives of y=x^2 where x is a scalar valued tensor with value 3.0. The code is listed below.</p>
<blockquote>
<p>x = torch.tensor(3., requires_grad = True)<br>
y = x**2<br>
dy_dx = torch.autograd.grad(outputs = (y, ), inputs = (x, ), create_graph = True)<br>
print(f’dy_dx at x={x.data}:\t\t{dy_dx[0].data}‘)<br>
d2y_dx2 = torch.autograd.grad(outputs = dy_dx, inputs = (x, ), create_graph = True)<br>
print(f’d2y_dx2 at x={x.data}:\t{d2y_dx2[0].data}’)<br>
d3y_dx3 = torch.autograd.grad(outputs = d2y_dx2, inputs = (x, ))<br>
print(f’d3y_dx3 at x={x.data}:\t{d3y_dx3[0].data}')</p>
</blockquote>
<p>I get the expected results as shown below:</p>
<blockquote>
<p>dy_dx at x=3.0:		6.0<br>
d2y_dx2 at x=3.0:	2.0<br>
d3y_dx3 at x=3.0:	0.0</p>
</blockquote>
<p>Further the requires_grad attribute of dy_dx, and d2y_dx2 are automatically True.</p>
<p><strong>Second Example</strong><br>
In this example I tried to compute upto 2nd order derivatives of u=2*z where z=x+y and, x and y are 2d tensors of size 2x2. The first order derivative is computed correctly but I get an error  “<em>One of the differentiated Tensors appears to not have been used in the graph. Set allow_unused=True if this is the desired behavior</em>” while computing second order derivative. Further, unlike in the first example, the requires_grad attribute of the first order derivative is not set to True. I’m pasting the code and the runtime behaviour of the code below.</p>
<blockquote>
<p>x = torch.tensor([[1., 2.], [3., 4.]], requires_grad = True)<br>
y = torch.tensor([[5., 6.], [7., 8.]], requires_grad = True)<br>
z = x+y<br>
u = 2*z</p>
<p>grads_1 = torch.autograd.grad(outputs = (u, ), inputs = (z, ), grad_outputs = (torch.ones(u.size()), ), create_graph = True)<br>
print(f’du_dz: {grads_1[0]}‘)<br>
print(f’Requires grad attribute of du_dz: {grads_1[0].requires_grad}’)</p>
<p>for i in range(len(grads_1)):<br>
grads_1[i].requires_grad_(requires_grad = True)</p>
<p>grads2 = torch.autograd.grad(outputs = grads_1, inputs = (z, ), grad_outputs = (torch.ones(u.size()), ))<br>
print(f’du2_dz2: {grads_2[0]}')</p>
</blockquote>
<p><strong>Runtime Behavior</strong></p>
<blockquote>
<p>du_dz: tensor([[2., 2.],<br>
[2., 2.]])<br>
Requires grad attribute of du_dz: False</p>
</blockquote>
<blockquote>
<p>RuntimeError                              Traceback (most recent call last)<br>
 in ()<br>
11     grads_1[i].requires_grad_(requires_grad = True)<br>
12<br>
—&gt; 13 grads2 = torch.autograd.grad(outputs = grads_1, inputs = (z, ), grad_outputs = (torch.ones(u.size()), ))<br>
14 print(f’du2_dz2: {grads_2[0]}')</p>
<p>/usr/local/lib/python3.6/dist-packages/torch/autograd/<strong>init</strong>.py in grad(outputs, inputs, grad_outputs, retain_graph, create_graph, only_inputs, allow_unused)<br>
147     return Variable._execution_engine.run_backward(<br>
148         outputs, grad_outputs, retain_graph, create_graph,<br>
 → 149         inputs, allow_unused)<br>
150<br>
151</p>
<p>RuntimeError: One of the differentiated Tensors appears to not have been used in the graph. Set allow_unused=True if this is the desired behavior.</p>
</blockquote>
<p>I seek clarification.</p>