class_docstr: Loss used in iBOT (https://arxiv.org/pdf/2111.07832.pdf)
  
  Mostly copy-pasted from the official iBOT repository:
  https://github.com/bytedance/ibot/blob/da316d82636a7a7356835ef224b13d5f3ace0489/main_ibot.py#L478
code: def __init__(
      self,
      out_dim: int,
      patch_out_dim: int,
      ngcrops: int,
      nlcrops: int,
      warmup_teacher_temp: float,
      teacher_temp: float,
      warmup_teacher_temp2: float,
      teacher_temp2: float,
      warmup_teacher_temp_epochs: int,
      nepochs: int,
      student_temp=0.1,
      center_momentum=0.9,
      center_momentum2=0.9,
      lambda1=1.0,
      lambda2=1.0,
      mim_start_epoch=0,
  ):
      super().__init__()
      self.student_temp = student_temp
      self.center_momentum = center_momentum
      self.center_momentum2 = center_momentum2
      self.ngcrops = ngcrops
      self.nlcrops = nlcrops
      self.ncrops = ngcrops + nlcrops
      self.register_buffer("center", torch.zeros(1, out_dim))
      self.register_buffer("center2", torch.zeros(1, 1, patch_out_dim))
      self.lambda1 = lambda1
      self.lambda2 = lambda2
  
      # we apply a warm up for the teacher temperature because
      # a too high temperature makes the training instable at the beginning
      self.teacher_temp_schedule = np.concatenate(
          (
              np.linspace(
                  warmup_teacher_temp,
                  teacher_temp,
                  warmup_teacher_temp_epochs,
              ),
              np.ones(nepochs - warmup_teacher_temp_epochs)
              * teacher_temp,
          )
      )
      self.teacher_temp2_schedule = (
          np.concatenate(
              (
                  np.linspace(
                      warmup_teacher_temp2,
                      teacher_temp2,
                      warmup_teacher_temp_epochs,
                  ),
                  np.ones(nepochs - warmup_teacher_temp_epochs)
                  * teacher_temp2,
              )
          )
          if mim_start_epoch == 0
          else np.concatenate(
              (
                  np.ones(mim_start_epoch) * warmup_teacher_temp2,
                  np.linspace(
                      warmup_teacher_temp2,
                      teacher_temp2,
                      warmup_teacher_temp_epochs,
                  ),
                  np.ones(
                      nepochs
                      - warmup_teacher_temp_epochs
                      - mim_start_epoch
                  )
                  * teacher_temp2,
              )
          )
      )
  
imports: import logging
  import pprint
  from typing import List
  import numpy
  import torch
  import torch.distributed
  import torch.nn
  import torch.nn.functional
  from classy_vision.losses import ClassyLoss, register_loss
  from fairscale.nn import FullyShardedDataParallel
  from vissl.config import AttrDict
  from vissl.models.model_helpers import get_no_ddp_model
  from vissl.utils.distributed_utils import concat_all_gather
label_desc: Use image node_id 1 to create a new iBOTCriterion object from inherited base classes: nn with example: obj = iBOTCriterion(out_dim, patch_out_dim, ngcrops, nlcrops, warmup_teacher_temp, teacher_temp, warmup_teacher_temp2, teacher_temp2, warmup_teacher_temp_epochs, nepochs, student_temp, center_momentum, center_momentum2, lambda1, lambda2, mim_start_epoch)