Hi junyuphybies!



 junyuphybies:

def Afunction(phi):
return torch.tensor([torch.cos(phi[0]),torch.sin(phi[1])])
I find when I define it in the above way, the derivative of A is lost.


I am not an expert on autograd, but (if I understand your question)
I don’t believe that there is a convenient way of doing what you want.
The problem, as I see it, is that the grad_fn of a tensor is attached
to the tensor as a whole, and is not attached to individual elements
of the tensor.
The proper way to accomplish you goal would be to write a custom
autograd function that has its own backward() method that knows
how to compute the derivative of its forward() method.
See Extending torch.autograd 2 for the details.
However, in the special case that you really do want cos() and sin()
(and they’re not just for the purposes of a simple example), you can
use pytorch’s (recent) support for complex autograd, together with
the fact that the (complex) exponential function has cos() and sin()
inside of it.
Here is a script that implements this approach:
import torch
print (torch.__version__)

def Afunction (phi):   # your version
    return torch.tensor ([torch.cos (phi[0]), torch.sin (phi[1])])

def Bfunction (phi):   # version using complex exp() with autograd
    z = torch.exp (1.0j * phi)
    w = torch.tensor ([1.0 + 0.0j, 0.0 - 1.0j]) * z
    f = w.real
    return f

phi = torch.tensor ([ 0.2366, -0.5896], requires_grad = True)

print (phi)
print (Afunction (phi))
print (Bfunction (phi))

Bfunction (phi).backward (gradient = torch.tensor ([1.0, 1.0]))
print (phi.grad)

print (-torch.sin (phi[0]), torch.cos (phi[1]))   # check phi.grad

And here is its output:
1.9.0.dev20210412
tensor([ 0.2366, -0.5896], requires_grad=True)
tensor([ 0.9721, -0.5560])
tensor([ 0.9721, -0.5560], grad_fn=<SelectBackward>)
tensor([-0.2344,  0.8312])
tensor(-0.2344, grad_fn=<NegBackward>) tensor(0.8312, grad_fn=<CosBackward>)

Good luck.
K. Frank