class_docstr: A version of TracInCPFast which is optimized for "interactive" calls to
  `influence` for the purpose of calculating proponents / opponents, or
  influence scores. "Interactive" means there will be multiple calls to
  `influence`, with each call for a different batch of test examples, and
  subsequent calls rely on the results of previous calls. The implementation in
  this class has been optimized so that each call to `influence` is fast, so that
  it can be used for interactive analysis. This class should only be used for
  interactive use cases. It should not be used if `influence` will only be
  called once, because to enable fast calls to `influence`, time and memory
  intensive preprocessing is required in `__init__`. Furthermore, it should not
  be used to calculate self influence scores - `TracInCPFast` should be used
  instead for that purpose. To enable interactive analysis, this implementation
  computes and saves "embedding" vectors for all training examples in
  `train_dataset`. Crucially, the influence score of a training
  example on a test example is simply the dot-product of their corresponding
  vectors, and proponents / opponents can be found by first storing vectors for
  training examples in a nearest-neighbor data structure, and then finding the
  nearest-neighbors for a test example in terms of dot-product (see appendix F
  of the TracIn paper). This class should only be used if calls to `influence`
  to obtain proponents / opponents or influence scores will be made in an
  "interactive" manner, and there is sufficient memory to store vectors for the
  entire `train_dataset`. This is because in order to enable interactive
  analysis, this implementation incures overhead in `__init__` to setup the
  nearest-neighbors data structure, which is both time and memory intensive, as
  vectors corresponding to all training examples needed to be stored. To reduce
  memory usage, this implementation enables random projections of those vectors.
  Note that the influence scores computed with random projections are less
  accurate, though correct in expectation.
  
  In more detail regarding the "embedding" vectors - the influence of a training
  example on a test example, when only considering gradients in the last
  fully-connected layer, the sum of the contribution from each checkpoint. The
  contribution from a given checkpoint is
  :math`(x^T x')(\nabla_y f(y)^T \nabla_{y'} f(y'))`, using the notation in the
  description of `TracInCPFast`. As is, this is not a dot-product of 2 vectors.
  However, we can rewrite that contribution as
  :math`(x \nabla_y f(y)^T) \dot (x' f(y')^T)`. Both terms in this
  product are 2D matrices, as they are outer products, and the "product" is actually
  a dot-product, treating both matrices as vectors. Therefore, for a given
  checkpoint, its contribution to the "embedding" of an example is just the
  outer-product :math`(x \nabla_y f(y)^T)`, flattened. Furthemore, to reduce the
  dimension of this contribution, we can right-multiply and
  left-multiply the outer-product with two separate projection matrices. These
  transform :math`\nabla_y f(y)` and :math`x` to lower dimensional vectors. While
  the dimension of these two lower dimensional vectors do not necessarily need to
  be the same, in our implementation, we let them be the same, both equal to the
  square root of the desired projection dimension. Finally, the embedding of an
  example is the concatenation of the contributions from each checkpoint.
