docstr: :param input_logits: NxCxHxW
  :param gt_semantic_masks: NxCxHxW
  :return: final loss
docstr_tok: [":","param","input_logits",":","NxCxHxW",":","param","gt_semantic_masks",":","NxCxHxW",":","return",":","final","loss"]
code: def forward(self, input_logits, gts, ignore_pixel=255):
      """
      :param input_logits: NxCxHxW
      :param gt_semantic_masks: NxCxHxW
      :return: final loss
      """
      N, C, H, W = input_logits.shape
      th = 1e-8  # 1e-10
      eps = 1e-10
      ignore_mask = (gts == ignore_pixel).detach()
      input_logits = torch.where(
          ignore_mask.view(N, 1, H, W).expand(N, 19, H, W),
          torch.zeros(N, C, H, W).cuda(),
          input_logits,
      )
      gt_semantic_masks = gts.detach()
      gt_semantic_masks = torch.where(
          ignore_mask,
          torch.zeros(N, H, W).long().cuda(),
          gt_semantic_masks,
      )
      gt_semantic_masks = _one_hot_embedding(
          gt_semantic_masks, 19
      ).detach()
  
      g = _gumbel_softmax_sample(input_logits.view(N, C, -1), tau=0.5)
      g = g.reshape((N, C, H, W))
      g = compute_grad_mag(g, cuda=self._cuda)
  
      g_hat = compute_grad_mag(gt_semantic_masks, cuda=self._cuda)
  
      g = g.view(N, -1)
      g_hat = g_hat.view(N, -1)
      loss_ewise = F.l1_loss(g, g_hat, reduction="none", reduce=False)
  
      p_plus_g_mask = (g >= th).detach().float()
      loss_p_plus_g = torch.sum(loss_ewise * p_plus_g_mask) / (
          torch.sum(p_plus_g_mask) + eps
      )
  
      p_plus_g_hat_mask = (g_hat >= th).detach().float()
      loss_p_plus_g_hat = torch.sum(loss_ewise * p_plus_g_hat_mask) / (
          torch.sum(p_plus_g_hat_mask) + eps
      )
  
      total_loss = 0.5 * loss_p_plus_g + 0.5 * loss_p_plus_g_hat
  
      return total_loss
  
file_path: pywick/pywick/models/segmentation/testnets/gscnn/my_functionals/DualTaskLoss.py
imports: import torch
  import torch.nn
  import torch.nn.functional
  import numpy
  from .custom_functional import compute_grad_mag
label_desc: Use image node_id 2 for calling the DualTaskLoss obj's underlying member method code with example usage: obj.forward(input_logits, gts, ignore_pixel) and returns: total_loss