class_docstr: Decorate a perturbation-based attribution algorthm to make it work with dataloaders.
  The decorated instance will calculate attribution in the
  same way as configured in the original attribution instance, but it will provide a
  new "attribute" function which accepts a pytorch "dataloader" instance as the input
  instead of a single batched "tensor" and supports customizing a "reduce" function to
  determine how the forward return of each iteration of the dataloader should be
  aggregated to single metric tensor to attribute. This would
  be specially useful to attribute against some corpus-wise metrics,
  e.g., Precision & Recall.
class_docstr_tok: ["Decorate","a","perturbation-based","attribution","algorthm","to","make","it","work","with","dataloaders",".","The","decorated","instance","will","calculate","attribution","in","the","same","way","as","configured","in","the","original","attribution","instance",",","but","it","will","provide","a","new","``","attribute","''","function","which","accepts","a","pytorch","``","dataloader","''","instance","as","the","input","instead","of","a","single","batched","``","tensor","''","and","supports","customizing","a","``","reduce","''","function","to","determine","how","the","forward","return","of","each","iteration","of","the","dataloader","should","be","aggregated","to","single","metric","tensor","to","attribute",".","This","would","be","specially","useful","to","attribute","against","some","corpus-wise","metrics",",","e.g.",",","Precision","&","Recall","."]
docstr: Wrapper of the original given forward_func to be used in the attribution method
  It iterates over the dataloader with the given forward_func
docstr_tok: ["Wrapper","of","the","original","given","forward_func","to","be","used","in","the","attribution","method","It","iterates","over","the","dataloader","with","the","given","forward_func"]
code: def _forward_with_dataloader(
      self,
      batched_perturbed_feature_indices: Tensor,
      dataloader: torch.utils.data.DataLoader,
      input_roles: Tuple[int],
      baselines: Tuple[Union[int, float, Tensor], ...],
      feature_mask: Tuple[Tensor, ...],
      reduce: Callable,
      to_metric: Optional[Callable],
      show_progress: bool,
      feature_idx_to_mask_idx: Dict[int, List[int]],
  ):
      """
      Wrapper of the original given forward_func to be used in the attribution method
      It iterates over the dataloader with the given forward_func
      """
  
      # batched_perturbed_feature_indices in shape(n_perturb, n_features)
      # n_perturb is not always the same as perturb_per_pass if not enough perturb
      perturbation_mask_list: List[Tuple[Union[Tensor, None], ...]] = [
          _create_perturbation_mask(
              perturbed_feature_indices,
              feature_mask,
              feature_idx_to_mask_idx,
          )
          for perturbed_feature_indices in batched_perturbed_feature_indices
      ]
  
      # each perturbation needs an accum state
      accum_states = [None for _ in range(len(perturbation_mask_list))]
  
      # tranverse the dataloader
      for inputs in dataloader:
          # for each batch read from the dataloader,
          # apply every perturbation based on perturbations_per_pass
          for i, perturbation_mask in enumerate(perturbation_mask_list):
              perturbed_inputs = _perturb_inputs(
                  inputs, input_roles, baselines, perturbation_mask
              )
  
              # due to explicitly defined roles
              # we can keep inputs in their original order
              # regardless of if they need attr
              # instead of using additional_forward_inputs
              forward_inputs = tuple(
                  _
                  for _, role in zip(perturbed_inputs, input_roles)
                  if role != InputRole.no_forward
              )
  
              output = _run_forward(
                  self.forward_func,
                  forward_inputs,
              )
  
              accum_states[i] = reduce(
                  accum_states[i], output, perturbed_inputs
              )
  
      accum_results = [
          to_metric(accum) if to_metric else accum
          for accum in accum_states
      ]
  
      assert all(type(r) is Tensor for r in accum_results), (
          "Accumulated metrics for attribution must be a Tensor,"
          f"received: {next(r for r in accum_results if type(r) is not Tensor)}"
      )
  
      # shape(n_perturb * output_dims[0], *output_dims[1:])
      # the underneath attr method needs to support forward_func output's
      # 1st dim to grow with perturb_per_eval
      batched_accum = torch.stack(accum_results, dim=0)
      return batched_accum
  
file_path: captum/captum/attr/_core/dataloader_attr.py
imports: from collections import defaultdict
  from copy import copy
  from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union
  import torch
  from captum._utils.common import _format_baseline, _format_feature_mask, _format_output, _format_tensor_into_tuples, _get_max_feature_index, _run_forward
  from captum._utils.typing import BaselineType
  from captum.attr._core.feature_ablation import FeatureAblation
  from captum.attr._utils.attribution import Attribution
  from torch import Tensor
label_desc: Use image node_id 2 for calling the DataLoaderAttribution obj's underlying member method code with example usage: obj._forward_with_dataloader(batched_perturbed_feature_indices, dataloader, input_roles, baselines, feature_mask, reduce, to_metric, show_progress, feature_idx_to_mask_idx) and returns: batched_accum