class_docstr_tok: ["A","version","of","TracInCPFast","which","is","optimized","for","``","interactive","''","calls","to","`","influence","`","for","the","purpose","of","calculating","proponents","\/","opponents",",","or","influence","scores",".","``","Interactive","''","means","there","will","be","multiple","calls","to","`","influence","`",",","with","each","call","for","a","different","batch","of","test","examples",",","and","subsequent","calls","rely","on","the","results","of","previous","calls",".","The","implementation","in","this","class","has","been","optimized","so","that","each","call","to","`","influence","`","is","fast",",","so","that","it","can","be","used","for","interactive","analysis",".","This","class","should","only","be","used","for","interactive","use","cases",".","It","should","not","be","used","if","`","influence","`","will","only","be","called","once",",","because","to","enable","fast","calls","to","`","influence","`",",","time","and","memory","intensive","preprocessing","is","required","in","`","__init__","`",".","Furthermore",",","it","should","not","be","used","to","calculate","self","influence","scores","-","`","TracInCPFast","`","should","be","used","instead","for","that","purpose",".","To","enable","interactive","analysis",",","this","implementation","computes","and","saves","``","embedding","''","vectors","for","all","training","examples","in","`","train_dataset","`",".","Crucially",",","the","influence","score","of","a","training","example","on","a","test","example","is","simply","the","dot-product","of","their","corresponding","vectors",",","and","proponents","\/","opponents","can","be","found","by","first","storing","vectors","for","training","examples","in","a","nearest-neighbor","data","structure",",","and","then","finding","the","nearest-neighbors","for","a","test","example","in","terms","of","dot-product","(","see","appendix","F","of","the","TracIn","paper",")",".","This","class","should","only","be","used","if","calls","to","`","influence","`","to","obtain","proponents","\/","opponents","or","influence","scores","will","be","made","in","an","''","interactive","''","manner",",","and","there","is","sufficient","memory","to","store","vectors","for","the","entire","`","train_dataset","`",".","This","is","because","in","order","to","enable","interactive","analysis",",","this","implementation","incures","overhead","in","`","__init__","`","to","setup","the","nearest-neighbors","data","structure",",","which","is","both","time","and","memory","intensive",",","as","vectors","corresponding","to","all","training","examples","needed","to","be","stored",".","To","reduce","memory","usage",",","this","implementation","enables","random","projections","of","those","vectors",".","Note","that","the","influence","scores","computed","with","random","projections","are","less","accurate",",","though","correct","in","expectation",".","In","more","detail","regarding","the","``","embedding","''","vectors","-","the","influence","of","a","training","example","on","a","test","example",",","when","only","considering","gradients","in","the","last","fully-connected","layer",",","the","sum","of","the","contribution","from","each","checkpoint",".","The","contribution","from","a","given","checkpoint","is",":","math","`","(","x^T","x","'",")","(","\\nabla_y","f","(","y",")","^T","\\nabla_","{","y","'","}","f","(","y","'",")",")","`",",","using","the","notation","in","the","description","of","`","TracInCPFast","`",".","As","is",",","this","is","not","a","dot-product","of","2","vectors",".","However",",","we","can","rewrite","that","contribution","as",":","math","`","(","x","\\nabla_y","f","(","y",")","^T",")","\\dot","(","x","'","f","(","y","'",")","^T",")","`",".","Both","terms","in","this","product","are","2D","matrices",",","as","they","are","outer","products",",","and","the","``","product","''","is","actually","a","dot-product",",","treating","both","matrices","as","vectors",".","Therefore",",","for","a","given","checkpoint",",","its","contribution","to","the","``","embedding","''","of","an","example","is","just","the","outer-product",":","math","`","(","x","\\nabla_y","f","(","y",")","^T",")","`",",","flattened",".","Furthemore",",","to","reduce","the","dimension","of","this","contribution",",","we","can","right-multiply","and","left-multiply","the","outer-product","with","two","separate","projection","matrices",".","These","transform",":","math","`","\\nabla_y","f","(","y",")","`","and",":","math","`","x","`","to","lower","dimensional","vectors",".","While","the","dimension","of","these","two","lower","dimensional","vectors","do","not","necessarily","need","to","be","the","same",",","in","our","implementation",",","we","let","them","be","the","same",",","both","equal","to","the","square","root","of","the","desired","projection","dimension",".","Finally",",","the","embedding","of","an","example","is","the","concatenation","of","the","contributions","from","each","checkpoint","."]
docstr: This method computes vectors that can be used to compute influence. (see
  Appendix F, page 15). Crucially, the influence score between a test example
  and a training example is simply the dot product of their respective
  vectors. This means that the training example with the largest influence score
  on a given test example can be found using a nearest-neighbor (more
  specifically, largest dot-product) data structure.
  
  Args:
      inputs (Tuple, or DataLoader): Either a single tuple of any, or a
              `DataLoader`, where each batch yielded is a tuple of any. In
              either case, the tuple represents a single batch, where the last
              element is assumed to be the labels for the batch. That is,
              `model(*batch[0:-1])` produces the output for `model`, and
              and `batch[-1]` are the labels, if any. Here, `model` is model
              provided in initialization. This is the same assumption made for
              each batch yielded by training dataset `train_dataset`. Please see
              documentation for the `train_dataset` argument to
              `TracInCPFastRandProj.__init__` for more details on the assumed
              structure of a batch.
      projection_quantities (tuple or None): Is either the two tensors defining
              the randomized projections to apply, or None, which means no
              projection is to be applied.
      test (bool): If True, the intermediate quantities are computed using
              `self.test_loss_fn`. Otherwise, they are computed using
              `self.loss_fn`.
              Default: False
  
  Returns:
      intermediate_quantities (Tensor): A tensor of dimension
              (N, D * C), where N is total number of examples in `dataloader`, C
              is the number of checkpoints passed as the `checkpoints` argument
              of `TracInCPFastRandProj.__init__`, and each row represents the
              vector for an example. Regarding D: Let I be the dimension of the
              output of the last fully-connected layer times the dimension of the
              input of the last fully-connected layer. If `self.projection_dim`
              is specified in initialization,
              D = min(I * C, `self.projection_dim` * C). Otherwise, D = I * C.
              In summary, if `self.projection_dim` is None, the dimension of each
              vector will be determined by the size of the input and output of
              the last fully-connected layer of `model`. Otherwise,
              `self.projection_dim` must be an int, and random projection will be
              performed to ensure that the vector is of dimension no more than
              `self.projection_dim` * C. `self.projection_dim` corresponds to
              the variable d in the top of page 15 of the TracIn paper:
              https://arxiv.org/abs/2002.08484.
