Applying operator loses causes loss of gradient

I’m trying to apply a hook to a tensor which should require a gradient, but I get the error:

RuntimeError: cannot register a hook on a tensor that doesn’t require gradient

This happens on the line where I register the hook.

    def forward(self, x):
        c_outputs = [c(x) for c in self.children]
        output = torch.exp(c_outputs[0])
        print(c_outputs[0].requires_grad)
        print(output.requires_grad)
        if self.clip_grad:
            output.register_hook(modify_grad)
        return output

Output:

True
False
[...]
File /tree.py", line 251, in forward
    output.register_hook(modify_grad)
  File "xxx/anaconda3/envs/deep/lib/python3.8/site-packages/torch/_tensor.py", line 430, in register_hook
    raise RuntimeError("cannot register a hook on a tensor that "
RuntimeError: cannot register a hook on a tensor that doesn't require gradient

However the print statements indicate that whatever I’m putting inside the exp operator requires a gradient while the output after applying the exp operator does not. I found similar behaviour for the repeat operator, but switching it out for the expand operator helped. Any idea how I can make the output require a gradient?

Hi Joe!

Your reasoning is correct that applying exp() to a tensor should not
reset its requires_grad property to False.

I cannot reproduce your issue. Here is a minimal, fully self-contained,
runnable script (based on your code) that does not reproduce your
issue:

>>> import torch
>>> torch.__version__
'1.12.0'
>>>
>>> _ = torch.manual_seed (2022)
>>>
>>> def dummy_hook (grad):
...     print ('dummy_hook: grad = ...')
...     print (grad)
...     return None
...
>>> children = [torch.nn.Linear (2, 2), torch.nn.Linear (2, 2), torch.nn.Linear (2, 2)]
>>> t = torch.randn (5, 2)
>>> clip_grad = True
>>>
>>> def forward(x):
...     c_outputs = [c(x) for c in children]
...     output = torch.exp(c_outputs[0])
...     print(c_outputs[0].requires_grad)
...     print(output.requires_grad)
...     if clip_grad:
...         output.register_hook (dummy_hook)
...     return output
...
>>> out = forward (t)
True
True
>>> print (out)
tensor([[0.2549, 1.3924],
        [0.3643, 1.0232],
        [0.4743, 1.4320],
        [0.7217, 0.5773],
        [0.2918, 0.4463]], grad_fn=<ExpBackward0>)
>>>
>>> out.sum().backward()
dummy_hook: grad = ...
tensor([[1., 1.],
        [1., 1.],
        [1., 1.],
        [1., 1.],
        [1., 1.]])
>>> print (children[0].weight.grad)
tensor([[-0.0651, -0.4404],
        [ 2.6920, -1.8137]])

Could you post a minimal, fully self-contained, runnable script that does
reproduce your issue?

The [...] in your output catches my eye and suggests that you have
edited away some of your output. Is it possible that the cause of your
problem lies somewhere in those magic ellipses?

Best.

K. Frank