class_docstr: Contrastive Model, currently mainly focused on memory bank and CSC.
class_docstr_tok: ["Contrastive","Model",",","currently","mainly","focused","on","memory","bank","and","CSC","."]
code: def compute_key_feat(
      self,
      clips_k,
      compute_predictor_keys=False,
      batched_inference=True,
  ):
      assert self.training
      # momentum update key encoder
      self._update_history()
      self.iter += 1
      n_clips = len(clips_k)
      bsz = clips_k[0][0].shape[0]
      if (
          n_clips * bsz * clips_k[0][0].numel()
          > 4 * 64 * 3 * 8 * 224 * 224
      ):
          batched_inference = False  # hack to avoid oom on large inputs
      assert n_clips > 0
      if batched_inference and all(
          [
              clips_k[i][j].shape[1:] == clips_k[0][j].shape[1:]
              for i in range(len(clips_k))
              for j in range(len(clips_k[i]))
          ]
      ):
          clips_k = [self.batch_clips(clips_k)]
          batched = True
      else:
          batched = False
  
      keys, pred_keys = [], []
      for k in range(0, len(clips_k)):
          clip_k = clips_k[k]
          if self._batch_shuffle_on:
              with torch.no_grad():
                  clip_k, idx_restore = self._batch_shuffle(clip_k)
          with torch.no_grad():
              hist_feat = self.backbone_hist(clip_k)
              if isinstance(hist_feat, list):
                  hist_time = hist_feat[1:]
                  hist_feat = hist_feat[0]
                  if compute_predictor_keys:
                      tks = []
                      for tk in hist_time:
                          tk = self.l2_norm(tk)
                          if self._batch_shuffle_on:
                              tk = self._batch_unshuffle(
                                  tk, idx_restore
                              ).detach()
                          tks.append(tk)
                      pred_keys.append(tks)
              x_hist = self.l2_norm(hist_feat)
              if self._batch_shuffle_on:
                  x_hist = self._batch_unshuffle(
                      x_hist, idx_restore
                  ).detach()
          keys.append(x_hist)
      if batched:
          assert len(keys) == 1, "batched input uses single clip"
          batched_key = keys[0]
          if compute_predictor_keys:
              batched_pred_key = pred_keys[0]
          keys, pred_keys = [], []
          for k in range(0, n_clips):
              keys.append(batched_key[k * bsz : (k + 1) * bsz])
              if compute_predictor_keys:
                  pred_keys.append(
                      batched_pred_key[k * bsz : (k + 1) * bsz]
                  )
      if compute_predictor_keys:
          return keys, pred_keys
      else:
          return keys
  
imports: import math
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  import slowfast.models.losses
  import slowfast.utils.distributed
  import slowfast.utils.logging
  from slowfast.models.video_model_builder import X3D, MViT, ResNet, SlowFast
  from .build import MODEL_REGISTRY
label_desc: Use image node_id 12 for calling the ContrastiveModel obj's underlying member method code with example usage: obj.compute_key_feat(clips_k, compute_predictor_keys, batched_inference) and returns: keys,  pred_keys, keys