code: def get_inverse_hvp_lissa(
      vs: Sequence[torch.Tensor],
      model: Model,
      used_params: Sequence[torch.Tensor],
      lissa_data_loader: DataLoader,
      damping: float,
      num_samples: int,
      scale: float,
  ) -> torch.Tensor:
      """
      This function approximates the product of the inverse of the Hessian and
      the vectors `vs` using LiSSA.
  
      Adapted from [github.com/kohpangwei/influence-release]
      (https://github.com/kohpangwei/influence-release/blob/0f656964867da6ddcca16c14b3e4f0eef38a7472/influence/genericNeuralNet.py#L475),
      the repo for [Koh, P.W., & Liang, P. (2017)](https://api.semanticscholar.org/CorpusID:13193974),
      and [github.com/xhan77/influence-function-analysis]
      (https://github.com/xhan77/influence-function-analysis/blob/78d5a967aba885f690d34e88d68da8678aee41f1/bert_util.py#L336),
      the repo for [Han, Xiaochuang et al. (2020)](https://api.semanticscholar.org/CorpusID:218628619).
      """
      inverse_hvps = [torch.tensor(0) for _ in vs]
      for _ in Tqdm.tqdm(
          range(num_samples), desc="LiSSA samples", total=num_samples
      ):
          # See a explanation at "Stochastic estimation" paragraph in [https://arxiv.org/pdf/1703.04730.pdf]
          # initialize \tilde{H}^{−1}_0 v = v
          cur_estimates = vs
          recursion_iter = Tqdm.tqdm(
              lissa_data_loader,
              desc="LiSSA depth",
              total=len(lissa_data_loader),
          )
          for j, training_batch in enumerate(recursion_iter):
              # TODO (epwalsh): should we make sure `model` is in "train" or "eval" mode here?
              model.zero_grad()
              train_output_dict = model(**training_batch)
              # Hessian of loss @ \tilde{H}^{−1}_{j - 1} v
              hvps = get_hvp(
                  train_output_dict["loss"], used_params, cur_estimates
              )
  
              # This is the recursive step:
              # cur_estimate = \tilde{H}^{−1}_{j - 1} v
              # (i.e. Hessian-Vector Product estimate from last iteration)
              # Updating for \tilde{H}^{−1}_j v, the new current estimate becomes:
              # v + (I - (Hessian_at_x + damping)) * cur_estimate
              # = v + (I + damping) * cur_estimate - Hessian_at_x * cur_estimate
              # We divide `hvp / scale` here (or, equivalently `Hessian_at_x / scale`)
              # so that we're effectively dividing the loss by `scale`.
              cur_estimates = [
                  v + (1 - damping) * cur_estimate - hvp / scale
                  for v, cur_estimate, hvp in zip(
                      vs, cur_estimates, hvps
                  )
              ]
  
              # Update the Tqdm progress bar with the current norm so the user can
              # see it converge.
              if (j % 50 == 0) or (j == len(lissa_data_loader) - 1):
                  norm = np.linalg.norm(
                      _flatten_tensors(cur_estimates).cpu().numpy()
                  )
                  recursion_iter.set_description(
                      desc=f"calculating inverse HVP, norm = {norm:.5f}"
                  )
  
          # Accumulating X_{[i,S_2]}  (notation from the LiSSA (algo. 1) [https://arxiv.org/pdf/1602.03943.pdf]
          # Need to divide by `scale` again here because the `vs` represent gradients
          # that haven't been scaled yet.
          inverse_hvps = [
              inverse_hvp + cur_estimate / scale
              for inverse_hvp, cur_estimate in zip(
                  inverse_hvps, cur_estimates
              )
          ]
      return_ihvp = _flatten_tensors(inverse_hvps)
      return_ihvp /= num_samples
      return return_ihvp
  
file_path: allennlp/allennlp/interpret/influence_interpreters/simple_influence.py
imports: import logging
  from typing import List, Optional, Tuple, Union, Sequence
  import numpy
  import torch
  import torch.autograd
  from allennlp.common import Lazy
  from allennlp.common.tqdm import Tqdm
  from allennlp.data import DatasetReader, DatasetReaderInput, Instance
  from allennlp.data.data_loaders import DataLoader, SimpleDataLoader
  from allennlp.interpret.influence_interpreters.influence_interpreter import InfluenceInterpreter
  from allennlp.models.model import Model
label_desc: Use image node_id 1 for calling a global function with example usage: get_inverse_hvp_lissa(vs, model, used_params, lissa_data_loader, damping, num_samples, scale) and returns: return_ihvp