def METHOD_NAME(self, train_x, train_y, valid_x, valid_y, xi, w_optim):
    """ Compute unrolled loss and backward its gradients
    Args:
        xi: learning rate for virtual gradient step (same as model lr)
        w_optim: weights optimizer - for virtual step
    """
    # Do virtual step (calc w')
    self.virtual_step(train_x, train_y, xi, w_optim)
    # Calculate unrolled loss
    # Loss for validation with w'. L_valid(w')
    loss = self.v_model.loss(valid_x, valid_y)
    # Calculate gradient
    v_alphas = tuple(self.v_model.getAlphas())
    v_weights = tuple(self.v_model.getWeights())
    v_grads = torch.autograd.grad(loss, v_alphas + v_weights)
    dalpha = v_grads[:len(v_alphas)]
    dws = v_grads[len(v_alphas):]
    hessian = self.compute_hessian(dws, train_x, train_y)
    # Update final gradient = dalpha - xi * hessian
    with torch.no_grad():
        for alpha, da, h in zip(self.model.getAlphas(), dalpha, hessian):
            alpha.grad = da - torch.FloatTensor(xi) * h