class_docstr: Implementation of the permutation feature importance for tabular datasets. The method measure the importance
  of a feature as the relative increase/decrease in the loss/score function when the feature values are permuted.
  Supports black-box models.
  
  For details of the method see the papers:
  
   - https://link.springer.com/article/10.1023/A:1010933404324
  
   - https://arxiv.org/abs/1801.01489
docstr: Helper function to compute the "exact" value of the permutation feature importance.
  
  Parameters
  ----------
  X, y, kind, sample_weight, features, loss_orig, score_orig
      See :py:meth:`alibi.explainers.permutation_importance.PermutationImportance._compute_permutation_importance`.  # noqa
  
  Returns
  -------
  A dictionary having as keys the metric names and as values the permutation feature importance associated
  with the corresponding metrics.
docstr_tok: ["Helper","function","to","compute","the","``","exact","''","value","of","the","permutation","feature","importance",".","Parameters","--","--","--","--","--","X",",","y",",","kind",",","sample_weight",",","features",",","loss_orig",",","score_orig","See",":","py",":","meth",":","`","alibi.explainers.permutation_importance.PermutationImportance._compute_permutation_importance","`",".","#","noqa","Returns","--","--","--","-","A","dictionary","having","as","keys","the","metric","names","and","as","values","the","permutation","feature","importance","associated","with","the","corresponding","metrics","."]
code: def _compute_exact(
      self,
      X: np.ndarray,
      y: np.ndarray,
      kind: str,
      sample_weight: Optional[np.ndarray],
      features: Union[int, Tuple[int, ...]],
      loss_orig: Dict[str, List[float]],
      score_orig: Dict[str, List[float]],
  ) -> Dict[str, Any]:
      """
      Helper function to compute the "exact" value of the permutation feature importance.
  
      Parameters
      ----------
      X, y, kind, sample_weight, features, loss_orig, score_orig
          See :py:meth:`alibi.explainers.permutation_importance.PermutationImportance._compute_permutation_importance`.  # noqa
  
      Returns
      -------
      A dictionary having as keys the metric names and as values the permutation feature importance associated
      with the corresponding metrics.
      """
      y_perm, y_perm_hat = [], []
      weights: Optional[List[np.ndarray]] = (
          [] if sample_weight else None
      )
  
      for i in range(len(X)):
          # create input features dataset: (1, F1, F2, ...) -> (N - 1, F1, F2, ... )
          # where N is the number of instances in the dataset and Fi is the dimension in the axis i.
          X_tmp = np.tile(
              X[i : i + 1],
              reps=(len(X) - 1,) + (1,) * (len(X.shape) - 1),
          )
          X_tmp[:, features] = np.delete(
              arr=X[:, features], obj=i, axis=0
          )
  
          # create ground-truth labels: (1, C1, C2, ...) -> (N - 1, C1, C2, ... )
          # where N is the number of instances in the dataset and Ci is the dimension in the axis i.
          y_tmp = np.tile(
              y[i : i + 1],
              reps=(len(y) - 1,) + (1,) * (len(y.shape) - 1),
          )
  
          # compute predictions
          y_perm_hat.append(self.predictor(X_tmp))
          y_perm.append(y_tmp)
  
          # create sample weights if necessary
          if sample_weight is not None:
              weights.append(np.full(shape=(len(X_tmp),), fill_value=sample_weight[i]))  # type: ignore[union-attr]
  
      # concatenate all predictions and construct ground-truth array. At this point, the `y_hat` vector
      # should contain `N x (N - 1)` predictions, where `N` is the number of samples in `X`.
      y_perm_hat = np.concatenate(y_perm_hat, axis=0)
      y_perm = np.concatenate(y_perm, axis=0)
  
      if weights is not None:
          weights = np.concatenate(weights, axis=0)
  
      # compute loss values for the altered dataset
      loss_permuted = PermutationImportance._compute_metrics(
          metric_fns=self.loss_fns,
          y=y_perm,  # type: ignore[arg-type]
          y_hat=y_perm_hat,  # type: ignore[arg-type]
          sample_weight=weights,
      )  # type: ignore[arg-type]
  
      # compute score values for the altered dataset
      score_permuted = PermutationImportance._compute_metrics(
          metric_fns=self.score_fns,
          y=y_perm,  # type: ignore[arg-type]
          y_hat=y_perm_hat,  # type: ignore[arg-type]
          sample_weight=weights,
      )  # type: ignore[arg-type]
  
      # compute feature importance for the loss functions
      loss_feature_importance = (
          PermutationImportance._compute_importances(
              metric_orig=loss_orig,
              metric_permuted=loss_permuted,
              kind=kind,
              lower_is_better=True,
          )
      )
  
      # compute feature importance for the score functions
      score_feature_importance = (
          PermutationImportance._compute_importances(
              metric_orig=score_orig,
              metric_permuted=score_permuted,
              kind=kind,
              lower_is_better=False,
          )
      )
  
      return {**loss_feature_importance, **score_feature_importance}
  
imports: import copy
  import inspect
  import logging
  import math
  import numbers
  import sys
  from collections import defaultdict
  from copy import deepcopy
  from enum import Enum
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union, no_type_check
  import matplotlib.pyplot
  import numpy
  import sklearn.metrics
  from tqdm import tqdm
  from alibi.api.defaults import DEFAULT_DATA_PERMUTATION_IMPORTANCE, DEFAULT_META_PERMUTATION_IMPORTANCE
  from alibi.api.interfaces import Explainer, Explanation
label_desc: Use image node_id 7 for calling the PermutationImportance obj's underlying member method code with example usage: obj._compute_exact(X, y, kind, sample_weight, features, loss_orig, score_orig) and returns: dict