Gradiant cusom variables

I have a pytorch nn, as shown below. I want my neural network to calobirate the variables (sigma and lam).

class SDE(nn.Module):
    def __init__(self,lam,sigma):
        super().__init__()
        self.lam = lam
        self.sigma = sigma

    def forward(self, T, steps, Npaths):
        np.random.seed(4)
        lam = self.lam.detach().numpy()
        sigma= self.sigma.detach().numpy()
         .....
        return sigma * lam * xx

My main nn is:

class MyModel(nn.Module):
    def __init__(self, args):
        super(MyModel, self).__init__()
        self.lam = nn.Parameter(torch.tensor(1.0), requires_grad=True)
        self.sigma = nn.Parameter(torch.tensor(0.2), requires_grad=True)
        # GRU layers
        self.gru = nn.GRU(
            self.input_dim, self.hidden_dim, self.layer_dim, batch_first=True, 
                                                dropout=args.dropout, bidirectional=True)

        # SDE 
         levy = SDE(self.lam, self.sigma) 
        # Fully connected layer
        self.fc = nn.Linear(self.hidden_dim * 2, self.output_dim)
   
    def forward(self, x):
            lev = torch.from_numpy(levy(1.0, 16, 1))
            .....
            h0 = torch.zeros(self.args['num_layers']* 2, x.size(0), self.args['n_hidden_units'], 
                                                                                     device=x.device).requires_grad_()
            out, _ = self.gru(x, h0.detach())
            out = out[:, -1, :]
            out = self.fc(out)
            out_m = torch.mul(out, lev)
            return out

Does this netwok calibirate the sigma and lam variables?
I’m a beginner and don’t know if I’m doing it wright.

The train will besomething like this:

    # Makes predictions
      yhat = self.model(x)
      # Computes loss
      loss = self.loss_fn(y, yhat)
      # Computes gradients
      #loss.requires_grad = True
      loss.backward()
      # Updates parameters and zeroes gradients
      self.optimizer.step()
      self.optimizer.zero_grad()

Hi @Mohammed_Alruqimi,

So, to get the gradients to work within pytorch, you need to use only pytorch functions (so, don’t use numpy for example). When you call .detach(), you delete the history of all operations on that variable, so you can’t compute gradients.

Likewise here as well, calling .requires_grad_() and .detach() will delete the history of operations and will stop backprop.

If you want to define a custom function (which uses numpy operations), you must define a torch.autograd.Function object where you manually define the forward and backward methods, the docs can be found here: Extending PyTorch — PyTorch 2.3 documentation

1 Like

Thank you @AlphaBetaGamma96
That is helpful.
However, it would be easier to use pure tensor calculation instead of defining custom torch.autogard.function.
If i can extend this question, my fumction that includes the numpu calculation is:

def merton_jump_paths_numpy( T, r, sigma,  lam, m, v, steps, Npaths):
    size=(steps,Npaths)
    dt = T/steps
    poi_rv = np.multiply(np.random.poisson( lam*dt, size=size),
                     np.random.normal(m,v, size=size)).cumsum(axis=0)
    geo = np.cumsum(((r -  sigma**2/2 -lam*(m  + v**2*0.5))*dt +\
                          sigma*np.sqrt(dt) * \
                          np.random.normal(size=size)), axis=0)

    return np.exp(geo+poi_rv)

So, I think I need to find tensor-based alternatives to np.cumsum, np.random.poisson, np.sqrt, np.random.normal and np.multiply.
Can you help in this regard?

Most of these functions require replacing numpy.X with torch.X where X is the given function within a given namespace, you can check for the equivalents in the docs here: PyTorch documentation — PyTorch 2.3 documentation

1 Like