def train(self, environments, args, reg=0):

        n = environments[0][0].size(1)
        dim_x = environments[0][0].size(1)

        # self.phi = torch.nn.Parameter(torch.rand(dim_x, 1))
        self.phi = torch.nn.Parameter(EmpiricalRiskMinimizer(environments, args).solution().view(dim_x, 1))

        opt = torch.optim.Adam([self.phi], lr=args["lr"])
        loss = torch.nn.MSELoss()

        for iteration in range(args["n_iterations"]):
            opt.zero_grad()

            error = torch.zeros(1)
            pen_mrg = torch.zeros(1)
            grad = []
            for i, (x_e, y_e) in enumerate(environments):
                error_e = loss(x_e @ self.phi, y_e)
                #print('er', self.phi, error_e)
                grad_e = torch.autograd.grad(error_e, self.phi, retain_graph=True)[0]
                grad.append(grad_e)
                error += error_e

            grad = torch.cat(grad, dim=1)
            m = grad.mean(dim=1)
            p = grad.var(dim=1) # / (m * m + 1e-3)
            p_sum = (self.phi * self.phi * p).sum()
            #print(grad)
            assert not torch.isnan(p_sum).any()
            error_t = (1-self.alpha) * error + self.alpha * p_sum
            grad_p = torch.autograd.grad(p_sum, self.phi, retain_graph=True)[0]
            grad_ee = torch.autograd.grad(error, self.phi, retain_graph=True)[0]

            # print(error)
            error_t.backward()
            opt.step()
            if args["verbose"] and iteration % 1000 == 0:
                err_flt = (1-self.alpha) * float(error.detach())
                p_flt = self.alpha * float(p_sum.detach())
                w_str = pretty(self.solution())
                p_str = pretty(p)
                print("{:05d} | {:.5f} | {:.5f} | {} | {}".format(iteration,
                                                                  err_flt,
                                                                  p_flt,
                                                                  w_str,
                                                                  p_str))

                print('GRAD error', - grad)
                print('P', - p)
                print('uncentered', - grad.pow(2).sum(dim=1))
                print('GRAD penalty', - grad_p)
                print('GRAD EE', - grad_ee)
                print(f'phi grad {pretty(self.phi.grad)}')
                print(f'm {pretty(m)} v {pretty(p)}')
Example #2
0
def penalty(label, y):
    scale = torch.tensor(1.).cuda().requires_grad_()
    # loss = mean_nll(logits * scale, y)
    # real_traj = label * scale
    # fake_traj = y
    # loss_trajectory_x = trajectory_criterion(real_traj.view(opt.batch_size, 16,2)[:,:,0]*opt.max_dist, fake_traj.view(opt.batch_size, 16,2)[:,:,0]*opt.max_dist)
    # loss_trajectory_y = trajectory_criterion(real_traj.view(opt.batch_size, 16,2)[:,:,1]*opt.max_dist, fake_traj.view(opt.batch_size, 16,2)[:,:,1]*opt.max_dist)
    # loss_trajectory = (loss_trajectory_x + 5*loss_trajectory_y)#/2
    # loss = loss_trajectory
    loss = trajectory_criterion(label * opt.max_dist, y * scale * opt.max_dist)
    grad = torch.autograd.grad(loss, [scale], create_graph=True)[0]
    return torch.sqrt(grad.pow(2).mean())
Example #3
0
def compute_gradient_norm(output: Tensor, model: Module):
    """
    Compute the norm of the gradient of an output (e.g a loss) with respect to a model parameters

    :param output:
    :param model:
    :return:
    """
    ret = 0
    output.backward(retain_graph=True)
    for parameter in model.parameters():
        grad = parameter.grad
        ret += grad.pow(2).sum().cpu().detach().numpy()
        parameter.grad = None # Reset gradient accumulation

    return ret
Example #4
0
def grad_penalty(loss, net):
    total_grad = 0
    for param in net.parameters():
        grad = torch.autograd.grad(loss, [param], create_graph=True)[0]
        total_grad += grad.pow(2).mean()
    return total_grad
Example #5
0
def cal_norm_grad(grad_params):
    grad_norm = 0
    for grad in grad_params:
        grad_norm += grad.pow(2).sum()
    grad_norm = grad_norm.sqrt()
    return grad_norm