docstr: Explains the instances in the array `X`.
  
  Parameters
  ----------
  X
      Instances to be explained.
  summarise_result
      Specifies whether the shap values corresponding to dimensions of encoded categorical variables should be
      summed so that a single shap value is returned for each categorical variable. Both the start indices of
      the categorical variables (`cat_vars_start_idx`) and the encoding dimensions (`cat_vars_enc_dim`)
      have to be specified
  cat_vars_start_idx
      The start indices of the categorical variables. If specified, `cat_vars_enc_dim` should also be specified.
  cat_vars_enc_dim
      The length of the encoding dimension for each categorical variable. If specified `cat_vars_start_idx` should
      also be specified.
  **kwargs
      Keyword arguments specifying explain behaviour. Valid arguments are:
  
          - `nsamples` - controls the number of predictor calls and therefore runtime.
          
          - `l1_reg` - the algorithm is exponential in the feature dimension. If set to `auto` the algorithm will                 first run a feature selection algorithm to select the top features, provided the fraction of sampled                 sets of missing features is less than 0.2 from the number of total subsets. The Akaike Information                 Criterion is used in this case. See our examples for more details about available settings for this                 parameter. Note that by first running a feature selection step, the shapley values of the remainder of                 the features will be different to those estimated from the entire set.
  
      For more details, please see the shap library `documentation`_ .
  
          .. _documentation:
             https://shap.readthedocs.io/en/stable/.
  
  Returns
  -------
  explanation
      An explanation object containing the shap values and prediction in the `data` field, along with a `meta`
      field containing additional data. See usage at `KernelSHAP examples`_ for details.
  
      .. _KernelSHAP examples:
         https://docs.seldon.io/projects/alibi/en/stable/methods/KernelSHAP.html
code: def explain(
      self,
      X: Union[np.ndarray, pd.DataFrame, sparse.spmatrix],
      summarise_result: bool = False,
      cat_vars_start_idx: Optional[Sequence[int]] = None,
      cat_vars_enc_dim: Optional[Sequence[int]] = None,
      **kwargs,
  ) -> Explanation:
      """
          Explains the instances in the array `X`.
  
          Parameters
          ----------
          X
              Instances to be explained.
          summarise_result
              Specifies whether the shap values corresponding to dimensions of encoded categorical variables should be
              summed so that a single shap value is returned for each categorical variable. Both the start indices of
              the categorical variables (`cat_vars_start_idx`) and the encoding dimensions (`cat_vars_enc_dim`)
              have to be specified
          cat_vars_start_idx
              The start indices of the categorical variables. If specified, `cat_vars_enc_dim` should also be specified.
          cat_vars_enc_dim
              The length of the encoding dimension for each categorical variable. If specified `cat_vars_start_idx` should
              also be specified.
          **kwargs
              Keyword arguments specifying explain behaviour. Valid arguments are:
  
                  - `nsamples` - controls the number of predictor calls and therefore runtime.
                  
                  - `l1_reg` - the algorithm is exponential in the feature dimension. If set to `auto` the algorithm will \
                  first run a feature selection algorithm to select the top features, provided the fraction of sampled \
                  sets of missing features is less than 0.2 from the number of total subsets. The Akaike Information \
                  Criterion is used in this case. See our examples for more details about available settings for this \
                  parameter. Note that by first running a feature selection step, the shapley values of the remainder of \
                  the features will be different to those estimated from the entire set.
  
              For more details, please see the shap library `documentation`_ .
  
                  .. _documentation:
                     https://shap.readthedocs.io/en/stable/.
  
          Returns
          -------
          explanation
              An explanation object containing the shap values and prediction in the `data` field, along with a `meta`
              field containing additional data. See usage at `KernelSHAP examples`_ for details.
  
              .. _KernelSHAP examples:
                 https://docs.seldon.io/projects/alibi/en/stable/methods/KernelSHAP.html
          """  # noqa W605
  
      if not self._fitted:
          raise TypeError(
              "Called explain on an unfitted object! Please fit the explainer using the .fit method first!"
          )
  
      if self.distribute:
          if isinstance(X, sparse.spmatrix) or isinstance(
              X, pd.DataFrame
          ):
              raise TypeError(
                  "Incorrect type for `X` due to distributed context. Cast `X` to np.ndarray."
              )
  
      # convert data to dense format if sparse
      if self.use_groups and isinstance(X, sparse.spmatrix):
          X = X.toarray()
  
      shap_values = self._explainer.get_explanation(X, **kwargs)
      self.expected_value = self._explainer.expected_value
      expected_value = self.expected_value
      # for scalar model outputs a single numpy array is returned
      if isinstance(shap_values, np.ndarray):
          shap_values = [shap_values]
      if isinstance(expected_value, float):
          expected_value = [expected_value]
  
      # TODO: @janis: the type is ignored because the distributed explainer can also return a generator or something
      #  else than a list of objects (because it's a generic class). An API update is necessary in order to seamlessly
      #  deal with this. Ignoring with the assumption that this feature is WIP and will not be used for now
      #  (aka, return_generator=True is not passed to the DistributedExplainer)
      explanation = self._build_explanation(
          X,
          shap_values,  # type: ignore
          expected_value,
          summarise_result=summarise_result,
          cat_vars_start_idx=cat_vars_start_idx,
          cat_vars_enc_dim=cat_vars_enc_dim,
      )
  
      return explanation
  
imports: import copy
  import logging
  from functools import partial
  from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
  import numpy
  import pandas
  import shap
  import shap.utils._legacy
  from scipy import sparse
  from scipy.special import expit
  from shap import KernelExplainer
  from alibi.api.defaults import DEFAULT_DATA_KERNEL_SHAP, DEFAULT_DATA_TREE_SHAP, DEFAULT_META_KERNEL_SHAP, DEFAULT_META_TREE_SHAP
  from alibi.api.interfaces import Explainer, Explanation, FitMixin
  from alibi.utils.wrappers import methdispatch
label_desc: Use image node_id 12 for calling the KernelShap obj's underlying member method code with example usage: obj.explain(X, summarise_result, cat_vars_start_idx, cat_vars_enc_dim) and returns: explanation