class_docstr: Grouped Conditional Expectation plots are generated for a given instance and set of features.
  They show how the model prediction is affected when a pair of features of a given instance are
  perturbed. The perturbed features can be either a provided subset of the input covariates, or
  the top K features based on the importance rank obtained by a global explainer (e.g., SHAP).
  If the user provides a single feature then the algorithm produces a standard ICE plot where the
  selected feature varies according to a linespace grid. If the user chooses more than one feature,
  then the explainer produces 3D ICE plots. Here, two features vary simultaneously according to a
  meshgrid, the output of the model is stored for each pair of values.
docstr: Produces local explanation of the target model for selected feature(s).
  
  Args:
      instance (Union[pd.DataFrame, np.ndarray]): input instance to be explained.
  
  Returns:
      dict: explanation object
          Dictionary with feature_name, feature_value, ice_value, current_value
          for ICE explanation. Dictionary with gce_values, x_grid, y_pred,
          current_values for GCE explanation.
docstr_tok: ["Produces","local","explanation","of","the","target","model","for","selected","feature","(","s",")",".","Args",":","instance","(","Union","[","pd.DataFrame",",","np.ndarray","]",")",":","input","instance","to","be","explained",".","Returns",":","dict",":","explanation","object","Dictionary","with","feature_name",",","feature_value",",","ice_value",",","current_value","for","ICE","explanation",".","Dictionary","with","gce_values",",","x_grid",",","y_pred",",","current_values","for","GCE","explanation","."]
code: def explain_instance(
      self,
      instance: Union[pd.DataFrame, np.ndarray],
      **kwargs,  # CAN STAY
  ):
      """Produces local explanation of the target model for selected feature(s).
  
      Args:
          instance (Union[pd.DataFrame, np.ndarray]): input instance to be explained.
  
      Returns:
          dict: explanation object
              Dictionary with feature_name, feature_value, ice_value, current_value
              for ICE explanation. Dictionary with gce_values, x_grid, y_pred,
              current_values for GCE explanation.
  
      """
  
      np.random.seed(self.random_seed)
      return_instances = kwargs.get("return_instances", True)
      feat_perturbation = kwargs.get("feature_perturbations", {})
  
      if len(self.features_selected) < 1:
          raise ValueError(
              f"Error: explain_instance API expects at least one "
              f"numeric feature specification."
          )
  
      for feat in self.features_selected:
          if not self._is_numeric_feature(feat):
              raise ValueError(
                  f"Error: supports numeric features only, "
                  f"{feat} is not a numeric feature!"
              )
  
      if instance.shape[0] != 1:
          raise RuntimeError(
              f"Error: explain_instance must be invoked for single instance only"
          )
  
      if isinstance(instance, np.ndarray):
          instance = pd.DataFrame(instance, columns=self.feature_names)
  
      if not all([feat in instance for feat in self.feature_names]):
          raise ValueError(
              f"Error: expects instance indices or dataframe "
              f"with all feature columns"
          )
  
      instance = instance[self.feature_names]
      feature_sample = {}
  
      # generate perturbed feature samples
      for feat in self.features_selected:
          mn = self.feature_range[feat]["min"]
          mx = self.feature_range[feat]["max"]
          if feat in feat_perturbation:
              perturb_mn = feat_perturbation[feat]["min"]
              perturb_mx = feat_perturbation[feat]["max"]
  
              feature_sample[feat] = np.linspace(
                  perturb_mn, perturb_mx, self.n_samples
              )
          else:
              feature_sample[feat] = np.linspace(mn, mx, self.n_samples)
  
      # compute conditional expectation
      if len(self.features_selected) == 1:  # ICE
          feature_name = self.features_selected[0]
          curr_value = instance[feature_name].values[0]
          ordered_values = feature_sample[feature_name]
  
          x_perturbed = pd.concat(
              [instance for _ in ordered_values]
          ).reset_index(drop=True)
          x_perturbed.loc[:, feature_name] = ordered_values
  
          predictions = self._batch_predict(x_perturbed.values)
  
          y_pred = np.squeeze(np.asarray(predictions))
  
          explanation = {
              "feature_name": feature_name,
              "feature_value": ordered_values,
              "ice_value": y_pred,
              "current_value": curr_value,
          }
  
      else:  # GroupedCE
          x_sample = pd.DataFrame(
              [
                  instance.values[0]
                  for _ in range(self.n_samples * self.n_samples + 1)
              ],
              columns=self.feature_names,
          )
  
          explanation = {"selected_features": self.features_selected}
          for i, feat_1 in enumerate(self.features_selected):
              if feat_1 not in explanation:
                  explanation[feat_1] = {}
              for feat_2 in self.features_selected[i + 1 :]:
                  feat_value_1, feat_value_2 = np.meshgrid(
                      feature_sample[feat_1], feature_sample[feat_2]
                  )
                  x_perturbed = x_sample.copy()
                  x_perturbed[feat_1] = np.append(
                      feat_value_1.reshape(-1),
                      [instance[feat_1].values[0]],
                  )
                  x_perturbed[feat_2] = np.append(
                      feat_value_2.reshape(-1),
                      [instance[feat_2].values[0]],
                  )
                  predictions = self._batch_predict(x_perturbed.values)
  
                  predictions = np.squeeze(np.asarray(predictions))
                  value_grid = predictions[:-1].reshape(
                      (self.n_samples, self.n_samples)
                  )
                  explanation[feat_1][feat_2] = {
                      "gce_values": value_grid.tolist(),
                      "x_grid": feature_sample[feat_1],
                      "y_grid": feature_sample[feat_2],
                  }
                  if return_instances:
                      explanation[feat_1][feat_2]["current_values"] = {
                          feat_1: instance[feat_1].values[0],
                          feat_2: instance[feat_2].values[0],
                      }
                      explanation[feat_1][feat_2][
                          "prediction"
                      ] = predictions[-1]
      return explanation
  
file_path: AIX360/aix360/algorithms/gce/gce.py
imports: import warnings
  from typing import List, Union, Callable
  import numpy
  import pandas
  import shap
  from aix360.algorithms.lbbe import LocalBBExplainer
label_desc: Use image node_id 8 for calling the GroupedCEExplainer obj's underlying member method code with example usage: obj.explain_instance(instance) and returns: explanation