class_docstr: Hard distillation using cross-entropy for classification tasks. Given an input sample, hard-labels
  are generated from a teacher and cross-entropy loss is computed between hard-labels and student model's output.
  
  Args:
      opts: command-line arguments
class_docstr_tok: ["Hard","distillation","using","cross-entropy","for","classification","tasks",".","Given","an","input","sample",",","hard-labels","are","generated","from","a","teacher","and","cross-entropy","loss","is","computed","between","hard-labels","and","student","model","'s","output",".","Args",":","opts",":","command-line","arguments"]
docstr: Computes cross entropy loss between students and hard labels generated from teacher.
  
  Args:
      input_sample: Input image tensor
      prediction: Output of student model
  
  Shapes:
      input_sample: Shape is [Batch size, 3, height, width]
      prediction: Shape is [Batch size, Number of classes]
  
  Returns:
      A scalar loss value
  
  ...note:
      When top-k labels extracted from teacher are used for distillation, binary cross entropy loss is used.
docstr_tok: ["Computes","cross","entropy","loss","between","students","and","hard","labels","generated","from","teacher",".","Args",":","input_sample",":","Input","image","tensor","prediction",":","Output","of","student","model","Shapes",":","input_sample",":","Shape","is","[","Batch","size",",","3",",","height",",","width","]","prediction",":","Shape","is","[","Batch","size",",","Number","of","classes","]","Returns",":","A","scalar","loss","value","...","note",":","When","top-k","labels","extracted","from","teacher","are","used","for","distillation",",","binary","cross","entropy","loss","is","used","."]
code: def _forward_distill(
      self, input_sample: Tensor, prediction: Tensor, *args, **kwargs
  ) -> Tensor:
      """
      Computes cross entropy loss between students and hard labels generated from teacher.
  
      Args:
          input_sample: Input image tensor
          prediction: Output of student model
  
      Shapes:
          input_sample: Shape is [Batch size, 3, height, width]
          prediction: Shape is [Batch size, Number of classes]
  
      Returns:
          A scalar loss value
  
      ...note:
          When top-k labels extracted from teacher are used for distillation, binary cross entropy loss is used.
      """
  
      with torch.no_grad():
          teacher_logits = self._logits_from_teacher(input_sample)
          teacher_probs = F.softmax(teacher_logits, dim=-1).detach()
          _, teacher_topk_labels = torch.topk(
              teacher_probs,
              k=self.topk,
              dim=-1,
              largest=True,
              sorted=True,
          )
  
      if self.topk > 1:
          num_classes = prediction.shape[-1]
          teacher_topk_labels = F.one_hot(
              teacher_topk_labels, num_classes=num_classes
          )
          teacher_topk_labels = teacher_topk_labels.sum(1)
          teacher_topk_labels = teacher_topk_labels.to(
              dtype=prediction.dtype
          )
  
          # smooth labels corresponding to multiple classes
          smooth_class_p = (1.0 - self.label_smoothing) / self.topk
          # distribute the mass over remaining classes
          smooth_non_class_p = self.label_smoothing / (
              num_classes - self.topk
          )
  
          teacher_topk_labels = torch.where(
              teacher_topk_labels == 1.0,
              smooth_class_p,
              smooth_non_class_p,
          )
  
          # scale by number of classes. Otherwise, the contribution is small
          loss = (
              F.binary_cross_entropy_with_logits(
                  input=prediction,
                  target=teacher_topk_labels,
                  reduction="mean",
              )
              * num_classes
          )
      else:
          teacher_topk_labels = teacher_topk_labels.reshape(-1)
          loss = F.cross_entropy(
              input=prediction,
              target=teacher_topk_labels,
              reduction="mean",
              label_smoothing=self.label_smoothing,
          )
      return loss
  
file_path: ml-cvnets/loss_fn/distillation/hard_distillation.py
imports: import argparse
  import torch
  from torch import Tensor
  from torch.nn import functional
  from loss_fn import LOSS_REGISTRY
  from loss_fn.distillation.base_distillation import BaseDistillationCriteria
  from utils import logger
label_desc: Use image node_id 3 for calling the HardDistillationLoss obj's underlying member method code with example usage: obj._forward_distill(input_sample, prediction) and returns: loss