docstr_tok: ["This","method","computes","vectors","that","can","be","used","to","compute","influence",".","(","see","Appendix","F",",","page","15",")",".","Crucially",",","the","influence","score","between","a","test","example","and","a","training","example","is","simply","the","dot","product","of","their","respective","vectors",".","This","means","that","the","training","example","with","the","largest","influence","score","on","a","given","test","example","can","be","found","using","a","nearest-neighbor","(","more","specifically",",","largest","dot-product",")","data","structure",".","Args",":","inputs","(","Tuple",",","or","DataLoader",")",":","Either","a","single","tuple","of","any",",","or","a","`","DataLoader","`",",","where","each","batch","yielded","is","a","tuple","of","any",".","In","either","case",",","the","tuple","represents","a","single","batch",",","where","the","last","element","is","assumed","to","be","the","labels","for","the","batch",".","That","is",",","`","model","(","*","batch","[","0",":","-1","]",")","`","produces","the","output","for","`","model","`",",","and","and","`","batch","[","-1","]","`","are","the","labels",",","if","any",".","Here",",","`","model","`","is","model","provided","in","initialization",".","This","is","the","same","assumption","made","for","each","batch","yielded","by","training","dataset","`","train_dataset","`",".","Please","see","documentation","for","the","`","train_dataset","`","argument","to","`","TracInCPFastRandProj.__init__","`","for","more","details","on","the","assumed","structure","of","a","batch",".","projection_quantities","(","tuple","or","None",")",":","Is","either","the","two","tensors","defining","the","randomized","projections","to","apply",",","or","None",",","which","means","no","projection","is","to","be","applied",".","test","(","bool",")",":","If","True",",","the","intermediate","quantities","are","computed","using","`","self.test_loss_fn","`",".","Otherwise",",","they","are","computed","using","`","self.loss_fn","`",".","Default",":","False","Returns",":","intermediate_quantities","(","Tensor",")",":","A","tensor","of","dimension","(","N",",","D","*","C",")",",","where","N","is","total","number","of","examples","in","`","dataloader","`",",","C","is","the","number","of","checkpoints","passed","as","the","`","checkpoints","`","argument","of","`","TracInCPFastRandProj.__init__","`",",","and","each","row","represents","the","vector","for","an","example",".","Regarding","D",":","Let","I","be","the","dimension","of","the","output","of","the","last","fully-connected","layer","times","the","dimension","of","the","input","of","the","last","fully-connected","layer",".","If","`","self.projection_dim","`","is","specified","in","initialization",",","D","=","min","(","I","*","C",",","`","self.projection_dim","`","*","C",")",".","Otherwise",",","D","=","I","*","C.","In","summary",",","if","`","self.projection_dim","`","is","None",",","the","dimension","of","each","vector","will","be","determined","by","the","size","of","the","input","and","output","of","the","last","fully-connected","layer","of","`","model","`",".","Otherwise",",","`","self.projection_dim","`","must","be","an","int",",","and","random","projection","will","be","performed","to","ensure","that","the","vector","is","of","dimension","no","more","than","`","self.projection_dim","`","*","C.","`","self.projection_dim","`","corresponds","to","the","variable","d","in","the","top","of","page","15","of","the","TracIn","paper",":","https",":","\/\/arxiv.org\/abs\/2002.08484","."]
code: def _get_intermediate_quantities_tracincp_fast_rand_proj(
      self,
      inputs: Union[Tuple[Any, ...], DataLoader],
      projection_quantities: Optional[
          Tuple[torch.Tensor, torch.Tensor]
      ],
      test: bool = False,
  ) -> torch.Tensor:
      r"""
      This method computes vectors that can be used to compute influence. (see
      Appendix F, page 15). Crucially, the influence score between a test example
      and a training example is simply the dot product of their respective
      vectors. This means that the training example with the largest influence score
      on a given test example can be found using a nearest-neighbor (more
      specifically, largest dot-product) data structure.
  
      Args:
          inputs (Tuple, or DataLoader): Either a single tuple of any, or a
                  `DataLoader`, where each batch yielded is a tuple of any. In
                  either case, the tuple represents a single batch, where the last
                  element is assumed to be the labels for the batch. That is,
                  `model(*batch[0:-1])` produces the output for `model`, and
                  and `batch[-1]` are the labels, if any. Here, `model` is model
                  provided in initialization. This is the same assumption made for
                  each batch yielded by training dataset `train_dataset`. Please see
                  documentation for the `train_dataset` argument to
                  `TracInCPFastRandProj.__init__` for more details on the assumed
                  structure of a batch.
          projection_quantities (tuple or None): Is either the two tensors defining
                  the randomized projections to apply, or None, which means no
                  projection is to be applied.
          test (bool): If True, the intermediate quantities are computed using
                  `self.test_loss_fn`. Otherwise, they are computed using
                  `self.loss_fn`.
                  Default: False
  
      Returns:
          intermediate_quantities (Tensor): A tensor of dimension
                  (N, D * C), where N is total number of examples in `dataloader`, C
                  is the number of checkpoints passed as the `checkpoints` argument
                  of `TracInCPFastRandProj.__init__`, and each row represents the
                  vector for an example. Regarding D: Let I be the dimension of the
                  output of the last fully-connected layer times the dimension of the
                  input of the last fully-connected layer. If `self.projection_dim`
                  is specified in initialization,
                  D = min(I * C, `self.projection_dim` * C). Otherwise, D = I * C.
                  In summary, if `self.projection_dim` is None, the dimension of each
                  vector will be determined by the size of the input and output of
                  the last fully-connected layer of `model`. Otherwise,
                  `self.projection_dim` must be an int, and random projection will be
                  performed to ensure that the vector is of dimension no more than
                  `self.projection_dim` * C. `self.projection_dim` corresponds to
                  the variable d in the top of page 15 of the TracIn paper:
                  https://arxiv.org/abs/2002.08484.
      """
      # if `inputs` is not a `DataLoader`, turn it into one.
      inputs = _format_inputs_dataset(inputs)
  
      # internally, whether `projection_quantities` is None determines whether
      # any projection will be applied to reduce the dimension of the "embedding"
      # vectors. If projection will be applied, there are actually 2 different
      # projection matrices - one to project the `input_jacobians`, and one to
      # project the `layer_inputs`. See below for details of those two quantities.
      # here, we extract the corresponding projection matrices for those two
      # quantities, if doing projection. Note that the same projections are used
      # for each checkpoint.
      project = False
      if projection_quantities is not None:
          project = True
          (
              jacobian_projection,
              layer_input_projection,
          ) = projection_quantities
  
      # for each checkpoint, we will populate a list containing the contribution of
      # the checkpoint for each batch
      checkpoint_contributions: List[Union[List, Tensor]] = [
          [] for _ in self.checkpoints
      ]
  
      # the "embedding" vector is the concatenation of contributions from each
      # checkpoint, which we compute one by one
      for j, checkpoint in enumerate(self.checkpoints):
          assert (
              checkpoint is not None
          ), "None returned from `checkpoints`, cannot load."
  
          learning_rate = self.checkpoints_load_func(
              self.model, checkpoint
          )
          learning_rate_root = learning_rate**0.5
  
          # after loading a checkpoint, we compute the contribution of that
          # checkpoint, for *all* batches (instead of a single batch). this enables
          # increased efficiency.
          for batch in inputs:
              # compute `input_jacobians` and `layer_inputs`, for a given checkpoint
              # using a helper function. `input_jacobians` is a 2D tensor,
              # where each row is the jacobian of the loss, with respect to the
              # *output* of the last fully-connected layer. `layer_inputs` is a 2D
              # tensor, where each row is the *input* to the last fully-connected
              # layer. For both, the length is the number of examples in `batch`
              (
                  input_jacobians,
                  layer_inputs,
              ) = _basic_computation_tracincp_fast(
                  self,
                  batch[0:-1],
                  batch[-1],
                  self.test_loss_fn,
                  self.test_reduction_type,
              )
  
              # if doing projection, project those two quantities
              if project:
                  input_jacobians = torch.matmul(
                      input_jacobians, jacobian_projection
                  )
  
                  layer_inputs = torch.matmul(
                      layer_inputs, layer_input_projection
                  )
  
              # for an example, the contribution to the "embedding" vector from each
              # checkpoint is the outer product of its `input_jacobian` and its
              # `layer_input`, flattened to a 1D tensor. here, we perform this
              # for the entire batch. we append the contribution to a list containing
              # the contribution of all batches, from the checkpoint.
              cast(list, checkpoint_contributions[j]).append(
                  torch.matmul(
                      torch.unsqueeze(
                          input_jacobians, 2
                      ),  # size is (batch_size, output_size, 1)
                      torch.unsqueeze(
                          layer_inputs, 1
                      ),  # size is (batch_size, 1, input_size)
                  ).flatten(
                      start_dim=1
                  )  # matmul does a batched matrix multiplication to return a 3D
                  # tensor. each element along the batch (0-th) dimension is the
                  # matrix product of a (output_size, 1) and (1, input_size) tensor
                  # in other words, each element is an outer product, and the matmul
                  # is just doing a batched outer product. this is what we want, as
                  # the contribution to the "embedding" for an example is the outer
                  # product of the last layer's input and the gradient of its output.
                  # finally, we flatten the 3rd dimension so that the contribution to
                  # the embedding for this checkpoint is a 2D tensor, i.e. each
                  # example's contribution to the embedding is a 1D tensor.
                  * learning_rate_root
              )
  
          # once we have computed the contribution from each batch, for a given
          # checkpoint, we concatenate them along the batch dimension to get a
          # single 2D tensor for that checkpoint
          checkpoint_contributions[j] = torch.cat(
              checkpoint_contributions[j], dim=0  # type: ignore
          )
  
      # finally, we concatenate along the checkpoint dimension, to get a tensor of
      # shape (batch_size, projection_dim * number of checkpoints)
      # each row in this result is the "embedding" vector for an example in `batch`
      return torch.cat(checkpoint_contributions, dim=1)
  
imports: import threading
  import warnings
  from collections import defaultdict
  from typing import Any, Callable, cast, Dict, Iterator, List, Optional, Tuple, Union
  import torch
  from captum._utils.common import _get_module_from_name, _sort_key_list
  from captum._utils.gradient import _gather_distributed_tensors
  from captum._utils.progress import NullProgress, progress
  from captum.influence._core.tracincp import _influence_route_to_helpers, KMostInfluentialResults, TracInCPBase
  from captum.influence._utils.common import _check_loss_fn, _format_inputs_dataset, _get_k_most_influential_helper, _jacobian_loss_wrt_inputs, _load_flexible_state_dict, _self_influence_by_batches_helper, _tensor_batch_dot
  from captum.influence._utils.nearest_neighbors import AnnoyNearestNeighbors, NearestNeighbors
  from captum.log import log_usage
  from torch import device, Tensor
  from torch.nn import Module
  from torch.utils.data import DataLoader, Dataset
label_desc: Use image node_id 8 for calling the TracInCPFastRandProj obj's underlying member method code with example usage: obj._get_intermediate_quantities_tracincp_fast_rand_proj(inputs, projection_quantities, test) and returns: torch