class_docstr: Analysis block that estimates column importance with SHAP (SHapley Additive exPlanations), a game theoretic approach
  to explain the ouput of any machine learning model. SHAP assigns each feature an importance value for a particular
  prediction.
  
  Reference:
      https://shap.readthedocs.io/en/stable/
      https://proceedings.neurips.cc/paper/2017/file/8a20a8621978632d76c43dfd28b67767-Paper.pdf
class_docstr_tok: ["Analysis","block","that","estimates","column","importance","with","SHAP","(","SHapley","Additive","exPlanations",")",",","a","game","theoretic","approach","to","explain","the","ouput","of","any","machine","learning","model",".","SHAP","assigns","each","feature","an","importance","value","for","a","particular","prediction",".","Reference",":","https",":","\/\/shap.readthedocs.io\/en\/stable\/","https",":","\/\/proceedings.neurips.cc\/paper\/2017\/file\/8a20a8621978632d76c43dfd28b67767-Paper.pdf"]
code: def analyze(
      self, info: Dict[str, object], **kwargs
  ) -> Dict[str, object]:
      log.info(
          "Preparing to compute feature importance values with SHAP"
      )
      ns = SimpleNamespace(**kwargs)
  
      output_dtype = ns.dtype_dict[ns.target]
      train_data: EncodedDs = ns.train_data
  
      if output_dtype in (dtype.integer, dtype.float, dtype.quantity):
          pass
      elif output_dtype in (
          dtype.binary,
          dtype.categorical,
          dtype.tags,
      ):
          self.label_encoder.fit(
              train_data.data_frame[ns.target].values
          )
      else:
          log.warning(
              f"ShapleyValues analyzers not supported for type: {output_dtype}"
          )
          return info
  
      self.target = ns.target
      self.columns = list(set(ns.dtype_dict.keys()) - {self.target})
      input_df = train_data.data_frame[self.columns]
  
      def model(x: np.ndarray) -> np.ndarray:
          assert isinstance(x, np.ndarray)
          df = pd.DataFrame(data=x, columns=self.columns)
          ds = EncodedDs(
              encoders=train_data.encoders,
              data_frame=df,
              target=train_data.target,
          )
  
          decoded_predictions = ns.predictor(
              ds=ds, args=PredictionArguments()
          )
          if output_dtype in (
              dtype.integer,
              dtype.float,
              dtype.quantity,
          ):
              encoded_predictions = decoded_predictions[
                  "prediction"
              ].values
          elif output_dtype in (
              dtype.binary,
              dtype.categorical,
              dtype.tags,
          ):
              encoded_predictions = self.label_encoder.transform(
                  decoded_predictions["prediction"].values
              )
  
          return encoded_predictions
  
      info["shap_explainer"] = shap.KernelExplainer(
          model=model, data=input_df
      )
  
      return info
  
file_path: lightwood/lightwood/analysis/helpers/shap.py
imports: import warnings
  from types import SimpleNamespace
  from typing import Dict, Optional, Tuple
  import numpy
  import pandas
  from lightwood.analysis.base import BaseAnalysisBlock
  from type_infer.dtype import dtype
  from lightwood.api.types import PredictionArguments
  from lightwood.data.encoded_ds import EncodedDs
  from lightwood.helpers.log import log
  from sklearn.preprocessing import LabelEncoder
  import shap
label_desc: Use image node_id 2 for calling the ShapleyValues obj's underlying member method code with example usage: obj.analyze(info) and returns: info, encoded_predictions, info