class_docstr: This class defines the training and validation code for training models with CVNets
docstr: This function identifies easy samples in the training set and removes them from training.
  
  .. note::
      Currently, this is implemented separately to avoid breaking the training and validation pipeline. In future,
      this will be combined with main training loop to reduce overhead.
docstr_tok: ["This","function","identifies","easy","samples","in","the","training","set","and","removes","them","from","training",".","..","note",":",":","Currently",",","this","is","implemented","separately","to","avoid","breaking","the","training","and","validation","pipeline",".","In","future",",","this","will","be","combined","with","main","training","loop","to","reduce","overhead","."]
code: def find_easy_samples(self, epoch, model, *args, **kwargs):
      """
      This function identifies easy samples in the training set and removes them from training.
  
      .. note::
          Currently, this is implemented separately to avoid breaking the training and validation pipeline. In future,
          this will be combined with main training loop to reduce overhead.
      """
  
      time.sleep(
          if_test_env(0.5, otherwise=2)
      )  # To prevent possible deadlock during epoch transition
  
      model.eval()
      if model.training and self.is_master_node:
          logger.warning(
              "Model is in training mode. Switching to evaluation mode"
          )
          model.eval()
  
      if self.is_master_node:
          logger.log(
              "Trying to find easy samples in epoch {}".format(epoch)
          )
  
      with torch.no_grad():
          easy_sample_ids_tensor = torch.zeros_like(
              self.running_sum_tensor
          )
  
          for batch_id, batch in enumerate(self.train_loader_set):
              batch = move_to_device(
                  opts=self.opts, x=batch, device=self.device
              )
  
              samples, targets = batch["samples"], batch["targets"]
  
              sample_ids = None
              if "sample_id" in batch:
                  sample_ids = batch["sample_id"]
              else:
                  self.sample_efficient_training = False
                  if self.is_master_node:
                      logger.log(
                          "Sample Ids are required in a batch for sample efficient training. "
                          "sample_id key not found in batch. Disabling sample efficient training."
                      )
                  break
  
              if sample_ids is None:
                  logger.log("Sample Ids can't be none")
                  break
  
              with autocast_fn(
                  enabled=self.mixed_precision_training,
                  amp_precision=self.mixed_precision_dtype,
              ):
                  # prediction
                  pred_label = model(samples)
                  pred_label = F.softmax(pred_label, dim=-1)
  
              pred_conf, pred_indices = torch.max(pred_label, dim=-1)
  
              easy_samples = torch.logical_and(
                  pred_indices.eq(
                      targets
                  ),  # condition 1: Predicted label == Target label
                  pred_conf
                  >= self.sample_confidence,  # condition 2: prediction confidence >= desired confidence
              )
  
              if easy_samples.numel() > 0:
                  easy_sample_ids = sample_ids[easy_samples]
                  # find easy samples as per condition 1 and 2 and set their values to 1
                  easy_sample_ids_tensor[easy_sample_ids] = 1
  
          # synchronize tensors
          if self.use_distributed:
              # sync across all GPUs.
              easy_sample_ids_tensor = reduce_tensor_sum(
                  easy_sample_ids_tensor
              )
  
          # some samples which are classified easy earlier may have been classified hard now.
          easy_sample_ids_tensor[easy_sample_ids_tensor == 0] = -1
  
          if self.is_master_node:
              logger.debug(
                  "Number of easy samples found during epoch {} are {}".format(
                      epoch,
                      easy_sample_ids_tensor[easy_sample_ids_tensor > 0]
                      .sum()
                      .item(),
                  )
              )
  
          self.running_sum_tensor = torch.clip(
              self.running_sum_tensor + easy_sample_ids_tensor,
              min=0,
              max=self.min_sample_frequency,
          )
  
          if self.running_sum_tensor.sum() > 0:
              skip_sample_ids = (
                  self.running_sum_tensor >= self.min_sample_frequency
              ).nonzero(as_tuple=True)[0]
  
              if skip_sample_ids.numel() > 0:
                  skip_samples = skip_sample_ids.cpu().numpy().tolist()
  
                  new_sample_ids = [
                      s_id
                      for s_id in self.sample_ids_orig
                      if s_id not in skip_sample_ids
                  ]
  
                  # update the train loader indices
                  self.train_loader.update_indices(new_sample_ids)
  
                  if self.is_master_node:
                      logger.debug(
                          "Number of samples to skip after epoch {} are {}".format(
                              epoch, len(skip_samples)
                          )
                      )
  
imports: import copy
  import gc
  import shutil
  import time
  import traceback
  from itertools import product
  from typing import Dict, Union
  import numpy
  import torch
  from torch import Tensor
  from torch.nn import functional
  from common import DEFAULT_EPOCHS, DEFAULT_ITERATIONS, DEFAULT_LOG_FREQ, if_test_env
  from data.transforms.image_torch import apply_mixing_transforms
  from engine.utils import autocast_fn, get_batch_size, get_log_writers, log_metrics
  from loss_landscape import landscape_utils
  from metrics.stats import Statistics
  from options.parse_args import parse_validation_metric_names
  from utils import logger
  from utils.checkpoint_utils import copy_weights, save_checkpoint, save_interval_checkpoint
  from utils.common_utils import move_to_device, unwrap_model_fn
  from utils.ddp_utils import dist_barrier, is_master
  from utils.tensor_utils import reduce_tensor_sum
label_desc: Use image node_id 6 for calling the Trainer obj's underlying member method code with example usage: obj.find_easy_samples(epoch, model) without return types